Skip to content

ADR-018: Docs Authoring Format

Decision

Storybook design-system documentation is authored as self-contained .mdx files that consume legal and prose components through the canonical @dmwd-io/design-system/mdx provider, follow a fixed typographic and heading contract, and derive component prop metadata from TypeScript via react-docgen.

Key rules

  • All Storybook design-system docs under /docs/ use the .mdx extension — no .md files in that surface. CI check check-mdx-only-in-docs blocks PRs that add .md files there.
  • Every doc file derives its Storybook title and sidebar slot from its file path.
  • Doc files are self-contained — never import content from sibling MDX files to compose a single doc page.
  • Exception: legal document case files under src/components/patterns/myfreelawyer/ may use MDX-imports-MDX composition per the Orders folder pattern. This exception is scoped to myfreelawyer/ only.
  • Converting an existing .md file: rename to .mdx and place it in the folder that should own its sidebar location.
  • Import MDX consumers from the @dmwd-io/design-system/mdx subpath export — never from internal paths.
  • legalRemarkPlugins / legalRehypePlugins are the canonical plugin arrays for legal MDX — use them, never reassemble them per project.
  • MDXLegalProvider supplies all legal components to MDX consumers — no individual component imports inside MDX files, and no design-system imports inside MDX files.
  • Numbered-paragraph shorthand works inside <LegalSection> — use it.
  • No // comments at the top level of MDX files — they are a parse error.
  • Exactly one h1 per document — the document title is the only h1.
  • Never skip heading levels (no h2h4 with no h3 between).
  • No **Bold:** pseudo-headings — if it opens a paragraph and the content beneath could stand alone, promote it to a real heading.
  • Prose styles are scoped to [data-docs-mdx-article], unlayered so they beat Storybook defaults; h2 gets 3.5rem top spacing with no decorative border below it.
  • Consecutive metadata lines (date, author, etc.) use a trailing two-space line break, not blank lines between them.
  • Default prop docgen is react-docgen, set in .storybook/main.ts as typescript: { reactDocgen: "react-docgen", check: false }.
  • TSDoc comments on *Props interfaces are the source of truth for prop descriptions. A missing description is fixed in the TSDoc, not in Storybook argTypes.
  • Never switch to react-docgen-typescript without a project-scoped ADR — it carries a significant performance cost.

Code patterns

.storybook/main.ts
const config = {
typescript: { reactDocgen: "react-docgen", check: false },
};

Why

A single authoring format keeps documentation portable across Storybook, removes per-project plugin drift, and makes the prose contract enforceable in CI. Pinning docgen to react-docgen keeps the Storybook build fast while TSDoc remains the one place prop descriptions live. This record reconciles the MDX-only rule to current dmwd-io practice: it is scoped to the Storybook design-system docs surface, since the global markdown standard still authors ordinary repo docs as .md/.mdx under docs/. It also adopts the global no-pseudo-heading and heading-hierarchy rules as the canonical statement of the typography contract, retiring the per-ADR phrasings in ADR-018.

Applies when

You are creating or converting a Storybook design-system doc, authoring or wiring up MDX (including legal documents), configuring Storybook prop metadata, or reviewing docs prose, heading structure, or Controls-panel output.

  • ADR-030 — MyfreeLawyer legal document architecture (the myfreelawyer/ composition exception).
  • ADR-020 — docs folder convention and information architecture.
  • ADR-003 — typography and density governance.
  • ADR-017 — Storybook documentation truthfulness contract.