Skip to content

Conversation

@akornmeier
Copy link

@akornmeier akornmeier commented Nov 18, 2025

🚀 Nuxt 3.18.1+ and Nuxt 4+ / Storybook 10+ Support

This pull request introduces major upgrades and breaking changes to support Storybook 10 and Nuxt 4, along with significant improvements to developer experience and dependency management. The update transitions all relevant dependencies, configurations, and documentation to ensure compatibility with the latest ESM-only architecture of Storybook 10 and the new requirements of Nuxt 4. It also adds workarounds for common issues with module pre-bundling, updates ESLint configuration, and refines package build and export settings.

Closes: #963

Key changes include:

Major Breaking Changes and Upgrades

  • Storybook 10 and Nuxt 4 Support: Upgrades all dependencies and peer dependencies to require Storybook 10 (ESM-only) and Nuxt 4, dropping support for Nuxt 3.x and Storybook 9.x. Updates minimum Node.js version to 20.19+. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13]

  • Package and Build System Updates: Refactors the storybook-addon package to use tsdown for building, updates exports for ESM compatibility, and revises bundler entry points for better alignment with Storybook 10's architecture. [1] [2] [3] [4]

Dependency and Configuration Enhancements

  • Vite Pre-bundling Workarounds: Adds viteFinal configuration in example .storybook/main.js files and documents how to pre-bundle critical dependencies to avoid race conditions and module resolution errors during Storybook startup. [1] [2] [3] [4]

  • Example and Playground Updates: Updates all example projects (showcase, starter, tailwind) to use the new Storybook 10 and Nuxt 4 versions, and applies the new Vite and Storybook configuration patterns. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]

Developer Experience and Linting

  • ESLint Storybook Plugin: Integrates eslint-plugin-storybook with recommended settings for improved linting of Storybook files. [1] [2] [3]

Documentation and Migration

  • Comprehensive Changelog and Migration Guide: Documents all breaking changes, upgrade steps, and troubleshooting tips for migrating from previous versions, including known issues with ESM and Vite. [1] [2]

These changes ensure the project is fully compatible with the latest releases of Nuxt and Storybook, improve reliability during development, and provide clear guidance for users upgrading from previous versions.

  - Add full compatibility with Storybook 10's ESM-only architecture
  - Fix errx module MIME type error in Vite dependency optimization
  - Fix Nuxt app manifest 404 errors in Storybook preview
  - Update peerDependencies to require Nuxt 4.0.0+ and Storybook 10.0.0+
  - Add comprehensive migration guide with step-by-step upgrade
    instructions
  - Enhance code documentation for ESM workarounds

  BREAKING CHANGE: Requires Nuxt 4.0.0+, Storybook 10.0.0+, and Node.js
  20.19+/22.12+/24+. Drops support for Nuxt 3.x and Storybook 8/9.

  This message:
  - ✅ Follows conventional commit format (feat:)
  - ✅ Highlights the main feature (Storybook 10 & Nuxt 4 support)
  - ✅ Lists key technical changes
  - ✅ Includes BREAKING CHANGE: footer for major version indication
  - ✅ Matches the repository's existing commit style
  - ✅ Includes the Claude Code attribution as per the project's
    convention
@netlify
Copy link

netlify bot commented Nov 18, 2025

👷 Deploy request for nuxt-storybook pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit d97de4d

@akornmeier
Copy link
Author

Hi @tobiasdiez - I took a shot at adding Storybook 10 and Nuxt 4.2 support to the package. I noticed the 3 failing integration tests had some visual difference errors. I attempted to access the report in the GitHub Action, but it looks to be password-protected. Can I run those locally and get the visual diffs? I am very curious to know what changed.

The other minor detraction I made from the previous versions was using TSDown as the package bundler, in an attempt to resolve the Nuxt 4.2 compatibility issue.

I look forward to any feedback you or any other maintainers may have.

@rpauls-scayle
Copy link

Cheers @akornmeier, thanks for taking on the upgrade. 🙏🏻

Out of curiosity, are there particular technical reason why the upgrade to Storybook v10 needs to be accompanied by raising the minimum supported version to Nuxt v4?

While Nuxt v3 will reach EoL end of January 2026, a portion of projects might not yet have migrated to Nuxt 4. Raising the minimum supported Nuxt version would exclude those projects from benefiting of the Storybook v10 upgrade.

@akornmeier
Copy link
Author

Cheers @akornmeier, thanks for taking on the upgrade. 🙏🏻

Out of curiosity, are there particular technical reason why the upgrade to Storybook v10 needs to be accompanied by raising the minimum supported version to Nuxt v4?

While Nuxt v3 will reach EoL end of January 2026, a portion of projects might not yet have migrated to Nuxt 4. Raising the minimum supported Nuxt version would exclude those projects from benefiting of the Storybook v10 upgrade.

Great question @rpauls-scayle, I will take a look and see if that minimum support can be relaxed back to Nuxt 3 and get back to you. Thanks for your insight!

@akornmeier
Copy link
Author

Cheers @akornmeier, thanks for taking on the upgrade. 🙏🏻
Out of curiosity, are there particular technical reason why the upgrade to Storybook v10 needs to be accompanied by raising the minimum supported version to Nuxt v4?
While Nuxt v3 will reach EoL end of January 2026, a portion of projects might not yet have migrated to Nuxt 4. Raising the minimum supported Nuxt version would exclude those projects from benefiting of the Storybook v10 upgrade.

Great question @rpauls-scayle, I will take a look and see if that minimum support can be relaxed back to Nuxt 3 and get back to you. Thanks for your insight!

@rpauls-scayle - Was able to confirm that Nuxt >= v3.18.1 is compatible with the new version of Storybook. I went ahead and adjusted the Peer dependencies and updated the README.md to reflect the supported versions. Good catch, thanks!

@rpauls-scayle
Copy link

rpauls-scayle commented Nov 21, 2025

Thanks @akornmeier for taking the time to look into Nuxt 3 compatibility.

@akornmeier
Copy link
Author

Hey @chakAs3 @tobiasdiez! 👋 I've submitted a PR and would love to get your feedback on it when you have a chance. Really excited about the @nuxtjs/storybook package and looking forward to using it in my projects. Happy to make any adjustments or help out however I can!

Thanks!

Copy link
Collaborator

@tobiasdiez tobiasdiez left a comment

Choose a reason for hiding this comment

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

Thanks a lot for your work. It's really awesome to have Nuxt 4 and Storybook 10 support, so this is much appreciated.

I have a few comments of mostly very minor nature.

The biggest question mark in my head is about the switch from ubuild to tsdown. This is fine with me in principle, but then we should probably migrate also the nuxt module to it - and not use two different builders. There is also the 'official' successor obuild. @chakAs3 do you have an opinion here?

"@storybook/addon-docs": "9.1.16",
"@storybook/addon-links": "9.1.16",
"storybook": "9.1.16"
"@nuxtjs/storybook": "workspace:*",
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think using workspace here would break the examples in stackblitz, eg https://storybook.nuxtjs.org/examples/basic. Do you happen to know how stackblitz handles workspace dependencies?

Copy link
Author

Choose a reason for hiding this comment

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

Good question, I will look into that. What are your thoughts on changing this to:

"@nuxtjs/storybook: latest",

That would keep the StackBlitz examples up to date w/o a maintenance burden.

Copy link
Author

Choose a reason for hiding this comment

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

These examples will fail in CI due to the changes. We can update the versions back to "@nuxtjs/storybook": "latest" once the packages are bumped and released.

@chakAs3
Copy link
Collaborator

chakAs3 commented Nov 25, 2025

Thanks @akornmeier for the contribution. I already have an open PR (#980) for the Nuxt 4 + Storybook 10 update, with the Windows e2e tests being the only blocker there.

The unbuild → tsdown migration is a separate concern, and it’s better to handle it in its own PR with a clear justification of the switch. @tobiasdiez I’m not sure we should move to a new bundler right now or just stay aligned with the Nuxt ecosystem and keep unbuild. We can always do a proper migration later if it turns out necessary.

  - Upgrade all Storybook packages from 10.0.8 to 10.1.0 - Switch
  storybook-addon build system from tsdown to unbuild - Revert starter
  example configs to TypeScript with proper types - Simplify example
  configs by removing viteFinal workarounds - Add resolveModule helper
  for ESM/CJS compatibility - Add useRouter composable override for
  Storybook context - Pre-bundle React dependencies in Vite config for
  addon-docs
Copilot AI review requested due to automatic review settings November 27, 2025 13:44
Copilot finished reviewing on behalf of akornmeier November 27, 2025 13:49
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request upgrades the Nuxt Storybook module to support Storybook 10 (ESM-only) and Nuxt 4, introducing breaking changes that require Node.js 20.19+ and updates to dependency management, build configuration, and examples.

Key Changes:

  • Upgrades all Storybook dependencies from 9.x to 10.x and updates peerDependencies to reflect minimum supported versions
  • Adds tsdown configuration for improved ESM build output and introduces Vite pre-bundling workarounds to prevent race conditions
  • Updates all example projects (playground, starter, showcase, tailwind) and documentation to reflect new requirements and configuration patterns

Reviewed changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
playground/package.json Updates dependencies to Nuxt 4.2.1, Storybook 10.1.0, and adds eslint-plugin-storybook for improved linting
packages/storybook-addon/tsdown.config.ts Adds new build configuration using tsdown for ESM-compliant output with separate browser and node entry points
packages/storybook-addon/tsconfig.json Updates TypeScript config to include tsdown.config.ts and DOM libraries for browser compatibility
packages/storybook-addon/src/preview.ts Adds re-exports from @storybook/vue3/entry-preview to support Storybook 10's ESM architecture
packages/storybook-addon/src/preset.ts Adds resolveModule helper, disables app manifest feature, pre-bundles React dependencies, and updates core preset paths
packages/storybook-addon/preset.js Changes export from preset.mjs to preset.cjs (potential issue identified)
packages/storybook-addon/package.json Updates Storybook dependencies to 10.1.0, adds preset import export, updates Node engine to 20.19.0, and adds tsdown
packages/nuxt-module/package.json Updates chalk, storybook devDependency, and vite versions for Storybook 10 compatibility
package.json Upgrades ESLint config, test utils, and adds eslint-plugin-storybook to root dependencies
examples/tailwind/package.json Updates Storybook to 10.1.0 but keeps Nuxt at 3.20.1 (inconsistency with other examples)
examples/tailwind/nuxt.config.ts Removes empty line for cleaner formatting
examples/tailwind/.storybook/main.js Reorders configuration to put framework first, consistent with Storybook conventions
examples/starter/package.json Updates to Nuxt 4.2.1 and Storybook 10.1.0 with workspace references
examples/showcase/package.json Updates package name, upgrades dependencies to Nuxt 4.2.1 and Storybook 10.1.0
examples/showcase/nuxt.config.ts Refactors runtimeConfig to use public namespace for client-accessible values
examples/showcase/.storybook/main.js Reorders configuration to put framework first
eslint.config.mjs Integrates eslint-plugin-storybook with recommended flat config settings
docs/package.json Updates Nuxt to 4.2.1 for documentation site
README.md Adds Vite optimization configuration guidance and updates requirements to reflect Nuxt 3.18.1+/4+ and Storybook 10+ support
CHANGELOG.md Documents breaking changes, enhancements, fixes, and migration guide for Storybook 10 and Nuxt 4 upgrade
.github/workflows/e2e.yml Updates STORYBOOK_VERSION environment variable to 10.1.0 for CI testing

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

CHANGELOG.md Outdated

### 🚨 Breaking Changes

- ⚠️ **Requires Nuxt 4.0.0+** - Dropped support for Nuxt 3.x
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

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

The changelog states "Requires Nuxt 4.0.0+" and "Dropped support for Nuxt 3.x", but the peerDependencies in package.json still allow "^3.18.1 || ^4.0.0". This is inconsistent. Either the peerDependencies should be updated to only require Nuxt 4, or this breaking change description should be corrected to reflect continued support for Nuxt 3.18.1+.

Suggested change
- ⚠️ **Requires Nuxt 4.0.0+** - Dropped support for Nuxt 3.x
- ⚠️ **Requires Nuxt 3.18.1+ or 4.0.0+** - Supports Nuxt 3.18.1 and Nuxt 4.0.0 or later

Copilot uses AI. Check for mistakes.
Comment on lines +87 to +90
"pnpm": {
"overrides": {
"@nuxtjs/storybook": "workspace:*"
}
Copy link
Author

@akornmeier akornmeier Nov 28, 2025

Choose a reason for hiding this comment

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

Adds support for local testing of the local packages, while keeping the package explicitly set to @nuxtjs/storybook@latest in the StackBlitz examples/* directories.

@akornmeier
Copy link
Author

@chakAs3 / @tobiasdiez - The PR is ready for review. I reverted the bundler change, made the edits Tobias suggested, and updated e2e.yml to pull local packages from Verdaccio. This allows the use of @latest in the StackBlitz examples and ensures the CI is always working from the latest changes in the packages.

@tobiasdiez
Copy link
Collaborator

Thanks a lot. I went through the reported issues in chromatic, and they are mostly about expected changes (eg nuxt welcome changed in v4).

But the following in showcase > Router: Home looks like a regression indeed:

image

Could you have a look at this well? If not, I try to carve some time free in the next few days.

@chakAs3
Copy link
Collaborator

chakAs3 commented Dec 1, 2025

@akornmeier, thanks for the changes.

I tested this PR locally and found a critical regression in the main Nuxt application. The Nuxt package update within this PR is causing our Storybook module to break the loading of build assets because it fails to resolve necessary virtual files.
image

@tobiasdiez, we need to add some tests against the main Nuxt app to check it is running properly.

@akornmeier
Copy link
Author

@akornmeier, thanks for the changes.

I tested this PR locally and found a critical regression in the main Nuxt application. The Nuxt package update within this PR is causing our Storybook module to break the loading of build assets because it fails to resolve necessary virtual files. image

@tobiasdiez, we need to add some tests against the main Nuxt app to check it is running properly.

@chakAs3 - Thanks for looking into this. I hadn't seen this behavior in the stories. How can I replicate this issue locally? I'll dive into the error and fix it.

@akornmeier
Copy link
Author

Thanks a lot. I went through the reported issues in chromatic, and they are mostly about expected changes (eg nuxt welcome changed in v4).

But the following in showcase > Router: Home looks like a regression indeed:
image

Could you have a look at this well? If not, I try to carve some time free in the next few days.

Thanks for flagging this @tobiasdiez! After investigation, this change from /iframe.html to / is actually expected and correct behavior — not a regression.

What's Happening

The CustomNav.vue component displays the current route path:

<!-- examples/showcase/components/CustomNav.vue -->
<div class="text-center p-4 op-50">
  Current route: <code>{{ route.path }}</code>
</div>

And the "Router: Home" story explicitly navigates to /:

// examples/showcase/components/CustomNav.stories.ts
export const Home: Story = {
  render(args) {
    return {
      setup() {
        useRouter().push('/')  // ← Pushes to root route
        return { args }
      },
      template: '<div><CustomNav /></div>',
    }
  },
}

Why the Old Behavior Was Incorrect

Behavior route.path Explanation
Old /iframe.html Nuxt's router was leaking Storybook's container URL
New (this PR) / Router correctly reflects the pushed route

The old behavior showed /iframe.html because the Nuxt router wasn't properly isolated — it was seeing the actual browser URL (Storybook renders stories in an iframe at /iframe.html).

With this PR, the vue-router instance inside Storybook is correctly isolated, so useRoute().path returns the route that the story navigated to (/), not Storybook's iframe URL.

Documentation References

Summary

This Chromatic diff shows the router integration is now working correctly. The visual change is expected and represents a fix rather than a regression.

@akornmeier
Copy link
Author

@akornmeier, thanks for the changes.
I tested this PR locally and found a critical regression in the main Nuxt application. The Nuxt package update within this PR is causing our Storybook module to break the loading of build assets because it fails to resolve necessary virtual files. image
@tobiasdiez, we need to add some tests against the main Nuxt app to check it is running properly.

@chakAs3 - Thanks for looking into this. I hadn't seen this behavior in the stories. How can I replicate this issue locally? I'll dive into the error and fix it.

@chakAs3 - I think I found the culprit:

Root Cause: Storybook was starting during Nuxt's module setup() phase, before Nuxt's HTTP server was listening. When Storybook's proxy tried to connect to localhost:3000, it failed with EAGAIN errors.

Fix: Defer Storybook startup to the listen hook:

// packages/nuxt-module/src/module.ts
nuxt.hook('listen', () => {
  setupStorybook(options, nuxt)
})

I also added an integration test to help detect this behavior and prevent regressions in the future.

Moves Storybook initialization from module setup to the 'listen' hook, ensuring Nuxt's HTTP server is ready before Storybook's proxy attempts to connect. This fixes EAGAIN proxy errors for /_nuxt/* requests.

- Resolves virtual file resolution errors reported in nuxt-modules#981
- Storybook proxy now reliably connects to Nuxt dev server
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Storybook 10 support

4 participants