> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# Configuration

Storybook Rsbuild provides several ways to customize the build process and behavior. This guide covers the configuration options available in your `.storybook/main.ts`.

:::tip Storybook Documentation
This guide focuses on Rsbuild-specific configurations. For general Storybook configuration (stories, addons, refs, etc.), please refer to the [Storybook Configure](https://storybook.js.org/docs/configure) documentation.
:::

## rsbuildFinal

The `rsbuildFinal` field gives you direct access to the Rsbuild configuration. You can use it to customize the build config, similar to [webpackFinal](https://storybook.js.org/docs/builders/webpack#extending-storybooks-webpack-config) in the Webpack builder.

This function receives the current Rsbuild config and an options object, and should return the modified config.

:::warning Use `mergeRsbuildConfig` for modifications
Always use [`mergeRsbuildConfig`](https://rsbuild.rs/api/javascript-api/core#mergersbuildconfig) from `@rsbuild/core` to modify the config in `rsbuildFinal`; returning a brand-new config is unsupported. Directly replacing properties like `config.tools.rspack = {...}` may also be silently ignored because internal configs can be arrays of functions and objects. Inside the function form of `tools.rspack`, modify and return the provided config or use the callback's `mergeConfig` utility; returning a brand-new object silently drops Storybook-injected wiring such as the `sb.mock` machinery.
:::

```ts twoslash title=".storybook/main.ts"
// @noErrors
import type { StorybookConfig } from 'storybook-react-rsbuild'
import { mergeRsbuildConfig } from '@rsbuild/core'

const config: StorybookConfig = {
  framework: 'storybook-react-rsbuild',
  stories: ['../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: [],
  async rsbuildFinal(config, { configType }) {
    // Customize Rsbuild config here
    if (configType === 'PRODUCTION') {
      return mergeRsbuildConfig(config, {
        performance: {
          removeConsole: true,
        },
      })
    }

    // Example: add resolve alias
    return mergeRsbuildConfig(config, {
      resolve: {
        alias: {
          '@components': './src/components',
        },
      },
    })
  },
}

export default config
```

## Builder Options

You can configure the underlying Rsbuild builder through the `core.builder` options.

```ts twoslash title=".storybook/main.ts"
// @noErrors
import type { StorybookConfig } from 'storybook-react-rsbuild'

const config: StorybookConfig = {
  framework: 'storybook-react-rsbuild',
  stories: [],
  core: {
    builder: {
      name: 'storybook-builder-rsbuild',
      options: {
        // Path to your existing rsbuild.config.ts
        // Defaults to the root rsbuild.config.ts if found
        rsbuildConfigPath: './custom-rsbuild.config.ts',

        // Enable filesystem cache for faster rebuilds
        // Default: false
        fsCache: true,

        // Lazy-compile entries as well as dynamic imports
        // lazyCompilation: true,

        // Specify Rsbuild environment to use (for multi-environment configs)
        // environment: 'web',
      },
    },
  },
}

export default config
```

### Inherited Rsbuild Configuration

The config selected by `rsbuildConfigPath` is automatically merged into the Storybook preview build. Production-only settings can affect or break the preview, so the following fields are not inherited:

- `source.entry`
- `output.distPath`, `output.filename`, `output.cleanDistPath`, `output.externals`, and `output.assetPrefix`
- `server.publicDir`
- `dev.progressBar`, `dev.assetPrefix`, and `dev.writeToDisk`
- `tools.htmlPlugin`
- `tools.rspack.output.library`, `tools.rspack.output.globalObject`, and `tools.rspack.output.umdNamedDefine`

This boundary also applies to configuration inherited by `storybook-addon-rslib`, `storybook-addon-rstack`, and `storybook-addon-modernjs`. Function-form `tools.rspack` values are opaque and cannot be stripped. Prefer a dedicated [Rsbuild environment](https://rsbuild.rs/config/environments) selected with `environment` to isolate Storybook-safe settings. To restore a stripped field intentionally, add it explicitly in Storybook's `rsbuildFinal`; explicit configuration runs after inherited configuration is stripped.

Plugins remain inherited because they commonly provide transforms required by the preview build. The Storybook CLI sets `process.env.STORYBOOK` to `'true'` before loading project configuration, so use that condition to omit an app-only plugin that should not run in Storybook.

### Option Reference

| Option              | Type                                                                               | Default                                                  | Description                                                                                                            |
| :------------------ | :--------------------------------------------------------------------------------- | :------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------- |
| `rsbuildConfigPath` | `string`                                                                           | `cwd/rsbuild.config.ts`                                  | Path to an existing Rsbuild config file to merge.                                                                      |
| `fsCache`           | `boolean`                                                                          | `false`                                                  | Enables Rspack's persistent filesystem cache.                                                                          |
| `lazyCompilation`   | `boolean` \| [`LazyCompilationOptions`](https://rspack.rs/config/lazy-compilation) | `{ entries: false }` (development); `false` (production) | Configures Rspack's lazy compilation.                                                                                  |
| `environment`       | `string`                                                                           | `undefined`                                              | Selects an [environment](https://rsbuild.rs/config/environments) from the Rsbuild config; an explicit name must exist. |

When `environment` is omitted, zero environments uses top-level config, one is selected automatically, and multiple environments require a name.

In development, the default `{ entries: false }` compiles entry chunks eagerly while lazily compiling dynamically imported story modules. In production, this builder option is not applied, so lazy compilation remains off by default; lower-level Rsbuild or Rspack configuration can override that behavior. In development, automatic MSW detection also changes the default to `false` unless you explicitly configure this option. This differs from the Storybook webpack builder, where lazy compilation is opt-in and remains off unless enabled.

## Webpack Addons Compatibility

Since Rspack is compatible with the webpack loader/plugin API, you can often use Storybook addons designed for Webpack. To do this, use the `webpackAddons` field instead of `addons`.

```ts twoslash title=".storybook/main.ts"
// @noErrors
import type { StorybookConfig } from 'storybook-react-rsbuild'

const config: StorybookConfig = {
  framework: 'storybook-react-rsbuild',
  stories: [],
  // Addons that depend on Webpack loaders/plugins
  webpackAddons: ['@storybook/addon-coverage'],
}

export default config
```

## Framework Options

Framework-specific options allow you to tailor the behavior for React, Vue, etc.

### React Options

For `storybook-react-rsbuild`, you can configure `reactDocgen` and legacy root API.

```ts twoslash title=".storybook/main.ts"
// @noErrors
import type { StorybookConfig } from 'storybook-react-rsbuild'

const config: StorybookConfig = {
  framework: {
    name: 'storybook-react-rsbuild',
    options: {
      // Configure strict mode
      strictMode: true,

      // Use legacy ReactDOM.render instead of createRoot (React 18+)
      legacyRootApi: false,
    },
  },
  stories: [],
  typescript: {
    // Configure docgen for TypeScript
    // 'react-docgen-typescript' | 'react-docgen' | false
    reactDocgen: 'react-docgen-typescript',

    // Pass options to react-docgen-typescript-plugin
    reactDocgenTypescriptOptions: {
      propFilter: (prop) => {
        return prop.parent ? !/node_modules/.test(prop.parent.fileName) : true
      },
    },
  },
}

export default config
```

## TypeScript Options

Storybook Rsbuild uses `@rsbuild/plugin-type-check` for type checking. You can configure it via the `typescript` field.

```ts twoslash title=".storybook/main.ts"
// @noErrors
import type { StorybookConfig } from 'storybook-react-rsbuild'

const config: StorybookConfig = {
  framework: 'storybook-react-rsbuild',
  stories: [],
  typescript: {
    // Enable/disable fork-ts-checker-webpack-plugin
    check: true,

    // Options passed to fork-ts-checker-webpack-plugin
    checkOptions: {
      typescript: {
        memoryLimit: 4096,
      },
    },
  },
}

export default config
```

See [Storybook TypeScript Docs](https://storybook.js.org/docs/configure/integration/typescript) for general TypeScript configuration.

## Preview Output Layout

`storybook build` emits the preview with a flat layout — bundled JS and CSS land directly in the output directory (`storybook-static` by default), the same as the official webpack5 builder:

```text
storybook-static/
├── iframe.html
├── main.<hash>.iframe.bundle.js
├── <chunk-id>.<hash>.iframe.bundle.js
├── <entry>.<hash>.css
├── <name>.<hash>.svg      # imported SVGs and WebAssembly also land at the root
└── static/media/          # imported images, fonts, and media
```

Versions before v3.4.0 nested these files under `static/js/`, `static/js/async/`, and `static/css/`.
