Creating Stories
Process
Step 1: Determine Story Type
Answer these questions:
- •Is this a single component or a full page?
- •Which interface type? (Search, Commerce, Insight, IPX, Recommendations)
- •Is this a result template component?
- •What API mocking is needed?
Locations:
- •Components:
packages/atomic/src/components/<category>/<name>/<name>.new.stories.tsx - •Pages:
packages/atomic/storybook-pages/<use-case>/<name>.new.stories.tsx
Step 2: Generate Template
This skill includes a small generator that renders Handlebars templates from .claude/skills/creating-stories/assets/.
# Component story node .claude/skills/creating-stories/scripts/generate-story-template.mjs \ atomic-component-name --category search # Result template component node .claude/skills/creating-stories/scripts/generate-story-template.mjs \ atomic-result-field --category search --result # Sample page node .claude/skills/creating-stories/scripts/generate-story-template.mjs \ page-name --type page --category commerce
Allowed values:
- •
--type:component(default),page - •
--category:search(default),commerce,insight,ipx,recommendations
Notes:
- •
--resultis only valid for--type component(using it with--type pageis an error).
Step 3: Complete the Story
- •Add API mocking - Configure MSW harness for expected responses
- •Create story variants - Add stories for different states (empty, error, selected)
- •Add custom props - Set component-specific arguments
- •Test interactions - Verify story renders and behaves correctly
For EndpointHarness overview and methods, see endpoint-harness-reference.md.
For advanced API mocking patterns, see msw-patterns.md.
For creating a new API mock domain, see creating-new-api-mock.md.
For component examples, see component-examples.md.
For page examples, see sample-page-examples.md.
Step 4: Validate
# Validate the story file node .claude/skills/creating-stories/scripts/validate_story.mjs packages/atomic/src/components/.../component.new.stories.tsx # Run Storybook to verify visually cd packages/atomic && pnpm storybook
Story Structure
Component Story Anatomy
// 1. Create API harness at top level
const searchApiHarness = new MockSearchApi();
// 2. Get interface wrapper
const {decorator, play} = wrapInSearchInterface();
// 3. Get component helpers
const {events, args, argTypes, template} = getStorybookHelpers('atomic-name');
// 4. Configure meta
const meta: Meta = {
component: 'atomic-name',
decorators: [decorator],
parameters: {
msw: {handlers: [...searchApiHarness.handlers]},
},
beforeEach: () => {
searchApiHarness.searchEndpoint.clear();
},
play,
};
// 5. Export stories
export const Default: Story = {};
API Mocking Patterns
Default response:
// Uses base response automatically
Modify for all stories:
searchApiHarness.searchEndpoint.mock((response) => ({
...response,
results: response.results.slice(0, 10),
}));
Story-specific response:
export const NoResults: Story = {
beforeEach: () => {
searchApiHarness.searchEndpoint.mockOnce((response) => ({
...response,
results: [],
totalCount: 0,
}));
},
};
Available API Mocks
| Mock | Import | Use Case |
|---|---|---|
MockSearchApi | @/storybook-utils/api/search/mock | Search interface |
MockCommerceApi | @/storybook-utils/api/commerce/mock | Commerce interface |
MockInsightApi | @/storybook-utils/api/insight/mock | Insight interface |
MockAnswerApi | @/storybook-utils/api/answer/mock | Answer/RGA |
MockRecommendationApi | @/storybook-utils/api/recommendation/mock | Recommendations |
MockMachineLearningApi | @/storybook-utils/api/machinelearning/mock | ML/User Actions |
Interface Wrappers
| Wrapper | Import | Options |
|---|---|---|
wrapInSearchInterface | @/storybook-utils/search/search-interface-wrapper | skipFirstSearch, includeCodeRoot |
wrapInCommerceInterface | @/storybook-utils/commerce/commerce-interface-wrapper | skipFirstSearch, includeCodeRoot |
wrapInInsightInterface | @/storybook-utils/insight/insight-interface-wrapper | skipFirstSearch |
wrapInResultTemplate | @/storybook-utils/search/result-template-wrapper | autoLoad |
Reference Documentation
| Reference | When to Load |
|---|---|
| endpoint-harness-reference.md | EndpointHarness overview, methods, type safety |
| msw-patterns.md | Advanced MSW techniques, pagination, errors |
| creating-new-api-mock.md | Add a new mock domain when needed |
| component-examples.md | Facets, search box, pager, result components |
| sample-page-examples.md | Full page patterns for all interfaces |
Scripts
| Script | Purpose |
|---|---|
generate-story-template.mjs | Generate story boilerplate from templates |
validate_story.mjs | Validate created story files for correctness |
Templates
Templates in assets/ directory:
- •
component.new.stories.tsx.hbs- Standard component story - •
result-component.new.stories.tsx.hbs- Result template component - •
page.new.stories.tsx.hbs- Sample page story
Validation Checklist
Before completing:
- • Story file named
<component-name>.new.stories.tsx - • MSW handlers included in parameters
- •
beforeEachclears mocked responses - • At least
Defaultstory exported - • Component imports use path aliases (
@/storybook-utils/...) - • For pages: initialization function and
playhandler included - • Story follows patterns from similar components
Common Edge Cases
Forgetting to clear endpoints
Always clear in meta-level beforeEach, not afterEach:
beforeEach: () => {
harness.searchEndpoint.clear();
}
Stories show wrong data in docs mode
Every story needs story-level beforeEach queuing mockOnce(). Create helper:
const mockDefault = () => harness.endpoint.mockOnce(r => r);
Call in ALL stories' beforeEach, even for default responses.
State persists between stories
Cause: Missing endpoint clear in meta beforeEach
Fix: Add harness.endpoint.clear() to meta-level beforeEach
Not spreading base response
Always spread to maintain all required fields:
mockOnce((response) => ({
...response,
results: [], // Modify only what you need
}))
Wrong import paths
Use @/storybook-utils/... path aliases, not relative paths
Missing MSW handlers
Include all harness handlers in parameters:
parameters: {
msw: {handlers: [...harness.handlers]},
}
Wrong decorator order
Result templates require specific decorator order—check similar components for the pattern
API calls return default responses
Check:
- •Endpoint path in harness matches actual API call
- •HTTP method (GET/POST) is correct
- •Handlers included:
msw: {handlers: [...harness.handlers]}
Using mock() instead of mockOnce()
Use mockOnce() for story-specific responses to prevent pollution