| name | creating-stories |
| description | Creates and modifies Storybook stories for Atomic components and sample pages. Uses MSW for API mocking, follows ui-kit conventions. Use when creating stories, adding component examples, building sample pages, debugging MSW mock pollution, or when user mentions Storybook, stories, visual testing, or e2e tests that reference stories. |
| license | Apache-2.0 |
| metadata | {"author":"coveo","version":"1.0","package":"atomic"} |
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 assets/.
node .agents/skills/creating-stories/scripts/generate-story-template.mjs \
atomic-component-name --category search
node .agents/skills/creating-stories/scripts/generate-story-template.mjs \
atomic-result-field --category search --result
node .agents/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:
--result is only valid for --type component (using it with --type page is 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
node .agents/skills/creating-stories/scripts/validate_story.mjs packages/atomic/src/components/.../component.new.stories.tsx
cd packages/atomic && pnpm storybook
Story Structure
Component Story Anatomy
import '@/src/components/search/atomic-name/atomic-name.js';
const searchApiHarness = new MockSearchApi();
const {decorator, play} = wrapInSearchInterface();
const {events, args, argTypes, template} = getStorybookHelpers('atomic-name');
const meta: Meta = {
component: 'atomic-name',
decorators: [decorator],
parameters: {
msw: {handlers: [...searchApiHarness.handlers]},
},
beforeEach: () => {
searchApiHarness.searchEndpoint.clear();
},
play,
};
export const Default: Story = {};
API Mocking Patterns
Default response:
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 | @coveo/platform-mock-api/search/mock | Search interface |
MockCommerceApi | @coveo/platform-mock-api/commerce/mock | Commerce interface |
MockInsightApi | @coveo/platform-mock-api/insight/mock | Insight interface |
MockAnswerApi | @coveo/platform-mock-api/answer/mock | Answer/RGA |
MockRecommendationApi | @coveo/platform-mock-api/recommendation/mock | Recommendations |
MockMachineLearningApi | @coveo/platform-mock-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
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:
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: [],
}));
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