Create Storybook "user journey" storyboards for React apps (page/screen stories, MSW API mocking, interaction play functions, and optional Storybook test-runner setup). Use when the user wants Storybook demos of flows (not just atomic components), e.g., signup/login/checkout, with mocked APIs and scripted interactions.
Creates Storybook user journey stories for React apps with MSW API mocking and interaction scripts. Use when users want to demo end-to-end flows (login, signup, checkout) with mocked APIs and scripted interactions.
/plugin marketplace add jagreehal/jagreehal-claude-skills/plugin install jagreehal-claude-skills@jagreehal-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
You are a specialist in turning React apps into Storybook storyboards that demonstrate end-to-end user journeys inside Storybook:
play function (click/type/wait/assert)Treat journeys as products, not demos.
Storybook is the "stage", MSW is the "world", play is the "script".
parameters.msw.handlers).play: simulate user interactions after render.Each journey needs at least 3 states
Use this skill when the user asks for any of:
// Button.stories.tsx — misses the journey context
export const Primary: Story = {
args: { label: 'Submit', variant: 'primary' }
}
export const Loading: Story = {
args: { label: 'Submit', loading: true }
}
This only tests the button's appearance, not how it behaves in a real flow.
// SignupJourney.stories.tsx
export const HappyPath: Story = {
parameters: {
msw: {
handlers: [
http.post('/api/signup', () => HttpResponse.json({ success: true }))
]
}
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement)
await userEvent.type(canvas.getByLabelText('Email'), 'user@example.com')
await userEvent.type(canvas.getByLabelText('Password'), 'SecurePass123!')
await userEvent.click(canvas.getByRole('button', { name: 'Sign Up' }))
await waitFor(() => {
expect(canvas.getByText('Welcome!')).toBeInTheDocument()
})
}
}
// Mocks inline, duplicated across stories
export const Success: Story = {
parameters: {
msw: {
handlers: [
http.get('/api/user', () => HttpResponse.json({
id: '123', name: 'John', email: 'john@test.com', role: 'admin'
}))
]
}
}
}
// fixtures.ts
export const mockUser: User = {
id: '123',
name: 'John Doe',
email: 'john@example.com',
role: 'admin'
}
// ProfileJourney.stories.tsx
import { mockUser } from './fixtures'
export const ViewProfile: Story = {
parameters: {
msw: {
handlers: [
http.get('/api/user', () => HttpResponse.json(mockUser))
]
}
}
}
play: async ({ canvasElement }) => {
const submitBtn = canvasElement.querySelector('.btn-primary.submit-form')
await userEvent.click(submitBtn!)
}
play: async ({ canvasElement }) => {
const canvas = within(canvasElement)
await userEvent.click(canvas.getByRole('button', { name: 'Submit' }))
}
If not provided, make best-effort assumptions and proceed, but quickly ask for missing details only if required to implement:
@storybook/react-vite, @storybook/nextjs, etc.)If unknown, default to:
*.stories.tsx)parameters.msw.handlersplay function using userEvent, canvas queriesWhen implementing, produce:
play function for at least the happy path.Use one of these patterns (pick whichever matches the repo style):
src/stories/journeys/<JourneyName>/<JourneyName>.stories.tsxsrc/stories/journeys/<JourneyName>/mocks.tssrc/stories/journeys/<JourneyName>/fixtures.tssrc/pages/<RouteOrPage>.journey.stories.tsxsrc/pages/<RouteOrPage>.mocks.tsStory titles:
Journeys/Auth/SignupJourneys/Checkout/HappyPathJourneys/Settings/ProfileAlways use layout: 'fullscreen' for page journeys unless the user requests otherwise.
Define:
If the user provides acceptance criteria, mirror them in story names.
Create a wrapper that can mount the page like the real app:
Keep the harness reusable and minimal.
Use Storybook MSW integration via story parameters:
parameters: { msw: { handlers: [...] } }Include common mock variants:
If the app uses GraphQL, mock with MSW GraphQL handlers. If it uses REST, use MSW REST handlers.
Story file should:
meta with component/renderrender function that mounts the page/harnessargs only if meaningful; don’t arg-spam page storiesplay interactionsUse play to enact the journey:
canvas (prefer role/label queries)userEvent to type/clickawait + waitFor-style patterns (avoid arbitrary timeouts)Reminder: play runs after render and can be debugged in the Interactions panel.
If requested (or if the repo already uses it), wire Storybook Test Runner:
test-storybook) and config if neededStorybook test runner runs through stories and can be configured via hooks.
When the user says “storyboard”, implement at least one:
Step1_EnterDetailsStep2_ConfirmEmailStep3_OnboardingCompleteCreate an MDX doc showing each step in order (if the repo uses docs).
Only if the app supports a single mounted flow; otherwise prefer separate stories.
play that reaches a meaningful end stateThis skill works together with other patterns in this repository:
| Skill | Integration |
|---|---|
| testing-strategy | Journey stories complement integration tests; use journeys for visual/interactive validation, integration tests for headless CI |
| validation-boundary | Mock Zod validation responses in MSW; test form error states with invalid payloads |
| result-types | Mock Result<T, E> API responses; test both ok and err paths in separate stories |
| fn-args-deps | Journey harnesses can inject mock deps for components that follow fn(args, deps) |
| observability | Verify telemetry events fire during journeys by mocking/spying on the telemetry dependency |
When creating journey stories:
result-types error shapes in your MSW error handlersvalidation-boundary patterns for form validation mock responsesfn-args-depsUser: "Make a Storybook storyboard for signup with MSW, include happy + server error."
You: Create Journeys/Auth/Signup stories:
HappyPath with MSW success handlers and play that completes signupServerError with 500 handler and UI assertionUser: "We want to demo the checkout flow in Storybook, not just components."
You: Mount the Checkout page with providers + router, mock cart/pricing APIs with MSW, script the flow in play, and add error/empty states.
play function approach for interactions.This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.