storybook icon indicating copy to clipboard operation
storybook copied to clipboard

feat!: add Storybook 10 and Nuxt 4 support

Open akornmeier opened this issue 1 month ago β€’ 15 comments

This pull request introduces full support for Storybook 10 and Nuxt 4, along with several breaking changes and enhancements to the Nuxt Storybook integration. The updates include ESM-only compatibility, revised documentation, major dependency upgrades, and improvements to the build process and developer experience.

Storybook 10 and Nuxt 4 Support

  • Added full compatibility with Storybook 10's ESM-only architecture and Nuxt 3.x/4.x, including documentation updates and breaking change notices. [1] [2] [3] [4] [5]

Dependency and Example Updates

  • Upgraded all relevant dependencies and peer dependencies to support Storybook 10.x and Nuxt 4.x across the main module, examples, and documentation. This includes changes in package.json, example app package.json files, and workflow scripts. [1] [2] [3] [4] [5] [6] [7]

Build and Module Improvements

  • Refactored the build configuration for the Nuxt module to use unbuild, re-exported Storybook preset/preview, and improved type exports for better ESM/CJS compatibility and developer experience. [1] [2] [3] [4] [5]

Developer Experience and CI Enhancements

  • Improved the end-to-end workflow for local publishing and testing with Verdaccio, including more robust registry handling and project initialization steps.

Breaking Changes and Migration Notes

  • Updated documentation and changelogs to highlight breaking changes (e.g., Node.js 20.19+ requirement, Storybook 10.x ESM-only), and provided guidance for users of previous Storybook/Nuxt versions. [1] [2] [3]

Other Notable Changes

  • Deferred Storybook startup in the Nuxt module until the Nuxt HTTP server is ready for improved reliability.
  • Updated example and showcase configurations for consistency with new Storybook/Nuxt versions and best practices. [1] [2] [3] [4] [5]

These changes collectively modernize the Nuxt Storybook integration, ensure compatibility with the latest ecosystem releases, and improve the onboarding and usage experience for developers.

akornmeier avatar Nov 18 '25 17:11 akornmeier

Deploy request for nuxt-storybook pending review.

Visit the deploys page to approve it

Name Link
Latest commit d97de4dd7833e8e8372659b9eca44f36f8e0d7ed

netlify[bot] avatar Nov 18 '25 17:11 netlify[bot]

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.

akornmeier avatar Nov 19 '25 12:11 akornmeier

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.

rpauls-scayle avatar Nov 20 '25 12:11 rpauls-scayle

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 avatar Nov 20 '25 12:11 akornmeier

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!

akornmeier avatar Nov 20 '25 16:11 akornmeier

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

rpauls-scayle avatar Nov 21 '25 13:11 rpauls-scayle

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!

akornmeier avatar Nov 24 '25 13:11 akornmeier

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.

chakAs3 avatar Nov 25 '25 15:11 chakAs3

@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.

akornmeier avatar Nov 29 '25 12:11 akornmeier

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.

tobiasdiez avatar Nov 29 '25 19:11 tobiasdiez

@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 avatar Dec 01 '25 18:12 chakAs3

@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 avatar Dec 03 '25 16:12 akornmeier

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

  • https://nuxt.com/docs/4.x/api/composables/use-route: Documents that route.path returns "the encoded pathname section of the URL" β€” this should reflect the application's route, not the browser's iframe URL.
  • https://storybook.js.org/docs/configure/story-rendering: Explains that "stories render in a particular 'preview' iframe... inside the larger Storybook web application" β€” the router should be isolated within this preview context.
  • https://router.vuejs.org/api/interfaces/RouteLocationNormalizedLoaded.html: The underlying vue-router type that defines path as the route's pathname.

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 avatar Dec 03 '25 18:12 akornmeier

@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.

akornmeier avatar Dec 03 '25 20:12 akornmeier

@chakAs3 / @tobiasdiez - Is there anything else you would like me to test or any other release-related tasks needed for this PR?

akornmeier avatar Dec 08 '25 18:12 akornmeier