ScreenshotNeo

BlogGuides

How Storybook Composition Works

Learn how Storybook composition adds stories from other Storybooks to a host sidebar, with setup examples, environment-specific refs, package composition, and troubleshooting.

By the ScreenshotNeo team4 October 20268 min read

Storybook composition lets a host Storybook browse stories from other Storybooks in its sidebar. Configure references, or refs, in the host project’s .storybook/main.js or .storybook/main.ts. Each reference points to another Storybook URL; that Storybook can be published or running locally. The projects remain separate: composition makes their stories discoverable together without merging their source trees. Storybook’s composition guide and the Storybook 9 refs API document the configuration.

1. Add a reference to another Storybook

For a fixed reference, add a refs object to the host’s main configuration. The following illustrative example points to a published design-system Storybook. Replace the example URL with a reachable URL for your own Storybook.

// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';

const config: StorybookConfig = {
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: [],
  framework: '@storybook/your-framework',
  refs: {
    designSystem: {
      title: 'Design System',
      url: 'https://design-system.example.com/storybook',
      expanded: true,
      sourceUrl: 'https://github.com/example/design-system',
    },
  },
};

export default config;

@storybook/your-framework and the story globs are placeholders: keep the framework and story configuration already used by your project. The composition-specific part is the refs entry. A reference key such as designSystem identifies the ref; title is its sidebar label and url is the referenced Storybook’s address. expanded and sourceUrl are optional fields shown in Storybook’s example. Consult the docs for your installed Storybook major version before copying version-sensitive configuration.

  1. Start or deploy the referenced Storybook and identify its externally reachable URL.
  2. Add a uniquely keyed entry under the host’s refs setting.
  3. Run the host Storybook and check that the reference appears in the sidebar and its stories load.
  4. When deploying the host, make sure the deployed environment can reach the referenced URL too.

2. Compose locally running Storybooks

Local development can use the same URL-based mechanism. For example, if two Storybooks are running on separate ports, point the host’s ref at the port serving the other Storybook:

// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';

const config: StorybookConfig = {
  stories: ['../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: [],
  framework: '@storybook/your-framework',
  refs: {
    components: {
      title: 'Components',
      url: 'http://localhost:6007',
    },
  },
};

export default config;

The port is an example, not a universal Storybook default. Use the actual port and host where the referenced Storybook is listening. A host Storybook opened in a different environment, such as a container or remote development machine, may not be able to reach the browser machine’s localhost. In that case, use an address reachable from the host’s environment.

3. Choose URLs by environment

The refs setting can be a function. Storybook’s documented pattern selects development URLs in development and hosted URLs otherwise. This lets collaborators browse local changes while deployed users see stable hosted references.

// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';

const config: StorybookConfig = {
  stories: ['../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: [],
  framework: '@storybook/your-framework',
  refs: (configType) => ({
    designSystem: {
      title: 'Design System',
      url:
        configType === 'DEVELOPMENT'
          ? 'http://localhost:6007'
          : 'https://design-system.example.com/storybook',
    },
  }),
};

export default config;

Use the configuration type supported by your installed Storybook version. The function chooses a URL; it does not start a local server, deploy a Storybook, or verify that a URL is reachable. Confirm both destinations independently.

4. Understand package composition

Package composition is a separate setup path from manually adding a URL ref. A package author can publish a storybook property in the package’s package.json that points to the library’s Storybook. A consumer’s Storybook can then load the package’s stories automatically when the package and publishing setup support the feature.

{
  "name": "@example/design-system",
  "storybook": "https://design-system.chromatic.com"
}

This is illustrative metadata, not a complete publishing integration. Storybook’s documentation says package composition requires a secure integration between the publishing service and Storybook APIs, and recommends Chromatic for full support. With Chromatic, the stable project URL can select the build corresponding to the installed package version; package authors can also supply versions for a selector. Do not assume that arbitrary static hosting provides this automatic version-aware behavior. See the package composition guide.

If automatic package composition adds a ref you do not want, the consumer can disable it by package name in refs:

// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';

const config: StorybookConfig = {
  stories: ['../src/**/*.stories.@(js|jsx|ts|tsx)'],
  addons: [],
  framework: '@storybook/your-framework',
  refs: {
    '@example/design-system': { disable: true },
  },
};

export default config;

5. Know what composition does and does not do

  • It combines browsing, not source code. The host sidebar can surface stories from referenced projects, but each Storybook remains a separate project.
  • References can be local or published. The deciding factor is whether the host environment can reach the URL.
  • Manual refs and package composition are different. Manual refs are configured by the consumer with URLs; package composition relies on package metadata and a compatible publishing integration.
  • Composed addons have limitations. Storybook warns: “Addons in composed Storybooks will not work as they normally do in a non-composed Storybook.” Treat browsing stories as the core use and verify any addon-dependent workflow you need.
  • The host still needs local content. Storybook’s FAQ says a glue Storybook needs at least one local story or docs page even when it composes other Storybooks. See the Storybook FAQ.

6. Pick the composition approach

Need Approach What to check
A known Storybook URL Fixed refs object The URL is reachable wherever the host runs.
Different local and deployed targets refs function Both URLs exist and match the relevant environment.
Automatic library stories tied to a package Package composition Package metadata and publishing integration support it; Chromatic is the documented full-support recommendation.
A package ref should not appear Disable that package in refs The disable key matches the package name.

7. Troubleshoot common problems

Symptom Likely cause What to do
The ref is missing The entry is absent, malformed, disabled, or the host config was not reloaded. Check the refs shape, key, and URL; restart the host Storybook after configuration changes.
The ref appears but its stories do not load The URL is wrong or unreachable from the host’s runtime environment. Open the referenced Storybook directly from that environment and correct the URL, host, port, or deployment access.
Works locally but not after deployment The development URL points at localhost, or the deployed host cannot access the chosen target. Use the hosted target outside development and confirm it is reachable by the deployed Storybook.
A localhost ref fails in a container or remote environment localhost resolves to the environment running the host, not necessarily the developer’s machine. Use a network address reachable from the host environment and ensure the referenced server listens on it.
Composed stories behave differently with addons Composed Storybooks do not provide normal standalone addon behavior. Check the addon’s expected behavior against Storybook’s composition caveat and keep addon-dependent tasks in the standalone project when needed.
Legacy composition guidance mentions extract The instruction may be for an older Storybook workflow. The composition docs describe npx storybook@7.5.3 extract as legacy guidance and say it is unavailable in Storybook 8.0 or higher. Do not apply it as a general current setup step; consult docs for your version.
A package’s stories are not selected for the installed version Automatic version-aware package composition depends on its publishing integration. Verify package metadata and the publishing service integration; the documented full-support path is Chromatic.

8. Performance, reliability, and maintenance

Composition depends on the referenced Storybook being available to the host and on the configured URL remaining valid. Prefer stable hosted URLs for deployed hosts, use environment-specific URLs when local iteration requires them, and check every reference when changing ports, domains, or publishing setup. The cited Storybook guidance does not provide performance benchmarks, so measure load behavior in your own environment if startup or navigation time matters.

Keep refs focused on Storybooks people need to browse, give entries clear titles, and document which project owns each target. For package composition, account for the publishing integration and installed package version when diagnosing which build appears. Storybook’s documented addon limitation should be part of any workflow that expects composed projects to behave exactly like standalone ones.

9. Capture a Storybook page as an image or PDF

If you need a shareable visual record of a composed Storybook page, capture its URL as an image or PDF. The do-it-yourself option is to use your browser’s capture tools or automate a browser; ensure the host and referenced content have finished loading before saving the result. For repeatable API captures, ScreenshotNeo is a website screenshot API and MCP server for developers.

Or skip the browser setup

One GET request can return a screenshot. Replace the example URL with the Storybook page you want to capture and use your API key. See the ScreenshotNeo API documentation for options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server gives AI agents the take_screenshot, get_page_info, and capture_pdf tools. The Free plan includes 1,000 screenshots a month without a card; paid plans start at $5 for 3,000 shots, and every feature is available on every plan. Sign up free for 1,000 screenshots a month, with no card required.

10. FAQ

Can the host and referenced Storybook use different frameworks?

Yes. Storybook’s composition guidance says references can use different view layers, stacks, or dependencies.

Does composition merge components into the host project?

No. It lets the host browse external stories; the referenced project remains separate.

Do I need Chromatic for every kind of composition?

No. Manual URL refs can point to reachable Storybooks. Chromatic is relevant to the documented package-composition integration and is recommended for full support there.

Which Storybook version should I follow?

Use the documentation for your installed major version. The refs API source cited here is the Storybook 9 documentation, and some older composition instructions do not apply to Storybook 8 and later.

Sources