Skip to main content
The withStorybook function wraps your Metro configuration to enable Storybook support in React Native projects using Metro bundler.

Basic Usage

metro.config.js
const { getDefaultConfig } = require('expo/metro-config');
const { withStorybook } = require('@storybook/react-native/metro/withStorybook');

const config = getDefaultConfig(__dirname);

module.exports = withStorybook(config);

Configuration Options

interface WithStorybookOptions {
  configPath?: string;
  websockets?: WebsocketsOptions | 'auto';
  useJs?: boolean;
  enabled?: boolean;
  docTools?: boolean;
  liteMode?: boolean;
  experimental_mcp?: boolean;
}

Options

configPath
string
default:"./.rnstorybook"
The path to the Storybook config folder where your main.ts and preview.ts files are located.
withStorybook(config, {
  configPath: path.resolve(__dirname, './.storybook'),
});
websockets
WebsocketsOptions | 'auto'
default:"undefined"
WebSocket configuration for syncing Storybook instances or sending events. When provided, creates a WebSocket server for real-time communication.Set to 'auto' to use port 7007 with auto-detected host.
// Auto configuration
withStorybook(config, {
  websockets: 'auto',
});

// Custom configuration
withStorybook(config, {
  websockets: { port: 7007, host: 'localhost' },
});
See WebSocket Configuration for details.
useJs
boolean
default:"false"
Whether to use JavaScript files for Storybook configuration instead of TypeScript.When true, generates storybook.requires.js instead of storybook.requires.ts.
withStorybook(config, {
  useJs: true,
});
enabled
boolean
default:"true"
If false, attempts to remove Storybook modules from the JavaScript bundle to reduce bundle size.Useful for disabling Storybook in production builds.
withStorybook(config, {
  enabled: process.env.EXPO_PUBLIC_STORYBOOK_ENABLED === 'true',
});
docTools
boolean
default:"true"
Whether to include doc tools in the storybook.requires file.Doc tools provide additional documentation features like component metadata extraction.
withStorybook(config, {
  docTools: true,
});
liteMode
boolean
default:"false"
Whether to use lite mode for Storybook.In lite mode, the default Storybook UI is mocked out so you don’t need to install all its dependencies like react-native-reanimated, react-native-gesture-handler, etc.This is useful for reducing bundle size and dependencies.
withStorybook(config, {
  liteMode: true,
});
Lite mode removes the full Storybook UI. You’ll need to provide your own UI or use the headless story rendering.
experimental_mcp
boolean
default:"false"
Whether to enable MCP (Model Context Protocol) server support.When enabled, adds an /mcp endpoint to the channel server, allowing AI agents (Claude Code, Cursor, etc.) to query component documentation.If WebSockets are disabled, MCP documentation tools still work but story selection is unavailable.
withStorybook(config, {
  experimental_mcp: true,
});
This is an experimental feature. The MCP endpoint runs on the same port as the WebSocket server (default 7007).

Examples

Full Configuration

metro.config.js
const { getDefaultConfig } = require('expo/metro-config');
const { withStorybook } = require('@storybook/react-native/metro/withStorybook');
const path = require('path');

const projectRoot = __dirname;
const config = getDefaultConfig(projectRoot);

module.exports = withStorybook(config, {
  configPath: path.resolve(projectRoot, './.rnstorybook'),
  websockets: { port: 7007, host: 'localhost' },
  useJs: false,
  docTools: true,
  liteMode: false,
});

Production Build with Storybook Disabled

metro.config.js
const { getDefaultConfig } = require('expo/metro-config');
const { withStorybook } = require('@storybook/react-native/metro/withStorybook');

const config = getDefaultConfig(__dirname);

module.exports = withStorybook(config, {
  enabled: process.env.EXPO_PUBLIC_STORYBOOK_ENABLED === 'true',
});

Lite Mode for Smaller Bundle

metro.config.js
const { getDefaultConfig } = require('expo/metro-config');
const { withStorybook } = require('@storybook/react-native/metro/withStorybook');

const config = getDefaultConfig(__dirname);

module.exports = withStorybook(config, {
  liteMode: true,
  websockets: 'auto',
});

How It Works

The withStorybook function modifies your Metro configuration:
  1. Enables require.context: Sets unstable_allowRequireContext: true for dynamic story imports
  2. Generates story manifest: Automatically creates storybook.requires.ts file with all your stories
  3. Starts WebSocket server: Optionally creates a WebSocket server for remote control (when websockets option is provided)
  4. Resolves Storybook modules: Configures Metro to properly resolve Storybook package exports
  5. Strips Storybook in production: When enabled: false, removes Storybook from the bundle
The withStorybook function wraps your existing Metro config, so any custom configuration you have will be preserved.

Telemetry

Storybook collects anonymous usage data to improve the project. To disable telemetry, set the environment variable:
STORYBOOK_DISABLE_TELEMETRY=true

Build docs developers (and LLMs) love