A public continuation of Scaling mobile component docs with AI
Type a shadcn/ui component name and get structured documentation written for designers and product managers, not engineers. The tool fetches live docs directly from the shadcn/ui, Radix UI, and Base UI GitHub repositories, so the output is grounded in current source material, not training data.
You can also paste a JSON schema directly, which is useful if you’re working with a custom or internal component library.
In April 2025, I built the first version of this while at Amazon, for a mobile app team with no designated writer. I referenced Apple’s HIG, Material Design, and Shopify’s Polaris principles to create an AI agent that cut documentation time from 3+ hours to 30 minutes per component.
It’s main friction point was that every draft started with copy-pasting a component’s JSON schema into the generator. I wanted to see if I could rebuild the tool on my own, remove that step, and make something that could stand on its own. The public version pulls component schemas directly from shadcn/ui’s GitHub repos. Users search for a component the same way they would on the shadcn docs site and get structured design documentation back.
The tool has two input modes:
Fetch from docs: type any shadcn/ui component name and the tool pulls raw MDX directly from the shadcn/ui, Radix UI, and Base UI GitHub repositories. The live source content becomes the grounding material for generation. The tool tries both the base/ and radix/ subdirectories in the shadcn repo and combines what it finds. This means the output reflects current documentation, not a snapshot from training data.
Custom schema: paste a JSON schema for any component. The schema determines what sections are generated and what gets covered. This is the no-hallucination constraint for custom libraries: the tool doesn’t invent props or variants that aren’t in the schema.
A curated knowledge layer in src/platform-guidelines.js contains best practices from Apple’s Human Interface Guidelines and Google’s Material Design: touch target sizes, disabled state guidance, label conventions, accessibility requirements, and more. This layer is injected into every prompt as a reference.
The model draws from this encoded knowledge rather than recalling best practices from training data. The result is guidance that’s grounded and auditable: if something looks wrong, you can check it against the source file.
src/prompt.js is where the documentation philosophy becomes machine-readable: the section structure, the framing rules, the editorial standards, and the instruction to lead with positive framing and always include the “why.” Most AI tools treat the prompt as an implementation detail. Here it’s the primary design artifact: versioned, readable, and separable from the platform knowledge layer so both can be maintained independently.
Input schema:
{
"component": "Button",
"props": {
"variant": {
"type": "enum",
"values": ["default", "destructive", "outline", "secondary", "ghost", "link"],
"default": "default"
},
"size": {
"type": "enum",
"values": ["default", "sm", "lg", "icon"],
"default": "default"
},
"disabled": {
"type": "boolean",
"default": false
}
}
}
Generated output (excerpted):
# Button
Triggers a single, discrete action wherever a user needs to confirm, submit, or initiate something.
## When to use
Use a button when a user action produces an immediate result, like submitting a form, saving changes,
or opening a dialog. For link-style navigation to another page, use the `link` variant or a plain
anchor. For toggling between states, consider a toggle or checkbox instead.
## Variants and options
**Default:** the primary action. Use once per view for the most important thing the user can do.
**Destructive:** for actions that delete data or cannot be undone. Always pair with a confirmation dialog.
**Ghost:** low-emphasis actions where a filled or outlined button would compete with more important UI.
**Icon (size):** use only when the icon is universally understood. Always include an `aria-label`.
## Accessibility
Set `aria-label` on every icon-only button. The label names the action, not the icon: "Close dialog," not "X."
Use `aria-disabled="true"` instead of the HTML `disabled` attribute to keep the element in the tab
order while communicating that it's unavailable.
Use `aria-pressed` when the button toggles between two states. Update the value on each selection.
Both Enter and Space activate a button. Don't override or block these key bindings.
The eval/ directory contains a lightweight evaluation framework for testing prompt changes against expected output quality. Each test case defines traits the output must contain and antitraits it must not.
The prompt changelog tracks what changed in the prompt, why, and what effect it had on output quality.