Component docs rot because they are written apart from the code. Generate them from what cannot lie — the component source, its types, and its stories — and the docs stay a projection of reality: usage guidelines, do/don't examples, and migrate-off-the-old-component guides, all reviewable in one sitting.
Tier: Foundation · Workflow area: Design-to-code & design systems
This playbook produces two artifacts your design system is probably missing: per-component usage docs that answer "which variant, when?", and migration guides that finally let you delete the deprecated component.
any everywhere) — fix the types first; docs generated from props: any are fiction.tags: ['autodocs']) if you want the output rendered next to the live component.Feed the model evidence, not adjectives. For each component, provide the four files that constrain the truth:
Context: Button.tsx (source), Button.stories.tsx, Button.test.tsx, and
grep output of 12 real call sites across the repo. Write usage docs as
MDX with sections: Purpose (2 sentences), When to use / When not to
(link the alternative component for each "not"), Props worth explaining
(skip the autodocs table — only props with non-obvious behavior),
Do/Don't pairs (4, each with a code snippet), Accessibility contract
(keyboard behavior, ARIA it manages, what the CONSUMER must still
provide). Every claim must be derivable from the provided files — if
the source doesn't show it, don't write it.
The call-site grep matters most: real usage teaches the model your team's idioms, so examples come out in your patterns instead of generic React.
Make the do/don'ts concrete pairs. Vague guidance ("use appropriately") is filler. Demand the failure mode:
Each Don't must show code someone on this team actually might write
(check the call sites for near-misses) and name the consequence:
broken focus ring, off-token color, double padding. Pair it with the
Do that fixes it, using the same scenario.
A generated pair worth keeping looks like:
// Don't: onClick on a styled div — invisible to keyboard and AT
<div className="btn-primary" onClick={save}>Save</div>
// Do: variant prop carries the styling, semantics come free
<Button variant="primary" onClick={save}>Save</Button>
Verify against the source, not your memory. Read the draft with the component open. Three checks per doc: does every named prop exist with that exact name and type; does the accessibility contract match what the code does (if docs say "manages aria-expanded", find that line); do the examples compile — paste one into the repo and typecheck it. Models write plausible props (isDisabled for disabled) constantly; this five-minute pass catches them.
Generate the migration guide from both sources. For the deprecated-component problem, give the model old source, new source, and the diff of one already-migrated call site if you have one:
OldModal.tsx is deprecated in favor of Dialog.tsx. Produce
MIGRATION.md with: (1) a prop-mapping table — old prop | new prop |
notes, flagging every behavioral difference (default changed, prop
removed, event signature changed); (2) three before/after examples
covering the common, the composed, and the gnarly call-site patterns
you see in the attached grep of all 60 current usages; (3) a
"cannot migrate mechanically" list for call sites using removed
behavior, each with the recommended rewrite.
The prop-mapping table is the load-bearing part — it is what turns 60 manual migrations into a checklist, and what a codemod (or a follow-up agent sweep) can execute against.
Wire the output where engineers already look. Paste the MDX into the story file's docs page or a co-located Button.mdx so Storybook autodocs renders prose and live props table together. Migration guides live next to the deprecated component with a @deprecated JSDoc tag linking to them — that puts the guide in the editor tooltip at every one of the 60 call sites.
Regenerate on API change, not on a schedule. Add a CI reminder (or a PR-template checkbox) that fires when Button.tsx's props change: "props changed — regenerate or amend Button.mdx." Generated docs are cheap to refresh; stale docs are expensive to trust.
Generation order matters — source and stories first, call sites second, old docs last if at all. A model given the stale docs first will faithfully reproduce their errors with new formatting.
@workspace finds call sites for you; verify it actually pulled them rather than summarizing from the source alone.@Composable source plus @Preview functions, or the SwiftUI view plus #Preview blocks, and output lands in KDoc/DocC instead of MDX.@deprecated tag, not in a wiki nobody opens.Run the migration guide against one real call site yourself before publishing — convert it using only the guide, no source-diving. Every place you got stuck is a missing row or example; fix the guide, not the reader.