-
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
CLI: Modernize Storybook CLI with new init workflow, Clack UI, and Generator System #32717
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
📝 WalkthroughWalkthroughModularized create/init flows, centralized command execution and logging/prompting, consolidated mocking utilities, introduced typed enums (frameworks, renderers, builders, features, languages, project types), reworked generator and command modules, refactored Vitest addon/postinstall and builder mocking integrations, and updated CI test-init features to include a11y. Changes
Sequence Diagram(s)%% Primary init/create-storybook flow (high level)
sequenceDiagram
autonumber
actor User
participant CLI as "create-storybook CLI"
participant Pre as "PreflightCheck"
participant Detect as "ProjectDetection"
participant Frm as "FrameworkDetection"
participant Pref as "UserPreferences"
participant Gen as "GeneratorExecution"
participant Dep as "DependencyInstallation"
participant Add as "AddonConfiguration"
participant Fin as "Finalization"
User->>CLI: initiate(options)
CLI->>Pre: execute(options)
Pre-->>CLI: { packageManager, isEmptyProject }
CLI->>Detect: execute(...)
Detect-->>CLI: { projectType, language }
CLI->>Frm: execute(...)
Frm-->>CLI: { renderer, builder, framework }
CLI->>Pref: execute(...)
Pref-->>CLI: { selectedFeatures }
CLI->>Gen: execute(...)
Gen-->>CLI: { configDir?, storybookCommand?, extraAddons }
CLI->>Dep: execute(...)
Dep-->>CLI: { status }
CLI->>Add: execute(...)
Add-->>CLI: { status }
CLI->>Fin: execute(...)
Fin-->>CLI: done
%% Addon Vitest interactions (high level)
sequenceDiagram
autonumber
participant Caller
participant AddV as "AddonVitestService"
participant PM as "JsPackageManager"
Caller->>AddV: validateCompatibility(opts)
AddV-->>Caller: { compatible, reasons? }
Caller->>AddV: collectDependencies(PM)
AddV-->>Caller: [packages]
Caller->>AddV: validateConfigFiles(directory)
AddV-->>Caller: { compatible, reasons? }
Caller->>AddV: installPlaywright(PM, { yes? })
AddV-->>Caller: errors[]
Estimated code review effort🎯 5 (Critical) | ⏱️ ~150 minutes
Possibly related issues
Possibly related PRs
✨ Finishing touches
Comment |
|
View your CI Pipeline Execution ↗ for commit b01def1
☁️ Nx Cloud last updated this comment at |
Package BenchmarksCommit: The following packages have significant changes to their size or dependencies:
|
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 2 | 2 | 0 |
| Self size | 414 KB | 181 KB | 🎉 -232 KB 🎉 |
| Dependency size | 2.97 MB | 2.97 MB | 0 B |
| Bundle Size Analyzer | Link | Link |
@storybook/addon-vitest
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 6 | 2 | 🎉 -4 🎉 |
| Self size | 441 KB | 375 KB | 🎉 -66 KB 🎉 |
| Dependency size | 570 KB | 338 KB | 🎉 -232 KB 🎉 |
| Bundle Size Analyzer | Link | Link |
@storybook/builder-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 11 | 17 | 🚨 +6 🚨 |
| Self size | 291 KB | 304 KB | 🚨 +13 KB 🚨 |
| Dependency size | 1.30 MB | 2.00 MB | 🚨 +701 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/builder-webpack5
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 187 | 191 | 🚨 +4 🚨 |
| Self size | 66 KB | 75 KB | 🚨 +9 KB 🚨 |
| Dependency size | 31.98 MB | 32.19 MB | 🚨 +215 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
storybook
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 44 | 39 | 🎉 -5 🎉 |
| Self size | 21.70 MB | 19.20 MB | 🎉 -2.50 MB 🎉 |
| Dependency size | 17.16 MB | 16.40 MB | 🎉 -755 KB 🎉 |
| Bundle Size Analyzer | Link | Link |
@storybook/angular
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 187 | 191 | 🚨 +4 🚨 |
| Self size | 114 KB | 118 KB | 🚨 +3 KB 🚨 |
| Dependency size | 29.99 MB | 30.22 MB | 🚨 +224 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/ember
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 191 | 195 | 🚨 +4 🚨 |
| Self size | 15 KB | 15 KB | 0 B |
| Dependency size | 28.69 MB | 28.91 MB | 🚨 +224 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/html-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 14 | 20 | 🚨 +6 🚨 |
| Self size | 22 KB | 22 KB | 🚨 +12 B 🚨 |
| Dependency size | 1.63 MB | 2.34 MB | 🚨 +715 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/nextjs
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 533 | 537 | 🚨 +4 🚨 |
| Self size | 645 KB | 645 KB | 🎉 -5 B 🎉 |
| Dependency size | 58.91 MB | 59.13 MB | 🚨 +224 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/nextjs-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 124 | 128 | 🚨 +4 🚨 |
| Self size | 1.12 MB | 1.12 MB | 🚨 +85 B 🚨 |
| Dependency size | 21.72 MB | 21.95 MB | 🚨 +229 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/preact-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 14 | 20 | 🚨 +6 🚨 |
| Self size | 13 KB | 13 KB | 🚨 +12 B 🚨 |
| Dependency size | 1.61 MB | 2.33 MB | 🚨 +715 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/react-native-web-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 156 | 160 | 🚨 +4 🚨 |
| Self size | 30 KB | 30 KB | 0 B |
| Dependency size | 22.90 MB | 23.13 MB | 🚨 +229 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/react-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 114 | 118 | 🚨 +4 🚨 |
| Self size | 35 KB | 35 KB | 🚨 +112 B 🚨 |
| Dependency size | 19.52 MB | 19.75 MB | 🚨 +229 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/react-webpack5
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 273 | 277 | 🚨 +4 🚨 |
| Self size | 24 KB | 24 KB | 🚨 +12 B 🚨 |
| Dependency size | 43.85 MB | 44.08 MB | 🚨 +224 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/server-webpack5
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 199 | 203 | 🚨 +4 🚨 |
| Self size | 16 KB | 16 KB | 0 B |
| Dependency size | 33.23 MB | 33.45 MB | 🚨 +224 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/svelte-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 19 | 24 | 🚨 +5 🚨 |
| Self size | 56 KB | 56 KB | 0 B |
| Dependency size | 26.75 MB | 27.00 MB | 🚨 +255 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/sveltekit
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 20 | 25 | 🚨 +5 🚨 |
| Self size | 56 KB | 56 KB | 🎉 -24 B 🎉 |
| Dependency size | 26.80 MB | 27.06 MB | 🚨 +255 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/vue3-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 109 | 114 | 🚨 +5 🚨 |
| Self size | 35 KB | 35 KB | 🎉 -24 B 🎉 |
| Dependency size | 43.90 MB | 44.15 MB | 🚨 +255 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/web-components-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 15 | 21 | 🚨 +6 🚨 |
| Self size | 19 KB | 19 KB | 🎉 -12 B 🎉 |
| Dependency size | 1.65 MB | 2.37 MB | 🚨 +715 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/cli
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 188 | 173 | 🎉 -15 🎉 |
| Self size | 840 KB | 770 KB | 🎉 -70 KB 🎉 |
| Dependency size | 71.37 MB | 66.17 MB | 🎉 -5.21 MB 🎉 |
| Bundle Size Analyzer | Link | Link |
@storybook/codemod
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 170 | 166 | 🎉 -4 🎉 |
| Self size | 30 KB | 30 KB | 🎉 -25 B 🎉 |
| Dependency size | 67.91 MB | 64.74 MB | 🎉 -3.17 MB 🎉 |
| Bundle Size Analyzer | Link | Link |
create-storybook
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 45 | 40 | 🎉 -5 🎉 |
| Self size | 1.45 MB | 998 KB | 🎉 -454 KB 🎉 |
| Dependency size | 38.86 MB | 35.60 MB | 🎉 -3.25 MB 🎉 |
| Bundle Size Analyzer | node | node |
…init-features job
…clean up type definitions - Changed framework property in FrameworkDetectionResult to be required instead of optional. - Updated getFramework method to throw an error if a framework cannot be found, improving error handling. - Removed unused type definition for Builder in project_types.ts to streamline code.
…work handling and type definitions - Updated generatorOptions to include framework and renderer properties for better configuration. - Simplified the getFrameworkDetails function to improve clarity and error handling. - Removed unused builder details logic to streamline the baseGenerator function. - Adjusted types in GeneratorOptions to reflect the new structure.
- Removed the externalFrameworks function to simplify framework detection logic. - Updated getFrameworkDetails to enhance clarity by directly applying the require wrapper on the framework package. - Improved overall readability and maintainability of the baseGenerator code.
- Added a prompt to ask users if they want to use Compodoc for documentation in Angular projects. - Improved user experience by providing information about the benefits of Compodoc. - Updated the logic to determine Compodoc usage based on user input instead of a fixed feature flag.
… addon configuration - Updated the `doInitiate` function to pass `projectType` to user preferences and generator execution. - Simplified the `executeGeneratorExecution` function to accept a single options object. - Enhanced the `UserPreferencesCommand` to determine selected features based on project type. - Adjusted addon configuration logic to utilize `extraAddons` from generator execution results. - Improved overall code readability and maintainability by streamlining function signatures and logic.
…turn structure - Updated the `GeneratorExecutionResult` type to improve clarity and structure by formatting the return type. - Adjusted the return statement in `executeProjectGenerator` to conditionally include `configDir` based on the generator result. - Improved overall readability and maintainability of the `GeneratorExecutionCommand` class.
- Updated the logging in `useStatics` to display relative paths for static directories instead of absolute paths, enhancing clarity. - Removed unused `Builder` type imports and replaced them with `SupportedBuilder` in various files to improve type consistency and maintainability.
- Replaced string literals with SupportedBuilder constants in the AddonManager test cases for improved type safety and consistency. - Enhanced clarity in the tests by using the defined types for builder options.
…aths - Updated the `useStatics` function to utilize `getProjectRoot` for calculating relative static directory paths, enhancing accuracy in logging. - Changed the logger to use `CLI_COLORS` for improved visual consistency in log messages.
- Consolidated the logging message in the `promptForCompoDocs` function to a single line for better clarity and maintainability. - Enhanced user experience by providing a concise message about the benefits of using Compodoc for documentation in Angular projects.
- Included the `yes` option in the `GeneratorExecutionCommand` to allow automatic confirmation for prompts. - Enhanced the command's flexibility by enabling users to bypass interactive prompts based on their preferences.
- Updated postinstall function to accept logger and prompt from options. - Enhanced ClackPromptProvider to manage task logging more effectively. - Streamlined logger usage in add and postinstallAddon functions. - Removed redundant task messages in baseGenerator for cleaner output.
- Removed leading arrows from logger messages in various files to standardize output format. - Introduced ConsoleLogger and StyledConsoleLogger classes for enhanced logging functionality. - Added new console logger methods to improve logging capabilities and maintainability.
| optionValues: { | ||
| loglevel: debug ? 'debug' : 'info', | ||
| yes: true, | ||
| ...extra, | ||
| ...(template.initOptions || {}), | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was removal of skip-install intentional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it was. Otherwise, addons cannot be set up properly
| }; | ||
|
|
||
| /** Service encapsulating helpers for ProjectType usage */ | ||
| export class ProjectTypeService { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file doesn't have unit tests it seems. Did you want to add some?
| // Don't install test in CI but install in non-TTY environments like agentic installs | ||
| if (isTestFeatureAvailable) { | ||
| features.add(Feature.TEST); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment is outdated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (6)
code/core/src/telemetry/notify.ts (1)
20-25: Reconsider the wording "Storybook now collects".The word "now" may mislead users into thinking telemetry is newly introduced. Based on previous review context, telemetry has been in place for some time. Consider rephrasing to avoid implying this is a new feature.
Apply this diff to clarify the message:
logger.info( dedent` - Attention: Storybook now collects completely anonymous telemetry regarding usage. This information is used to shape Storybook's roadmap and prioritize features. You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL: + Attention: Storybook collects completely anonymous telemetry regarding usage. This information is used to shape Storybook's roadmap and prioritize features. You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL: https://storybook.js.org/telemetry ` );code/lib/create-storybook/src/commands/FrameworkDetectionCommand.ts (2)
12-16: Align framework nullability with downstream consumers.As previously noted,
frameworkis typed as nullable but downstream code inGeneratorExecutionCommandexpects a non-nullableSupportedFramework. This contract mismatch should be resolved by either makingframeworknon-nullable (and ensuring detection logic always throws on failure) or adding explicit null-handling whereGeneratorOptionsare constructed.
24-28: Add test coverage for FrameworkDetectionCommand.As previously noted, this command lacks tests unlike other command modules. Please add unit tests covering builder detection logic, framework resolution branches, and error cases.
code/lib/create-storybook/src/commands/UserPreferencesCommand.ts (2)
61-63: Honor theskipPromptoption parameter.The
skipPromptcalculation ignoresoptions.skipPrompt, so callers that explicitly request non-interactive mode via this parameter will still see prompts (unlessyesis also set). This regresses workflows that rely on theskipPromptoption.Apply this diff to include the option parameter:
- const skipPrompt = !isInteractive || !!this.commandOptions.yes; + const skipPrompt = !isInteractive || !!this.commandOptions.yes || !!options.skipPrompt;
122-125: Avoid persisting defaults when prompts are skipped.When
skipPromptis true butskipOnboardingis undefined, this code setssettings.value.init.skipOnboarding = false, persisting a default choice that the user never made. Non-interactive runs (CI, agentic installs) should not mutate user settings.Apply this diff to only persist explicit user choices:
- if (skipPrompt || skipOnboarding) { + if (skipOnboarding !== undefined) { settings.value.init ||= {}; settings.value.init.skipOnboarding = !!skipOnboarding; } else {code/lib/create-storybook/src/bin/run.ts (1)
76-89: Normalize--logfileto avoid booleantruecrashingwriteToFileWhen a user passes bare
--logfilewithout a path, Commander sets the option value totrue. Thattruecurrently flows intologTracker.writeToFile(getOptionValue('logfile')), which is likely expecting a string (or possiblyundefined) and will fail once it hitsfs.writeFile.You’re already documenting that omitting
[path]should fall back todebug-storybook.log, so normalizing the option before writing would make this robust:- .hook('postAction', async ({ getOptionValue }) => { - if (logTracker.shouldWriteLogsToFile) { - await logTracker.writeToFile(getOptionValue('logfile')); - } - }); + .hook('postAction', async ({ getOptionValue }) => { + if (logTracker.shouldWriteLogsToFile) { + const logfileOption = getOptionValue('logfile'); + const logfilePath = + typeof logfileOption === 'string' && logfileOption.trim().length > 0 + ? logfileOption + : undefined; // let logTracker use its default path (debug-storybook.log) + + await logTracker.writeToFile(logfilePath); + } + });That keeps
--logfileworking with or without a value, and prevents accidental boolean values from blowing up the CLI.Also applies to: 90-104, 105-109
🧹 Nitpick comments (4)
code/lib/create-storybook/src/commands/FrameworkDetectionCommand.ts (2)
44-46: Validate builder option or remove unsafe type assertion.The type assertion
options.builder as SupportedBuilderbypasses type safety. IfCommandOptions.builderis already typed asSupportedBuilder | undefined, the cast is redundant. If there's a type mismatch, consider adding runtime validation to ensure the provided builder value is valid before using it.
73-75: Consider logging when framework detection returns null.If
frameworkcan legitimately be null (per the interface contract), consider logging that scenario for debugging purposes, especially since the PR emphasizes improved logging and error handling.code/lib/create-storybook/src/bin/run.ts (2)
28-33: Clarify and harden--features/--no-featuresnormalizationThe
--featuresvariadic option plus explicit--no-featuresflag is a nice API, and theoptions.features === falseguard correctly normalizes the--no-featurescase to an empty array.Two things to consider tightening here:
Type safety for downstream consumers
options.featurescan be:
Feature[](from--features),false(from--no-features, normalized to[]),undefined(no flag).To make this more robust for
CommandOptionsand future refactors, it would help to ensure that by the time you callinitiate,options.featuresis always eitherFeature[]orundefined(never bare booleans). For example, you could explicitly coerce any non-array truthy value toundefined:if (options.features === false) { options.features = []; } else if (!Array.isArray(options.features)) { options.features = undefined; }Commander semantics for combined value + negated options
Because this uses both--features <list...>and--no-featuresmapped to the same underlying option name, Commander’s defaulting/negation behavior can get subtle. It would be good to add a small test matrix (no flag,--features a b,--no-features) to assert the exact shapes you expect and to guard against Commander upgrades changing this behavior.Also applies to: 118-121
81-89: Minor: simplify log-level precedence logic for readabilityFunctionally, the
preActionhook behaves as “--logleveloverrides--debug”, which is reasonable. You currently implement this by callingsetLogLevel('debug')and then callingsetLogLevel(options.loglevel)if present.For slightly clearer intent (and to avoid double-calling the setter), you could invert the condition:
const options = self.opts(); if (options.loglevel) { logger.setLogLevel(options.loglevel); } else if (options.debug) { logger.setLogLevel('debug'); }The behavior stays the same, but it’s easier to scan and makes the precedence explicit.
Also applies to: 90-103
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
code/core/src/telemetry/notify.ts(2 hunks)code/lib/create-storybook/src/bin/run.ts(4 hunks)code/lib/create-storybook/src/commands/FrameworkDetectionCommand.ts(1 hunks)code/lib/create-storybook/src/commands/UserPreferencesCommand.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Select/Select.tsx:200-204
Timestamp: 2025-11-05T09:38:47.712Z
Learning: Repo: storybookjs/storybook — Guidance: Until Storybook 11 is released, do not suggest using React.useId anywhere (e.g., in code/core/src/components/components/Select/Select.tsx) to maintain compatibility with React 17 runtimes. Prefer advising: accept a caller-provided props.id and, if needed, generate a client-only fallback id to minimize SSR hydration issues — but avoid useId. Resume prompting for useId after Storybook 11.
📚 Learning: 2025-11-05T09:38:47.712Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Select/Select.tsx:200-204
Timestamp: 2025-11-05T09:38:47.712Z
Learning: Repo: storybookjs/storybook — Guidance: Until Storybook 11 is released, do not suggest using React.useId anywhere (e.g., in code/core/src/components/components/Select/Select.tsx) to maintain compatibility with React 17 runtimes. Prefer advising: accept a caller-provided props.id and, if needed, generate a client-only fallback id to minimize SSR hydration issues — but avoid useId. Resume prompting for useId after Storybook 11.
Applied to files:
code/lib/create-storybook/src/bin/run.tscode/lib/create-storybook/src/commands/FrameworkDetectionCommand.tscode/lib/create-storybook/src/commands/UserPreferencesCommand.tscode/core/src/telemetry/notify.ts
🧬 Code graph analysis (3)
code/lib/create-storybook/src/bin/run.ts (2)
code/core/src/manager/settings/shortcuts.tsx (1)
Feature(141-141)code/core/src/node-logger/logger/log-tracker.ts (1)
logTracker(97-97)
code/lib/create-storybook/src/commands/FrameworkDetectionCommand.ts (3)
code/lib/create-storybook/src/services/FrameworkDetectionService.ts (1)
FrameworkDetectionService(13-78)code/lib/create-storybook/src/generators/types.ts (1)
CommandOptions(118-137)code/lib/create-storybook/src/generators/GeneratorRegistry.ts (1)
generatorRegistry(34-34)
code/lib/create-storybook/src/commands/UserPreferencesCommand.ts (3)
code/lib/create-storybook/src/services/TelemetryService.ts (1)
TelemetryService(10-105)code/lib/create-storybook/src/generators/types.ts (1)
CommandOptions(118-137)code/lib/create-storybook/src/services/FeatureCompatibilityService.ts (1)
FeatureCompatibilityService(22-61)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: daily
- GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (12)
code/core/src/telemetry/notify.ts (2)
2-4: LGTM! Import modernization aligns with centralized logging.The migration from
CLI_COLORS/picocolorstologgerand addition ofdedentimproves consistency and readability.
8-16: LGTM! Guard logic correctly prevents notification spam.The cache check ensures users are only notified once about telemetry, which is the intended behavior.
code/lib/create-storybook/src/commands/FrameworkDetectionCommand.ts (2)
1-10: LGTM: Imports are clean and appropriate.All imports are used and properly scoped.
85-91: LGTM: Clean public API.The helper function provides a clean, functional interface to the command while maintaining testability of the class.
code/lib/create-storybook/src/commands/UserPreferencesCommand.ts (7)
16-33: LGTM!Type definitions are clean and well-structured. The optional
skipPromptparameter inUserPreferencesOptionsprovides the flexibility needed for non-interactive flows.
46-54: LGTM!Constructor properly initializes services with appropriate dependency injection. The default
FeatureCompatibilityServiceinstance provides good testability while allowing injection.
99-114: LGTM!The method correctly handles all three states of the
featuresarray: undefined, empty, and populated. The optional chaining and explicit length checks make the intent clear.
157-187: LGTM!The method correctly handles both interactive and non-interactive modes, defaulting to
'recommended'when prompts are skipped. Telemetry tracking happens in both paths, which ensures visibility into installation patterns.
189-211: LGTM!Feature determination logic is clean and correctly implements the tiered approach. The A11Y addon inclusion for recommended installs aligns with the PR objectives and improves accessibility support by default.
213-227: LGTM!Clean delegation to the feature compatibility service. Using
process.cwd()is appropriate since the command runs in the project root context.
230-235: LGTM!The helper function provides a clean functional API for command execution while maintaining proper separation of concerns between
CommandOptionsandUserPreferencesOptions.code/lib/create-storybook/src/bin/run.ts (1)
38-64: Typed.choicesfor package manager/parser/type/builder look solidThe use of Commander
.addOption(...).choices(...)for--package-manager,--parser,--type, and--buildergives you strict, discoverable CLIs and lines up with the internal enums (PackageManagerName,ProjectType,SupportedBuilder). The filtering out ofUNDETECTED,UNSUPPORTED, andNXfromProjectTypeavoids exposing invalid/unsupported project types on the CLI.No issues here from my side.
…uage and improve version satisfaction checks in ProjectTypeService
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (1)
code/lib/create-storybook/src/generators/baseGenerator.ts (1)
165-172: Feature selections are still being ignored by AddonService.The
AddonService.configureAddons()method receives thefeaturesparameter but never callsgetAddonsForFeatures(features)to retrieve the corresponding addon packages. This means user selections forFeature.TEST,Feature.A11Y,Feature.DOCS, etc., are silently dropped—those addons won't appear inmain.jsorpackage.json.The fix belongs in
AddonService.configureAddons: merge the results ofthis.getAddonsForFeatures(features)into bothaddonsForMainandaddonPackagesbefore returning.
🧹 Nitpick comments (2)
code/lib/create-storybook/src/generators/baseGenerator.ts (2)
199-220: Consider whethereslintPluginPackagevariable is needed.The
eslintPluginPackagevariable is assigned at line 207 and used once at line 208, but the actual string'eslint-plugin-storybook'could be directly added topackagesToInstall. Unless this variable serves a future purpose (logging, debugging, etc.), it adds no value.Apply this diff if you want to simplify:
- let eslintPluginPackage: string | null = null; try { if (!isCI()) { const { hasEslint, isStorybookPluginInstalled, isFlatConfig, eslintConfigFile } = // TODO: Investigate why packageManager type does not match on CI await extractEslintInfo(packageManager as any); if (hasEslint && !isStorybookPluginInstalled) { - eslintPluginPackage = 'eslint-plugin-storybook'; - packagesToInstall.push(eslintPluginPackage); + packagesToInstall.push('eslint-plugin-storybook'); taskLog.message(`- Configuring ESLint plugin`);
226-233: Clarify the dependency collection comment.The comment "When using the dependency collector, just collect the packages" implies the collector is optional, but
dependencyCollectoris a required parameter inGeneratorOptionsand is always used in this refactored flow.Consider rephrasing to:
- // When using the dependency collector, just collect the packages + // Collect packages for installation; the collector will install them in a single batch later
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
code/yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (1)
code/lib/create-storybook/src/generators/baseGenerator.ts(7 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-11-05T09:38:47.712Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Select/Select.tsx:200-204
Timestamp: 2025-11-05T09:38:47.712Z
Learning: Repo: storybookjs/storybook — Guidance: Until Storybook 11 is released, do not suggest using React.useId anywhere (e.g., in code/core/src/components/components/Select/Select.tsx) to maintain compatibility with React 17 runtimes. Prefer advising: accept a caller-provided props.id and, if needed, generate a client-only fallback id to minimize SSR hydration issues — but avoid useId. Resume prompting for useId after Storybook 11.
Applied to files:
code/lib/create-storybook/src/generators/baseGenerator.ts
📚 Learning: 2025-09-17T07:31:04.432Z
Learnt from: ndelangen
Repo: storybookjs/storybook PR: 32484
File: code/core/package.json:326-326
Timestamp: 2025-09-17T07:31:04.432Z
Learning: In Storybook's core package, dependencies like `open` are bundled into the final distribution during the build process, so they should remain in devDependencies rather than being moved to dependencies. End users don't need these packages as separate runtime dependencies since they're included in the bundled code.
Applied to files:
code/lib/create-storybook/src/generators/baseGenerator.ts
📚 Learning: 2025-09-29T13:20:23.346Z
Learnt from: mrginglymus
Repo: storybookjs/storybook PR: 32556
File: code/core/package.json:309-313
Timestamp: 2025-09-29T13:20:23.346Z
Learning: The `fast-printf` dependency in Storybook's core package is bundled into the final distribution during the build process, so it should remain in devDependencies rather than being moved to dependencies, following the same pattern as other bundled dependencies like `open`.
Applied to files:
code/lib/create-storybook/src/generators/baseGenerator.ts
🧬 Code graph analysis (1)
code/lib/create-storybook/src/generators/baseGenerator.ts (6)
code/lib/create-storybook/src/generators/types.ts (2)
FrameworkOptions(31-47)GeneratorOptions(16-29)code/core/src/common/utils/get-storybook-info.ts (1)
frameworkPackages(38-61)code/core/src/node-logger/prompts/prompt-functions.ts (1)
taskLog(161-230)code/core/src/node-logger/prompts/prompt-provider-clack.ts (1)
taskLog(111-159)code/lib/create-storybook/src/services/AddonService.ts (1)
AddonService(11-77)code/lib/create-storybook/src/generators/configure.ts (2)
configureMain(46-107)configurePreview(109-155)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: daily
- GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (7)
code/lib/create-storybook/src/generators/baseGenerator.ts (7)
18-19: LGTM: Import updates support the new architecture.The new imports (
promptfor taskLog,AddonServicefor addon configuration) align with the modular command-based pipeline and centralized logging approach described in the PR objectives.Also applies to: 24-24
28-40: LGTM: Good use of TypeScript'ssatisfiesoperator.Using
satisfies FrameworkOptionsprovides type safety while preserving the specific literal types of the default values.
42-61: LGTM: Helper function correctly maps enum values to package names.The
getPackageByValuefunction properly searches the package registry and provides a clear error message when a package cannot be found.
75-95: LGTM: Object parameter pattern improves API clarity.The refactored
getFrameworkDetailsfunction uses object parameters (more maintainable) and correctly delegates framework package resolution togetPackageByValue.
108-125: LGTM: Enum-based framework list improves type safety.The use of
SupportedFrameworkenum values instead of strings prevents typos and ensures only valid framework identifiers are checked.
260-285: LGTM: Configuration generation with proper progress logging.Both
configureMainandconfigurePrevieware called with the correct parameters, andtaskLog.messageprovides clear progress updates to the user.
287-320: LGTM: Script addition, component copying, and return value are correct.The function properly:
- Logs each step using
taskLog- Falls back from framework to renderer templates when needed
- Uses
invariantto fail fast if neither template source is available- Returns the enhanced configuration object (
configDir,storybookCommand,shouldRunDev) as specified in the updated API
This reverts commit 0abdc8c.
Closes #25389
Closes #32043
Closes #32778
Closes #31880
Closes #31914
What I did
This PR represents a massive refactor and modernization of the Storybook CLI, primarily focused on the
initcommand. The original initiate.ts file, a monolithic, 900+ line behemoth, was brittle, hard to maintain, and difficult to test.This new architecture replaces it with a clean, command-based pipeline that is modular, testable, and far more extensible. We've also swapped our CLI's user interface from prompts to @clack/prompts, providing a significantly improved, modern, and interactive experience for users.
Highlights of the Change
Command-Based init Workflow: The entire init process is now orchestrated as a series of discrete, testable commands:
New Generator System:
Introduced a generatorRegistry and a new GeneratorModule interface.
All framework generators (React, Angular, Next.js, Nuxt, etc.) have been refactored to this new, modular standard, separating metadata and configuration logic .
Modern Clack UI:
prompts,ora, andboxenwith@clack/promptsacross the entire CLI (init, add, upgrade, automigrate) for a unified, beautiful, and interactive experience.Centralized Addon & Feature Logic:
a11y in
recommended:The test feature now also includes @storybook/addon-a11y by default, as it's a prerequisite for accessibility testing.
New Next.js-Vite Support:
The Next.js generator now defaults to @storybook/nextjs-vite (Vite builder) for new projects. It intelligently detects custom webpack.config.js or .babelrc files and prompts the user to fall back to @storybook/nextjs (Webpack 5) if needed.
Added a new nextjs-to-nextjs-vite automigration to help users move from the old Webpack-based setup .
Rsbuild Support during initialization:
Enhanced Logging & Error Handling:
debug-storybook.logfile on failure, making debugging much easier.Introduced new StorybookError subclasses for CLI failures (e.g., AddonVitestPostinstallError)
Checklist for Contributors
Testing
The changes in this PR are covered in the following automated tests:
Manual testing
This is a massive change. Please test the init and add commands thoroughly.
storybook initcdinto a new React + Vite project.npx storybook@<canary> init.cdinto a new React + Vite project.npx storybook@<canary> init --yes.cdinto a new React + Vite project.npx storybook@latest init --features docs a11y.cdinto a clean Next.js project. Run init --yes.rm -rf .storybookand add awebpack(config) { return config; }block to next.config.js.storybook addcdinto a project without the test feature (e.g., init --features docs).npx storybook@<canary> add @storybook/addon-vitest.storybook automigratecdinto a project using the old @storybook/nextjs (Webpack).Documentation
MIGRATION.MD
Checklist for Maintainers
When this PR is ready for testing, make sure to add
ci:normal,ci:mergedorci:dailyGH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found incode/lib/cli-storybook/src/sandbox-templates.tsMake sure this PR contains one of the labels below:
Available labels
bug: Internal changes that fixes incorrect behavior.maintenance: User-facing maintenance tasks.dependencies: Upgrading (sometimes downgrading) dependencies.build: Internal-facing build tooling & test updates. Will not show up in release changelog.cleanup: Minor cleanup style change. Will not show up in release changelog.documentation: Documentation only changes. Will not show up in release changelog.feature request: Introducing a new feature.BREAKING CHANGE: Changes that break compatibility in some way with current major version.other: Changes that don't fit in the above categories.🦋 Canary release
This pull request has been released as version
0.0.0-pr-32717-sha-7a16d827. Try it out in a new sandbox by runningnpx [email protected] sandboxor in an existing project withnpx [email protected] upgrade.More information
0.0.0-pr-32717-sha-7a16d827valentin/cli-init-rework7a16d8271763547934)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=32717Summary by CodeRabbit
New Features
Improvements
Tests