Skip to main content
Configuration options that can be passed to the withStorybook() function to customize Storybook’s Metro integration.

Interface

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. This is where your main.js/ts and preview.js/ts files are located.
module.exports = withStorybook(config, {
  configPath: path.resolve(__dirname, './.rnstorybook'),
});
enabled
boolean
default:true
If false, attempts to remove Storybook modules from the JavaScript bundle to reduce bundle size.When true, enables Storybook metro configuration and generates the storybook.requires file. When false, removes all Storybook code from the bundle by replacing imports with empty modules.Useful for conditionally including Storybook in development but excluding it from production builds:
module.exports = withStorybook(config, {
  enabled: process.env.EXPO_PUBLIC_STORYBOOK_ENABLED === 'true',
});
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.
module.exports = withStorybook(config, {
  useJs: true,
});
docTools
boolean
default:true
Whether to include doc tools in the storybook.requires file.Doc tools provide additional documentation features and work with babel-plugin-react-docgen-typescript.
module.exports = 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. This is useful for reducing bundle size and dependencies.Use this when using @storybook/react-native-ui-lite instead of @storybook/react-native-ui.
module.exports = withStorybook(config, {
  liteMode: true,
});
websockets
WebsocketsOptions | 'auto'
WebSocket configuration for syncing Storybook instances or sending events to Storybook.When provided, creates a WebSocket server for real-time communication. This allows you to sync up multiple devices to show the same story and arg values.Use 'auto' to automatically detect your LAN IP and inject host/port into the generated storybook.requires file.See WebSocket Options below for detailed configuration.
// Manual configuration
module.exports = withStorybook(config, {
  websockets: {
    port: 7007,
    host: 'localhost',
  },
});

// Auto-detect LAN IP
module.exports = withStorybook(config, {
  websockets: 'auto',
});
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.Available from v10.3 onwards.
module.exports = withStorybook(config, {
  experimental_mcp: true,
});

// With websockets enabled
module.exports = withStorybook(config, {
  websockets: { port: 7007 },
  experimental_mcp: true,
});

WebSocket Options

interface WebsocketsOptions {
  port?: number;
  host?: string;
}
websockets.port
number
default:7007
The port WebSocket server will listen on.
module.exports = withStorybook(config, {
  websockets: {
    port: 8080,
  },
});
websockets.host
string
default:"'localhost'"
The host WebSocket server will bind to.When using 'auto' for the websockets option, the host is automatically detected and set to undefined (allowing connections from any interface).
module.exports = withStorybook(config, {
  websockets: {
    host: '0.0.0.0',
    port: 7007,
  },
});

Examples

Minimal Configuration

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

const config = getDefaultConfig(__dirname);
module.exports = withStorybook(config);

Full Configuration

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

const config = getDefaultConfig(__dirname);

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

Production Build (Disabled)

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.NODE_ENV !== 'production',
});

Lite Mode (Reduced Dependencies)

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

const config = getDefaultConfig(__dirname);

module.exports = withStorybook(config, {
  liteMode: true,
  docTools: false,
});

Build docs developers (and LLMs) love