Use after React components are built (Phase 4.5 of the Figma/Canva/screenshot pipeline) or whenever a project needs Storybook coverage — auto-generates .stories.tsx and .mdx docs from components via ts-morph AST parsing, with prop controls, variant stories, action args, and default args. Keywords: Storybook, generate stories, .stories.tsx, MDX docs, argTypes, controls, autodocs, CSF3, variant stories, action args, component documentation, story generation, ts-morph
Scanned 9/13/2026
Install to Claude Code
npx -y skills add PMDevSolutions/Aurelius --skill storybook-story-generation --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Storybook Story Generation?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/pmdevsolutions-storybook-story-generation)More formats (shields.io, HTML) on the badges page.
---
name: storybook-story-generation
description: Use after React components are built (Phase 4.5 of the Figma/Canva/screenshot pipeline) or whenever a project needs Storybook coverage — auto-generates .stories.tsx and .mdx docs from components via ts-morph AST parsing, with prop controls, variant stories, action args, and default args. Keywords: Storybook, generate stories, .stories.tsx, MDX docs, argTypes, controls, autodocs, CSF3, variant stories, action args, component documentation, story generation, ts-morph
---
# Storybook Story Generation — AST-Based Stories + MDX Docs
## Purpose
Auto-generate Storybook 8 (CSF3) stories and MDX documentation from built React
components. The generator parses each component's TypeScript source with a
`ts-morph` AST — not regex — so it can reliably extract prop types, string-literal
unions, default values, callback props, and JSDoc comments, then emit:
- **`Component.stories.tsx`** — `Meta` with `tags: ['autodocs']`, prop-aware
`argTypes`/controls, a `Default` story seeded with destructured defaults, one
variant story per union value, `True`/`False` stories for booleans, action args
for callbacks, and optional responsive-viewport stories.
- **`Component.mdx`** — an autodocs page with `Meta`, `Canvas`, `Controls`, and
`ArgTypes` blocks, plus the component's JSDoc description and a `Canvas` per
variant.
The skill wraps `scripts/generate-stories.sh` (a thin wrapper over
`scripts/generate-stories.js`). It is a **non-blocking** step: a failure never
fails the build.
## When to Use
- **Phase 4.5** of `/build-from-figma`, `/build-from-canva`, and
`/build-from-screenshot` — immediately after components are built and unit tests
pass, before/alongside visual QA (runs in parallel, non-blocking).
- Backfilling Storybook coverage for an existing component library.
- When the user asks to "generate Storybook stories", "add stories for these
components", "create autodocs", or "document components in Storybook".
**Trigger phrases:**
- "Generate Storybook stories"
- "Auto-generate stories for my components"
- "Add MDX docs to Storybook"
- "Create stories with controls and variants"
**Do NOT use for:** hand-authored interaction/`play()` tests (those belong to the
`react-testing-workflows` skill), or non-React output targets.
## Inputs
- **Required:** Built components under `src/components/**/*.tsx` (override with
`--src-dir`). Components must be **exported** and named with an uppercase first
letter (function, arrow-const, or default export).
- **Recommended:** A props `interface ComponentNameProps` — the generator keys off
this naming convention to build controls and variants.
- **Optional:** `.claude/pipeline.config.json` → `storybook` (thresholds and
toggles; see [Configuration](#configuration)).
- **Optional:** `tsconfig.json` — used by `ts-morph` when present; otherwise a
sensible in-memory compiler config is used.
## Process
### Step 1: Read configuration
Load `.claude/pipeline.config.json` → `storybook` (falls back to defaults if the
file is missing or `autoGenerate` is unset). Relevant keys: `skipPatterns`,
`generateMdx`, `maxVariantsPerProp`, `includeResponsiveViewports`, `viewports`
(widths resolved from `visualDiff.breakpoints`).
### Step 2: Scan for components
Recursively walk `src/components`, collecting `.tsx` files while excluding
`*.test.tsx`, `*.stories.tsx`, `*.d.ts`, `index.tsx`, and the `node_modules`,
`__tests__`, and `__mocks__` directories. Files matching a `skipPatterns` glob are
skipped. Components that already have a `.stories.tsx` sibling are skipped unless
`--force` is passed.
### Step 3: Extract prop metadata (AST)
For each component the generator:
1. Finds the first exported uppercase component (function decl, exported
`const`, or default export).
2. Locates its `ComponentNameProps` interface.
3. For each prop, records: name, optionality, control type, union options,
JSDoc description, and whether it is a callback.
4. Reads default values from the parameter destructuring pattern
(`({ size = 'md' })` → `size: 'md'`).
**Control mapping:**
| Prop type | Control | Notes |
|-----------|---------|-------|
| `string` | `text` | |
| `number` | `number` | |
| `boolean` | `boolean` | also emits `True`/`False` variant stories |
| `'a' \| 'b' \| 'c'` (string-literal union) | `select` | `options` populated; one variant story per value |
| `on*` function (e.g. `onClick`) | action arg | `{ action: 'clicked' }` (past-tense of the event) |
| other / complex | `text` | falls back to `text`; adjust manually if needed |
### Step 4: Generate `.stories.tsx`
Emit CSF3 with `title: 'Components/<path-relative-to-src>'`, `tags: ['autodocs']`,
`argTypes`, a `Default` story (seeded with destructured defaults), variant stories
(capped at `maxVariantsPerProp` per prop), and viewport stories when
`includeResponsiveViewports` is enabled.
```tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Badge } from './Badge';
const meta: Meta<typeof Badge> = {
title: 'Components/ui/Badge',
component: Badge,
tags: ['autodocs'],
argTypes: {
variant: { control: 'select', options: ['info', 'success', 'warning', 'error'] },
onDismiss: { action: 'dismissed' },
},
};
export default meta;
type Story = StoryObj<typeof Badge>;
export const Default: Story = { args: { variant: 'info' } };
export const Info: Story = { args: { variant: 'info' } };
export const Success: Story = { args: { variant: 'success' } };
// …one per union value
```
### Step 5: Generate `.mdx` (unless `--no-mdx` or `generateMdx: false`)
Emit an autodocs page importing `@storybook/blocks`, referencing the sibling
`.stories`, and embedding the component's JSDoc description, the `Default`
`Canvas`, `Controls`, a `Canvas` per variant, and the full `ArgTypes` table.
```mdx
import { Meta, Canvas, Controls, ArgTypes } from '@storybook/blocks';
import * as Stories from './Badge.stories';
<Meta of={Stories} />
# Badge
A status badge with semantic color variants.
<Canvas of={Stories.Default} />
<Controls of={Stories.Default} />
<Canvas of={Stories.Info} />
<ArgTypes of={Stories} />
```
### Step 6: Run and report
```bash
./scripts/generate-stories.sh # generate stories + MDX for all components
./scripts/generate-stories.sh --dry-run # report what would be written, write nothing
./scripts/generate-stories.sh --force # overwrite existing stories
./scripts/generate-stories.sh --no-mdx # stories only, skip MDX
./scripts/generate-stories.sh --json # machine-readable { generated, skipped, files }
```
Because this step is **non-blocking**, log the generated/skipped counts and
continue the pipeline even if generation fails.
## CLI Reference
| Flag | Default | Effect |
|------|---------|--------|
| `--src-dir <path>` | `src/components` | Component source directory to scan |
| `--config <path>` | `.claude/pipeline.config.json` | Pipeline config path |
| `--force` | off | Overwrite existing `.stories.tsx` files |
| `--dry-run` | off | Report only; write nothing |
| `--no-mdx` | off | Skip `.mdx` generation |
| `--json` | off | Emit JSON (suppresses human logs) |
## Configuration
`.claude/pipeline.config.json` → `storybook`:
| Key | Default | Purpose |
|-----|---------|---------|
| `autoGenerate` | `true` | Enable/disable generation in the pipeline |
| `includeResponsiveViewports` | `true` | Add a viewport story per breakpoint |
| `viewports` | `["mobile","tablet","desktop"]` | Which breakpoints to emit (widths from `visualDiff.breakpoints`) |
| `skipPatterns` | `["**/index.ts","**/*.test.*","**/*.stories.*"]` | Globs to exclude |
| `generateMdx` | `true` | Emit `.mdx` docs alongside stories |
| `maxVariantsPerProp` | `10` | Cap variant stories per prop (prevents explosion) |
## Output
| File | Purpose |
|------|---------|
| `src/components/**/Component.stories.tsx` | CSF3 stories with controls, variants, actions |
| `src/components/**/Component.mdx` | Autodocs page (Meta/Canvas/Controls/ArgTypes) |
## Common Mistakes
- **No controls generated.** Props are declared as a `type` alias rather than an
`interface ComponentNameProps`. The generator detects the type but does not yet
expand its members — convert to an `interface` (or add controls manually).
- **Component skipped.** The export is lowercase, not exported, or the file is a
`*.test.tsx`/`index.tsx`. Ensure the component is exported with an uppercase name.
- **Stories not overwritten.** Existing `.stories.tsx` are preserved by design; pass
`--force` to regenerate.
- **`children`/complex props show a text control.** Non-primitive props fall back to
a `text` control — refine `argTypes` by hand where richer controls matter.
- **Action name looks odd.** Action args derive a past-tense label from the event
name (`onClick` → `clicked`, `onChange` → `changed`); rename the arg in the story
if a different label reads better.
## Integration
- **figma-to-react-workflow skill** — invokes this skill as Phase 4.5, right after
components are built and unit tests pass (non-blocking, in parallel with visual QA).
- **react-testing-workflows skill** — owns hand-authored `play()`/interaction tests;
this skill produces the base stories those can extend.
- **parallel-orchestration skill** — runs the `storybook` phase (depends on
`component-build`, `blocking: false`) alongside `visual-diff` and `dark-mode`.
- **scripts/generate-stories.sh** — bash wrapper; forwards all flags to the Node
generator.
- **scripts/generate-stories.js** — the `ts-morph` AST generator that does the work.
- **.claude/pipeline.config.json → storybook** — thresholds and toggles.
---
**Skill Version:** 1.0.0
**Last Updated:** 2026-07-01
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!