Skip to main content

How it works

This page walks through the moving parts of the integration, from the CLI command down to the webpack loaders. Package entry points of @archibald/storybook:

Entry pointContents
@archibald/storybookStorybookProvider (runtime, used in preview.tsx)
@archibald/storybook/configdefineConfig() (used in main.ts)
@archibald/storybook/presetthe Storybook preset that injects the Archibald build config
@archibald/storybook/loaderthe babel shadowing loader plugin (registered by the preset)

The CLI command

archibald storybook (reference) does not reimplement Storybook — it prepares the environment and delegates to the Storybook CLI:

  1. Dependency check — verifies @archibald/storybook is installed and aborts with a hint otherwise.
  2. Prompting — asks for environment, tenant, platform, and compile mode (plus the Vercel question when cli/storybook/vercel/active is true), unless the values were passed as flags.
  3. Environment setup — sets APP_CODE=client and serializes the selected parameters and the full resolved Archibald config into the STORYBOOK_PARAMS and STORYBOOK_CONFIG environment variables. This is how the preset and the story loader — which run inside Storybook's own process — learn about the selected tenant/platform and your archibald.json.
  4. Launch — spawns npx storybook with
    • dev -c <cli/storybook/config> -p <cli/storybook/port> in development mode, or
    • build -c <cli/storybook/config> --output-dir <dist>/<storybook output path> in production mode, forwarding --no-open, --quiet, and the configured log level.
  5. Vercel transform (optional) — after a production build with --vercel, converts the static output into a Vercel Build Output under .vercel/output (see Deploying Storybook to Vercel).

defineConfig()

defineConfig() from @archibald/storybook/config produces the Storybook main config by deep-merging your overrides onto this base:

{
stories: loadStories, // the shadowing-aware story loader
addons: [
'@storybook/addon-docs',
'@storybook/addon-onboarding',
'@storybook/addon-a11y',
'@chromatic-com/storybook',
'@archibald/storybook/preset'
],
framework: { name: '@storybook/react-webpack5', options: {} },
docs: { defaultName: 'Documentation' },
typescript: { reactDocgen: 'react-docgen-typescript' }
}

Merge rules:

  • Arrays (e.g. addons) are concatenated, with your entries first.
  • defineConfig(config, { override: true }) makes your arrays replace the base arrays instead.
  • Passing your own stories value replaces the automatic loader entirely.

Note that the Archibald preset is registered as one of the addons — that is how it hooks into Storybook's build.

The preset

@archibald/storybook/preset is a standard Storybook preset. It reads STORYBOOK_CONFIG/STORYBOOK_PARAMS, resolves the tenant and platform chains, and exports:

  • addons — registers @storybook/addon-webpack5-compiler-swc, so Storybook compiles with swc.
  • swc(config) — swc options matching the app build: TypeScript + TSX parsing, decorators, and the automatic or classic JSX runtime depending on cli/development/automaticRuntime.
  • webpackFinal(config) — the core piece. It mutates Storybook's webpack config to match the Archibald client build:
    • Removes Storybook's built-in CSS rule and points resolve.modules at the project's src folder, so base-path imports (shop/client/...) resolve.
    • Adds the TypeScript rule: babel-loader running the @archibald/storybook/loader babel plugin (the same shadowing loader as the app build, configured with the selected tenant/platform chains), optionally @babel/preset-env + core-js (when cli/optimization/coreJS is enabled and a .browserslistrc exists) and react/prefresh fast-refresh in dev — followed by swc-loader.
    • Adds the style rules described below.
    • Adds the SVGR rule when cli/optimization/svgComponents is enabled.
    • Defines the same compile-time constants as the app bundle via DefinePlugin — notably process.env.APP_CODE = "client" and process.env.ARC_SINGLE_ROOT_ISLANDS, so a story rendering a hydration island exercises the same withHydration implementation the project ships.
    • Aliases each platform name to its src/<platform> folder, aliases react-native to react-native-web when installed, and stubs Node built-ins (child_process, os, module) for the browser.

The story loader

defineConfig() sets stories to a loader function instead of a glob list. On (re)build it:

  1. reads the selected tenant/platform from STORYBOOK_PARAMS,
  2. recursively lists src/<selected platform> and, if different, src/<default platform>,
  3. keeps files matching **/*.mdx and **/*.stories.@(js|jsx|mjs|ts|tsx),
  4. runs entries from the default-platform fallback through the shadowing resolver and drops any file that resolves to a more specific override for the selected tenant/platform chain.

The behavior from a story author's perspective is described in Writing stories.

The style pipeline

Styles use the same loader chain as the application's client build, with one difference: since Storybook serves everything from one dev bundle, styles are injected with style-loader instead of being extracted to CSS files. The chain is:

  1. style-loader
  2. css-loader — CSS modules on or off (and hashed class names in production) according to cli/style/modules
  3. resolve-url-loader
  4. sass-loadersass-embedded with the modern API, includePaths covering src and node_modules, and the scssShadowingImporter configured with the selected tenant/platform chains, so @use/@import statements resolve tenant and platform style overrides exactly like the app build.

StorybookProvider

The runtime export (@archibald/storybook) is a thin wrapper for use in preview.tsx decorators or individual stories:

  • renders TestingProviders from @archibald/testing/providers with a context created via createContext — providing the app client, data client, and translation contexts,
  • wraps children in a MemoryRouter,
  • adds the theme class to document.body while mounted (removed on unmount).

Configuration reference

The cli/storybook block in archibald.json:

KeyTypeDefaultDescription
openbooleantrueOpen the browser after the dev build.
configstring.storybookPath to the Storybook config folder.
portnumber3400Port of the Storybook dev server.
vercel.activebooleanfalseOffer the --vercel flag on production builds.
vercel.configobjectOptional vercel.json overrides for the generated Vercel Build Output.

The static production build lands in project/output/paths/dist + project/output/paths/storybook (defaults: dist + storiesdist/stories).