Describe the bug
When a CSF story uses an imported wrapper/demo component, Storybook AI manifests generate the story snippet from the wrapper usage in the .stories.tsx file instead of
the actual demo source.
For example, if the story is written like this:
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from 'antd-mobile';
import React from 'react';
import _Demo01 from './demo01';
const meta = {
title: 'General/Button',
component: Button,
} satisfies Meta<typeof Button>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Demo01: Story = {
name: 'Page',
render: () => <_Demo01 />,
};
and ./demo01.tsx contains the actual example source, the generated manifest snippet is still something like:
const Demo01 = () => <_Demo01 />;
instead of the real source from demo01.tsx.
This also appears to ignore parameters.docs.source.code / docs.source.originalSource as an override for the AI manifest snippet.
Actual behavior
The manifest snippet is based on the inline story render wrapper from the .stories.tsx file:
const Demo01 = () => <_Demo01 />;
Expected behavior
One of the following should happen:
- Storybook should respect parameters.docs.source.code / docs.source.originalSource for AI manifest snippets.
- Or Storybook should provide a hook/plugin API to preprocess story source before snippet extraction.
- Or Storybook should support resolving simple imported wrapper components when generating snippets.
At minimum, it would be helpful if the behavior were documented clearly.
Why this is a problem
A common pattern is to keep demos/examples in separate files and keep .stories.tsx minimal. In that setup, the generated AI manifest snippet becomes low-value because it
only shows the wrapper component usage, not the actual example code.
Reproduction link
example code see above
Reproduction steps
-
Create a story file that imports an external demo/wrapper component:
import _Demo01 from './demo01';
export const Demo01: Story = {
render: () => <_Demo01 />,
};
-
Put the actual example implementation in demo01.tsx.
-
Run Storybook with AI manifests enabled.
-
Inspect the generated manifest.``
System
- Storybook: 10.3.4
- @storybook/csf-plugin: 10.3.4
- storybook-react-rsbuild: 3.3.2
- React: 19
- Builder: Rsbuild / Rspack
- Node: 24.11.1
Additional context
Technical context
From local inspection, the source snippet generation seems to happen in @storybook/csf-plugin, where the loader reads the raw .stories.tsx file from disk and parses that
source again for CSF enrichment. In other words, bundler/runtime transforms do not affect the snippet extraction path.
That means:
- transforming the story at bundler level does not help
- overriding docs.source.code also does not appear to affect the AI manifest snippet
This makes it difficult to customize snippet generation for stories that delegate rendering to external demo files.
Question
Is this the intended behavior for AI manifests/snippets, or would you consider supporting an override/preprocess mechanism for this use case?
Describe the bug
When a CSF story uses an imported wrapper/demo component, Storybook AI manifests generate the story snippet from the wrapper usage in the
.stories.tsxfile instead ofthe actual demo source.
For example, if the story is written like this:
and ./demo01.tsx contains the actual example source, the generated manifest snippet is still something like:
const Demo01 = () => <_Demo01 />;
instead of the real source from demo01.tsx.
This also appears to ignore parameters.docs.source.code / docs.source.originalSource as an override for the AI manifest snippet.
Actual behavior
The manifest snippet is based on the inline story render wrapper from the .stories.tsx file:
const Demo01 = () => <_Demo01 />;
Expected behavior
One of the following should happen:
At minimum, it would be helpful if the behavior were documented clearly.
Why this is a problem
A common pattern is to keep demos/examples in separate files and keep .stories.tsx minimal. In that setup, the generated AI manifest snippet becomes low-value because it
only shows the wrapper component usage, not the actual example code.
Reproduction link
example code see above
Reproduction steps
Create a story file that imports an external demo/wrapper component:
import _Demo01 from './demo01';
export const Demo01: Story = {
render: () => <_Demo01 />,
};
Put the actual example implementation in demo01.tsx.
Run Storybook with AI manifests enabled.
Inspect the generated manifest.``
System
Additional context
Technical context
From local inspection, the source snippet generation seems to happen in @storybook/csf-plugin, where the loader reads the raw .stories.tsx file from disk and parses that
source again for CSF enrichment. In other words, bundler/runtime transforms do not affect the snippet extraction path.
That means:
This makes it difficult to customize snippet generation for stories that delegate rendering to external demo files.
Question
Is this the intended behavior for AI manifests/snippets, or would you consider supporting an override/preprocess mechanism for this use case?