Skip to content

CLI: Prompt for framework when project type cannot be detected#35373

Open
MahinAnowar wants to merge 1 commit into
storybookjs:nextfrom
MahinAnowar:fix/prompt-on-undetected-framework
Open

CLI: Prompt for framework when project type cannot be detected#35373
MahinAnowar wants to merge 1 commit into
storybookjs:nextfrom
MahinAnowar:fix/prompt-on-undetected-framework

Conversation

@MahinAnowar

@MahinAnowar MahinAnowar commented Jul 5, 2026

Copy link
Copy Markdown

Closes #35045

What I did

When create storybook can't detect a supported framework it previously hard-failed with an error that never mentioned the --type flag — leaving vanilla-HTML / Web Components users (and monorepo users in the wrong folder) stuck.

Following the fix shape prescribed by @Sidnioulz in the issue:

  • ProjectTypeService.autoDetectProjectType now returns ProjectType.UNDETECTED instead of logging + throwing (its "prompting handled by command layer" comment is now actually true; the NX error path is unchanged).
  • ProjectDetectionCommand handles UNDETECTED: it prints the education message (now mentioning --type, e.g. --type html) and, when interactive, prompts:
    1. Install the HTML framework (for projects without a framework)
    2. Choose a framework to install (second select over all installable project types)
    3. Cancel the installation (fails with a non-zero exit as before)
  • Non-interactive runs (--yes) keep the previous fail-with-error behavior, without prompting.

The prompt mirrors the existing promptReactNativeVariant pattern, including createPromptCancelOptions telemetry.

How to test

Automated: 4 new cases in ProjectDetectionCommand.test.ts (HTML selection, framework selection, cancel, non-interactive fail) + updated ProjectTypeService.test.ts expectations. All 313 create-storybook package tests pass; the new tests fail without the source change.

Manual:

  1. mkdir empty-dir && cd empty-dir && npm init -y
  2. npx create-storybook@latest (built from this branch)
  3. Observe the error now mentions --type, followed by the "How would you like to proceed?" prompt; selecting HTML proceeds with the HTML framework install; selecting Cancel exits non-zero.
  4. npx create-storybook@latest --yes in the same dir still fails immediately with a non-zero exit (no prompt).

Checklist

  • Make sure to add/update documentation for your changes (n/a — behavior change is CLI-interactive; docs update for --type html tracked separately per the issue)
  • Make sure to add/update tests for your changes

Summary by CodeRabbit

  • New Features

    • Improved setup flow for projects that can’t be automatically identified.
    • Users can now choose to install the HTML framework, pick another supported framework, or cancel.
    • In non-interactive mode, the process now stops cleanly without prompting.
  • Bug Fixes

    • Undetected projects now return a clear “unrecognized” state instead of failing earlier.
    • Framework detection no longer shows an error until the setup flow needs user input.

@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor
Fails
🚫

PR is not labeled with one of: ["cleanup","BREAKING CHANGE","feature request","bug","documentation","maintenance","build","dependencies"]

🚫

PR is not labeled with one of: ["ci:normal","ci:merged","ci:daily","ci:docs"]

🚫

PR is not labeled with one of: ["qa:needed","qa:skip","qa:success"]

🚫 PR description is missing the mandatory "#### Manual testing" section. Please add it so that reviewers know how to manually test your changes.

Generated by 🚫 dangerJS against 2d27554

@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Project type detection for undetected frameworks moved from ProjectTypeService, which previously threw a HandledError, to ProjectDetectionCommand, which now resolves ProjectType.UNDETECTED and interactively prompts the user to install HTML, select another framework, or cancel, failing immediately in non-interactive mode.

Changes

Undetected Project Type Handling

Layer / File(s) Summary
Service returns UNDETECTED instead of throwing
code/lib/create-storybook/src/services/ProjectTypeService.ts, code/lib/create-storybook/src/services/ProjectTypeService.test.ts
autoDetectProjectType no longer logs an error and throws HandledError when detection fails; it resolves to ProjectType.UNDETECTED, and tests were updated to assert resolution instead of rejection.
Command-level interactive prompt for undetected type
code/lib/create-storybook/src/commands/ProjectDetectionCommand.ts, code/lib/create-storybook/src/commands/ProjectDetectionCommand.test.ts
ProjectDetectionCommand imports HandledError and calls a new promptUndetectedProjectType() when detection is UNDETECTED, which logs the issue, throws in non-interactive mode, or prompts to install HTML/select a framework/cancel; new tests cover all four outcomes.

Estimated code review effort: 2 (Simple) | ~12 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ProjectDetectionCommand
  participant ProjectTypeService

  ProjectDetectionCommand->>ProjectTypeService: autoDetectProjectType()
  ProjectTypeService-->>ProjectDetectionCommand: ProjectType.UNDETECTED
  ProjectDetectionCommand->>ProjectDetectionCommand: promptUndetectedProjectType()
  alt non-interactive (--yes)
    ProjectDetectionCommand->>ProjectDetectionCommand: throw HandledError
  else interactive
    ProjectDetectionCommand->>User: prompt.select(install HTML / choose framework / cancel)
    User-->>ProjectDetectionCommand: selection
    alt cancel or no selection
      ProjectDetectionCommand->>ProjectDetectionCommand: throw HandledError
    else HTML or framework selected
      ProjectDetectionCommand->>ProjectDetectionCommand: proceed with selected ProjectType
    end
  end
Loading

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
code/lib/create-storybook/src/commands/ProjectDetectionCommand.ts (2)

116-119: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate "installable types" filter logic.

This filter (!['undetected','unsupported','nx'].includes(String(t))) duplicates the identical logic already in ProjectTypeService.validateProvidedType (Line 168-170 of ProjectTypeService.ts). Extract this into a shared method on ProjectTypeService (e.g. getInstallableProjectTypes()) so both call sites stay in sync if the excluded set ever changes.

♻️ Proposed refactor
+  getInstallableProjectTypes(): ProjectType[] {
+    return Object.values(ProjectType).filter(
+      (t) => !['undetected', 'unsupported', 'nx'].includes(String(t))
+    );
+  }
+
   async validateProvidedType(projectTypeProvided: ProjectType): Promise<ProjectType> {
-    // Allow only installable types according to core list
-    const installable = Object.values(ProjectType).filter(
-      (t) => !['undetected', 'unsupported', 'nx'].includes(String(t))
-    );
+    const installable = this.getInstallableProjectTypes();
     if (installable.includes(projectTypeProvided)) {
     if (choice === 'select') {
-      const installable = Object.values(ProjectType).filter(
-        (t) => !['undetected', 'unsupported', 'nx'].includes(String(t))
-      );
+      const installable = this.projectTypeService.getInstallableProjectTypes();
       const manualType = await prompt.select(
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@code/lib/create-storybook/src/commands/ProjectDetectionCommand.ts` around
lines 116 - 119, The installable-types filter in ProjectDetectionCommand is
duplicated and should be centralized. Move the exclusion logic from the local
Object.values(ProjectType).filter(...) usage into a shared ProjectTypeService
helper such as getInstallableProjectTypes(), then update both
ProjectDetectionCommand and ProjectTypeService.validateProvidedType to use that
shared method so the excluded project types stay consistent.

120-124: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Raw enum values used as prompt labels.

label: String(t) will render internal enum values (e.g. react_native, sveltekit, web_components) verbatim in the CLI prompt, whereas promptReactNativeVariant above uses hand-crafted, capitalized labels with picocolors.bold. Consider a small display-name map for consistency with the rest of the CLI's presentation quality.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@code/lib/create-storybook/src/commands/ProjectDetectionCommand.ts` around
lines 120 - 124, The prompt in ProjectDetectionCommand is using raw enum strings
as visible labels, so replace String(t) in the prompt.select options with a
small display-name mapping that formats framework names consistently with the
rest of the CLI. Use the existing promptReactNativeVariant approach as the
reference for how labels should be human-friendly and styled, and keep the
underlying value unchanged while only improving the displayed label.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@code/lib/create-storybook/src/commands/ProjectDetectionCommand.ts`:
- Around line 46-51: The React Native variant prompt in ProjectDetectionCommand
is checking the original detected value instead of the updated projectType
selected by the user. Update the conditional in the project detection flow so
the React Native variant check uses projectType after
promptUndetectedProjectType() may have changed it, while keeping the existing
yes-option guard. This fix should be applied in ProjectDetectionCommand where
promptUndetectedProjectType() and promptReactNativeVariant() are used.

---

Nitpick comments:
In `@code/lib/create-storybook/src/commands/ProjectDetectionCommand.ts`:
- Around line 116-119: The installable-types filter in ProjectDetectionCommand
is duplicated and should be centralized. Move the exclusion logic from the local
Object.values(ProjectType).filter(...) usage into a shared ProjectTypeService
helper such as getInstallableProjectTypes(), then update both
ProjectDetectionCommand and ProjectTypeService.validateProvidedType to use that
shared method so the excluded project types stay consistent.
- Around line 120-124: The prompt in ProjectDetectionCommand is using raw enum
strings as visible labels, so replace String(t) in the prompt.select options
with a small display-name mapping that formats framework names consistently with
the rest of the CLI. Use the existing promptReactNativeVariant approach as the
reference for how labels should be human-friendly and styled, and keep the
underlying value unchanged while only improving the displayed label.
🪄 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: 47348798-2ee9-4678-95db-b310d35f77db

📥 Commits

Reviewing files that changed from the base of the PR and between fac05a5 and 2d27554.

📒 Files selected for processing (4)
  • code/lib/create-storybook/src/commands/ProjectDetectionCommand.test.ts
  • code/lib/create-storybook/src/commands/ProjectDetectionCommand.ts
  • code/lib/create-storybook/src/services/ProjectTypeService.test.ts
  • code/lib/create-storybook/src/services/ProjectTypeService.ts

Comment on lines +46 to 51
if (detected === ProjectType.UNDETECTED) {
projectType = await this.promptUndetectedProjectType();
}
if (detected === ProjectType.REACT_NATIVE && !this.options.yes) {
projectType = await this.promptReactNativeVariant();
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the relevant file and surrounding symbols.
ast-grep outline code/lib/create-storybook/src/commands/ProjectDetectionCommand.ts --view expanded

# Show the relevant section with line numbers.
sed -n '1,220p' code/lib/create-storybook/src/commands/ProjectDetectionCommand.ts

# Find the project-type prompt logic and enum values used by the command.
rg -n "promptUndetectedProjectType|promptReactNativeVariant|ProjectType.REACT_NATIVE|REACT_NATIVE_WEB|REACT_NATIVE_AND_RNW|Choose a framework to install|undetected|unsupported|nx" code/lib/create-storybook/src -S

Repository: storybookjs/storybook

Length of output: 15410


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '160,260p' code/lib/create-storybook/src/commands/ProjectDetectionCommand.test.ts
sed -n '1,260p' code/lib/create-storybook/src/services/ProjectTypeService.ts

Repository: storybookjs/storybook

Length of output: 12891


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,160p' code/lib/create-storybook/src/commands/ProjectDetectionCommand.test.ts

Repository: storybookjs/storybook

Length of output: 6164


Use projectType for the React Native variant check
The undetected/manual select flow can return ProjectType.REACT_NATIVE, but this branch still checks the stale detected value, so the variant prompt is skipped there.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@code/lib/create-storybook/src/commands/ProjectDetectionCommand.ts` around
lines 46 - 51, The React Native variant prompt in ProjectDetectionCommand is
checking the original detected value instead of the updated projectType selected
by the user. Update the conditional in the project detection flow so the React
Native variant check uses projectType after promptUndetectedProjectType() may
have changed it, while keeping the existing yes-option guard. This fix should be
applied in ProjectDetectionCommand where promptUndetectedProjectType() and
promptReactNativeVariant() are used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: npm create storybook@latest in framework-less project doesn't work because it can't detect a framework

1 participant