ReactNative: Overhaul RN setup#34333
Conversation
|
View your CI Pipeline Execution ↗ for commit 0872682
☁️ Nx Cloud last updated this comment at |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds React Native Storybook support: generates an RN entrypoint, derives platform run scripts, applies a Metro config codemod (with fallback), integrates these into the RN generator lifecycle, and documents an on-device addons migration. Changes
Sequence DiagramssequenceDiagram
participant User
participant Generator
participant PackageManager
participant FileSystem
participant MetroCodemod
participant Logger
User->>Generator: configure({ language, yes? })
Generator->>PackageManager: read package.json scripts
PackageManager-->>Generator: scripts
Generator->>Generator: deriveStorybookPlatformScripts(scripts)
Generator->>FileSystem: write .rnstorybook/index.<ts|js>
FileSystem-->>Generator: targetPath
Generator->>MetroCodemod: runMetroCodemodOrFallback({ packageManager, yes })
MetroCodemod-->>Generator: MetroCodemodResult
Generator->>PackageManager: addScripts(derived scripts + storybook-generate)
Generator->>Logger: save derivation & codemod result
Generator-->>User: configure complete
User->>Generator: postConfigure()
Generator->>Logger: print "Storybook run scripts" guidance
alt missing base scripts
Generator->>Logger: print STORYBOOK_ENABLED=true fallback instruction
end
Generator->>Logger: print Metro codemod status
Estimated code review effort🎯 4 (Complex) | ⏱️ ~70 minutes Possibly related PRs
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
code/lib/create-storybook/src/generators/REACT_NATIVE/generateScripts.test.ts (1)
5-48: Consider adding edge case tests.The current tests cover the main scenarios well. Consider adding tests for edge cases like
undefinedscripts, empty string values, and non-string script values (e.g.,{ ios: 123 }), which the implementation handles but aren't explicitly tested.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@code/lib/create-storybook/src/generators/REACT_NATIVE/generateScripts.test.ts` around lines 5 - 48, Add edge-case unit tests for deriveStorybookPlatformScripts: add cases where input scripts contain undefined values (e.g., { ios: undefined }), empty strings ({ android: '' }), and non-string values ({ ios: 123 }) and assert the function treats those as missing base scripts (appear in missingBaseScripts) and does not add corresponding storybook:* entries to scriptsToAdd; also confirm the function does not mutate the original input object (compare against a snapshot) and that scriptsToAdd only contains entries for valid string commands. Use deriveStorybookPlatformScripts, scriptsToAdd, and missingBaseScripts in the new tests to mirror existing test style.code/lib/create-storybook/src/generators/REACT_NATIVE/index.test.ts (1)
99-120: Consider making the output assertions more robust.The test relies on checking the last logged message via
mock.calls.at(-1). If additional log calls are added in the future, this could become fragile.Consider using
toHaveBeenCalledWith(expect.stringContaining(...))or iterating over all calls to find relevant messages:const allLogs = vi.mocked(logger.log).mock.calls.map(c => String(c[0])); expect(allLogs.some(log => log.includes('npm run storybook:ios'))).toBe(true);That said, testing the final output message is reasonable for verifying user-facing behavior.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.test.ts` around lines 99 - 120, The test "postConfigure removes legacy entry replacement copy" is brittle because it asserts on the last logger.log call via vi.mocked(logger.log).mock.calls.at(-1); update the assertions to inspect all logger.log calls instead: map vi.mocked(logger.log).mock.calls to strings (or use expect(vi.mocked(logger.log)).toHaveBeenCalledWith(expect.stringContaining(...))) and assert that some log includes 'npm run storybook:ios' and 'npm run storybook:android' and that none include 'Replace the contents of your app entry'; update the assertions around logger.log in this test and keep the rest of the test (including invoking reactNativeGenerator.configure/postConfigure) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@code/lib/create-storybook/src/generators/REACT_NATIVE/generateScripts.ts`:
- Around line 8-12: The generated Storybook scripts use the STORYBOOK_ENV_PREFIX
(which includes "cross-env") via withStorybookEnv, but the configure function in
REACT_NATIVE/index.ts never adds cross-env to devDependencies; update the
configure function to add "cross-env" to the devDependencies/packages list
that's installed for React Native projects so the generated scripts will run.
Locate the configure function in REACT_NATIVE/index.ts and include "cross-env"
alongside the other dev packages added during setup (ensure it's added as a
devDependency, not a runtime dependency).
In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts`:
- Around line 19-20: The module-level variables lastMetroCodemodResult and
lastScriptDerivationResult can leak state between generator runs; update the
implementation so state is not stored at module scope—either clear these
variables at the start of configure or move them into per-run storage (e.g.,
capture them in a closure/class instance or return them from configure for
postConfigure to consume). Concretely, remove reliance on the module-level
lastMetroCodemodResult/lastScriptDerivationResult and ensure configure
initializes fresh per-run state (or returns a state object) that postConfigure
uses, updating references in configure and postConfigure accordingly (symbols:
lastMetroCodemodResult, lastScriptDerivationResult, configure, postConfigure,
GeneratorModule).
In `@code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.ts`:
- Around line 8-14: Replace the placeholder constants that will be exposed to
users: update METRO_SETUP_DOCS_LINK to point to the real React Native Metro docs
URL and replace EXPO_CREATE_METRO_COMMAND (the command and args in the
EXPO_CREATE_METRO_COMMAND constant) with the actual Expo CLI command and
arguments used to generate a metro config; ensure the values are accurate,
user-friendly, and tested (references: METRO_SETUP_DOCS_LINK and
EXPO_CREATE_METRO_COMMAND in this file), and keep METRO_CONFIG_CANDIDATES and
METRO_FALLBACK_COMMENT_MARKER unchanged unless you need to add another candidate
or alter the marker text for clarity.
---
Nitpick comments:
In
`@code/lib/create-storybook/src/generators/REACT_NATIVE/generateScripts.test.ts`:
- Around line 5-48: Add edge-case unit tests for deriveStorybookPlatformScripts:
add cases where input scripts contain undefined values (e.g., { ios: undefined
}), empty strings ({ android: '' }), and non-string values ({ ios: 123 }) and
assert the function treats those as missing base scripts (appear in
missingBaseScripts) and does not add corresponding storybook:* entries to
scriptsToAdd; also confirm the function does not mutate the original input
object (compare against a snapshot) and that scriptsToAdd only contains entries
for valid string commands. Use deriveStorybookPlatformScripts, scriptsToAdd, and
missingBaseScripts in the new tests to mirror existing test style.
In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.test.ts`:
- Around line 99-120: The test "postConfigure removes legacy entry replacement
copy" is brittle because it asserts on the last logger.log call via
vi.mocked(logger.log).mock.calls.at(-1); update the assertions to inspect all
logger.log calls instead: map vi.mocked(logger.log).mock.calls to strings (or
use
expect(vi.mocked(logger.log)).toHaveBeenCalledWith(expect.stringContaining(...)))
and assert that some log includes 'npm run storybook:ios' and 'npm run
storybook:android' and that none include 'Replace the contents of your app
entry'; update the assertions around logger.log in this test and keep the rest
of the test (including invoking reactNativeGenerator.configure/postConfigure)
unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6cf731fa-ff73-4e11-a696-0e40bc249414
📒 Files selected for processing (9)
code/lib/create-storybook/src/generators/REACT_NATIVE/generateEntrypoint.test.tscode/lib/create-storybook/src/generators/REACT_NATIVE/generateEntrypoint.tscode/lib/create-storybook/src/generators/REACT_NATIVE/generateScripts.test.tscode/lib/create-storybook/src/generators/REACT_NATIVE/generateScripts.tscode/lib/create-storybook/src/generators/REACT_NATIVE/index.test.tscode/lib/create-storybook/src/generators/REACT_NATIVE/index.tscode/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.test.tscode/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.tscode/lib/create-storybook/src/generators/REACT_NATIVE/templates/index.js
Package BenchmarksCommit: The following packages have significant changes to their size or dependencies:
|
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 184 | 184 | 0 |
| Self size | 782 KB | 785 KB | 🚨 +4 KB 🚨 |
| Dependency size | 68.22 MB | 68.24 MB | 🚨 +17 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
create-storybook
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 51 | 51 | 0 |
| Self size | 1.04 MB | 1.06 MB | 🚨 +16 KB 🚨 |
| Dependency size | 37.10 MB | 37.10 MB | 🚨 +740 B 🚨 |
| Bundle Size Analyzer | node | node |
- Add `deviceAddons` field to `StorybookConfigRaw` type in core-common.ts - Create `rn-ondevice-addons-to-device-addons` automigration fix that moves addons with 'ondevice' in their name from `addons` to `deviceAddons` in React Native Storybook projects - Register the new fix in the allFixes list - Add comprehensive tests (9 tests) for the check and run phases Agent-Logs-Url: https://github.com/storybookjs/storybook/sessions/4e6650e3-b5dc-4d8c-b331-2c0b7f9506e4 Co-authored-by: ndelangen <3070389+ndelangen@users.noreply.github.com>
Agent-Logs-Url: https://github.com/storybookjs/storybook/sessions/4e6650e3-b5dc-4d8c-b331-2c0b7f9506e4 Co-authored-by: ndelangen <3070389+ndelangen@users.noreply.github.com>
Per review feedback, deviceAddons is React Native-specific and should not live in the shared core type. The automigration fix uses ConfigFile string-path APIs so it works without the type definition. Agent-Logs-Url: https://github.com/storybookjs/storybook/sessions/98fca5c1-3428-4436-8892-f4254f66193f Co-authored-by: ndelangen <3070389+ndelangen@users.noreply.github.com>
…eviceAddons Agent-Logs-Url: https://github.com/storybookjs/storybook/sessions/d4b80472-bc2f-4c03-a3e4-64604df8f1ec Co-authored-by: ndelangen <3070389+ndelangen@users.noreply.github.com>
Co-authored-by: ndelangen <3070389+ndelangen@users.noreply.github.com>
|
@copilot, can you update this PR to match the base branch and resolve any merge conflicts? |
# Conflicts: # code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts Co-authored-by: ndelangen <3070389+ndelangen@users.noreply.github.com>
Done. Merged |
…opilot/add-device-addons-property Co-authored-by: ndelangen <3070389+ndelangen@users.noreply.github.com>
…s and add a test for template literal imports/exports
There was a problem hiding this comment.
Pull request overview
Overhauls the React Native storybook init flow to generate a dedicated .rnstorybook entrypoint, automatically update Metro config via codemod, and add platform run scripts; also adds an automigration to move on-device addons from addons to deviceAddons.
Changes:
- Add Metro config codemod with fallback commenting + tests.
- Generate
.rnstorybook/index.(ts|js)entrypoint and derivestorybook:ios/storybook:androidscripts (with optionalcross-env). - Add RN automigration for on-device addons and document it in
MIGRATION.md; improve RN project detection (treatexpoas RN signal).
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
code/lib/create-storybook/templates/react-native/index.js |
New user-editable RN Storybook entrypoint template. |
code/lib/create-storybook/src/services/ProjectTypeService.ts |
Adds expo as a dependency signal for React Native project detection. |
code/lib/create-storybook/src/services/ProjectTypeService.test.ts |
Adds coverage for RN detection via expo. |
code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.ts |
Implements Metro config codemod + fallback comment behavior. |
code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.test.ts |
Adds unit tests for Metro codemod behavior and prompting paths. |
code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts |
Orchestrates RN init: entrypoint generation, Metro codemod, script derivation, updated post-configure messaging. |
code/lib/create-storybook/src/generators/REACT_NATIVE/index.test.ts |
Adds unit tests for RN generator orchestration and messaging. |
code/lib/create-storybook/src/generators/REACT_NATIVE/generateScripts.ts |
Derives storybook:ios/android scripts from existing platform scripts. |
code/lib/create-storybook/src/generators/REACT_NATIVE/generateScripts.test.ts |
Unit tests for script derivation behavior. |
code/lib/create-storybook/src/generators/REACT_NATIVE/generateEntrypoint.ts |
Generates `.rnstorybook/index.(ts |
code/lib/create-storybook/src/generators/REACT_NATIVE/generateEntrypoint.test.ts |
Unit tests for entrypoint generation behavior. |
code/lib/cli-storybook/src/automigrate/multi-project.ts |
Uses shared RN config dir constant during RN automigration path rewriting. |
code/lib/cli-storybook/src/automigrate/fixes/rnstorybook-config.ts |
Uses shared RN config dir constant for .rnstorybook rename operations. |
code/lib/cli-storybook/src/automigrate/fixes/rn-ondevice-addons-to-device-addons.ts |
New automigration moving ondevice addons to deviceAddons (including sibling .storybook/.rnstorybook). |
code/lib/cli-storybook/src/automigrate/fixes/rn-ondevice-addons-to-device-addons.test.ts |
Unit tests for the new automigration. |
code/lib/cli-storybook/src/automigrate/fixes/index.ts |
Registers the new RN automigration fix. |
code/core/src/shared/constants/config-folder.ts |
Introduces RN_STORYBOOK_DIR constant. |
MIGRATION.md |
Documents RN on-device addon migration in 10.3 → 10.4 section. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| '@storybook/addon-ondevice-controls@10.4.0-canary-20260410142651', | ||
| '@storybook/addon-ondevice-actions@10.4.0-canary-20260410142651', | ||
| '@storybook/react-native@10.4.0-canary-20260410142651', |
There was a problem hiding this comment.
The generator pins @storybook/react-native and on-device addons to a specific canary timestamp version. Because these packages are external to this monorepo, getVersionedPackages() will keep the exact canary string, which can quickly become stale and makes storybook init non-reproducible across releases. Prefer leaving these unpinned (let getVersionedPackages() choose @^<latest>), or pin them via a stable tag/channel that you control (e.g. next) rather than a one-off canary build.
| '@storybook/addon-ondevice-controls@10.4.0-canary-20260410142651', | |
| '@storybook/addon-ondevice-actions@10.4.0-canary-20260410142651', | |
| '@storybook/react-native@10.4.0-canary-20260410142651', | |
| '@storybook/addon-ondevice-controls', | |
| '@storybook/addon-ondevice-actions', | |
| '@storybook/react-native', |
There was a problem hiding this comment.
I'll revert this change before merging, but only after the RN PR has been merged.
| import { logger, prompt } from 'storybook/internal/node-logger'; | ||
|
|
||
| export const METRO_CONFIG_CANDIDATES = ['metro.config.ts', 'metro.config.js', 'metro.config.cjs']; | ||
| export const METRO_SETUP_DOCS_LINK = 'TODO_REPLACE_WITH_REACT_NATIVE_METRO_DOCS_LINK'; |
There was a problem hiding this comment.
METRO_SETUP_DOCS_LINK is still a TODO placeholder string. This will surface to users both in the inserted fallback comment and in the post-configure CLI output, leaving them without a real docs URL. Replace this constant with the actual React Native Metro setup documentation link (and consider adding a simple test asserting it's not left as a TODO).
| export const METRO_SETUP_DOCS_LINK = 'TODO_REPLACE_WITH_REACT_NATIVE_METRO_DOCS_LINK'; | |
| export const METRO_SETUP_DOCS_LINK = 'https://reactnative.dev/docs/metro'; |
There was a problem hiding this comment.
No, this should likely point to a page created/updated in this PR:
storybookjs/react-native#877
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…s and improve logging for manual setup guidance
…ul' of github.com:storybookjs/storybook into norbert/rn-init-overhaul
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (1)
code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts (1)
20-21:⚠️ Potential issue | 🟡 MinorAvoid carrying per-run results in module globals.
lastMetroCodemodResultandlastScriptDerivationResultstill persist across invocations, so a later generator run in the same process can print stale post-configure guidance. Please reset them per run or thread the data throughconfigure/postConfigureinstead.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts` around lines 20 - 21, lastMetroCodemodResult and lastScriptDerivationResult are stored as module-level globals and can leak stale data between generator runs; instead reset them at the start of each run or pass their values through the configure/postConfigure flow. Update the generator so that before each invocation you clear or reinitialize lastMetroCodemodResult and lastScriptDerivationResult, or refactor the logic to return the MetroCodemodResult and StorybookPlatformScriptDerivationResult from the configure function and accept them as parameters to postConfigure (referencing the configure and postConfigure functions and the symbols lastMetroCodemodResult and lastScriptDerivationResult). Ensure no code path relies on the module globals after the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts`:
- Around line 127-155: The metro codemod result 'skipped-codemod-failed' is not
being handled: update the metroCodemodSummary IIFE to include a branch for
lastMetroCodemodResult.status === 'skipped-codemod-failed' that returns a clear
failure message (referencing metroCodemodSummary and lastMetroCodemodResult),
and add 'skipped-codemod-failed' to the showWithStorybookManualSnippet condition
so the manual recovery snippet and notes are shown when
runMetroCodemodOrFallback() reports that failure.
- Line 89: generateReactNativeEntrypoint currently overwrites existing
.rnstorybook/index.* unconditionally; change it so existing user customizations
are preserved by only creating the entrypoint when it does not exist or by
prompting before replacing. Specifically, before calling
generateReactNativeEntrypoint (or inside that function), detect the presence of
.rnstorybook/index.js/.ts/.tsx and skip generation if any exist (or present an
interactive confirmation to overwrite), and ensure generateReactNativeEntrypoint
is updated to accept an option like overwrite: boolean or to return a status so
the caller can decide; reference generateReactNativeEntrypoint and the
.rnstorybook/index.* target files when making the change.
- Around line 118-125: Update the scriptWarningSummary so it does not hard-code
POSIX "STORYBOOK_ENABLED=true" but instead reuses the same cross-platform
environment-prefix helper used for the derived-script output (i.e., call the
shared env-prefix function the codebase uses for inferred scripts) to produce
the correct prefix and then render the fallback command(s); use
lastScriptDerivationResult?.missingBaseScripts to map each missing script into a
platform-safe command like `${envPrefix} <script>` (or show platform-specific
variants) rather than emitting the raw POSIX-only string.
---
Duplicate comments:
In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts`:
- Around line 20-21: lastMetroCodemodResult and lastScriptDerivationResult are
stored as module-level globals and can leak stale data between generator runs;
instead reset them at the start of each run or pass their values through the
configure/postConfigure flow. Update the generator so that before each
invocation you clear or reinitialize lastMetroCodemodResult and
lastScriptDerivationResult, or refactor the logic to return the
MetroCodemodResult and StorybookPlatformScriptDerivationResult from the
configure function and accept them as parameters to postConfigure (referencing
the configure and postConfigure functions and the symbols lastMetroCodemodResult
and lastScriptDerivationResult). Ensure no code path relies on the module
globals after the change.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: d92e83a8-89bd-46ef-bdf6-186f48848727
📒 Files selected for processing (1)
code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts
…ration, ensuring proper transformation and output verification
…tests for ESM import validation
|
I'm splitting this review up to make it easier to review. |
|
Closing this PR in favor of smaller, milestone-scoped PRs that are easier to review independently: M8 — deviceAddons automigration: #34659 Each PR is a complete, reviewable, mergeable unit. M8 is independent (different package). M1 and M2 are self-contained utilities with full test coverage. M3 wires them together and depends on M1 + M2 being merged first. |
…dons` Adds a new `rn-ondevice-addons-to-device-addons` automigration that moves on-device addons (packages whose name contains `ondevice`) from the shared `addons` array into a new `deviceAddons` array in `.rnstorybook/main.ts`. This is needed because Storybook Core evaluates every entry in `addons` as a Node.js preset, which on-device addons are not, and that causes `storybook extract` to fail. Split out of storybookjs#34333 (M8). Tracking issue: storybookjs#34276. Made-with: Cursor
Adds a self-contained generator that creates the `.rnstorybook/index.{ts,js}`
entry point for React Native projects, copying it from a static template and
choosing the file extension based on the project's language preference
(TypeScript vs JavaScript).
The entry point template registers a root component via
`AppRegistry.registerComponent` and configures `getStorybookUI` with storage,
producing a user-editable file.
Files added:
- `src/generators/REACT_NATIVE/generateEntrypoint.ts` — the generator
- `src/generators/REACT_NATIVE/generateEntrypoint.test.ts` — full coverage
- `templates/react-native/index.js` — the static template
This module is intentionally not yet wired into the React Native generator;
that orchestration arrives in M3.
Split out of storybookjs#34333 (M2). Tracking issue: storybookjs#34276.
Made-with: Cursor
Adds an AST-based codemod (using `recast` + `@babel/parser` via the existing
`storybook/internal/babel` re-export) that wraps a project's `metro.config.{js,ts,cjs}`
export with `withStorybook(...)` and adds the matching import.
Handles:
- CommonJS (`module.exports = ...`) and ESM (`export default ...`)
- Direct config objects, function declarations, and `async` functions
- TypeScript sources
- Idempotency (won't double-wrap configs that already include Storybook)
Also exports a fallback path that prepends a guidance comment to the metro
config when the AST transform can't be applied safely.
This module is intentionally a self-contained, tested utility — it is not
yet wired into the React Native generator. That orchestration arrives in M3.
Split out of storybookjs#34333 (M1). Tracking issue: storybookjs#34276.
Made-with: Cursor
Wires the React Native generator end-to-end during `storybook init`:
- Calls the M1 metro-config codemod to wrap the project's
`metro.config.{js,ts,cjs}` with `withStorybook(...)`, falling back to a
guidance comment when the AST transform can't be applied safely.
- Calls the M2 entrypoint generator to write `.rnstorybook/index.{ts,js}`.
- Adds `generateScripts` to derive `storybook:ios` / `storybook:android`
npm scripts and request `cross-env` when needed.
- Updates `ProjectTypeService` to detect React Native projects via the
`expo` dependency in addition to `react-native` / `react-native-scripts`.
This is the orchestration layer that makes the React Native init flow
user-facing. It depends on the M1 codemod and M2 entrypoint generator —
this PR is stacked on top of those branches and should be merged after
them. Once M1 and M2 land on `next`, this PR's diff will reduce to the
M3-only files.
Files added (M3):
- `src/generators/REACT_NATIVE/generateScripts.{ts,test.ts}`
- `src/generators/REACT_NATIVE/index.test.ts`
Files modified (M3):
- `src/generators/REACT_NATIVE/index.ts` — orchestration
- `src/services/ProjectTypeService.{ts,test.ts}` — expo detection
Split out of storybookjs#34333 (M3). Tracking issue: storybookjs#34276.
Made-with: Cursor
Tracked by #34276
Closes: M1, M2, M3 and partially M8
Companion PR: storybookjs/react-native#871
What I did
Overhauled
storybook initfor React Native to deliver a fully automated, zero-manual-config setup — matching the Storybook for Web mental model where Storybook runs as its own entry point.Metro config codemod (M1)
metro.config.jsto wrap the exported config withwithStorybook()Entrypoint generation (M2)
.rnstorybook/index.{ts,js}from a templatepreview.json webSB init orchestration (M3)
storybook:ios/storybook:androidnpm scriptsios/androidscripts withSTORYBOOK_ENABLED=truecross-envfor Windows compatibilityOn-device addons automigration (M8)
rn-ondevice-addons-to-device-addons: moves any addon withondevicein its name fromaddons→deviceAddonsin the user's.rnstorybook/main.ts{ name, options }) addon formsaddonsbreak extract on SB10 because Core evaluates them as Node.js presets — see Split addons from "ondevice" addons inmain.tsreact-native#873Project detection
expoas a recognized React Native dependency in ProjectTypeServiceChecklist for Contributors
Testing
The changes in this PR are covered in the following automated tests:
Manual testing
npx storybook@0.0.0-pr-34333-sha-865b50bc initin a fresh Expo project.rnstorybook/index.tsis generatedmetro.config.jsis wrapped withwithStorybook()storybook:iosandstorybook:androidscripts are added topackage.jsonnpx storybook@0.0.0-pr-34333-sha-865b50bc automigratein a project with on-device addons inaddons— verify they move todeviceAddonsI verified the above
Documentation
MIGRATION.MD
🦋 Canary release
This pull request has been released as version
0.0.0-pr-34333-sha-823a6755. Try it out in a new sandbox by runningnpx storybook@0.0.0-pr-34333-sha-823a6755 sandboxor in an existing project withnpx storybook@0.0.0-pr-34333-sha-823a6755 upgrade.More information
0.0.0-pr-34333-sha-823a6755norbert/rn-init-overhaul823a67551776969800)To request a new release of this pull request, mention the
@storybookjs/coreteam.core team members can create a new canary release here or locally with
gh workflow run --repo storybookjs/storybook publish.yml --field pr=34333Summary by CodeRabbit
New Features
Documentation
Tests