Skip to main content
This guide covers setting up Storybook in React Native projects using Re.Pack with Rspack or Webpack instead of Metro.
For a ready-to-go starter project, check out the RepackStorybookStarter repository.

Installation

1

Run CLI Init

Use the Storybook CLI to initialize Storybook in your project:
npm create storybook -- --type react_native --yes
2

Install Dependencies

Storybook’s default UI requires both react-native-reanimated and react-native-worklets. Re.Pack projects often already have reanimated, but worklets must be installed separately:
npm install react-native-reanimated react-native-worklets
react-native-worklets is not bundled with reanimated and must be installed separately.
Ensure the worklets babel plugin is in your babel config as the last plugin:
babel.config.js
module.exports = {
  presets: [
    // your existing preset, e.g.:
    'module:@react-native/babel-preset',
  ],
  plugins: [
    // ... any other plugins
    'react-native-worklets/plugin', // must be last
  ],
};
The worklets plugin must be the last plugin in the array.
3

Configure Rspack/Webpack

Add the StorybookPlugin to your rspack or webpack config. Use an environment variable (STORYBOOK_ENABLED) to control both the plugin behavior and a build-time constant:
rspack.config.mjs
import * as Repack from '@callstack/repack';
import rspack from '@rspack/core';
import { StorybookPlugin } from '@storybook/react-native/repack/withStorybook';

const storybookEnabled = process.env.STORYBOOK_ENABLED === 'true';

export default Repack.defineRspackConfig({
  // ... your existing config
  resolve: {
    ...Repack.getResolveOptions({
      enablePackageExports: true, // required for storybook package resolution
    }),
  },
  plugins: [
    new Repack.RepackPlugin(),
    new rspack.DefinePlugin({
      STORYBOOK_ENABLED: JSON.stringify(storybookEnabled),
    }),
    new StorybookPlugin({
      enabled: storybookEnabled,
      websockets: 'auto',
    }),
    // ... your other plugins
  ],
});
enablePackageExports: true is required for rspack to correctly resolve Storybook’s package exports (e.g., @storybook/react-native/preview). Without it, imports from Storybook packages will fail.
Unlike Metro setup, there’s no need to configure require.context support — rspack handles it natively.
4

Create Entrypoint

Conditionally render Storybook based on the STORYBOOK_ENABLED build-time constant:
App.tsx
import StorybookUI from './.rnstorybook';

declare const STORYBOOK_ENABLED: boolean;

export default function App() {
  if (STORYBOOK_ENABLED) {
    return <StorybookUI />;
  }

  // Your existing app code here
  return (
    // ...
  );
}
The declare const tells TypeScript about the global that rspack’s DefinePlugin injects. When STORYBOOK_ENABLED is false, rspack dead-code-eliminates the Storybook branch entirely.
5

Add NPM Scripts

Add convenience scripts to your package.json:
package.json
{
  "scripts": {
    "storybook": "STORYBOOK_ENABLED='true' react-native start",
    "storybook:ios": "STORYBOOK_ENABLED='true' react-native run-ios",
    "storybook:android": "STORYBOOK_ENABLED='true' react-native run-android"
  }
}
Replace react-native with rock if your project uses Rock CLI.
6

Run Storybook

Start your app with Storybook enabled:
npm run storybook

StorybookPlugin Options

The StorybookPlugin accepts the following options:
OptionTypeDefaultDescription
enabledbooleantrueStrip Storybook from bundle when false
configPathstring'./.rnstorybook'Storybook config directory
useJsbooleanfalseGenerate .js instead of .ts
docToolsbooleantrueAuto arg extraction
liteModebooleanfalseMock default UI deps (use with @storybook/react-native-ui-lite)
websockets'auto' | objectundefined'auto' detects LAN IP, or { port: 7007, host: 'localhost' }
experimental_mcpbooleanfalseEnable experimental MCP endpoint (/mcp) for AI tooling (v10.3+)

Next Steps

Writing Stories

Learn how to write your first story

Configuration

Explore configuration options

Build docs developers (and LLMs) love