PackageTrack

npm · #4082

@nuxt/kit

4.5.2nuxt/nuxt

Toolkit for authoring modules and interacting with Nuxt

Release timeline

151 releases since 2021
20222023202420252026

Releases

  1. 4.5.25 Aug 2026
    Release notes

    4.5.2 is the next patch release.

    👉 Changelog

    compare changes

    🔥 Performance

    • nuxt,kit: Skip rewriting unchanged generated files (#35902)
    • kit,nuxt: Use lazy imports to improve parsing speed (#35901)
    • vite: Skip html entry probes in bare-import resolver (#35907)
    • nuxt: Reuse app and component scans for unchanged structures (#35912)

    🩹 Fixes

    • vite: Resolve client manifest path from resolved config (#35883)
    • nuxt: Use client-side navigation for links inside islands (#35806)
    • nuxt: Generate types for route params defined with definePageMeta (#35857)
    • nuxt: Serialize island payloads for components with underscores in keys (#35807)
    • nitro: Dedupe island renders when prerendering (#35835)
    • nuxt: Drop prefetch hints for never-hydrated chunks (#35812)
    • vite: Use same asset filenames for worker builds (#35866)
    • nitro: Reject non-object island props (#35867)
    • nuxt: Support options api in v-for islands transform (#35877)
    • nuxt: Improve page meta extraction + performance (#35869)
    • nuxt: Set build outputs when restoring vue cache (#35895)
    • kit: Honour nested apply and applyToEnvironment in vite wrapper (#35899)
    • nuxt: Re-check for preview mode after prerendered page hydration (#35886)
    • kit,nuxt,vite: Handle missed chokidar watch events (#35887)
    • nuxt: Settle asyncData status when bailing (#35908)
    • kit: Clone resolved config with klona rather than klona/full (#35914)
    • kit: Honour nested plugins' enforce in vite wrapper (#35916)
    • nuxt: Collect build cache once build outputs are final (#35929)
    • vite: Resolve vite env api sourcemaps in vite-node (#35758)
    • nuxt: Don't warn about missing <NuxtPage> on nav + with slot (#35948)
    • kit: Prepend vite environment wrapper plugin when prepend is set (#35942)
    • nuxt: Depend on rolldown as a peer to reuse vite's copy (3fda97f60)
    • nitro: Define import.meta.test for server code (#35987)
    • nuxt: Match route rules against decoded paths (9123ed850)

    💅 Refactors

    • nuxt: Use vue-component-type-helpers instead of locally maintained helpers (#35840)
    • nuxt: Use isReferenceIdentifier in page-meta plugin (#35882)

    📖 Documentation

    • Sync mcp server page with live tools and providers (#35856)
    • Add server components guide and mostly-static site recipe (#35778)
    • Minor changes (#33479)
    • Add accessible routing guide (#34796)
    • Update testing guide to test-utils v4.1.0 (#35873)
    • Update .env provider reference from dotenv to c12 (#35911)
    • Add note to avoid using defineVitestProject in e2e tests (#35926)
    • Update roadmap (f6e6027fe)

    📦 Build

    • ui-templates: Copy generated templates from resolved output dir (#35921)

    🏡 Chore

    ✅ Tests

    • Skip webpack dev tests for island v-for transform (73030e55a)
    • Add regression test for #35893 (#35893)
    • vite: Cover windows drive letters in toFsUrl (a5ad667f7)

    🤖 CI

    • Shard the critical-path test jobs and cache playwright (#35832)
    • Add action to notify issues resolved on release (5fffe5718)
    • Make notification script more resilient (5337bd357)
    • Do not comment on issues in other repos (400dfdc11)
    • Add explicit permissions: {} to workflows (2e1a1cbeb)
    • Rebalance windows e2e matrix (dffe13742)
    • Let contributors know prs are backported (3e416c54f)
    • Regenerate templates in autofix job (95d33637f)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Matej Černý (@cernymatej)
    • Aubakirov Asker (@Askerka00)
    • Yoshihiro Yamaguchi (@yamachi4416)
    • Samuel Burkhard (@samydoesit)
    • Kenneth Sills (@Kenneth-Sills)
    • Spunkie (@Spunkie)
    • Bochkarev Ivan (@Ibochkarev)
    • Amulet Iris (@KazariAI)
    • Yash Bavadiya (@xevrion)
    • Alexander Lichter (@TheAlexLichter)
    • Mehraz Morshed (@mehrazmorshed)
    • mcrapts (@mcrapts)
    • Benjamin Canac (@benjamincanac)
    • Anthony Fu (@antfu)
    Open source →
  2. 4.5.127 Jul 2026
    Release notes

    ⚠️ This is a security release. We recommend upgrading as soon as possible with npx nuxt upgrade --dedupe.

    It fixes server-side RCE and unauthorized component instantiation via server island props, a route rule authorization bypass, server component DoS, cross-user payload disclosure on cached pages, and dev server path disclosure. Refreshing your lockfile also pulls in @nuxt/[email protected], which fixes a separate critical development-only RCE.

    If you already upgraded for the earlier route rule advisory (CVE-2026-53721), you still need this release: one of the fixes addresses a regression introduced by that fix.

    If you use the cache, swr or isr route rules, purge any CDN or edge cache after upgrading; a leaked _payload.json may already be cached upstream.

    Full details: Nuxt Security Patch Releases and GitHub Security Advisories.

    👉 Changelog

    compare changes

    🔥 Performance

    • nitro: Replace island teleports in a single html pass (#35515)
    • nuxt: Add vue.optionsApi and disable it for v5+ (#35791)
    • nuxt: Without pages, skip client plugins that require routing (#35794)
    • nuxt: Skip payload revival plugin when ssr: false (#35782)

    🩹 Fixes

    • nitro: Read rspack dev output fs lazily for server entry (#35740)
    • rspack,webpack: Resolve loaders and runtime deps from nuxt dirs (#35568)
    • nuxt: Return global route for useRoute in detached effect scope (#35659)
    • nuxt: Ignore custom name or path when reusing an existing page in pages:extend (#35661)
    • nuxt: Render client components in nested server components (#35669)
    • nuxt: Preserve explicit useFetch method inference (#35671)
    • nuxt: Revalidate cached route payloads instead of using force-cache (#35672)
    • nuxt: Correct default export detection in plugin metadata (#35676)
    • nuxt: Clear hide/reset timeouts in set() (#35534)
    • kit,nuxt,rspack,schema,webpack: Add .mts file extension in resolver (#33845)
    • nuxt: Preserve trailing slash in NuxtLink href when unset (#35501)
    • nuxt: Don't cross-pollute useAsyncData cache on reactive key change (#35656)
    • nuxt: Filter plugin dependencies by build target (#35682)
    • nuxt: Reload real page module on HMR of JSX render-function pages (#35678)
    • nuxt: Resolve @unhead/vue/* from nuxt's dependency tree (#35690)
    • kit: Surface module load errors instead of masking as missing (#35497)
    • nuxt: Type auto-imported $fetch with nitro's $Fetch (#35704)
    • nuxt: Don't reference app config sources in shared and node tsconfigs (#35673)
    • vite: Resolve SSR inlined CSS module class name mismatch (#35610)
    • nuxt: Generate layout types even when pages module is disabled (#35717)
    • nitro: Skip resource hints for stylesheets already rendered as blocking links (#35691)
    • kit: Dedupe layers that are both auto-scanned and explicitly extended (#35712)
    • nuxt: Don't apply scroll behaviour after a subsequent nav (#35719)
    • vite: Ensure server sourcemap-preserver plugin actually runs (#35680)
    • vite: Preserve css suffix when extracting ssr inline styles (#35714)
    • nuxt: Watch external component directories in development (#35652)
    • nuxt: Don't exclude client entry module from style extraction (#35720)
    • nuxt: Amend cleanup command in NUXT_B7014 error message (#35735)
    • nuxt: Only pull in vue-router when there are island pages (#35739)
    • vite: Suppress external warnings for internal vite-node paths (#35744)
    • nuxt: Use scope-aware oxc parser for auto-imports (#35743)
    • nuxt: Sync layout meta during middleware on SSR (#35633)
    • nitro: Add alias for h3 that pins it to the version nuxt depends on (#35774)
    • nuxt: Preserve query params in cached payload extraction (#35696)
    • nuxt: Mirror runtime route tree in generated typed-router types (#35788)
    • nuxt: Warn when an imports preset from cannot be resolved (#35799)
    • kit: Avoid mutating layer configs when resolving options (#35729)
    • nuxt: Convert inline route rules exactly or drop with a warning (#35455)
    • nitro,nuxt,vite: Dedupe and normalise global css links in dev (#35834)
    • vite: Register template HMR plugin on dev servers (929c6c138)
    • nuxt: Remove dev error overlay when error is cleared (#35821)
    • rspack,webpack: Resolve bundled postcss defaults from builder (#35823)
    • schema: Normalise slashes in app.buildAssetsDir (#35833)
    • nitro: Bound island props and v-for to prevent unauthenticated DoS (4e35ae9ba)
    • nitro: Confine runtime payload cache to prerendering (ac9b41a36)
    • nuxt: Case-fold route rule keys to match folded lookups (ad624a75a)
    • nitro: Require loopback peer for chrome devtools workspace endpoint (0769c4f9b)
    • nuxt: Reject reserved template island prop under runtime compiler (ee6c84633)
    • nuxt: Reject top-level as prop for islands (581651ff3)

    💅 Refactors

    • nuxt: Use tick based debounce for asyncData executes (#34151)
    • kit,nuxt: Replace semver with verkit (#35713)
    • rspack,webpack: Use DI model to split builders (#35751)

    📖 Documentation

    • Add dev container setup guide (#35665)
    • Fix dev container setup guide (#35666)
    • Add explanation of 200.html and 404.html SPA fallbacks (#34483)
    • Expand payload extraction documentation (#35648)
    • Clarify NuxtLink componentName is the internal (devtools) name (#35658)
    • Add example for components dir pattern option (#35663)
    • Require a single root element (#35677)
    • Add reason for why you should never import Vue app code in nitro code (#34481)
    • Document disabling code-splitting with codeSplitting: false (#35683)
    • Document nuxt-client caveat for non-SFC components (#35654)
    • Clarify favicon does not use cdnURL by default (#35681)
    • Standardize section order and headings across docs (#35685)
    • Clarify onPrehydrate example comment (#35684)
    • Add useId as a known limitation of nuxt island (#35693)
    • Recommend status over pending in data fetching (#35694)
    • Fill gaps in API minimalVersion badges after #34485 (#35708, #34485)
    • Explain dynamic asset paths (#35695)
    • Document runtimeConfig env var casting edge cases (#35709)
    • Clarify module dependency resolution (#35718)
    • Add more writing guidelines (#35662)
    • Add note with alternatives to using remote layers (#35721)
    • Use nuxt rather than nuxi (8891e179c)
    • Document relative baseURL workarounds (#34004)
    • Warn about runtimeCompiler security best practices (449b63ab1)
    • Warn about validating server component props (2c981cb07)

    📦 Build

    • nitro: Re-export type from augments to preserve module (dac937675)
    • nuxt: Remove .ts file extension from runtime/ imports (#35689)
    • ui-templates: Commit generated ui template files (#35770)

    🏡 Chore

    • Add extension 🤦 (d595fb3d4)
    • Move to pnpm catalogs (#35748)
    • Update knip config, resolve issues, and run in ci (#35742)
    • Ignore @nuxt/telemetry in knip (9824d4f10)
    • ui-templates: Pass config file path to unocss (34e7a810d)
    • Allow regenerating lockfile in release script (c31389df3)
    • nuxt: Bump @nuxt/devtools to v3.3.1 (#35815)
    • Ensure types are setup before unit tests (784d8f700)
    • Simplify knip configuration (#35827)

    ✅ Tests

    • Reproduce duplicate CSS in shared chunks (#35649)
    • Prepare fixtures automatically before fixture and e2e runs (e8b3e6411)
    • Improve and refactor basic fixture (#35687)
    • Slim down client-only, chunk-error and axis-independent suites (#35706)
    • Do not run type checking when benchmarking nuxt build (6355f3bc9)
    • kit: Scope loadNuxt temp dir so it doesn't delete sibling fixtures (37301dd51)
    • Guard against transient undefined _route in gotoPath (ca92d082b)
    • Retry fixture prepare on transient ENOTEMPTY (3a6b59f96)
    • Raise route-HMR polling timeout to reduce e2e flakiness (01dc27b7e)
    • Update bundle size snapshot (30d24817c)

    🤖 CI

    • Rebalance shards and drop non-vite windows fixtures (#35700)
    • Warm windows dependency cache on main (#35730)
    • Run knip in default and production modes (#35745)
    • Run knip on pull requests (d620aa972)
    • Prepare tests (c7bf7f738)
    • Also prepare tests in knip job (58f68bd64)
    • Check internal docs links on pull requests and all links weekly (#35767)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Lars Kappert (@webpro)
    • Matej Černý (@cernymatej)
    • Anthony Fu (@antfu)
    • Harlan Wilton (@harlan-zw)
    • Florian Heuberger (@Flo0806)
    • Anoesj Sadraee (@Anoesj)
    • Ryota Watanabe (@wattanx)
    • Alexander Lichter (@TheAlexLichter)
    • Nestor Vera (@hacknug)
    • Mateleo (@Mateleo)
    • Kevin Deng (@sxzz)
    • Robin (@OrbisK)
    • Bochkarev Ivan (@Ibochkarev)
    • Quentin Macq (@quentinmcq)
    • Julien Huang (@huang-julien)
    • Max (@onmax)
    • Luke Nelson (@luc122c)
    • Darlan José Batista do Prado (@DarlanPrado)
    • kealan (@KealanAU)
    • Sushant (@sushantguri)
    • raminjafary (@raminjafary)
    • Aubakirov Asker (@Askerka00)
    • lutejka (@lutejka)
    • Amulet Iris (@KazariAI)
    • bdbch (@bdbch)
    • Elecmonkey (@elecmonkey)
    Open source →
  3. 4.5.018 Jul 2026
    Release notes

    4.5.0 is the next minor release.

    📣 Some News

    Preparing for Nuxt 5

    A good chunk of this release is (hopefully) invisible plumbing for Nuxt 5. We've moved onto the latest major versions of several core dependencies (unhead v3, unctx v3, and Vite 8), switched the framework's own build over to tsdown, and introduced a stable nuxt/* build output contract with dev exports so that type-checking in the Nuxt monorepo works without a build step (#35463, #35605).

    Much of this is working to shrink the gap between v4 and v5 internally, so that the migration will be as boring as possible.

    [!TIP] If you want to test some of the breaking changes of Nuxt v5, you can already opt in with future.compatibilityVersion: 5. Keep an eye on the Upgrade Guide for details as they land.

    With the release of Nuxt v4.5, our focus as a team will turn to stabilising Nuxt v5 and creating compatibility utilities to make the upgrade as smooth as possible.

    Nuxt 3 End-of-Life

    Nuxt 3 reaches end-of-life on July 31, 2026, so this is one of the last few 3.x releases we'll ship. If you're still on v3, now is a great time to move across. Most people told us the v3 to v4 upgrade was smooth, and we've kept the upgrade guide up to date.

    Alongside v4.5.0 we're publishing a maintenance patch for the 3.x line (v3.21.9) with the compatible bug fixes and smaller improvements from this release backported. The headline items here (Vite 8, Rspack 2, unhead v3, unctx v3) are major upgrades and stay v4-only, so 3.x remains stable as it approaches end-of-life.

    👀 Highlights

    Nuxt 4.5 is a big one. This release ships three major upgrades to the build layer (Vite 8, Rspack 2, and a brand new Rsbuild-powered pipeline for the Rspack builder), an experimental SSR streaming mode, a handful of new composables and conventions, and a lot of groundwork that brings us closer to Nuxt 5.

    There's a lot here, so grab a coffee. ☕️

    ⚡️ Vite 8

    Nuxt now runs on Vite 8 (#34256). This brings faster cold starts, the latest Rolldown-powered internals, and many upstream improvements from the Vite team.

    For most apps this is a transparent upgrade. If you have custom Vite plugins or config, it's worth skimming the Vite migration guide to check for anything that affects you.

    [!WARNING] Vite 8 is a major version bump. If you depend on Vite directly (custom plugins, vite.config tweaks, or ecosystem plugins that pin a Vite version), make sure those are compatible before upgrading in production.

    🦀 Rspack 2 and Rsbuild

    If you use the Rspack builder, this release is a substantial upgrade. We've moved to Rspack 2 (#34929), which is faster and lighter, and rebuilt the builder on top of @rsbuild/core (#35489).

    The public surface stays the same. You still opt in with builder: 'rspack' and the existing rspack:* hooks continue to work:

    // nuxt.config.ts
    export default defineNuxtConfig({
      builder: 'rspack',
    })
    

    Under the hood, though, a lot has changed for the better:

    • The dev server now runs in middleware mode via Rsbuild, replacing webpack-dev-middleware and webpack-hot-middleware (#35575).
    • We use an Rspack-specific Vue loader for correct SSR scoped-style ids and stricter ESM resolution (#35566).

    [!NOTE] This is the foundation for first-class Rsbuild support. We kept the builder named rspack for now so nothing breaks, but the internals are now Rsbuild all the way down.

    🌊 Experimental SSR Streaming

    This is one I'm particularly excited about. You can now enable SSR streaming to dramatically improve Time to First Byte (#34411). Instead of buffering the whole rendered page and sending it in one go, Nuxt flushes the HTML shell (your <head>, styles, preload hints, and entry scripts) immediately, then streams the body as Vue renders it.

    // nuxt.config.ts
    export default defineNuxtConfig({
      experimental: {
        ssrStreaming: true,
      },
    })
    

    Streaming is automatically disabled for bots and crawlers so search engines still receive fully-rendered HTML. You can tune which user agents count as crawlers, and you can opt individual routes out:

    // nuxt.config.ts
    export default defineNuxtConfig({
      experimental: {
        ssrStreaming: {
          botRegex: /googlebot|bingbot|my-internal-crawler/i,
        },
      },
      routeRules: {
        '/no-stream/**': { streaming: false },
      },
    })
    

    There's one thing worth understanding before you turn it on. Because streaming commits the HTTP status and headers with the very first byte, anything that mutates the response after rendering has begun (a setResponseStatus() in a <script setup>, a cookie write during middleware, and so on) can't reach the client. Nuxt handles the common cases for you: routes with redirect, cache, isr, swr, noScripts, or ssr: false rules automatically fall back to the buffered renderer, and in development we log a warning naming any dropped mutations so nothing fails silently.

    [!WARNING] SSR streaming is experimental and off by default. It could be great for content-heavy routes where TTFB matters, but test it against your app's response-mutating logic (status codes, headers, cookies) before shipping it widely. The experimental features docs cover the fallback rules and caveats in detail.

    📖 SSR streaming documentation

    🩺 Stable Error Codes

    This one I'm really happy about. Nuxt now has a stable error code system (#35429). Warnings and errors raised during build and at runtime now carry a stable code (like NUXT_E1001 or NUXT_B5001), a short explanation of why it happened, and a concrete fix to try.

    Every code is greppable and bookmarkable, and the ones that need more than a one-line fix link straight to a dedicated docs page. For example, the classic "a composable was called outside a Nuxt context" now surfaces as NUXT_E1001 with the why/fix inline and a docs page explaining the context rules and how to use runWithContext().

    To keep production output lean, the verbose why/fix text is stripped from production builds, leaving just the stable code.

    This is the foundation for much better error messages across Nuxt, and we'll keep migrating existing warnings and errors onto it over the coming releases. If you've ever squinted at a cryptic Nuxt message, this is for you.

    🎨 useLayout Composable

    There's a new useLayout composable for reading the layout that's been resolved for the current route (#35623). Previously there was no clean, reactive way to ask "which layout is this page using?" from within a component.

    <!-- app/components/LayoutBadge.vue -->
    <script setup lang="ts">
    const layout = useLayout()
    </script>
    
    <template>
      <span>Current layout: {{ layout }}</span>
    </template>
    

    It returns a read-only computed ref, so it stays in sync as you navigate or as route rules and definePageMeta change the resolved layout.

    📖 useLayout documentation

    🪟 Named Views

    Nuxt now supports named views through a filename convention (#35123). If a parent page renders more than one <NuxtPage> outlet, you can give each outlet a name and provide a sibling page file for it using the [email protected] convention:

    # Directory Structure
    -| pages/
    ---| parent/
    -----| child.vue
    -----| [email protected]
    ---| parent.vue
    
    <!-- pages/parent.vue -->
    <template>
      <div>
        <NuxtPage />
        <aside>
          <NuxtPage name="sidebar" />
        </aside>
      </div>
    </template>
    

    Navigating to /parent/child renders child.vue into the default outlet and [email protected] into the sidebar outlet. This has actually been possible in Vue Router for a long time; this release wires it up to Nuxt's file-based routing.

    [!NOTE] definePageMeta is read from the default route file only, and per-view rendering modes aren't supported (the parent page's mode applies to the default view).

    📖 Named views documentation

    🚦 enabled Option for useFetch and useAsyncData

    You can now gate data fetching with a reactive enabled option (#33260). While enabled is false, every execution is blocked (the initial fetch, execute/refresh, and watch triggers), and if you flip it from true to false mid-flight, the in-flight request is cancelled without clearing your existing data.

    <script setup lang="ts">
    const query = ref('')
    
    const { data } = await useFetch('/api/search', {
      query: { q: query },
      // Only fetch once the user has typed something
      enabled: () => query.value.length > 2,
    })
    </script>
    

    This is perfect for dependent or conditional queries, where you don't want to fire a request until some precondition is met. It pairs naturally with a getter or a ref, so it stays reactive.

    📖 useAsyncData documentation

    🔗 NuxtLink Prefetch Control for Custom Slots

    When you use <NuxtLink> with the custom prop, Nuxt no longer attaches prefetch handlers for you, because it can't know how you've structured your markup. To make that ergonomic, the slot now exposes everything you need to wire prefetching up yourself (#34539):

    <template>
      <NuxtLink
        v-slot="{ href, navigate, prefetch, prefetched, shouldPrefetch }"
        to="/about"
        custom
      >
        <a
          :href="href"
          :class="{ 'is-prefetched': prefetched }"
          @click="navigate"
          @pointerenter="shouldPrefetch('interaction') && prefetch()"
          @focus="shouldPrefetch('interaction') && prefetch()"
        >
          About page
        </a>
      </NuxtLink>
    </template>
    

    You get prefetch to trigger it, prefetched to know whether it's already happened (great for a prefetched class), and shouldPrefetch to respect the user's connection and config.

    📖 NuxtLink documentation

    ⚡️ Forwarded Preload Hints on Prefetch

    Here's another one we'd love you to try. When you prefetch a link to a route with payload extraction, Nuxt already primes the destination's data and chunks. With the new opt-in experimental.prefetchPreloadTags (#35144), it also forwards the destination's <link rel="preload"> and modulepreload hints (whatever the page sets via useHead, or via modules like @nuxt/image's <NuxtImg preload>) into the current document, downgraded to rel="prefetch" so they don't compete with the resources the user is looking at right now.

    // nuxt.config.ts
    export default defineNuxtConfig({
      experimental: {
        prefetchPreloadTags: true,
      },
    })
    

    The practical effect is that heavy above-the-fold assets on the next page (a hero image, a critical script) start downloading while the user is still on the current one, so the navigation feels instant. It's off by default while we gather feedback, so please give it a spin and tell us how it behaves on your app.

    🌐 import.meta.envName

    The resolved Nuxt environment name is now available at runtime as import.meta.envName for both Vite and webpack/Rspack builds (#34844). This is the value set by --envName (or the resolved default), so you can branch on it in your app code:

    if (import.meta.envName === 'staging') {
      // enable staging-only behaviour
    }
    

    📖 import.meta documentation

    🔭 Tracing Channels for SSR Events

    Nuxt now publishes diagnostics-channel traces for its server-side subsystems (#35191). It's unopinionated: we emit nuxt.render, nuxt.island, nuxt.data, and nuxt.plugin channels following the untracing naming convention, and you can build OpenTelemetry (or anything else) on top. It works in Node, Deno, Bun, and Cloudflare Workers.

    // nuxt.config.ts
    export default defineNuxtConfig({
      // Turn on Nuxt's own channels
      tracingChannel: true,
    })
    

    You can also enable it granularly. In Nuxt v5, there will be additional Nitro-level channels:

    // nuxt.config.ts
    export default defineNuxtConfig({
      tracingChannel: {
        nuxt: true,
      },
    })
    

    [!NOTE] Channel names, payload shapes, and option keys may still change while the untracing registry settles.

    📦 Dependency Upgrades

    unhead v3

    Nuxt's head management now runs on unhead v3 (#34793). It's smaller, uses a synchronous engine internally, and ships better type-safety for useHead out of the box. This also unblocks SSR streaming.

    [!WARNING] unhead v3 introduces type-narrowing for useHead, which can be a breaking type change if you were relying on the looser v2 types. The runtime behaviour is compatible for the vast majority of apps, and promise input (deprecated in v2) is no longer supported. If you hit type errors after upgrading, they're almost always genuine tightening rather than regressions.

    unctx v3

    We've moved to unctx v3 (#35541), which resolves a class of long-standing async context issues (#33644). This is part of the composable-context reliability work that continues into v5.

    And more

    We've also updated magic-string to v1, Babel to v8, and pulled in the latest Rolldown across the board. Running nuxt upgrade --dedupe (see below) is the easiest way to pull these through cleanly.

    🛠️ Nuxt CLI

    This release bundles some improvements from @nuxt/cli v3.36 and v3.37:

    • nuxt module remove to uninstall a module and clean up its config (nuxt/cli#1306), the natural companion to nuxt module add.

    • Non-interactive nuxt init for scripting and CI (nuxt/cli#1341), plus it now respects the template's own package manager instead of prompting (nuxt/cli#1330).

    • Type-check onboarding: nuxt typecheck now offers to install vue-tsc and typescript for you if they're missing (nuxt/cli#1316).

    • Golar support for type-checking: nuxt typecheck can now use Golar as an alternative to vue-tsc (nuxt/cli#1362). It's picked up automatically if it's installed (or a golar.config.* file exists), and you can force a checker with --checker=vue-tsc or --checker=golar:

      nuxt typecheck --checker=golar
      
    • Layer-aware dev server: the dev server now reloads on changes to local layer nuxt.config files (nuxt/cli#1345).

    🧩 TypeScript Plugin and Named Layout Slots

    Nuxt's experimental TypeScript plugin is powered by @dxup/nuxt, and this release bundles a newer version of it. If you haven't tried it, turning on experimental.typescriptPlugin gives you a set of editor niceties: renaming an auto-imported component updates every usage, plus go-to-definition for glob imports, Nitro routes, definePageMeta, runtimeConfig, and typed route names.

    New in the bundled version is an opt-in runtime feature: named layout slots (KazariEX/dxup#20). You can write a top-level named-slot template in a page and have it forwarded into the matching named slot of the active layout. That lets a page inject content into its layout's slots, which file-based layouts don't otherwise allow.

    Enable it alongside the plugin:

    // nuxt.config.ts
    export default defineNuxtConfig({
      experimental: {
        typescriptPlugin: true,
      },
      dxup: {
        features: {
          namedLayoutSlots: true,
        },
      },
    })
    

    Then a layout can expose named slots:

    <!-- layouts/center.vue -->
    <template>
      <slot />
      <slot name="side" one="one" />
    </template>
    

    And any page using that layout can fill them:

    <!-- pages/about.vue -->
    <script setup lang="ts">
    definePageMeta({ layout: 'center' })
    </script>
    
    <template>
      <template #side="{ one }">
        This "{{ one }}" comes from the layout slot.
      </template>
      <div>About page</div>
    </template>
    

    📖 typescriptPlugin documentation

    🔥 Performance and Reliability

    As always, a lot of work has gone into making Nuxt faster and steadier.

    One you can opt into today is the shared file watcher (#35143). Vite already runs a chokidar-based watcher, so Nuxt can piggy-back on it instead of spinning up a second one, using less memory and fewer file handles. This becomes the default with compatibilityVersion: 5, but you can turn it on now and let us know how it goes:

    // nuxt.config.ts
    export default defineNuxtConfig({
      experimental: {
        watcher: 'builder',
      },
    })
    

    There are also some other good performance improvements that don't need to be opted into:

    • Faster dev startup: dev-only Nitro and pages work is now deferred and streamlined (#35381, #35383).
    • Leaner production builds: the island-renderer chunk is skipped entirely when you use no islands (#35456), and plugin handling is tree-shaken out of prod builds (#35278).
    • Improved island hashing: more stable island and key hashing, with getIslandHash and hashKey now exposed (#35583).
    • Concurrency and I/O wins across Kit path resolution and Nitro inline styles (#35511, #35514).

    A couple of other nice quality-of-life fixes:

    • $fetch is now auto-imported in user code, which fixes edge cases with top-level $fetch.create under Rolldown's output format (#35581).
    • Nuxt now honours system HTTP_PROXY / HTTPS_PROXY environment variables in the builder environment (#35183).
    • HMR now works for defineNuxtComponent in JSX (#35620).

    ⚠️ Heads-Up Before Upgrading

    As mentioned above, this release includes three major dependency bumps. For most apps they're transparent, but they're worth a moment of attention:

    • Vite 8: check custom Vite plugins and config against the Vite migration guide.
    • Rspack 2: if you use builder: 'rspack', the internals are now Rsbuild-based, so custom Rspack config may need review.
    • unhead v3: possible breaking type changes from stricter useHead typing.

    ⬆️ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe
    
    # or, if you are staying on the 3.x line
    npx nuxt@latest upgrade --dedupe --channel=v3
    

    This will deduplicate your lockfile and help ensure you pull in updates from the other dependencies Nuxt relies on, particularly across the unjs ecosystem (which matters more than usual this release, given the major bumps).

    [!TIP] Check out our upgrade guide if you're upgrading from an older version.

    Thank you to all of the many contributors to this release. This was a big one, and it wouldn't happen without you. 💚

    👉 Changelog

    compare changes

    🚀 Enhancements

    • rspack: Upgrade to rspack v2 (#34929)
    • nuxt: Migrate to unhead v3 (#34793)
    • nuxt: Support named views via filename convention (#35123)
    • nuxt: Expose environment name on import.meta (#34844)
    • nuxt: Forward destination preload hints on link prefetch (#35144)
    • nuxt: Honour http proxy env vars in builder environment (#35183)
    • kit: Support allowImportingTsExtensions (87c214b34)
    • nitro,nuxt,schema: Add experimental SSR streaming (5f4efe5a5)
    • vite: Migrate to Vite 8 (#34256)
    • nitro,nuxt: Add support for tracing channels for ssr events (#35191)
    • kit,nitro,nuxt,schema,vite,webpack: nuxt/* build output contract (#35463)
    • nuxt: Expose NuxtLink prefetch props for custom slot (#34539)
    • rspack: Use rspack-specific Vue loader (a085e8e34)
    • rspack: Use rspack-specific Vue loader (#35566)
    • nuxt,vite: Attach vite HMR to the shared dev server listener (a8ea0c7e2)
    • nuxt: Add enabled option to AsyncData (#33260)
    • rspack: Use rsbuild dev server in middleware mode (#35575)
    • nuxt: Expose getIslandHash + hashKey + improve hash for keys (#35583)
    • nuxt: Add useLayout composable for accessing the resolved route layout (#35623)
    • nuxt: Support enabled option in useFetch (#35627)
    • Error code system (#35429)
    • nuxt: Require keyed function 'source' with compatibilityVersion 5 (d56662647)
    • kit: Order layer aliases before generic root aliases (~, @) (#35641)
    • kit: Add updateAppConfig util for module authors (#35651)
    • nuxt: Warn when parent page lacks NuxtPage (#35639)

    🔥 Performance

    • nuxt,vite: Reuse vite watcher via experimental.watcher (#35143)
    • nuxt: Tree-shake unneeded plugin handling from prod builds (#35278)
    • nuxt: Defer dev-only nitro startup work (#35381)
    • nuxt: Reduce dev pages startup work (#35383)
    • vite: Skip unnecessary decorator transforms (#35395)
    • nuxt,rspack,vite,webpack: Migrate to rolldown-string (#35058)
    • nitro,nuxt,vite: Remove unused dependencies (#34861)
    • nuxt: Re-parse transformed file once in tree-shake plugin (#35509)
    • nuxt: Index scanned components by name to avoid quadratic lookup (#35510)
    • kit: Stat paths directly and probe extensions in parallel (#35511)
    • nitro: Load inline style chunks concurrently (#35514)
    • nuxt: Skip island-renderer chunk when no islands used (#35456)

    🩹 Fixes

    • nuxt: Fix explicit return types of factory types (40a80ec7d)
    • vite: Do not await ready event for vite watcher (6fe539f52)
    • vite: Invalidate modules for legacy vite server (#35315)
    • kit,nuxt: Pass error as cause when we re-throw (#35387)
    • nuxt: Make virtual module IDs stable across hosts (#35317)
    • vite: Inline CSS for lazy components imported from #components (#35215)
    • nuxt: Validate <ClientOnly> fallback tag name (#35325)
    • vite: Extract server page CSS when inlineStyles is disabled (#35209)
    • nitro: Include nested layers in nitro transforms (#35327)
    • kit: Don't exclude layer module runtime files from app tsconfig (#35326)
    • nitro: Export empty styles object with ssr: false (#35330)
    • nuxt: Emit auto-import paths as files, not directories (#35333)
    • nuxt: Suppress spurious slot warning in NuxtPage during nav (#35335)
    • vite: Preserve backslash separators in windows named pipe path (#35336)
    • nuxt: Detach in-flight promise on useAsyncData teardown (#35328)
    • nuxt: Respect per-page keepalive set via definePageMeta (#34526)
    • nuxt: Align useFetch error type with runtime (#35346)
    • nuxt: Unwrap getter body in useFetch (#35343)
    • rspack,webpack: Strip invalid webpack PURE annotations (#35386)
    • nuxt: Guard against -1 when unregistering a router hook (#35391)
    • nuxt: Clean up load/error listeners in preloadPayload (#35392)
    • nuxt: Avoid idle wait when refreshing data after hydration (#35358)
    • nuxt: Hash serialized island props (#35356)
    • nuxt: Ensure page:start finishes before page:finish starts (#35408)
    • vite: Invalidate lazily-created SSR modules on render (#35410)
    • nuxt: Preserve plugin navigation during app boot (#35344)
    • vite: Invalidate stale SSR virtual modules on render (#35413)
    • nitro: Don't preload JS for lazy-hydrated components (#35342)
    • vite: Add extension to vite-node-runner virtual specifier (0bf3f1d5d)
    • vite: Invalidate ssr copy of regenerated templates (33a581ce7)
    • vite: Set define for NODE_ENV and __VUE_PROD_DEVTOOLS__ (#35444)
    • vite: Avoid emitted ssr styles file name collisions (#35432)
    • nuxt: Avoid syncing route too early when reused page remounts (#35440)
    • nuxt: Skip showing route errors for crawlers (#35411)
    • nuxt: Keep nested layout on deferred route during suspended layout switch (#35443)
    • nuxt: Restore deferred query route before page is mounted (#35442)
    • kit,nuxt: Resolve auto-import type paths through shared resolver (#35451)
    • nuxt: Make islands hash backwards-compatible (#35452)
    • vite: Give ssr its own hmr websocket port on vite 8.1 (#35458)
    • nuxt: Auto-import $fetch where possible (#35581)
    • nuxt: Update unctx to v3 (#35541)
    • nitro: Point cache driver at .mjs runtime output (#35263)
    • nuxt: Add head.push for client side (#35498)
    • nitro: Only reload nitro after initial nitro build (30a573733)
    • nuxt: Pass nuxt rootDir to typed-router context (#35565)
    • nuxt: Type __nuxt_error marker on NuxtError (06e976d2e)
    • kit: noUncheckedSideEffectImports (v5) + disable libReplacement (#35548)
    • nuxt: Node10 compatible subpath exports (a216d732d)
    • nuxt: Unwrap module mutation trackers from options after installing (#35574)
    • nuxt: Entity-encode redirect body to preserve query separators (#35486)
    • rspack,webpack: Use async entry in dev to avoid circular import (#35586)
    • nuxt: Tolerate missing dirs in parcel watcher (#35585)
    • nuxt: Respect saved scroll position on same-page back navigation from hash (#35608)
    • nuxt: Resolve unctx helper to an absolute path for server bundling (#35602)
    • nuxt: Apply unctx transform marker through magic-string (#35618)
    • schema: Enable HMR for defineNuxtComponent in JSX (#35620)
    • nuxt: Evict stale forwarded prefetch hints and fix key mismatch (#35621)
    • nuxt: Re-add computeIslandHash for backwards compatibility (353164bb5)
    • nitro: Correct nitro runtime config type key (bc3b53add)
    • schema: Resolve Vite cache directory from workspace (#35626)
    • nitro: Externalise dev SSR entry to avoid slow rollup re-parse (ff42c54a7)
    • nuxt: Drop extension on diagnostics import (c699cc0de)
    • nitro: Write prerender cache files atomically (#35619)
    • nitro: Don't import node:process in diagnostics (d73b5df6d)
    • nuxt: Apply latest navigation on concurrent navigateTo in built-in router (#35631)
    • nuxt: Update client URL to match SSR on fatal middleware error (#35637)

    💅 Refactors

    • nitro,nuxt: Add explicit return types to runtime files (#35139)
    • nuxt: Resolve builder earlier + skip watcher for nuxt prepare (#35141)
    • nuxt: Delete cleared keys in clearNuxtData & clearNuxtState (#35142)
    • nuxt: Use jiti fsCache instead of deprecated cache (#35268)
    • nitro: Use walkResolver instead of deprecated resolveUnrefHeadInput (#35267)
    • nuxt: Add type predicates (#35208)
    • vite: Type vite-node-runner error data and resolve #vite-node types from source (#35334)
    • nuxt: Split head runtime plugin by environment (#35389)
    • nuxt: Use rolldown/utils instead of oxc-* dependencies (#34983)
    • kit,vite,webpack,nitro,schema: ssrStyles build output => lazy code provider (#35601)
    • nuxt,nitro: Use dev exports for no-build type-checking (#35605)
    • rspack: Use rsbuild to power rspack builder (#35489)
    • vite: Extract TemplateHMRPlugin from DevServerPlugin (#35579)

    📖 Documentation

    • Add builder guide (#35576)
    • Correct and improve useAsyncData and useFetch (#35528)
    • Improving testing documentation for better understanding (#35526)
    • Fix incorrect transform signature in useAsyncData/useFetch type docs (#35403)
    • Add minimal version badges to API documentation (#34485)
    • Clarify usage of await with useFetch (#33745)
    • Add badges for new features (1839fe01d)
    • Remove enabled from useFetch docs (bf7810600)
    • Add tip about prerendering registration for pages (#35635)
    • Clarify that useFetch keys are unique per call site (#35645)
    • Clarify useFetch custom data error (#35647)

    📦 Build

    • Use tsdown to build project (#35179)

    🏡 Chore

    • Update lockfile (92087005f)
    • Handle cleaning nuxt build dist manually (aaafe9879)
    • Upgrade oxc/tsdown/rolldown deps together (28173926d)
    • Use vp in nightly release script (97b56d98d)
    • Update lockfile for tsdown build and dev exports (5d9cd2d67)
    • Update bundle size snapshots (b9d353516)
    • Allow node version updates (#35297)
    • Update bundle size (d37b13b60)

    ✅ Tests

    • Strip host path from server bundle before measuring size (#35316)
    • Run playwright tests in dev mode too (#35329)
    • nuxt: Benchmark dev loadNuxt startup (#35382)
    • Update bundle size snapshot (64a834281)
    • Use h3 v1 syntax in test (1ea2eec07)
    • Use experimental.attachDebugInfo (7c2397ae6)
    • Update assertions (55f7ea025)
    • Pack with pnpm before running attw to honour publishConfig (e2f0dd69d)
    • Reduce flakiness on hydration tests (#35457)
    • Improve test stability on macos (#35462)
    • Force disable test mode for bundle size tests (#35558)
    • Pin typescript in basic-types fixture to dedupe vue (a3b824918)
    • webpack: Cover Vue loader scope hashes (824daffa0)
    • builders: Clean up Vue loader fixtures (ca18affc3)
    • Reenable webpack/rspack dev tests (#35571)
    • Await expectNoClientErrors (9f3123f60)
    • Mark tests as succeeding for rspack/webpack (513ad306e)
    • Add support for non-ascii filenames in public assets (#35636)
    • Minify server bundles in bundle size snapshot (#35638)
    • Run matrix-independent suites once across the fixture matrix (#35646)
    • Mark webpack/rspack tests as passing on 4.x (3ae095b29)

    🤖 CI

    • Reenable bundle size tests 😱 (#35279)
    • Only run workflow in nuxt org (#35377)
    • Skip entire job, not just step (#35378)
    • Error handling for webhook triggers (#35379)
    • Update agentscan (#35397)
    • Only run benchmark tests in Nuxt org (#35414)
    • Don't auto-close team prs 🫣 (cd965f569)
    • Use vite-plus to manage pnpm (#35570)
    • Use parallel keyword for concurrent workflow steps (#35448)
    • Handle missing base branch (for stacked prs) (8d3daa34e)
    • Unlink issues from autoclosed PRs (#35615)

    ❤️ Contributors

    • Jordan Labrosse (@Jorgagu)
    • Luke Nelson (@luc122c)
    • Florian Heuberger (@Flo0806)
    • Daniel Roe (@danielroe)
    • Yannik Schröder (@yschroe)
    • Mateleo (@Mateleo)
    • Matej Černý (@cernymatej)
    • Eduardo San Martin Morote (@posva)
    • Darlan José Batista do Prado (@DarlanPrado)
    • Ulrich-Matthias Schäfer (@Fuzzyma)
    • Bochkarev Ivan (@Ibochkarev)
    • Julien Huang (@huang-julien)
    • Damian Głowala (@DamianGlowala)
    • KazariAI (@KazariAI)
    • Fahad Khan (@oniChan1226)
    • skoenfaelt (@skoenfaelt)
    • Cynthia Rey (@cyyynthia)
    • meomking (@CaptainWang98)
    • antlis (@antlis)
    • Néstor (@Nsttt)
    • Issayah (@VividLemon)
    • Alexander Lichter (@TheAlexLichter)
    • Anoesj Sadraee (@Anoesj)
    • Quentin Macq (@quentinmcq)
    • raminjafary (@raminjafary)
    • Kurt Medley (@HeavyMedl)
    • isksss (@isksss)
    • Matteo Gabriele (@MatteoGabriele)
    • Max (@onmax)
    • Harlan Wilton (@harlan-zw)
    Open source →
  4. 4.4.88 Jun 2026
    Release notes

    4.4.8 is a hotfix release to address an issue running the dev server on MacOS.

    👉 Changelog

    compare changes

    🩹 Fixes

    • vite: Shorter socket name for macOs with tmp fallback (#35265)
    • kit: Respect type option in findPath (#35272)
    • deps: Update nuxt/scripts presets (905621594)
    • nuxt: Revert unhead dependency back to v2 (e6d578fea)

    📖 Documentation

    • Fix many typos (#35266)
    • Explain static fallback pages (#35277)
    • Change null to undefined in data-fetching docs to match actual types (#35301)
    • Fix broken internal links, useAsyncData watch type, and NuxtError type (#35303)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Ali Mahmmoud (@AliMahmoudDev)
    • Quentin Macq (@quentinmcq)
    • Pranav Rajeshirke (@Pranav188)
    • Eduardo San Martin Morote (@posva)
    Open source →
  5. 4.4.72 Jun 2026
    Release notes

    4.4.7 is a security hotfix release.

    👉 make sure to check https://github.com/nuxt/nuxt/security/advisories to view open advisories resolved by this release.

    👉 Changelog

    compare changes

    🩹 Fixes

    • nitro: Assign noSSR before deciding payload extraction (#35108)
    • vite: Avoid filtering out dirs with shared prefix from allowDirs (#35112)
    • nuxt: Use resolve from pathe for buildCache path boundary check (#35111)
    • nuxt: Prevent sibling-directory traversal in test component wrapper (#35110)
    • nitro: Pass event data to isValid in dev clipboard-copy listener (#35109)
    • nuxt: Validate protocols in reloadNuxtApp path before reload (#35115)
    • vite: Prefix public asset virtuals with null byte (9e303b438)
    • nuxt: Re-run getCachedData after initial fetch (#35122)
    • nuxt: Propagate useFetch/useAsyncData factory types (#35133)
    • vite: Close vite dev server on nuxt close (a10a68abc)
    • kit,nuxt: Handle cancelling prompts to install packages (e84813229)
    • kit: Avoid excluding node-context files in legacy tsconfig (#35152)
    • nuxt: Handle missing payload in chunkError listener (#35155)
    • nuxt: Await in-lifght template generation when closing nuxt (#35181)
    • nuxt: Clarify page and layout usage warnings (#35184)
    • webpack: Surface compilation errors when stats.toString is empty (073b07851)
    • nuxt: Reject prototype-chain keys in the island registry (#35205)
    • nuxt: Apply isScriptProtocol guard to navigateTo open option (#35206)
    • nuxt: Prevent server-only page island from recursing via <NuxtPage> (#35198)
    • rspack,webpack: Require loopback host when missing same-origin signals (#35200)
    • nitro: Gate chrome devtools workspace endpoint to local requests (#35201)
    • nuxt: Escape props in <NuxtClientFallback> ssr output (#35199)
    • kit: Improve TS extension stripping/substitutions (#35233)
    • nuxt: Preserve .d.mts/.d.cts in resolveTypePaths (#35235)
    • nuxt: Escape <NoScript> slot content (4b054e9d9)
    • nuxt: Match route rules case-insensitively to mirror vue-router (07e39cd6f)
    • nuxt: Reject script-capable protocols in <NuxtLink> href (0103ce06f)
    • nuxt: Block path-normalization open redirect in navigateTo (2cce6fb02)
    • nuxt: Reject cross-origin paths in reloadNuxtApp (e447a793c)
    • vite: Bind vite-node IPC to a permissioned filesystem socket (1f9f4767a)

    💅 Refactors

    • kit,nuxt,vite: Use es2023 array methods (#34980)
    • nuxt: Replace runInNewContext with AST walker (d72a89ef4)

    📖 Documentation

    • Document vite client and server options (#35090)
    • Add dedicated module dependencies page (#35171)
    • Add nodeTsConfig and sharedTsConfig options (#35231)
    • Edit for clarity and grammar (#35214)

    🏡 Chore

    ✅ Tests

    • Update test for js payload rendering (bdcb81536)
    • Cover add regression test for hmr in sibling local layers (#35125)
    • Improve reliability of hmr test (1d709b3cc)

    🤖 CI

    • Always run all tests for 4.x/3.x (0dc4665cf)
    • Migrate from tibdex (ded29dc0f)
    • Add zizmor github actions check (#35089)
    • Update to agentscan v1.8.0 (#35120)
    • Automatically close PRs from automated accounts (#35161)
    • Disable provenance-change enforcement in dependency-review (a2cf43e68)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • David Stack (@davidstackio)
    • David De Sloovere (@DavidDeSloovere)
    • anton-gor-dev (@anton-gor-dev)
    • Noah3521 (@Noah3521)
    • Shahar Aviram (@ShaharAviram1)
    • Matej Černý (@cernymatej)
    • Mohit Kumar (@mohitkum4r)
    • Matteo Gabriele (@MatteoGabriele)
    • Julien Huang (@huang-julien)
    • Damian Głowala (@DamianGlowala)
    Open source →
  6. 4.4.618 May 2026
    Release notes

    4.4.6 is the next patch release.

    👉 Changelog

    compare changes

    🩹 Fixes

    • vite: Use spa entry for vite-node fallback (#35037)
    • vite: Invalidate SSR module cache when modules are invalidated via plugin hooks (a86657a0e)
    • nuxt: Match deduplicated resolveComponent calls in jsx blocks (#35028)
    • nuxt: Prefer our own builder/server deps (#35029)
    • nuxt: Update useFetch key even with watch: false (#35002)
    • nitro: Mark @babel/plugin-syntax-typescript as optional peer dep (#35041)
    • nitro: Add json extension to payload cache items (#35043)
    • nuxt: Handle errors fetching app manifest (#35050)
    • nuxt: Encode html-significant characters in external redirect body (#35052)
    • nuxt: Preserve setPageLayout props on same-path navigation (#35055)
    • vite: Don't strip buildAssetsDir from vite-node SSR ids (#35040)
    • nuxt: Mark useLoadingIndicator properties as readonly (#35062)
    • vite: Strip queries in css inline styles map (#35067)
    • nitro: Validate island request hash matches props (#35077)
    • nitro: Use regexp to strip query (163e18d4b)
    • nitro: Use statusCode for nitro v2 compatibility (952f6841e)
    • nitro-server: Re-export h3 named symbols statically (cd99001c8)
    • nuxt: Render component-less parent routes during client-side nav (#35036)
    • kit: Respect tsConfig.exclude in legacy tsconfig.json (#35079)
    • nuxt: Run middleware for page islands (#35092)

    💅 Refactors

    • rspack,webpack: Extract same-origin check for dev middleware (#35051)

    📖 Documentation

    • Remove CSB, set node 22 and use steps for clarity (#35066)

    🏡 Chore

    ✅ Tests

    🤖 CI

    • Clean up agent-scan workflow (ab8317547)
    • Continue autofix workflow when test:engines fails (3025e561e)
    • Improve workflows (#35088)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Tim (@timhn-bm)
    • Julien Huang (@huang-julien)
    • Damian Głowala (@DamianGlowala)
    • Sébastien Chopin (@atinux)
    • Adrien Foulon (@Tofandel)
    • Sami El Achi (@samiashi)
    Open source →
  7. 4.4.510 May 2026
    Release notes

    4.4.5 is the next patch release.

    👉 Changelog

    compare changes

    🔥 Performance

    • kit: Cache layer roots and short-circuit isIgnored relative (#35015)

    🩹 Fixes

    • vite: Resolve vite clientServer with ssr: false (#34959)
    • nitro: Correct payload route rule for / + override ssr: true (#34990)
    • nitro: Break recursive rendering deadlocks during prerender (#34939)
    • vite: Drop redundant css link when entry styles are inlined (#34950)
    • vite: Sort optimizeDeps.include in pre-bundle hint (#34976)
    • nuxt: Only force suspense remount after first resolve (#34949)
    • kit: Read .env before resolving nuxt schema (#34958)
    • nitro: Preserve serverHandlers array after nitro:config (#34985)
    • nuxt: Cast partial nitro handlers when prepending to server arrays (61dcde4db)
    • vite: Only consider CSS inlined when styles are actually emitted (#35006)
    • nuxt: Dedupe getCachedData for concurrent callers sharing a key (#34999)
    • nuxt: Respect factory fetch/baseURL options in server useFetch (#35003)
    • nuxt: Handle string presets in auto-imports (#35013)
    • nuxt: Correct island transform for server pages and 'deep' mode (#35005)
    • vite: Inline css for non-island children of server components (#35001)
    • nuxt: Defer head DOM updates until page transition finishes (#35016)
    • nuxt: Explicitly freeze head during island plugin phase (#35010)
    • vite: Inline css imported from non-vue js modules (#35020)

    📖 Documentation

    • Add warning about routing in server components (#34994)

    🏡 Chore

    ✅ Tests

    • Extract server components fixture + add some failing tests (#34995)
    • Isolate buildDir per matrix project for shared fixtures (#35007)
    • Remove tests for 5.x runtimeBaseURL fature (816c25487)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Harlan Wilton (@harlan-zw)
    • Jonazzzz (@Bombastickj)
    • Damian Głowala (@DamianGlowala)
    • Florian Heuberger (@Flo0806)
    Open source →
  8. 4.4.429 Apr 2026

    Nothing published for this version

  9. 4.4.212 Mar 2026

    Nothing published for this version

  10. 4.4.112 Mar 2026

    Nothing published for this version

  11. 4.3.17 Feb 2026
    Release notes

    4.3.1 is a regularly scheduled patch release.

    👉 Changelog

    compare changes

    🩹 Fixes

    • nuxt: Correct reference format of server builder (#34177)
    • nuxt: Add status/statusText getters to NuxtError (#34188)
    • nuxt: Don't inject shared types for differing auto-imports (#34191)
    • schema: Add direnv and vendor to default ignore (#34190)
    • nuxt: Focus hash links after navigation (#34193)
    • nuxt: Exclude head runtime from unhead imports transform (#34195)
    • kit: Include prereleases in semver satisfy check (#34210)
    • nitro: Encode unicode paths in x-nitro-prerender header (#34202)
    • nuxt: Watch server/ for builder:watch hook (#34208)
    • nitro: Preserve error.message for fatal errors (#34226)
    • Only enable dynamic imports when ts plugin (#34205)
    • webpack: Use H3Error for 403 in dev server (#34233)
    • nuxt: Ensure NuxtError extends Error type (#34242)
    • vite: Use H3Error for 404 in dev server (#34225)
    • nuxt: Add backwards compat for #app barrel export in keyed functions (#34199)
    • nuxt: Track + re-add custom routes on hmr (#32044)
    • nuxt: Keep vnode when leaving deeper nested route (#33778)
    • vite: Prevent CSS flickering in dev mode after config changes (#33856)
    • nuxt: Do not start view transition if there is no route (#33723)
    • nuxt: Call deferHydration done on NuxtPage unmount (#34152)
    • nuxt: Handle invalid datetime in <NuxtTime>` (#33992)
    • nuxt: Preserve middleware error status in 404 fallback (#34148)
    • nitro: Do not augment nuxt/schema (#34255)
    • nuxt: Cache manifest files to preserve buildId (#34002)
    • nuxt: Don't decode query string in SSR context URL (#34252)
    • nuxt: Allow specifying moduleDependencies by meta.name (#34263)
    • nuxt: Resolve #components import mapping conflict for packages outside rootDir (#34139)
    • vite,webpack: Use node.res to send 403/404 (#34266)
    • nitro,nuxt: Align path encoding with vue-router (#34265)
    • nitro: Augment nuxt/schema once more (552bbd8d1)

    💅 Refactors

    • nuxt: Prefer genObjectKey to omit unnecessary quotes (#34245)
    • nuxt: Use ComponentProps helper to extract layout props (#34248)

    📖 Documentation

    • Update roadmap dates (#34166)
    • Correct default value of nitroAutoImports (#34182)
    • Clarify shared type context limitations for custom imports (#34194)
    • Fix broken links (#34223)
    • Document payload extraction for ISR/SWR routes (#34222)
    • Update default aliases in configuration reference (#34237)
    • Update example of email validation (#34247)
    • Align server alias examples with #server and rootDir (#34259)
    • Add documentation for keyedComposables (#34201)

    🏡 Chore

    • Remove px from width attribute (8d1cbb27a)
    • Add ai config in gitignore (#34220)

    ✅ Tests

    • Vitest v4 compatibility (825b2c202)
    • Add runtime tests for deeply nested <NuxtPage> navigation (048efc030)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Matej Černý (@cernymatej)
    • Octavio Araiza (@8ctavio)
    • Muhammad Yasir Ghaffar (@M-YasirGhaffar)
    • mrkaashee (@mrkaashee)
    • Max (@onmax)
    • Bobbie Goede (@BobbieGoede)
    • 纸鹿/Zhilu (@L33Z22L11)
    • Florian Heuberger (@Flo0806)
    • 山吹色御守 (@KazariEX)
    • ExXTreMe315 (@ExXTreMe315)
    • Eugene (@FlexIDK)
    • abeer0 (@iiio2)
    • Jonas Thelemann (@dargmuesli)
    • Erwan Jugand (@erwanjugand)
    Open source →
  12. 4.3.022 Jan 2026
    Release notes

    4.3.0 is the next minor release.

    Nuxt 4.3 brings powerful new features for layouts, caching, and developer experience – plus significant performance improvements under the hood.

    📣 Some News

    Extended v3 Support

    Early this month, I opened a discussion to find out how the upgrade had gone from v3 to v4. I was really pleased to hear how well it had gone for most people.

    Having said that, we're committed to making sure no one gets left behind. And so we will continue to provide security updates and critical bug fix releases beyond the previously announced end-of-life date of January 31, 2026, meaning Nuxt v3 will meet its end-of-life on July 31, 2026.

    [!TIP] As usual, today also brings a minor release for v3, with many of the same improvements backported from v4.3.

    Preparing for Nuxt 5

    We're closer than ever to the releases of Nuxt v5 and Nitro v3. In the coming weeks, the main branch of the Nuxt repository will begin receiving initial commits for Nuxt 5. However, it's still business as usual.

    • Continue making pull requests to the main branch
    • We'll backport changes to the 4.x and 3.x branches

    Keep an eye out on the Upgrade Guide – we'll be adding details about how you can already start migrating your projects to prepare for Nuxt v4 with future.compatibilityVersion: 5.

    🗂️ Route Rule Layouts

    But that's enough about the future. We have a lot of good things for you today!

    First, you can now set layouts directly in route rules using the new appLayout property (#31092). This provides a centralized, declarative way to manage layouts across your application without scattering definePageMeta calls throughout your pages.

    export default defineNuxtConfig({
      routeRules: {
        '/admin/**': { appLayout: 'admin' },
        '/dashboard/**': { appLayout: 'dashboard' },
        '/auth/**': { appLayout: 'minimal' }
      }
    })
    

    This might be useful for:

    • Admin panels with a shared layout across many routes
    • Marketing pages that need a different layout from the app

    [!TIP] Plus, you can pass props to layouts now! See the setPageLayout improvements below.

    📦 ISR/SWR Payload Extraction

    Payload extraction now works with ISR (incremental static regeneration), SWR (stale-while-revalidate) and cache routeRules (#33467). Previously, only pre-rendered pages could generate _payload.json files.

    This means:

    • Client-side navigation to ISR/SWR pages can use cached payloads
    • CDNs (Vercel, Netlify, Cloudflare) can cache payload files alongside HTML
    • Fewer API calls during navigation – data can be prefetched and served from the cached payload
    export default defineNuxtConfig({
      routeRules: {
        '/products/**': { 
          isr: 3600, // Revalidate every hour
        }
      }
    })
    

    🧹 Dev Mode Payload Extraction

    Related to the above, payload extraction now also works in development mode (#30784). This makes it easier to test and debug payload behavior without needing to run a production build.

    [!IMPORTANT] Payload extraction works in dev mode with nitro.static set to true, or for individual pages which have isr, swr, prerender or cache route rules.

    🚫 Disable Modules from Layers

    When extending Nuxt layers, you can now disable specific modules that you don't need (#33883). Just pass false to the module's options:

    export default defineNuxtConfig({
      extends: ['../shared-layer'],
      // disable @nuxt/image from layer
      image: false,
    })
    

    🏷️ Route Groups in Page Meta

    Route groups (folders wrapped in parentheses like (protected)/) are now exposed in page meta (#33460). This makes it easy to check which groups a route belongs to in middleware or anywhere you have access to the route.

    <script setup lang="ts">
    // This page's meta will include: { groups: ['protected'] }
    useRoute().meta.groups
    </script>
    
    export default defineNuxtRouteMiddleware((to) => {
      if (to.meta.groups?.includes('protected') && !isAuthenticated()) {
        return navigateTo('/login')
      }
    })
    

    This provides a clean, convention-based approach to route-level authorization without needing to add definePageMeta to every protected page.

    🎨 Layout Props with setPageLayout

    The setPageLayout composable now accepts a second parameter to pass props to your layout (#33805):

    export default defineNuxtRouteMiddleware((to) => {
      setPageLayout('admin', {
        sidebar: true,
        theme: 'dark'
      })
    })
    
    <script setup lang="ts">
    defineProps<{
      sidebar?: boolean
      theme?: 'light' | 'dark'
    }>()
    </script>
    

    🔧 #server Alias

    A new #server alias provides clean imports within your server directory (#33870), similar to how #shared works:

    // Before: relative path hell
    import { helper } from '../../../../utils/helper'
    
    // After: clean and predictable
    import { helper } from '#server/utils/helper'
    

    The alias includes import protection – you can't accidentally import #server code from client or shared contexts.

    🪟 Draggable Error Overlay

    The development error overlay introduced in Nuxt 4.2 is now draggable and can be minimized (#33695). You can:

    • Drag it to any corner of the screen (it snaps to edges)
    • Minimize it to a small pill button when you want to keep working
    • Your position and minimized state persist across page reloads

    This is a quality-of-life improvement when you're iterating on fixes and don't want the overlay blocking your view.

    https://github.com/user-attachments/assets/nuxt_4-3_error_demo.mp4

    ⚙️ Async Plugin Constructors

    Module authors can now use async functions when adding build plugins (#33619):

    export default defineNuxtModule({
      async setup() {
        // Lazy load only when actually needed
        addVitePlugin(() => import('my-cool-plugin').then(r => r.default()))
        
        // No need to load webpack plugin if using Vite
        addWebpackPlugin(() => import('my-cool-plugin/webpack').then(r => r.default()))
      }
    })
    

    This enables true lazy loading of build plugins, avoiding unnecessary code loading when plugins aren't needed.

    🚀 Performance Improvements

    This release includes several performance optimizations for faster builds:

    • Hook filters - Internal plugins now use filters to avoid running hooks unnecessarily (#33898)
    • SSR styles optimization - The nuxt:ssr-styles plugin is now significantly faster (#33862, #33865)
    • Layer alias transform - Skipped when using Vite (it handles this natively) (#33864)
    • Route rules compilation - Route rules are now compiled into a client chunk using rou3, removing the need for radix3 in the client bundle and eliminating app manifest fetches (#33920)

    🎨 Inline Styles for Webpack/Rspack

    The inlineStyles feature now works with webpack and rspack builders (#33966), not just Vite. This enables critical CSS inlining for better Core Web Vitals regardless of your bundler choice.

    ⚠️ Deprecations

    statusCodestatus, statusMessagestatusText

    In preparation for Nitro v3 and H3 v2, we're moving to use Web API naming conventions (#33912). The old properties still work but are deprecated in advance of v5:

    - throw createError({ statusCode: 404, statusMessage: 'Not Found' })
    + throw createError({ status: 404, statusText: 'Not Found' })
    

    🐛 Bug Fixes

    Notable fixes in this release:

    • Fixed head component deduplication using key attribute (#33958, #33963)
    • Fixed async data properties not being reactive in Options API (#34119)
    • Fixed useCookie unsafe number parsing during decode (#34007)
    • Fixed NuxtPage not re-rendering when nested NuxtLayout has layouts disabled (#34078)
    • Fixed client-side pathname decoding for non-ASCII route aliases (#34043)
    • Fixed suspense remounting when navigating after pending state (#33991)
    • Fixed clipboard copy in error overlay (#33873)
    • Enabled allowArbitraryExtensions by default in TypeScript config (#34084)
    • Added noUncheckedIndexedAccess to server tsconfig for safer typing (#33985)

    [!IMPORTANT] Enabling noUncheckedIndexedAccess in the Nitro server TypeScript config improves type safety but may surface new type errors in your server code. This change was necessary because Nuxt's app context performs type checks on server routes (learn more).

    While we recommend keeping this enabled for better type safety, you can disable it if needed:

    export default defineNuxtConfig({
      nitro: {
        typescript: {
          tsConfig: {
            compilerOptions: {
              noUncheckedIndexedAccess: false
            }
          }
        }
      }
    })
    

    Note that disabling this may allow type errors to slip through that could cause runtime issues with indexed access.

    📚 Documentation

    • Improved module author guides with clearer structure (#33803)
    • Added MCP setup instructions for Claude Desktop (#33914)
    • Added layers directory documentation (#33967)
    • Added Deno package manager examples (#34070)
    • Clarified type-checking context limitations for server routes (#33964)

    🎉 Nuxt 3.21.0

    Alongside v4.3.0, we're releasing Nuxt v3.21.0 with many of the same improvements backported to the 3.x branch. This release includes:

    • All the same features: Route rule layouts, ISR payload extraction, layout props with setPageLayout, #server alias, draggable error overlay, and more
    • All performance improvements: SSR styles optimization, hook filters, and route rules compilation
    • Module disabling: Disable layer modules by setting options to false
    • Critical bug fixes: Async data reactivity in Options API, useCookie number parsing, head component deduplication, and more

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe
    
    # or, if you are upgrading to v3.21
    npx nuxt@latest upgrade --dedupe --channel=v3
    

    This will deduplicate your lockfile and help ensure you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    [!TIP] Check out our upgrade guide if upgrading from an older version.

    👉 Changelog

    compare changes

    🚀 Enhancements

    • kit: Support async constructor for adding plugins (#33619)
    • kit: Export Nuxt major version type (#33700)
    • schema: Add #server alias for server directory imports (#33870)
    • ui-templates: Let it snow! ❄️ (#33804)
    • schema: Hoist nitro crossws types (5b16a51f5)
    • nitro,nuxt: Compile route rules into client chunk (#33920)
    • nuxt: Allow disabling modules by setting module options to false (#33883)
    • kit: Allow specifying moduleDependencies as an async function (#33504)
    • nuxt: Support appLayout in route rules (#31092)
    • nuxt: Add route groups to page meta (#33460)
    • nuxt: Enable payload extraction for ISR/SWR routes (#33467)
    • nuxt: Allow updating props with setPageLayout (#33805)
    • nuxt: Enable dragging and minimizing for error overlay (#33695)
    • nitro,nuxt: Add support for payload extraction in dev (#30784)
    • rspack,webpack: Add inline styles (#33966)
    • kit: Add forward-compatible nitro types (#34036)

    🔥 Performance

    • nuxt: Do not init layer alias transform when using vite (#33864)
    • vite: Add hook filters for ssr styles plugin (#33865)
    • vite: Optimize nuxt:ssr-styles plugin (#33862)
    • nuxt: Use filter for vfs plugin load (eb3d2d4c6)
    • nuxt,vite: Use filters to avoid running hooks unnecessarily (6b7fc7477)
    • nuxt,vite: Add more filters to internal plugins (#33898)

    🩹 Fixes

    • kit: Normalize local layer paths with trailing slashes (#33858)
    • nuxt: Avoid overwriting multiple head input in island handler (#33849)
    • nuxt: Update meta instead of calling router.replace in page hmr (#33897)
    • nuxt: Don't call page:loading:end in cache if already called (7789f73bd)
    • vite: Add error handling for parsing NUXT_VITE_NODE_OPTIONS (41a564d23)
    • nuxt: Do not skip middleware when appMiddleware references invalid key (323f27bc8)
    • nitro: Clipboard copy in error overlay (#33873)
    • webpack,rspack: Resolve deep imports in virtual files (#33927)
    • webpack: Disable async chunks in dev mode (0310c4070)
    • webpack: Correctly evaluate sourcemap name (653f364af)
    • nuxt: Handle node10 resolution for nuxt/meta (01c2c9b13)
    • nuxt: Do not early return if component priorities conflict (#33955)
    • nuxt: Use key for tag deduplication in <Head> component (#33958)
    • schema,vite: Resolve build.transpile when initialising vite (#33868)
    • nuxt,rspack,webpack: Inject module identifiers for webpack builders (#33962)
    • nuxt: Add key to head components for proper deduplication (#33963)
    • nitro: Check prettyResponse.body type before error overlay (#33977)
    • nuxt: Don't URI-encode static route paths (#33990)
    • nuxt: Skip internal stub routes from prerender (#34001)
    • kit,schema: Align module onUpgrade arguments with types (#33988)
    • nuxt: Handle unsafe number parsing in useCookie decode (#34007)
    • nuxt: Do not externalise rou3 (2df4e1ae3)
    • nitro: Add noUncheckedIndexedAccess to server tsconfig (#33985)
    • nuxt: Add auto-import declarations for shared/ context (#33978)
    • nuxt: Update global reference to globalThis in useRequestFetch (#33976)
    • vite: Configure hmr port for server build (#33929)
    • kit: Add forward compatible nitro v3 types (#34053)
    • nitro,nuxt: Do not import nitro deps in builders (#34054)
    • nitro: Add h3 types to auto-imports (#34035)
    • schema: Add some more directories to ignore (ebc2a66ab)
    • nitro: Also augment nuxt/schema (a6a044d81)
    • nuxt: Make asyncData properties reactive in Options API (#34119)
    • nuxt: Rerender NuxtPage when nested NuxtLayout has explicitly disabled layouts (#34078)
    • kit,nitro: Enable allowArbitraryExtensions by default (#34084)
    • nuxt: Decode client-side pathname for non-ASCII route aliases (#34043)
    • nuxt: Force remount suspense when navigating after pending (#33991)
    • nuxt: Add documentation link to server builder error message (#34122)
    • nuxt: Validate placeholder/fallback tags + warn about placeholder/fallback props (567a1c6fb)
    • nuxt: Force flush useAsyncData debounced execute post watcher flush (#34125)
    • nitro: Process isr/swr/cache keys (d84278622)
    • nuxt: Add typeFrom support for imports.d.ts template exports (#34135)
    • nuxt: Ensure we inline styles for hydrate-never components (#34132)

    💅 Refactors

    • kit: Add explicit return types for kit utilities (6cd1289d1)
    • nitro,nuxt,schema,vite: Provide explicit return types (1d2c0c25f)
    • kit,nuxt,schema: Use named imports from defu + consola (322dae3e0)
    • Add explicit .ts file extensions to relative imports (80778c0cd)
    • kit,nitro,nuxt,schema: Reduce barrels + move <> to as (f1713850c)
    • nitro,nuxt: Use ~ prefix for internal ssrContext properties (#33896)
    • nitro: Add explicit return types for runtime utils (a4fda917e)
    • nitro: Move tree-shaken flags from replace plugin -> vfs (#33907)
    • nitro,nuxt,vite,webpack: Use status/statusText + deprecate old props (#33912)
    • webpack: Use RuntimeModule API for chunk preloads (#33930)
    • nuxt: Use AST-aware function key injection (#33446)
    • nitro,nuxt,schema: Use augments for nitro schema types (#34039)
    • nitro,rspack,vite,webpack: Move cors handling -> nitro builder (#34048)

    📖 Documentation

    • Split and improve Module Author Guides (#33803)
    • Update links to module guide (86d67b24f)
    • Fix useHead return type (#33857)
    • Add note that middleware doesn't run when rendering islands (7df27c781)
    • Add note on default branch for layers (#33919)
    • Add mcp setup instructions for claude desktop (#33914)
    • Mention deno as package manager (#33875)
    • Clarify purpose of statusText (#32834)
    • Update lychee config and remove medium article link (c0b4e0f28)
    • Update module count and fix typo (#33950)
    • Add DeepWiki badge (#33508)
    • Give example of usage of defineWrappedResponseHandler (#33952)
    • Provide cleaner example code for vitest projects (#33960)
    • Improve addImports example (#34011)
    • Update yarn create command (4a3c08874)
    • Update roadmap with a11y (d3453d6a5)
    • Add a11y release (#34041)
    • Remove Nuxtr from recommendations (#34045)
    • Typo (#34050)
    • Remove duplicate feature (#34058)
    • Fix typo (#34057)
    • Provide deno package manager examples (#34070)
    • Update JSDoc for config.experimental properties (#34069)
    • Fix transition types (#34082)
    • Make custom wrapper recipe link more prominent (#34085)
    • Remove null from getCachedData trigger (f7cf3747e)
    • nuxt: Mention custom serializers in useState docs (#34105)
    • Add info about runtime directories + type checking (#34097)
    • Clarify module setups in .nuxtrc example (#34107)
    • Remove duplicate entries in table (#34094)
    • Clarify catch all notation for addServerHandler (#34060)
    • Add layers directory documentation (#33967)
    • Clarify type-checking context limitations for server routes (#33964)
    • Add a tip for appLayout (beda47955)
    • Add docs for disabling modules by passing false to its options (cdad9310c)
    • Add info about caching payloads with isr/swr (6e10ff04f)
    • Add example for async addVitePlugin (1098254f7)
    • Add example of passing props to layouts (1f9e6b82c)
    • Mark vite plugin as not typed (5e09fddfb)
    • Add warning about source from <NuxtIsland> (1586bbb6e)

    📦 Build

    • Remove babel debugging plugin from jiti stub options (bce8248b4)
    • vite: Add build entries for vite-node entrypoints (#33893)
    • nuxt: Tidy up subpath export types (a63d4a014)
    • Use obuild except for nuxt + nitro-server packages (#34049)
    • schema: Fix /builder-env subpath types (7f5034288)

    🏡 Chore

    ✅ Tests

    • Update tests for new version of nuxt/test-utils (#33842)
    • Avoid unnecessary tick (988f6657a)
    • Add regression test for asyncData HMR (#32182)
    • Add test for page hmr resetting state (#32418)
    • Add reproduction for vite pre-transform error (#31574)
    • Add regression test for #32154 (#32154)
    • Use vi.hoisted for klona mock (#34113)

    🤖 CI

    • Directly call webhook url (ce15997ce)
    • Use new reusable triage workflows (#34072)
    • Use new shared dependency review workflow (8c01e1ce9)

    ❤️ Contributors

    • Florian Heuberger (@Flo0806)
    • Octavio Araiza (@8ctavio)
    • Daniel Roe (@danielroe)
    • Robin (@OrbisK)
    • shaheer-arbisoft (@shaheer-arbisoft)
    • Matej Černý (@cernymatej)
    • Francesco Mussoni (@solidusite)
    • Danila Poyarkov (@dannote)
    • Victor Saa (@vis97c)
    • Teages (@Teages)
    • Eli Sterken (@eli-sterk)
    • Ryota Watanabe (@wattanx)
    • Jakub Andrzejewski (@Baroshem)
    • edison (@edison1105)
    • Max (@onmax)
    • Aidan Hibbard (@aidanhibbard)
    • Rahul Dogra (@rahuld109)
    • Julien Huang (@huang-julien)
    • abeer0 (@iiio2)
    • James Robert Lund III (@lundjrl)
    • Philipp Wagner (@imphil)
    • Maxime Pauvert (@maximepvrt)
    • Wind (@productdevbook)
    • Agatem (@agatemosu)
    • Pavel (@eL1fe)
    • Alois Sečkár (@AloisSeckar)
    • Lucie (@lihbr)
    • Sergiu Ravliuc (@YoSoySergio)
    • Saeid Zareie (@Saeid-Za)
    • Alireza Jahandideh (@Youhan)
    • kikuchan (@kikuchan)
    • Ragura (@Ragura)
    • Josh Deltener (@hecktarzuli)
    • Teena (@franklin-tina)
    • Frederik Bußmann (@freb97)
    • Benjamin Oddou (@BenjaminOddou)
    • Mukund Shah (@mukundshah)
    • Jessé Correia Lins (@linspw)
    • Jannik Sohn (@janniksohn)
    • Dawit (@oneminch)
    • Ali Sokkar (@NyllRE)
    • Horu (@HigherOrderLogic)
    • Anthony Fu (@antfu)
    • Harlan Wilton (@harlan-zw)
    • Alexander Lichter (@TheAlexLichter)
    • Ryan Wilson (@rywils)
    • Hugo (@HugoRCD)
    • yamachi4416 (@yamachi4416)
    Open source →
  13. 4.2.29 Dec 2025
    Release notes

    4.2.2 is the next patch release.

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🩹 Fixes

    • nitro: Do not show pretty error handler when testing (243261edb)
    • nuxt: Generate valid references for component declaration items (#33388)
    • nuxt: Sync internal route before calling page:finish hook (#33707)
    • kit: Add TypeScript path alias support for test files (#33672)
    • nitro: Ensure html is a string before injecting error handler (f70b70c97)
    • nitro: Include layer server directories in tsconfig.server.json (#33510)
    • nuxt: Ensure deduped async data executions return latest promise (#33740)
    • kit,nuxt: Type + respect moduleDependencies by meta name (#33774)
    • nuxt,schema: Ignore .d.vue.ts declarations (1c73525a2)
    • kit,nuxt: Protect against resolved nuxt module subpath (#33767)
    • nuxt: Re-execute callOnce during HMR (#33810)
    • nuxt: Resolve watch callback after reactive key change in useAsyncData (#33802)
    • nuxt: Escape HTML in development error page stack trace (#33820)
    • kit: Do not add resolved rootDir to cached layer config (#33779)
    • kit,schema: Add moduleDependencies -> installModule (#33689)

    💅 Refactors

    • nuxt: Improve type safety within callOnce function (#33825)

    📖 Documentation

    • Split directory structure and re-order guides (v4) (#33691)
    • Add hints release (#33701)
    • Fix link to vitest globals config (#33702)
    • Add mcp server and llms.txt (#33371)
    • Fix 404 link (98c2f1397)
    • Text consistency (#33709)
    • Type error as non-optional prop (#33763)
    • Reformat tables (#33813)

    🏡 Chore

    • Update pnpm to 10.21 and enable trust policy (d2c9711c0)
    • Revert pnpm trust policy and restore provenance action (f9d0e0a3d)
    • Update markdownlint config to ignore mdc issues (e7fff7132)
    • Pin to single version of unstorage (ec316eae8)

    ✅ Tests

    • Add patchProp and nodeOps to excluded Vue helpers (#33754)
    • Use fake timers for watch params test (08d9d2f3b)

    🤖 CI

    • Add --pnpm flag to correctly publish prerelease (#33688)
    • Update action lint config (#33710)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Florian Heuberger (@Flo0806)
    • Konstantin Telyakov (@kTelyakov)
    • abeer0 (@iiio2)
    • Julien Huang (@huang-julien)
    • Matej Černý (@cernymatej)
    • Robin (@OrbisK)
    • Dheeraj Joshi (@dheeraj3587)
    • Alexander Lichter (@TheAlexLichter)
    • Edwin Samodra (@edwinsamodra)
    • edison (@edison1105)
    • 山吹色御守 (@KazariEX)
    • Sébastien Chopin (@atinux)
    • Hugo (@HugoRCD)
    • pierreoa (@pierreoa)
    • Maxime Pauvert (@maximepvrt)
    Open source →
  14. 4.2.16 Nov 2025
    Release notes

    4.2.1 is the next patch release.

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🩹 Fixes

    • kit,nuxt,schema: Deprecate ImportPresetWithDeprecation (#33596)
    • nuxt: Correct warning message for prefetch/noPrefetch conflict (#33617)
    • nitro: Remove <nuxt-error-overlay> iframe border (#33625)
    • vite: Use rolldown replace only in build (#33615)
    • nitro: Use directory paths in moduleEntryPaths (#33628)
    • nitro: Start error overlay minimized based on status code (#33658)
    • vite: Ensure optimizeDeps config is applied before other plugins (#33586)
    • nuxt: Respect layer priority order for scanned components (#33654)
    • nuxt: Process prerender routes on pages:resolved (#33662)
    • nuxt: Remove abort signal event listeners after render (#33665)
    • nuxt: Cleanup event listener with cleanup signal (#33667)
    • vite: Update vite-node (#33663)
    • vite: Respect vite proxy in dev middleware (#33670)

    💅 Refactors

    • kit,nitro,nuxt,schema,vite: Explicitly import process/performance (#33650)

    📖 Documentation

    • Fix typo in eslint flat config description (#33569)
    • Add signal support to useAsyncData examples (#33601)
    • Document pending as alias of status === 'pending' (#33221)
    • Note that cookieStore is true by default (#33572)
    • Add information on types for server context (#33511)
    • Mark webstorm issue resolved (#33608)
    • Clarify route middleware doesn't affect API routes (#33643)
    • Improve docs for useHead/useHydration/useLazy* (#33626)
    • Update link to nitro source to v2 branch (08018af4f)
    • Add typescript documentation for module authors (#33637)
    • Typo (#33655)

    🏡 Chore

    🤖 CI

    • Disable cache in release action (ff37598bc)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Anthony Fu (@antfu)
    • Robin (@OrbisK)
    • abeer0 (@iiio2)
    • Bobbie Goede (@BobbieGoede)
    • Florian Heuberger (@Flo0806)
    • Matej Černý (@cernymatej)
    • Peter Budai (@peterbud)
    • Julien Huang (@huang-julien)
    • Max (@onmax)
    • 纸鹿/Zhilu (@L33Z22L11)
    • Hinata Oishi (@te19oishi)
    • Damian Głowala (@DamianGlowala)
    • Maxime Pauvert (@maximepvrt)
    • Raed Abdennadher (@RaedAbr)
    Open source →
  15. 4.2.025 Oct 2025
    Release notes

    4.2.0 is the next minor release.

    👀 Highlights

    We're excited to announce Nuxt 4.2, bringing new capabilities for better TypeScript DX, enhanced error handling, and improved control over data fetching! 🎉

    🎯 Abort Control for Data Fetching

    You can now use AbortController signals directly within useAsyncData, giving you fine-grained control over request cancellation (#32531).

    This works by passing an internal signal to your useAsyncData handler to cancel any promise that can be canceled, such as $fetch.

    <script setup lang="ts">
    const controller = new AbortController()
    
    const { data, error, clear, refresh } = await useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', {
      signal
    }))
    
    refresh() // will actually cancel the $fetch request (if dedupe: cancel)
    refresh() // will actually cancel the $fetch request (if dedupe: cancel)
    refresh()
      
    clear() // will cancel the latest pending handler
    </script>
    

    You also pass an AbortController signal directly to refresh/execute, giving you fine-grained control over request cancellation. This is particularly useful when you need to abort requests based on user actions or component lifecycle events.

    const { data, refresh } = await useAsyncData('posts', fetchPosts)
    
    // Abort an ongoing refresh
    const abortController = new AbortController()
    refresh({ signal: abortController.signal })
    
    // Later...
    abortController.abort()
    

    🎨 Better Error Pages in Development

    When an error occurs during development, Nuxt will now display both your custom error page and a detailed technical error overlay (#33359). This gives you the best of both worlds – you can see what your users will experience while also having immediate access to stack traces and debugging information.

    The technical overlay appears as a toggleable panel that doesn't interfere with your custom error page, making it easier to debug issues while maintaining a realistic preview of your error handling.

    🔮 Opt-in Vite Environment API

    For those wanting to experiment with cutting-edge features, you can now opt into the Vite Environment API (#33492).

    The Vite Environment API is a major architectural improvement in Vite 6. It closes the gap between development and production by allowing the Vite dev server to handle multiple environments concurrently (rather than requiring multiple Vite dev servers, as we have done previously in Nuxt).

    This should improve performance when developing and eliminate some edge case bugs.

    ... and it is the foundation for implementing Nitro as a Vite environment, which should speed up the dev server still further, as well as allowing more greater alignment in development with your Nitro preset.

    export default defineNuxtConfig({
      experimental: {
        viteEnvironmentApi: true
      }
    })
    

    This is also the first breaking change for Nuxt v5. You can opt in to these breaking changes by setting compatibilityVersion to 5:

    export default defineNuxtConfig({
      future: {
        compatibilityVersion: 5
      },
    })
    

    Please only use this for testing, as this opts in to unlimited future breaking changes, including updating to Nitro v3 once we ship the Nuxt integration.

    [!WARNING] This is highly experimental and the API may change. Only enable if you're prepared for potential breaking changes and want to help shape the future of Nuxt!

    📦 New @nuxt/nitro-server Package

    We've extracted Nitro server integration into its own package: @nuxt/nitro-server (#33462). This architectural change allows for different Nitro integration patterns and paves the way for future innovations in server-side rendering.

    While this change is mostly internal, it's part of our ongoing effort to make Nuxt more modular and flexible. The new package provides standalone Nitro integration and sets the foundation for alternative integration approaches (such as using Nitro as a Vite plugin in Nuxt v5+).

    [!NOTE] This is an internal refactor – no changes should be required in your code.

    ⚡ Performance Improvements

    We've also shipped several performance enhancements:

    • Precomputed renderer dependencies – We now compute renderer dependencies at build time rather than runtime, improving cold start and initial render performance (#33361)
    • Reduced dependencies – Removed unnecessary dependencies from kit and schema packages (7ae2cf563)

    📉 Async Data Handler Extraction

    One of the most exciting performance improvements is the new experimental async data handler extraction (#33131). When enabled, handler functions passed to useAsyncData and useLazyAsyncData are automatically extracted into separate chunks and dynamically imported.

    This is particularly effective for prerendered static sites, as the data fetching logic is only needed at build time and can be completely excluded from the client bundle.

    [!NOTE] In testing with a previous version of nuxt.com, this feature reduced JavaScript bundle size by 39%! Of course, your mileage may vary depending on how much data fetching logic you have.

    <script setup lang="ts">
    // This handler will be extracted into a separate chunk
    // and only loaded when needed
    const { data: post } = await useAsyncData('post', async () => {
      const content = await queryContent(`/blog/${route.params.slug}`).findOne()
      
      // Complex data processing that you don't want in the client bundle
      const processed = await processMarkdown(content)
      const related = await findRelatedPosts(content.tags)
      
      return {
        ...processed,
        related
      }
    })
    </script>
    

    For static/prerendered sites, enable it in your config:

    export default defineNuxtConfig({
      experimental: {
        extractAsyncDataHandlers: true
      }
    })
    

    The extracted handlers are then tree-shaken from your client bundle when prerendering, as the data is already available in the payload. This results in significantly smaller JavaScript files shipped to your users.

    🔧 Experimental TypeScript Plugin Support

    We're introducing experimental support for enhanced TypeScript developer experience through the @dxup/nuxt module.

    This module adds a number of TypeScript plugins that aim to improve your experience when using Nuxt-specific features:

    • Smart component renaming: Automatically updates all references when you rename auto-imported component files
    • Go to definition for dynamic imports: Navigate directly to files when using glob patterns like import(\~/assets/${name}.webp`)`
    • Nitro route navigation: Jump to server route handlers from data fetching functions ($fetch, useFetch, useLazyFetch)
    • Runtime config navigation: Go to definition works seamlessly with runtime config properties
    • Enhanced auto-import support: Includes the @dxup/unimport plugin for better navigation with auto-imported composables and utilities

    [!NOTE] Read more in the documentation.

    To enable this feature, set experimental.typescriptPlugin to true in your Nuxt configuration:

    export default defineNuxtConfig({
      experimental: {
        typescriptPlugin: true
      }
    })
    

    Once enabled, the module will be automatically installed and configured by Nuxt.

    [!IMPORTANT] This feature also requires selecting the workspace TypeScript version in VS Code. Run the "TypeScript: Select TypeScript Version" command and choose "Use Workspace Version".

    🎁 Other Improvements

    • Component declarationPath – You can now specify a custom declaration path for components (#33419)
    • Module resolution extensions – Kit's resolveModule now accepts an extensions option (#33328)
    • Global head utility – New setGlobalHead utility in kit for easier head management (#33512)

    🩹 Important Fixes

    • Route hash is now preserved when redirecting based on routeRules (#33222)
    • Fixed concurrent calls to loadNuxtConfig with proper cleanup (#33420)
    • Object-format href now works correctly in <NuxtLink> (c69e4c30d)
    • Component auto-imports now work as arguments to Vue's h() function (#33509)
    • Fixed app config array handling during HMR (#33555)

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe
    

    This will refresh your lockfile and pull in all the latest dependencies that Nuxt relies on, especially from the unjs ecosystem.

    👉 Changelog

    compare changes

    🚀 Enhancements

    • nuxt: Allow specifying component declarationPath (#33419)
    • kit: Add extensions option for resolveModule (#33328)
    • nuxt: Add abortController option to useAsyncData (#32531)
    • nuxt: Display youch error page w/ user error page in dev (#33359)
    • nuxt: Experimental typescript plugin support (#33314)
    • nuxt,schema: Extract asyncData handlers to chunks (#33131)
    • schema: Enable setting future.compatibilityVersion to 5 (22f4693a1)
    • kit,vite: Allow enabling vite environment api (#33492)
    • kit: Add setGlobalHead utility (#33512)

    🔥 Performance

    • nuxt: Precompute renderer dependencies at build time (#33361)
    • kit,schema: Remove some unnecessary dependencies (7ae2cf563)

    🩹 Fixes

    • nuxt: Preserve hash with redirecting based on routeRules (#33222)
    • kit: Safely cleanup loadNuxtConfig in concurrent calls (#33420)
    • nuxt: Allow object-format href in <NuxtLink> (c69e4c30d)
    • nuxt: Remove mergeModels from auto imports (#33344)
    • nuxt: Add back shortPath property (#33384)
    • nuxt: Do not allow native attrs to shadow nuxt link props (4751a6aca)
    • nuxt: Remove declarationPath from component dirs (191bcb7e9)
    • nuxt: Preserve root route in isPrerendered check (#33476)
    • nuxt: Exempt webpack vfs from pkg lookup (285eac31c)
    • nitro: Exempt nightly release from import protections (dd522394a)
    • webpack,rspack: Preserve prerender + nitro flags in server builds (#33503)
    • nuxt: Support component auto-imports as arguments of h() (#33509)
    • vite: Prevent assignment for rolldown's replacement plugin (#33526)
    • nuxt: Use sha256 hash for prerender cache keys (#33505)
    • nuxt: Add NuxtTime relative time numeric prop (#33552)
    • nuxt: Add NuxtTime relative time relativeStyle prop (#33557)
    • nuxt: Handle arrays in app config correctly during HMR (#33555)
    • vite: Unset optimizeDeps.include for server environment (#33550)

    💅 Refactors

    • Remove obsolete shortPath property (#33384)
    • kit: Extract trace utilities (9687505ac)
    • nuxt,vite,webpack: Allow builders to augment types (#33427)
    • schema: Deprecate extend, extendConfig, and configResolved hooks (e060b9695)
    • vite: Make vite plugins environment-compatible (#33445)
    • nitro,nuxt: Extract @nuxt/nitro-server package (#33462)
    • nuxt: Use RouteLocationNormalizedLoadedGeneric internally (b51cb3067)

    📖 Documentation

    • Update link to localisation issue (d32859da2)
    • Add nuxt module addServerPlugin note (#33409)
    • Remove deprecated node version (#33411)
    • Update declarationPath in addComponent (#33380)
    • Reproduction links for Nuxt v4 (#33429)
    • Add some notes/deprecations for vite hooks (31c5f26a2)
    • Fix incorrect ESM module field info (#33451)
    • Recommend getLayerDirectories() instead of nuxt.options._layers (#33484)
    • Add 4.x prefix (5c0bb9285)
    • Add docs for moduleDependencies (#33499)
    • Clarify extends removal in TypeScript config migration (#33523)
    • Pin codemod to v0.18.7 for migration recipe (#33522)
    • Fix links (#33554)

    🏡 Chore

    • Migrate gitpod to ona (#33159)
    • Use native node to run test:prepare (6ef632b82)
    • Do not use native node to run test:prepare (eca36cfe5)
    • Lint docs (3b9784111)
    • Update valid semantic scopes (3c38d1f8b)
    • Ignore nitro templates (27cf85bdc)
    • Update internal links (aac763017)
    • Remove vue-demi from ignoredBuiltDependencies (#33494)
    • Update vscode url (#33360)
    • Correct jsdoc location for function used as parameters (#33507)
    • Remove code comment (#33515)
    • Patch changelogen for large numbers of commits (bd36738b8)
    • Link Nuxt 1.x and 2.x (2016–2022) history to main (85838dfd9)
    • Filter out commits before last tag when constructing changelog (1c561daeb)
    • Also respect since date for bump type (08900f610)
    • Also respect since in nightly releases (74ca73ca1)
    • Ignore @rollup/plugin-commonjs (cd12980ce)

    ✅ Tests

    • Refactor suite to use common matrix utils (#33483)

    🤖 CI

    • Publish @nuxt/nitro-server on pkg-pr-new (b7ccf17bf)
    • Remove nitro-server publish until v4.2 is released (904d4f6ec)

    ❤️ Contributors

    • 山吹色御守 (@KazariEX)
    • Florian Heuberger (@Flo0806)
    • Daniel Roe (@danielroe)
    • Matej Černý (@cernymatej)
    • Trung Dang (@NamesMT)
    • 纸鹿/Zhilu (@L33Z22L11)
    • Julien Huang (@huang-julien)
    • Alexander Lichter (@TheAlexLichter)
    • abeer0 (@iiio2)
    • Max (@onmax)
    • Daniel Slepov (@imslepov)
    • Octavio Araiza (@8ctavio)
    • Bobbie Goede (@BobbieGoede)
    • DipakHalkude (@DipakHalkude)
    • Aleksander Błaszkiewicz (@ablaszkiewicz)
    Open source →
  16. 4.1.36 Oct 2025
    Release notes

    4.1.3 is a regularly scheduled patch release.

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🔥 Performance

    • vite: Use rolldown's replace plugin when applicable (#33258)

    🩹 Fixes

    • kit: Add default values when adding type references in prepare:types hook (#33239)
    • nuxt: Augment app config in server context (#33287)
    • nuxt: Make lazy component types compatible with h (#33046)
    • vite: Deduplicate inlined server style chunks (#33308)
    • nuxt: Support head option on useHead (#33318)
    • nuxt: Do not relativise importmap if cdnURL is set (#33333)
    • nuxt: Resolve aliases in imports.dirs (#33334)
    • nuxt: Add missing element/vnode props for <NuxtLink> (#33335)
    • nuxt: Do not generate server placeholder components (#33345)
    • nuxt: Dedupe generated component names (#33346)
    • webpack: Test watch instance before closing it (0e5a0a5a0)
    • nuxt: Correctly handle island rendering error (#33302)
    • nuxt: Support v-slot:fallback longform syntax in <DevOnly> (#33368)
    • nuxt: Support typeFrom when generating auto-import type templates (#33373)
    • nuxt: Don't trigger scroll when changing trailing slash (#33358)
    • nuxt: Add stubs for new scripts from @nuxt/scripts (bed410d60)
    • nuxt: Prevent duplicate execution on key change in useAsyncData (#33325)
    • nuxt: Make middleware _path property configurable for HMR (#33379)
    • nuxt: Handle non-immediate useAsyncData with different key on ssr (#33341)

    💅 Refactors

    • nuxt: Improve implementation of error composables (#33234)
    • nuxt: Resolve path of typed-router.d.ts early for consistency (#33285)
    • nuxt: Move server references to nitro:prepare:types hook (#33286)
    • nuxt: Place filename into componentsIslandsTemplate definition (#33394)
    • nuxt,vite: Use environment-api compatible plugins (#33403)

    📖 Documentation

    • Add 4.x prefix to all internal links (#33264)
    • Fix more links (#33265)
    • Update usage instructions for Windows users (#33284)
    • Update app config paths to use app/app.config.ts (#33297)
    • Remove d suffix in example (#33298)
    • Move directory structure to top-level (#33299)
    • Add information about useFetch reactivity (#33317)
    • Add more 4.x prefixes in urls (47ea684c7)
    • Lint code samples within docs (#33271)
    • Remove duplicated documentation from nuxt.config page (b438d44e1)
    • Remove docs for outdated asyncData configuration (3e4a999e6)
    • Note prepare command NODE_ENV behavior (#33330)
    • Update nuxt command pages (#33336)

    🏡 Chore

    ✅ Tests

    • nuxt: Set locale to en for nuxt-time tests (#33343)
    • Double gotoPath timeout in CI (f1e5a2d4c)

    🤖 CI

    • Add provenance action to check for downgrades in provenance (5ada6861e)
    • Pass commit sha when triggering ecosystem ci (399df6bab)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • 山吹色御守 (@KazariEX)
    • Julien Huang (@huang-julien)
    • Florian Heuberger (@Flo0806)
    • Ondrej Brendy (@bandiasek)
    • Octavio Araiza (@8ctavio)
    • Alex Liu (@Mini-ghost)
    • Bobbie Goede (@BobbieGoede)
    • abeer0 (@iiio2)
    • Harlan Wilton (@harlan-zw)
    • Alexander Lichter (@TheAlexLichter)
    • Sébastien Chopin (@atinux)
    • Ben Hong (@bencodezen)
    • Daniel Slepov (@imslepov)
    • Huseyn Guliyev (@husayt)
    • Hillary (@hillaryke)
    Open source →
  17. 4.1.212 Sept 2025
    Release notes

    4.1.2 is a regularly scheduled patch release.

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🔥 Performance

    • kit: Do not normalise templates in loop if dst is present (#33200)
    • nuxt: Remove watcher from hydrate-when lazy hydration strategy (#33199)
    • nuxt,schema: Normalise components + directories more efficiently (#33207)
    • kit,nuxt: Reduce unnecessary iteration in nuxt code (#33212)
    • nuxt: Skip running lazy hydration transform with filter (#33213)

    🩹 Fixes

    • schema: Add pkg-types to dependencies (9fe2541ca)
    • nuxt: Ignore errors when treeshaking composables within other composables (f99eac516)
    • nuxt: Do not tree-shake composables within other composables (#33153)
    • kit: Ensure module dependencies are typed correctly (4568e8451)
    • nuxt: Prevent Infinity backgroundSize in loading indicator (#33211)
    • nuxt: Remove unused enabled from components dir options (#32844)
    • nuxt: Sync watch request in useAsyncData (#33192)
    • nuxt: Move key imports logic after all modules run (#33214)

    📖 Documentation

    • Update reference to source dir (65712297a)
    • Update language on bridge head migration (c9d986889)
    • Update file path for pinia store (#33205)
    • Add app/ suffix to a few links (#33217)

    🏡 Chore

    ✅ Tests

    ❤️ Contributors

    • Julien Huang (@huang-julien)
    • Daniel Roe (@danielroe)
    • Adrien Foulon (@Tofandel)
    • Matej Černý (@cernymatej)
    • Антон Стасюк (@11Alone11)
    • wuiyang (@wuiyang)
    • Revadike (@Revadike)
    Open source →
  18. 4.1.15 Sept 2025
    Release notes

    v4.1.1 is a regularly scheduled patch release

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🩹 Fixes

    • nuxt: Correct relative path of auto imported components (#33122)
    • nuxt: Prefer accessing globalThis over window (#33125)
    • nuxt: Migrate to AST-aware tree-shaking + route injection (#33128)
    • nuxt: Ignore #components import mapping inside packages that use it internally (#33049)
    • vite: Remove explicit vite-node configuration of deps.inline (#33133)
    • nuxt: Include trace in dev-time useRoute usage warning (#33039)
    • kit: Improve DX by displaying module name when possible (#33137)
    • nuxt: Print route middleware path in warning (#33136)
    • nuxt: Include core auto-imports from imports:sources in override warning (#33050)
    • nuxt: Render relative importmap entry path if required (#33146)

    📖 Documentation

    • Add -- to bun create command (5e661f0ca)
    • Add app/ prefix in lots of cases (#33117)
    • Add JSDoc for navigateTo (#21442)

    🏡 Chore

    🤖 CI

    • Remove default discord reactions from thread (more noise than it's worth) (183913fe2)
    • Rewrite release workflow in ts + support multiple tags (4469ead82)
    • Pass correct flag (711037cda)
    • Pass tag via env variable (fb83cd5ba)
    • Drop 4x tags from releases (1cd8a6857)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Matej Černý (@cernymatej)
    • Bobbie Goede (@BobbieGoede)
    • Sébastien Chopin (@atinux)
    • Octavio Araiza (@8ctavio)
    • Michael Brevard (@GalacticHypernova)
    • abeer0 (@iiio2)
    • 山吹色御守 (@KazariEX)
    Open source →
  19. 4.1.02 Sept 2025
    Release notes

    👀 Highlights

    🔥 Build and Performance Improvements

    🍫 Enhanced Chunk Stability

    Build stability has been significantly improved with import maps (#33075). This prevents cascading hash changes that could invalidate large portions of your build when small changes are made:

    <!-- Automatically injected import map -->
    <script type="importmap">{"imports":{"#entry":"/_nuxt/DC5HVSK5.js"}}</script>
    

    By default, JS chunks emitted in a Vite build are hashed, which means they can be cached immutably. However, this can cause a significant issue: a change to a single component can cause every hash to be invalidated, massively increasing the chance of 404s.

    In short:

    1. a component is changed slightly - the hash of its JS chunk changes
    2. the page which uses the component has to be updated to reference the new file name
    3. the entry now has its hash changed because it dynamically imports the page
    4. every other file which imports the entry has its hash changed because the entry file name is changed

    Obviously this wasn't optimal. With this new feature, the hash of (otherwise) unchanged files which import the entry won't be affected.

    This feature is automatically enabled and helps maintain better cache efficiency in production. It does require native import map support, but Nuxt will automatically disable it if you have configured vite.build.target to include a browser that doesn't support import maps.

    And of course you can disable it if needed:

    export default defineNuxtConfig({
      experimental: {
        entryImportMap: false
      }
    })
    

    🦀 Experimental Rolldown Support

    Nuxt now includes experimental support for rolldown-vite (#31812), bringing Rust-powered bundling for potentially faster builds.

    To try Rolldown in your Nuxt project, you need to override Vite with the rolldown-powered version since Vite is a dependency of Nuxt. Add the following to your package.json:

    npm:

    {
      "overrides": {
        "vite": "npm:rolldown-vite@latest"
      }
    }
    

    pnpm:

    {
      "pnpm": {
        "overrides": {
          "vite": "npm:rolldown-vite@latest"
        }
      }
    }
    

    yarn:

    {
      "resolutions": {
        "vite": "npm:rolldown-vite@latest"
      }
    }
    

    bun:

    {
      "overrides": {
        "vite": "npm:rolldown-vite@latest"
      }
    }
    

    After adding the override, reinstall your dependencies. Nuxt will automatically detect when Rolldown is available and adjust its build configuration accordingly.

    For more details on Rolldown integration, see the Vite Rolldown guide.

    [!NOTE] This is experimental and may have some limitations, but offers a glimpse into the future of high-performance bundling in Nuxt.

    🧪 Improved Lazy Hydration

    Lazy hydration macros now work without auto-imports (#33037), making them more reliable when component auto-discovery is disabled:

    <script setup>
    // Works even with components: false
    const LazyComponent = defineLazyHydrationComponent(
      'visible',
      () => import('./MyComponent.vue')
    )
    </script>
    

    This ensures that components that are not "discovered" through Nuxt (e.g., because components is set to false in the config) can still be used in lazy hydration macros.

    📄 Enhanced Page Rules

    If you have enabled experimental extraction of route rules, these are now exposed on a dedicated rules property on NuxtPage objects (#32897), making them more accessible to modules and improving the overall architecture:

    // In your module
    nuxt.hook('pages:extend', pages => {
      pages.push({
        path: '/api-docs',
        rules: { 
          prerender: true,
          cors: true,
          headers: { 'Cache-Control': 's-maxage=31536000' }
        }
      })
    })
    

    The defineRouteRules function continues to work exactly as before, but now provides better integration possibilities for modules.

    🚀 Module Development Enhancements

    🪾 Module Dependencies and Integration

    Modules can now specify dependencies and modify options for other modules (#33063). This enables better module integration and ensures proper setup order:

    export default defineNuxtModule({
      meta: {
        name: 'my-module',
      },
      moduleDependencies: {
        'some-module': {
          // You can specify a version constraint for the module
          version: '>=2',
          // By default moduleDependencies will be added to the list of modules 
          // to be installed by Nuxt unless `optional` is set.
          optional: true,
          // Any configuration that should override `nuxt.options`.
          overrides: {},
          // Any configuration that should be set. It will override module defaults but
          // will not override any configuration set in `nuxt.options`.
          defaults: {}
        }
      },
      setup (options, nuxt) {
        // Your module setup logic
      }
    })
    

    This replaces the deprecated installModule function and provides a more robust way to handle module dependencies with version constraints and configuration merging.

    🪝 Module Lifecycle Hooks

    Module authors now have access to two new lifecycle hooks: onInstall and onUpgrade (#32397). These hooks allow modules to perform additional setup steps when first installed or when upgraded to a new version:

    export default defineNuxtModule({
      meta: {
        name: 'my-module',
        version: '1.0.0',
      },
    
      onInstall(nuxt) {
        // This will be run when the module is first installed
        console.log('Setting up my-module for the first time!')
      },
    
      onUpgrade(inlineOptions, nuxt, previousVersion) {
        // This will be run when the module is upgraded
        console.log(`Upgrading my-module from v${previousVersion}`)
      }
    })
    

    The hooks are only triggered when both name and version are provided in the module metadata. Nuxt uses the .nuxtrc file internally to track module versions and trigger the appropriate hooks. (If you haven't come across it before, the .nuxtrc file should be committed to version control.)

    [!TIP] This means module authors can begin implementing their own 'setup wizards' to provide a better experience when some setup is required after installing a module.

    🙈 Enhanced File Resolution

    The new ignore option for resolveFiles (#32858) allows module authors to exclude specific files based on glob patterns:

    // Resolve all .vue files except test files
    const files = await resolveFiles(srcDir, '**/*.vue', {
      ignore: ['**/*.test.vue', '**/__tests__/**']
    })
    

    📂 Layer Directories Utility

    A new getLayerDirectories utility (#33098) provides a clean interface for accessing layer directories without directly accessing private APIs:

    import { getLayerDirectories } from '@nuxt/kit'
    
    const layerDirs = await getLayerDirectories(nuxt)
    // Access key directories:
    // layerDirs.app        - /app/ by default
    // layerDirs.appPages   - /app/pages by default
    // layerDirs.server     - /server by default
    // layerDirs.public     - /public by default
    

    ✨ Developer Experience Improvements

    🎱 Simplified Kit Utilities

    Several kit utilities have been improved for better developer experience:

    • addServerImports now supports single imports (#32289):
    // Before: required array
    addServerImports([{ from: 'my-package', name: 'myUtility' }])
    
    // Now: can pass directly
    addServerImports({ from: 'my-package', name: 'myUtility' })
    

    🔥 Performance Optimizations

    This release includes several internal performance optimizations:

    • Improved route rules cache management (#32877)
    • Optimized app manifest watching (#32880)
    • Better TypeScript processing for page metadata (#32920)

    🐛 Notable Fixes

    • Improved useFetch hook typing (#32891)
    • Better handling of TypeScript expressions in page metadata (#32902, #32914)
    • Enhanced route matching and synchronization (#32899)
    • Reduced verbosity of Vue server warnings in development (#33018)
    • Better handling of relative time calculations in <NuxtTime> (#32893)

    ✅ Upgrading

    As usual, our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe
    

    This will refresh your lockfile and pull in all the latest dependencies that Nuxt relies on, especially from the unjs ecosystem.

    👉 Changelog

    compare changes

    🚀 Enhancements

    • kit: Add ignore option to resolveFiles (#32858)
    • kit: Add onInstall and onUpgrade module hooks (#32397)
    • nuxt,vite: Add experimental support for rolldown-vite (#31812)
    • nuxt: Extract defineRouteRules to page rules property (#32897)
    • nuxt,vite: Use importmap to increase chunk stability (#33075)
    • nuxt: Lazy hydration macros without auto-imports (#33037)
    • kit,nuxt,schema: Allow modules to specify dependencies (#33063)
    • kit,nuxt: Add getLayerDirectories util and refactor to use it (#33098)

    🔥 Performance

    • nuxt: Clear inline route rules cache when pages change (#32877)
    • nuxt: Stop watching app manifest once a change has been detected (#32880)

    🩹 Fixes

    • nuxt: Handle satisfies in page augmentation (#32902)
    • nuxt: Type response in useFetch hooks (#32891)
    • nuxt: Add TS parenthesis and as expression for page meta extraction (#32914)
    • nuxt: Use correct unit thresholds for relative time (#32893)
    • nuxt: Handle uncached current build manifests (#32913)
    • kit: Resolve directories in resolvePath and normalize file extensions (#32857)
    • schema,vite: Bump requestTimeout + allow configuration (#32874)
    • nuxt: Deep merge extracted route meta (#32887)
    • nuxt: Do not expose app components until fully resolved (#32993)
    • kit: Only exclude node_modules/ if no custom srcDir (#32987)
    • nuxt: Transform ts before page meta extraction (#32920)
    • nuxt: Compare final matched routes when syncing route object (#32899)
    • nuxt: Make vue server warnings much less verbose in dev mode (#33018)
    • schema: Allow disabling cssnano/autoprefixer postcss plugins (#33016)
    • kit: Ensure local layers are prioritised alphabetically (#33030)
    • kit,nuxt: Expose global types to vue compiler (#33026)
    • deps: Bump devalue (#33072)
    • nuxt: Support config type inference for defineNuxtModule().with() (#33081)
    • nuxt: Search for colliding names in route children (b58c139d2)
    • nuxt: Delete nuxtApp._runningTransition on resolve (#33025)
    • nuxt: Add validation for nuxt island reviver key (#33069)

    💅 Refactors

    • nuxt: Simplify page segment parsing (#32901)
    • nuxt: Remove unnecessary async/await in afterEach (#32999)
    • vite: Simplify inline chunk iteration (6f4da1b8c)
    • kit,nuxt,ui-templates,vite: Address deprecations + improve regexp perf (#33093)

    📖 Documentation

    • Switch example to use vitest projects (#32863)
    • Update testing setupTimeout and add teardownTimeout (#32868)
    • Update webRoot to use new app directory (df7177bff)
    • Add middleware to layers guide (6fc25ff79)
    • Use app/ directory in layer guide (eee55ea41)
    • Add documentation for --nightly command (#32907)
    • Update package information in roadmap section (#32881)
    • Add more info about nuxt spa loader element attributes (#32871)
    • Update features.inlineStyles default value (6ff3fbebb)
    • Correct filename in example (#33000)
    • Add more information about using useRoute and accessing route in middleware (#33004)
    • Avoid variable shadowing in locale example (#33031)
    • Add documentation for module lifecycle hooks (#33115)

    🏡 Chore

    • config: Migrate renovate config (#32861)
    • Remove stray test file (ca84285cc)
    • Ignore webpagetest.org when scanning links (6c974f0be)
    • Add type: 'module' in playground (#33099)

    ✅ Tests

    • Add failing test for link component duplication (#32792)
    • Simplify module hook tests (#32950)
    • Refactor stubbing of import.meta.dev (#33023)
    • Use findWorkspaceDir rather than relative paths to repo root (a6dec5bd9)
    • Improve router test for global transitions (5d783662c)
    • Use expect.poll (53fb61d5d)
    • Use expect.poll instead of expectWithPolling (357492ca7)
    • Use vi.waitUntil instead of custom retry logic (611e66a47)

    🤖 CI

    • Remove double set of tests for docs prs (6bc9dccf4)
    • Add workflow for discord team discussion threads (bc656a24d)
    • Fix some syntax issues with discord + github integrations (f5f01b8c1)
    • Use token for adding issue to project (66afbe0a2)
    • Use discord bot to create thread automatically (618a3cd40)
    • Only use discord bot (bfd30d8ce)
    • Update format of discord message (eb79a2f07)
    • Try bolding entire line (c66124d7b)
    • Oops (38644b933)
    • Add delay after adding each reaction (ecb49019f)
    • Use last lts node version for testing (e06e37d02)
    • Try npm trusted publisher (85f1e05eb)
    • Use npm trusted publisher for main releases (abf5d9e9f)
    • Change wording (#32979)
    • Add github ai moderator (#33077)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • abeer0 (@iiio2)
    • Julien Huang (@huang-julien)
    • kyumoon (@kyumoon)
    • Alexander Lichter (@TheAlexLichter)
    • Bobbie Goede (@BobbieGoede)
    • Rich Harris (@Rich-Harris)
    • mustafa60x (@mustafa60x)
    • Matej Černý (@cernymatej)
    • Alex Liu (@Mini-ghost)
    • Amitav Chris Mostafa (@semibroiled)
    • Romain Hamel (@romhml)
    • Jacky Lam (@jackylamhk)
    • Mukund Shah (@mukundshah)
    • Luke Nelson (@luc122c)
    • letianpailove (@letianpailove)
    • Erwan Jugand (@erwanjugand)
    • Alexander (@TheColorman)
    • Ryota Watanabe (@wattanx)
    • Yizack Rangel (@Yizack)
    Open source →
  20. 4.0.35 Aug 2025
    Release notes

    4.0.3 is a regularly scheduled patch release.

    👉 Changelog

    compare changes

    🔥 Performance

    • kit: Get absolute path from tinyglobby in resolveFiles (#32846)

    🩹 Fixes

    • nuxt: Do not throw undefined error variable (#32807)
    • vite: Include tsconfig references during typeCheck (#32835)
    • nuxt: Add sourcemap path transformation for client builds (#32313)
    • nuxt: Add warning for lazy-hydration missing prefix (#32832)
    • nuxt: Trigger call once navigation even when no suspense (#32827)
    • webpack: Handle null result from webpack call (84816d8a1)
    • kit,nuxt: Use reverseResolveAlias for better errors (#32853)

    📖 Documentation

    • Fix publicDir alias (#32841)
    • Mention bun.lock for lockfile (#32820)
    • Add a section about augmenting types with TS project references (#32843)
    • Improve explanation of global middleware (#32855)

    🏡 Chore

    • Update reproduction help text links (#32803)
    • Update pnpm ignored build scripts (#32849)
    • Improve internal types (052b98a35)

    ✅ Tests

    • Move tests for defineNuxtComponent out of e2e test (#32848)

    🤖 CI

    • Move nightly releases into different concurrency group (664041be7)

    ❤️ Contributors

    • RDistinct (@RDistinct)
    • Daniel Roe (@danielroe)
    • Oskar Lebuda (@OskarLebuda)
    • Peter Budai (@peterbud)
    • Matej Černý (@cernymatej)
    • Damian Głowala (@DamianGlowala)
    • Bobbie Goede (@BobbieGoede)
    • Robin (@OrbisK)
    • abeer0 (@iiio2)
    • Julien Huang (@huang-julien)
    Open source →
  21. 4.0.229 Jul 2025
    Release notes

    4.0.2 is the next patch release.

    Timetable: 28 July.

    👉 Changelog

    compare changes

    🩹 Fixes

    • nuxt: Provide typed slots for <ClientOnly> and <DevOnly> (#32707)
    • kit,nuxt,schema: Add trailing slash to some dir aliases (#32755)
    • nuxt: Constrain global defineAppConfig type (#32760)
    • kit: Include module types in app context (#32758)
    • nuxt: Include source base url for remote islands (#32772)
    • vite: Use vite node server to transform requests (#32791)
    • kit: Use mlly to parse module paths (#32386)
    • nuxt: Execute all plugins after error rendering error.vue (#32744)

    📖 Documentation

    • Update Nuxt installation command to use npm create nuxt@latest (#32726)
    • Add AI-assisted contribution guidelines (#32725)
    • Hydration best practice (#32746)
    • Add example for module .with() (#32757)
    • Replace dead Vue Router docs links (#32779)
    • Update nightly version references (#32776)

    🏡 Chore

    • Update reproduction links for bug-report template (#32722)
    • Update unbuild and use absolute path in dev stubs (#32759)

    ✅ Tests

    • Ignore vue module.exports export (c4317e057)

    🤖 CI

    • Release pkg.pr.new for main/3.x branches as well (b0f289550)
    • Apply 3x tag to latest v3 release (5f6c27509)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Bobbie Goede (@BobbieGoede)
    • Damian Głowala (@DamianGlowala)
    • Bobby (@xanzhu)
    • Dog (@dgxo)
    • Julien Huang (@huang-julien)
    • Stephen Jason Wang (@stephenjason89)
    • Mateleo (@Mateleo)
    • Robin (@OrbisK)
    • Alex Liu (@Mini-ghost)
    Open source →
  22. 4.0.121 Jul 2025
    Release notes

    v4.0.1 is the first regularly scheduled patch release of v4

    It will be followed up later this week with v3.18, which will backport a number of the features/fixes from Nuxt v4 to v3.

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🩹 Fixes

    • nuxt: Add nuxt.schema files to node tsconfig context (#32644)
    • nuxt,vite: Unpin nitropack (ed5ad64ad)
    • nuxt: Expose shared aliases within shared/ dir (#32676)

    💅 Refactors

    • nuxt: Pass file language directly to parser options (#32665)

    📖 Documentation

    • Remove rc tag in guide (232b14e2f)
    • Remove -t v4 tag from getting started (343f59235)
    • Added new Shared folder to the example of v4 folder structure (#32630)
    • Update nuxt.new links to v4 (#32639)
    • Improve grammar (#32640)
    • Typos (#32567)
    • Fix abbreviation (#32613)
    • Reference noUncheckedIndexedAccess rule change in v4 guide (#32643)
    • Add missing import in alias config example (#32648)
    • Correct alias for local fonts in styling guide (#32680)
    • Add best practices section (#31609)
    • Fix links to Nitro docs (#32691)

    📦 Build

    • vite: Specify nitropack types as external (39be1b3a9)

    🏡 Chore

    🤖 CI

    • Trigger website redeploy on main branch (#32695)

    ❤️ Contributors

    • Julien Huang (@huang-julien)
    • Alois Sečkár (@AloisSeckar)
    • Hashim Kalam (@hashimkalam)
    • Daniel Roe (@danielroe)
    • Matej Černý (@cernymatej)
    • Peter Buglavecz (@buglavecz)
    • Haythem Frikha (@Flamenate)
    • abeer0 (@iiio2)
    • Damian Głowala (@DamianGlowala)
    • Robin (@OrbisK)
    • Thomas (@ThomasWT)
    Open source →
  23. 4.0.015 Jul 2025
    Release notes

    Nuxt 4.0 is here! 🎉

    After a year of real-world testing, we're excited to announce the official release of Nuxt 4. This is a stability-focused major release, introducing a few thoughtful breaking changes in order to improve development experience.

    If you've been following along, you'll recognize many of these features and changes — and if you're new to them, we hope you'll welcome them.

    🔥 What's new?

    Nuxt 4 is all about making your development experience smoother:

    • Cleaner project organization with the new app/ directory structure
    • Smarter data fetching - we've taken the opportunity to address some inconsistencies and improve performance with the data layer
    • Better TypeScript support with project-based separation between the different contexts in your project - app code, server code, shared/ folder, and configuration
    • Faster CLI and development with adoption of internal sockets and a faster CLI

    Why these features in particular? Mostly because these kind of improvements have required making changes that are technically breaking.

    In general, we aim for a hype-free approach to releases. Rather than save up features for a big release, we've been shipping improvements in Nuxt 3 minor releases.

    We've also spent a lot of time figuring out how to implement these changes in a backwards-compatible way, and I hope that means that most Nuxt 3 projects can upgrade with a minimum of effort.

    I'd advise reading through the upgrade guide before you start, to understand what areas of your app might be affected.

    🗂️ New project structure

    The biggest visible change is how projects are organized. Your application code now lives in an app/ directory by default:

    my-nuxt-app/
    ├─ app/
    │  ├─ components/
    │  ├─ pages/
    │  ├─ layouts/
    │  └─ app.vue
    ├─ public/
    ├─ shared/
    ├─ server/
    └─ nuxt.config.ts
    

    This helps keep your code separate from node_modules/ and .git/, which makes file watchers faster (especially on Windows and Linux). It also gives your IDE better context about whether you're working with client or server code.

    [!TIP] Don't want to migrate? That's totally fine! Nuxt will detect your existing structure and keep working exactly as before.

    🎨 Updated UI templates

    Nuxt’s starter templates have an all new look, with improved accessibility, default titles, and template polish (#27843).

    🔄 Smarter data fetching

    We've made useAsyncData and useFetch work better. Multiple components using the same key now share their data automatically. There's also automatic cleanup when components unmount, and you can use reactive keys to refetch data when needed. Plus, we've given you more control over when cached data gets used.

    Some of these features have already been made available in Nuxt v3 minor releases, because we've been rolling this out gradually. Nuxt v4 brings different defaults, and we expect to continue to work on this data layer in the days to come.

    🔧 Better TypeScript experience

    Nuxt now creates separate TypeScript projects for your app code, server code, shared/ folder, and builder code. This should mean better autocompletion, more accurate type inference and fewer confusing errors when you're working in different contexts.

    [!TIP] With Nuxt 4, you will only need one tsconfig.json file in your project root!

    This is probably the single issue that is most likely to cause surprises when upgrading, but it should also make your TypeScript experience much smoother in the long run. Please report any issues you encounter. 🙏

    ⚡ Faster CLI and development

    In parallel with the release of v4, we've been working on speeding up @nuxt/cli.

    • Faster cold starts - Development server startup is noticeably faster
    • Node.js compile cache - Automatic reuse of the v8 compile cache
    • Native file watching - Uses fs.watch APIs for fewer system resources
    • Socket-based communication - The CLI and Vite dev server now communicate via internal sockets instead of network ports, reducing overhead — particularly on Windows

    These improvements combined can make a really noticeable difference in your day-to-day development experience, and we have more planned.

    🚀 How to upgrade

    Although any major release brings breaking changes, one of our main aims for this release is to ensure that the upgrade path is as smooth as possible. Most of the breaking changes have been testable with a compatibility flag for over a year.

    Most projects should upgrade smoothly, but there are a few things to be aware of:

    • Nuxt 2 compatibility has been removed from @nuxt/kit. (This will particularly affect module authors.)
    • Some legacy utilities and deprecated features have been cleaned up.
    • The new TypeScript setup might surface some type issues that were hidden before.
    • A few modules might need further updates for full Nuxt 4 compatibility.

    Don't worry though — for most breaking changes, there are configuration options to revert to the old behavior while you adjust.

    1. Update Nuxt

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    2. Optional: use migration tools

    We’ve also partnered with Codemod to automate many, though not all, migration steps:

    npx codemod@latest nuxt/4/migration-recipe
    

    3. Test and adjust

    Run your tests, check that everything builds correctly, and fix any issues that come up. The upgrade guide has detailed migration steps for specific scenarios.

    We'd recommend reading through it in full before starting your upgrade, to understand what areas of your app might be affected.

    🗺️ What's next?

    We're planning quick patch releases to address any issues that come up. Nuxt 3 will continue to receive maintenance updates (both bug fixes and backports of features from Nuxt 4) until the end of January 2026, so there's no rush if you need time to migrate.

    Looking ahead, we plan to release Nuxt 5 on the sooner side, which will bring Nitro v3 and h3 v2 for even better performance, as well as adopting the Vite Environment API for an improved (and faster!) development experience. And there's a lot more in the works too!

    And, quite apart from major releases, we have a lot of exciting features planned to make their way into Nuxt 3.x and 4.x release branches, including support for SSR streaming (#4753), a first-party accessibility module (#23255), built-in fetch caching strategies (#26017), more strongly typed fetch calls (landing in Nitro v3), dynamic route discovery (#32196), multi-app support (#21635) and more.

    ❤️ Thank you

    This release is credit to so many people, particularly those who have been testing v4 compatibility mode over the past year. I'm really grateful — thank you for all your help!

    Happy coding with Nuxt 4! 🚀

    👉 Changelog

    compare changes

    🚀 Enhancements

    • ui-templates: Update template branding for v4 (#27843)
    • deps: Upgrade to latest versions of c12, jiti and unbuild (#27995)
    • kit: Reimplement cjs utils using mlly (#28012)
    • nuxt: Generate basic jsdoc for module config entry (#27689)
    • schema: Split dev/prod build directories (#28594)
    • nuxt: Cache vue app build outputs (#28726)
    • deps: Update dependency vite to v6 (main) (#30042)
    • nuxt: Add integration with chrome devtools workspaces (#32084)
    • kit: Support single import in addServerImports (#32289)
    • nuxt: Add onWatcherCleanup to imports presets (#32396)
    • kit,nuxt,schema: Separate ts projects for node/app/nitro (#30665)
    • nuxt: Support lazy hydration macros (#31192)
    • nuxt: Export <NuxtTime> prop types (#32547)
    • nuxt: Add route announcer to default app.vue (#32621)
    • nuxt: Expose page routes to nitro for o11y (#32617)

    🔥 Performance

    • nuxt: ⚠️ Don't call render:html for server islands (#27889)
    • vite: Don't write stub manifest for legacy bundler (#27957)
    • kit: Update env expansion regex to match nitro (#30766)
    • vite: Communicate with vite-node via internal socket (#32417)

    🩹 Fixes

    • schema,vite: ⚠️ Do not allow configuring vite dev bundler (#27707)
    • schema: ⚠️ Default to compatibilityVersion: 4 (#27710)
    • nuxt: ⚠️ Emit absolute paths in builder:watch hook (#27709)
    • nuxt: ⚠️ Improve default asyncData value behaviour (#27718)
    • nuxt: ⚠️ Remove old experimental options (#27749)
    • kit: ⚠️ Support loading nuxt 4 and drop support for <=2 (#27837)
    • nuxt: ⚠️ Remove __NUXT__ after hydration (#27745)
    • ui-templates: Add default title back (3415241a6)
    • kit: ⚠️ Drop support for building nuxt 2 projects (1beddba6a)
    • nuxt: ⚠️ Bump internal majorVersion to 4 (7aae4033b)
    • kit: Mark resolvePath utils as sync (655e1473d)
    • kit: Revert change to tryResolveModule (2d136e04c)
    • kit: Add back requireModule and tryRequireModule (#28013)
    • nuxt: Hide unhandled error messages in prod (#28156)
    • nuxt: Add useScriptCrisp scripts stub (0c3cc4cf3)
    • nuxt: ⚠️ Remove unused globalName property (#28391)
    • nuxt: Use static import for updateAppConfig in HMR (#28349)
    • vite: Write dev manifest when ssr: false (#28488)
    • kit,nuxt,schema: ⚠️ Remove other support for nuxt2/bridge (#28936)
    • webpack: Only insert dynamic require plugin when building (b619b35e9)
    • nuxt: Guard window access (d874726ff)
    • nuxt: Remove unneeded subpath import (18a6ef1ca)
    • webpack: Handle new webpack chunk format (d293c06d2)
    • kit: ⚠️ Do not check compatibility for nuxt version < 2.13 (f94cda4c8)
    • ui-templates: Fix examples link and add bluesky (#30866)
    • vite: Use resolveId from vite-node to resolve deps (#30922)
    • nuxt: Import isEqual from main ohash export (3ec1a1e5e)
    • vite: Don't set output.preserveModules (ce49734aa)
    • nuxt: Ignore #app-manifest import in dev mode (#31539)
    • nuxt: Ensure layer array-type config is merged in order (#31507)
    • schema: Turn off purgeCachedData until v4 (7aa3a01ae)
    • schema: Re-enable purgeCachedData by default (06745604c)
    • webpack: Expand dynamic require regexp to match new pattern (62e700daa)
    • nuxt: Add back missing reset of .execute (d79e14612)
    • nuxt,schema: ⚠️ Remove support for compatibilityVersion: 3 (#32255)
    • kit,nuxt,schema,vite: ⚠️ Remove support for some deprecated options (#32257)
    • nuxt: ⚠️ Don't rerun asyncdata w/ existing data in useAsyncData (#32170)
    • nuxt: Scan nitro handlers before writing types (a3698c08b)
    • nuxt: Force asyncData errorValue/value to be undefined (7e4eac655)
    • nuxt: ⚠️ Remove public and assets aliases (#32119)
    • webpack: Update dynamic require pattern (#32278)
    • schema: ⚠️ Remove top level generate option (#32355)
    • ui-templates: Add aria tag on Nuxt logo (#32429)
    • nuxt: Augment runtime config in server context (#32482)
    • kit: Do not skip layer with defined srcDir (#32487)
    • deps: Upgrade to rc version of @nuxt/cli (#32488)
    • kit: Ensure legacy tsConfig doesn't exclude too many types (#32528)
    • kit: Ensure types of module entrypoints are in node project (#32551)
    • kit: Add layer app/ and server/ folders into tsconfigs (#32592)
    • schema: Disable changing compat version (#32600)
    • nuxt: Allow modules to add to typescript.hoist (#32601)
    • nuxt: Include shared declarations in tsconfig.server.json (#32594)
    • nuxt: Retain old data when computed key changes (#32616)
    • nuxt: ⚠️ Bump compatibilityDate to 2025-07-15 (e35e1ccb9)
    • nuxt: Only use scrollBehaviorType for hash scrolling (#32622)

    💅 Refactors

    • kit,nuxt: ⚠️ Drop nuxt 2 + ejs template compile support (#27706)
    • nuxt: ⚠️ Move #app/components/layout -> #app/components/nuxt-layout (209e81b60)
    • kit,nuxt,vite,webpack: ⚠️ Remove legacy require utils (#28008)
    • nuxt: Simplify check of dedupe option (#28151)
    • nuxt: Use direct import of installNuxtModule (501ccc375)
    • kit: Remove internal function (#32189)
    • schema: ⚠️ Remove config.schema.json export + defaults (#32254)
    • nuxt: Migrate to oxc-walker (#32250)
    • nuxt,schema: Use oxc for onPrehydrate transform (#32045)

    📖 Documentation

    • Indicate what useAsyncData must return (#28259)
    • Update deep default for useAsyncData & useFetch (#28564)
    • Fix link to issue (4d13f1027)
    • Improve wording for deep option (bec85dfcd)
    • Update v4 docs with new folder structure (#32348)
    • Update .nuxtignore examples for v4 structure (#32489)
    • Add reference to useNuxtData in data fetching composable pages (#32589)
    • Temporarily use v4 template for v4 docs (850a879d3)
    • Document the --modules flag in the init command (#32599)

    📦 Build

    • deps: Bump esbuild from 0.23.1 to 0.25.0 (#31247)

    🏡 Chore

    • Manage update to vite-plugin-checker separately (02d46dd3d)
    • Update docs typecheck command (#28433)
    • Improve accuracy of 4.x changelog (#28706)
    • Bump package versions internally to v4 (16fab7778)
    • kit: Fix regressed version v4 (a1c052057)
    • Dedupe lockfile (f14ef6bc9)
    • Update once more (4d22f4d5a)
    • Specify workspace engines.node compatibility (a26322f5f)
    • Remove special treatment for typescript (08766a0cd)
    • Reenable quarantine for webpack/memfs (for 3.x benefit) (9cb94e55e)
    • Remove extra dep (f0ec34298)
    • Add back nuxi (9aa4c7c3b)
    • Remove stray nuxi version again (#30547)
    • Fix lockfile (7d345c714)
    • Remove second version of vitest (#30868)
    • Ignore oxc-parser updates temporarily (1cd0fb5cb)
    • Ignore nitro/templates directory (e531477f8)
    • Fix ui-templates build (c8a1b9e80)
    • Mkdir for ui-templates (853408a1e)
    • Add webpack resolution (088bcd459)
    • Migrate playground + test fixtures to new directory format (#32357)
    • schema: Remove duplicated documentation (349f75447)

    ✅ Tests

    • Remove unused experimental options (6d971ddc9)
    • Add additional attw test for built packages (#30206)
    • Add minimal pages fixture (#30457)
    • Update bundle size assertion (f458153d9)
    • Update bundle size assertion (4cce6bf8d)
    • Benchmark minimal fixture instead (#31174)
    • Normalise scoped css + pass logger to configResolved (8d3bd4f9f)
    • More precise asyncData tests (023fb13eb)
    • Extend timeout when waiting for hydration (f34c6c240)
    • Also assert status (4f6bdf755)

    🤖 CI

    • Bump node v22 (#30251)
    • Run workflows on merge groups (ff37ad9df)
    • Do not invoke semantic-pr test on merge groups (fadd618d1)

    ⚠️ Breaking Changes

    • nuxt: ⚠️ Don't call render:html for server islands (#27889)
    • schema,vite: ⚠️ Do not allow configuring vite dev bundler (#27707)
    • schema: ⚠️ Default to compatibilityVersion: 4 (#27710)
    • nuxt: ⚠️ Emit absolute paths in builder:watch hook (#27709)
    • nuxt: ⚠️ Improve default asyncData value behaviour (#27718)
    • nuxt: ⚠️ Remove old experimental options (#27749)
    • kit: ⚠️ Support loading nuxt 4 and drop support for <=2 (#27837)
    • nuxt: ⚠️ Remove __NUXT__ after hydration (#27745)
    • kit: ⚠️ Drop support for building nuxt 2 projects (1beddba6a)
    • nuxt: ⚠️ Bump internal majorVersion to 4 (7aae4033b)
    • nuxt: ⚠️ Remove unused globalName property (#28391)
    • kit,nuxt,schema: ⚠️ Remove other support for nuxt2/bridge (#28936)
    • kit: ⚠️ Do not check compatibility for nuxt version < 2.13 (f94cda4c8)
    • nuxt,schema: ⚠️ Remove support for compatibilityVersion: 3 (#32255)
    • kit,nuxt,schema,vite: ⚠️ Remove support for some deprecated options (#32257)
    • nuxt: ⚠️ Don't rerun asyncdata w/ existing data in useAsyncData (#32170)
    • nuxt: ⚠️ Remove public and assets aliases (#32119)
    • schema: ⚠️ Remove top level generate option (#32355)
    • nuxt: ⚠️ Bump compatibilityDate to 2025-07-15 (e35e1ccb9)
    • kit,nuxt: ⚠️ Drop nuxt 2 + ejs template compile support (#27706)
    • nuxt: ⚠️ Move #app/components/layout -> #app/components/nuxt-layout (209e81b60)
    • kit,nuxt,vite,webpack: ⚠️ Remove legacy require utils (#28008)
    • schema: ⚠️ Remove config.schema.json export + defaults (#32254)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Connor Pearson (@cjpearson)
    • Stephen Jason Wang (@stephenjason89)
    • dwood-csi (@dwood-csi)
    • Alex (@hywax)
    • Alex Liu (@Mini-ghost)
    • Bobbie Goede (@BobbieGoede)
    • Marko (@aussieboi)
    • Igor Kononenko (@igorexa34314)
    • Alexander Lichter (@TheAlexLichter)
    • Robin (@OrbisK)
    • Matej Černý (@cernymatej)
    • Michael Brevard (@GalacticHypernova)
    • Andrej Adamcik (@adamcikado)
    • dependabot[bot] (@dependabot[bot])
    • Sébastien Chopin (@atinux)
    • Yauheni Vasiukevich (@EvgenyWas)
    • @beer (@iiio2)
    • Anthony Fu (@antfu)
    • pan93412 (@pan93412)
    • Tobias Diez (@tobiasdiez)
    • Aleksei Nagovitsyn (@al3xnag)
    • xjccc (@xjccc)
    • Julien Huang (@huang-julien)
    Open source →
  24. 4.0.0-rc.07 Jul 2025pre-release
    Release notes

    4.0.0-rc.0 is our first release candidate.

    🗺️ Roadmap

    This is our first release candidate. From now on we're focusing on bug fixes only until the release of v4 (we don't expect to merge additional features or breaking changes unless unexpectedly necessary to resolve bugs).

    We'd like to encourage users to test out adopting v4 from now on - feedback very welcome 🙏

    👉 Read more at https://nuxt.com/blog/roadmap-v4

    👉 Changelog

    compare changes

    🚀 Enhancements

    • nuxt: Export <NuxtTime> prop types (#32547)

    🩹 Fixes

    • nuxt: Skip external <NuxtLink>'s custom on click handler (#32499)
    • nuxt: Safe-guard extraPageMetaExtractionKeys (#32510)
    • nuxt: Expose loadBuilder error cause (3e0408bd8)
    • vite: Handle resolving string vite input (#32527)
    • kit: Ensure legacy tsConfig doesn't exclude too many types (#32528)
    • nuxt: Wrap only server components with island generic (#32540)
    • vite: Ignore when client entry cannot be resolved (6037b93dc)
    • kit: Ensure types of module entrypoints are in node project (#32551)

    📖 Documentation

    • Adjust wording to reduce confusion in lifecycle section (#32503)
    • Update fetch types (#32522)
    • Clarify that runtime env variables must start with NUXT_ (#32223)

    ✅ Tests

    • Reenable skipped unit tests (201cf1ac5)
    • Improve page scanning test stability (8eb92e66a)

    ❤️ Contributors

    • Andrei Hudalla (@paranoidPhantom)
    • Daniel Roe (@danielroe)
    • Alex (@hywax)
    • Julien Huang (@huang-julien)
    • Sigrid Huemer (@s1gr1d)
    • @xjccc
    • Alex Liu (@Mini-ghost)
    • Damian Głowala (@DamianGlowala)
    Open source →
  25. 4.0.0-alpha.427 Jun 2025pre-release
    Release notes

    4.0.0-alpha.4 is the fourth alpha release of Nuxt 4 for early testing

    🗺️ Roadmap

    👉 Read more at https://nuxt.com/blog/roadmap-v4

    👉 Changelog

    compare changes

    🚀 Enhancements

    • nuxt: Support lazy hydration macros (#31192)

    🩹 Fixes

    • nuxt: Ensure asyncData runs if changing key while fetcher is running (#32466)
    • kit: Do not skip layer with defined srcDir (#32487)
    • deps: Upgrade to rc version of @nuxt/cli (#32488)

    📖 Documentation

    • Update .nuxtignore examples for v4 structure (#32489)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Alex Liu (@Mini-ghost)
    • Robin (@OrbisK)
    Open source →
  26. 4.0.0-alpha.326 Jun 2025pre-release
    Release notes

    4.0.0-alpha.3 is the third alpha release of Nuxt 4 for early testing

    🗺️ Roadmap

    👉 Read more at https://nuxt.com/blog/roadmap-v4

    👉 Changelog

    compare changes

    🚀 Enhancements

    • nuxt: Add onWatcherCleanup to imports presets (#32396)
    • kit,nuxt,schema: Separate ts projects for node/app/nitro (#30665)

    🔥 Performance

    • nuxt: Decrease if checks when prerendering (#32455)
    • vite: Communicate with vite-node via internal socket (#32417)

    🩹 Fixes

    • nuxt: Handle pure hash link clicks with navigateTo (#32393)
    • nuxt: Set output.generatedCode.symbols for nitro build (#32358)
    • nuxt: Normalize segment catchall pattern before checking for parent (#32413)
    • nuxt: Lazily access runtimeConfig (#32428)
    • ui-templates: Add aria tag on Nuxt logo (#32429)
    • nuxt: Reload at base URL in nuxt:chunk-reload-immediate (#32382)
    • nuxt: Use rollup to calculate island component filenames (#32421)
    • nuxt: Augment runtime config in server context (#32482)
    • nuxt: Append set-cookie headers in error handler (#32483)

    💅 Refactors

    • vite: Migrate plugins internally to vite environments (#32461)

    📖 Documentation

    • Capitalise title (#32426)
    • Mention bun.lock for lockfile (#32427)
    • Clarify where logging tag is displayed (#32440)
    • Remove kit playground auto-import note (#32415)
    • Migrate to h3js (#32243)
    • Update the fetch clear function description (#32287)
    • defineNuxtPlugin function documentation (#32328)
    • Mention that <NuxtLink> encodes query params (#32361)
    • Enhance documentation for Nuxt composables (#32218)

    🏡 Chore

    • Rename deprecated vitest workspace to projects (#32388)
    • Remove space in URL in comment (#32394)
    • Allow setting TAG on commandline (43ac8ef01)
    • Update stackblitz reproduction link (6996303c2)

    ✅ Tests

    • nuxt: Add case for key only changes with immediate: false (#32473)
    • Separate nuxt legacy runtime tests (#32481)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Robin (@OrbisK)
    • Bobbie Goede (@BobbieGoede)
    • Ibrahimm (@Ibra-cesar)
    • Peter Budai (@peterbud)
    • Ali Soueidan (@lazercaveman)
    • Vachmara (@vachmara)
    • xjccc (@xjccc)
    • abeer0 (@iiio2)
    • David Stack (@davidstackio)
    • Damian Głowala (@DamianGlowala)
    • Mihailo Bursac (@djixadin)
    • Marko (@aussieboi)
    • Ezra Ashenafi (@Eazash)
    • Igor Kononenko (@igorexa34314)
    • 翠 (@sapphi-red)
    Open source →
  27. 4.0.0-alpha.212 Jun 2025pre-release
    Release notes

    4.0.0-alpha.2 is the second alpha release of Nuxt 4 for early testing

    🗺️ Roadmap

    👉 Read more at https://nuxt.com/blog/roadmap-v4

    👉 Changelog

    compare changes

    🚀 Enhancements

    • kit: Support single import in addServerImports (#32289)

    🩹 Fixes

    • webpack: Update dynamic require pattern (#32278)
    • nuxt: Update component loader regexp for minified code (#32298)
    • nuxt: Allow camelCase for lazy hydration attributes (#32297)
    • nuxt: Respect inheritAttrs: false in createClientOnly fn (#32323)
    • kit: Do not double-urlify file urls when resolving schema (#32354)
    • schema: ⚠️ Remove top level generate option (#32355)
    • nuxt: Align scroll behavior with page transition completion (#32239)

    📖 Documentation

    • Improve useCookie example (cf9f91e3f)
    • Update v4 docs with new folder structure (#32348)

    🏡 Chore

    • Update copilot instructions (483c05c9d)
    • Migrate playground + test fixtures to new directory format (#32357)
    • schema: Remove duplicated documentation (349f75447)

    🤖 CI

    • Set correct base branch label (#32325)

    ⚠️ Breaking Changes

    • schema: ⚠️ Remove top level generate option (#32355)

    ❤️ Contributors

    • Alex Liu (@Mini-ghost)
    • Daniel Roe (@danielroe)
    • Damian Głowala (@DamianGlowala)
    • Bobbie Goede (@BobbieGoede)
    • Julien Huang (@huang-julien)
    Open source →
  28. 4.0.0-alpha.12 Jun 2025pre-release
    Release notes

    4.0.0-alpha.1 is the first alpha release of Nuxt 4 for early testing

    We originally planned Nuxt 4 for June 2024, but things don't always go according to plan. I think it's appropriate to take a different approach:

    👉 Nuxt 4 alpha will ship June 2, 2025, with a stable release at the end of the month. Nuxt 5 will come later once Nitro v3 is ready.

    ...

    Today we release Nuxt v4 alpha 1! We'd love early adopters to test it. Please do report issues to Nuxt or any modules that you may be using.

    [!IMPORTANT]
    At the alpha stage, we are still planning additional breaking changes (and expect there will be bugs or 'friction'); at the beta stage, we are not planning breaking changes but they may occur if necessary. At the release candidate stage we expect only bug fixes.

    Here's what you can expect over the next few weeks:

    • We plan to open upstream PRs for community modules in the nuxt/modules registry, and create a migration guide for module authors.
    • We'll create a full upgrade guide for Nuxt 3 users, including a list of breaking changes and how to migrate. (The current upgrade guide explains how to enable compatibility mode, but there are some differences with Nuxt 4.)
    • We'll only release bugfixes for v3 this month, deferring backporting new features until after the release of v4.
    • We'll update the docs on nuxt.com to allow switching between 3.x, 4.x and (soon) 5.x documentation.
    • Once we release the release candidate (we're aiming for June 23) we'd love everyone to dive in again for a last round of testing. We'll only be expecting bugfixes from this point onward.
    • Once v4 is released, we'll separate the main branch to 4.x to adopt edge releases of h3 and nitro and begin development of Nuxt 5.

    [!TIP]
    You can follow the progress of the remaining work by checking these remaining tasks and the Nuxt 4 milestone on GitHub.

    I'm really excited with this timeline — and thank you for your patience and trust over the last year!

    👉 Read more at https://nuxt.com/blog/roadmap-v4

    compare changes

    🚀 Enhancements

    • kit,nuxt,schema,vite,webpack: Nitropack v3 nightly (#27702)
    • ui-templates: Update template branding for v4 (#27843)
    • deps: Upgrade to latest versions of c12, jiti and unbuild (#27995)
    • kit: Reimplement cjs utils using mlly (#28012)
    • nuxt: Generate basic jsdoc for module config entry (#27689)
    • schema: Split dev/prod build directories (#28594)
    • nuxt: Cache vue app build outputs (#28726)
    • deps: Update dependency vite to v6 (main) (#30042)
    • nuxt: Add integration with chrome devtools workspaces (#32084)

    🔥 Performance

    • nuxt: ⚠️ Don't call render:html for server islands (#27889)
    • vite: Don't write stub manifest for legacy bundler (#27957)
    • kit: Update env expansion regex to match nitro (#30766)
    • nuxt: Replace remaining instance of globby (#31688)

    🩹 Fixes

    • schema,vite: ⚠️ Do not allow configuring vite dev bundler (#27707)
    • schema: ⚠️ Default to compatibilityVersion: 4 (#27710)
    • nuxt: ⚠️ Emit absolute paths in builder:watch hook (#27709)
    • nuxt: ⚠️ Improve default asyncData value behaviour (#27718)
    • nuxt: ⚠️ Remove old experimental options (#27749)
    • kit: ⚠️ Support loading nuxt 4 and drop support for <=2 (#27837)
    • nuxt: ⚠️ Remove __NUXT__ after hydration (#27745)
    • ui-templates: Add default title back (3415241a6)
    • kit: ⚠️ Drop support for building nuxt 2 projects (1beddba6a)
    • nuxt: ⚠️ Bump internal majorVersion to 4 (7aae4033b)
    • kit: Mark resolvePath utils as sync (655e1473d)
    • kit: Revert change to tryResolveModule (2d136e04c)
    • kit: Add back requireModule and tryRequireModule (#28013)
    • nuxt: Hide unhandled error messages in prod (#28156)
    • nuxt: Add useScriptCrisp scripts stub (0c3cc4cf3)
    • nuxt: ⚠️ Remove unused globalName property (#28391)
    • nuxt: Use static import for updateAppConfig in HMR (#28349)
    • vite: Write dev manifest when ssr: false (#28488)
    • kit,nuxt,schema: ⚠️ Remove other support for nuxt2/bridge (#28936)
    • webpack: Only insert dynamic require plugin when building (b619b35e9)
    • nuxt: Guard window access (d874726ff)
    • nuxt: Remove unneeded subpath import (18a6ef1ca)
    • webpack: Handle new webpack chunk format (d293c06d2)
    • nuxt: Wrap slot with h() in ClientOnly (#30664)
    • kit: ⚠️ Do not check compatibility for nuxt version < 2.13 (f94cda4c8)
    • ui-templates: Fix examples link and add bluesky (#30866)
    • vite: Use resolveId from vite-node to resolve deps (#30922)
    • nuxt: Import isEqual from main ohash export (3ec1a1e5e)
    • vite: Don't set output.preserveModules (ce49734aa)
    • nuxt: Ignore #app-manifest import in dev mode (#31539)
    • nuxt: Ensure layer array-type config is merged in order (#31507)
    • schema: Turn off purgeCachedData until v4 (7aa3a01ae)
    • schema: Re-enable purgeCachedData by default (06745604c)
    • webpack: Expand dynamic require regexp to match new pattern (62e700daa)
    • nuxt: Add back missing reset of .execute (d79e14612)
    • nuxt: Remove unneeded pattern from regexp (cf4598d0d)
    • nuxt: Ensure appConfig sources are not duplicated (#32216)
    • nuxt,schema: ⚠️ Remove support for compatibilityVersion: 3 (#32255)
    • nuxt: Access asyncData state from nuxt app instance (#32232)
    • kit,nuxt,schema,vite: ⚠️ Remove support for some deprecated options (#32257)
    • nuxt: Make patterns relative to srcDir in buildCache (#32260)
    • nuxt: ⚠️ Don't rerun asyncdata w/ existing data in useAsyncData (#32170)
    • nuxt: Return non-existent route component in RouteProvider (#32266)
    • nuxt: Scan nitro handlers before writing types (a3698c08b)
    • nuxt: Force asyncData errorValue/value to be undefined (7e4eac655)
    • nuxt: ⚠️ Remove public and assets aliases (#32119)
    • nuxt: Use single asyncData watcher (#32247)

    💅 Refactors

    • kit,nuxt: ⚠️ Drop nuxt 2 + ejs template compile support (#27706)
    • nuxt: ⚠️ Move #app/components/layout -> #app/components/nuxt-layout (209e81b60)
    • kit,nuxt,vite,webpack: ⚠️ Remove legacy require utils (#28008)
    • nuxt: Simplify check of dedupe option (#28151)
    • nuxt: Use direct import of installNuxtModule (501ccc375)
    • kit: Remove internal function (#32189)
    • Downgrade to nitro v2 (#32252)
    • schema: ⚠️ Remove config.schema.json export + defaults (#32254)
    • nuxt: Migrate to oxc-walker (#32250)
    • nuxt,schema: Use oxc for onPrehydrate transform (#32045)

    📖 Documentation

    • Indicate what useAsyncData must return (#28259)
    • Update deep default for useAsyncData & useFetch (#28564)
    • Add props to special metadata (#29708)
    • Fix link to issue (4d13f1027)
    • Fix typos (#30413)
    • Update addRouteMiddleware path in example (#32171)
    • Narrow link to just middleware (#32203)
    • Use optional chaining in error example (#32214)
    • Give example of using --env-file (15fb7b30f)
    • Recommend nuxt command consistently (#32237)
    • Improve wording for deep option (bec85dfcd)
    • Fix wrong alert with warning in /guide/pages (#32270)

    📦 Build

    • deps: Bump esbuild from 0.23.1 to 0.25.0 (#31247)

    🏡 Chore

    ✅ Tests

    • Remove unused experimental options (6d971ddc9)
    • Add additional attw test for built packages (#30206)
    • Add minimal pages fixture (#30457)
    • Update bundle size assertion (f458153d9)
    • Update bundle size assertion (4cce6bf8d)
    • Benchmark minimal fixture instead (#31174)
    • Normalise scoped css + pass logger to configResolved (8d3bd4f9f)
    • More precise asyncData tests (023fb13eb)
    • Add regression test for useAsyncData + transition (8d65b941c)
    • Ensure builder tests run sequentially (095f5716f)

    🤖 CI

    • Bump node v22 (#30251)
    • Run workflows on merge groups (ff37ad9df)
    • Do not invoke semantic-pr test on merge groups (fadd618d1)

    ⚠️ Breaking Changes

    • nuxt: ⚠️ Don't call render:html for server islands (#27889)
    • schema,vite: ⚠️ Do not allow configuring vite dev bundler (#27707)
    • schema: ⚠️ Default to compatibilityVersion: 4 (#27710)
    • nuxt: ⚠️ Emit absolute paths in builder:watch hook (#27709)
    • nuxt: ⚠️ Improve default asyncData value behaviour (#27718)
    • nuxt: ⚠️ Remove old experimental options (#27749)
    • kit: ⚠️ Support loading nuxt 4 and drop support for <=2 (#27837)
    • nuxt: ⚠️ Remove __NUXT__ after hydration (#27745)
    • kit: ⚠️ Drop support for building nuxt 2 projects (1beddba6a)
    • nuxt: ⚠️ Bump internal majorVersion to 4 (7aae4033b)
    • nuxt: ⚠️ Remove unused globalName property (#28391)
    • kit,nuxt,schema: ⚠️ Remove other support for nuxt2/bridge (#28936)
    • kit: ⚠️ Do not check compatibility for nuxt version < 2.13 (f94cda4c8)
    • nuxt,schema: ⚠️ Remove support for compatibilityVersion: 3 (#32255)
    • kit,nuxt,schema,vite: ⚠️ Remove support for some deprecated options (#32257)
    • nuxt: ⚠️ Don't rerun asyncdata w/ existing data in useAsyncData (#32170)
    • nuxt: ⚠️ Remove public and assets aliases (#32119)
    • kit,nuxt: ⚠️ Drop nuxt 2 + ejs template compile support (#27706)
    • nuxt: ⚠️ Move #app/components/layout -> #app/components/nuxt-layout (209e81b60)
    • kit,nuxt,vite,webpack: ⚠️ Remove legacy require utils (#28008)
    • schema: ⚠️ Remove config.schema.json export + defaults (#32254)

    ❤️ Contributors

    • Alexander Lichter (@TheAlexLichter)
    • Julien Huang (@huang-julien)
    • Robin (@OrbisK)
    • Matej Černý (@cernymatej)
    • Daniel Roe (@danielroe)
    • Hugo Richard (@HugoRCD)
    • mxmxmmgg (@mxmxmmgg)
    • Baptiste Leproux (@larbish)
    • Phojie Rengel (@phojie)
    • Michael Brevard (@GalacticHypernova)
    • duolaameng (@1411430556)
    • David Stack (@davidstackio)
    • John Tanzer (@moshetanzer)
    • @beer (@iiio2)
    • हिमांशु (@CodeMan62)
    • Norbiros (@Norbiros)
    • watsonhaw5566 (@watsonhaw5566)
    • xjccc (@xjccc)
    • Ryota Watanabe (@wattanx)
    • Max (@onmax)
    • Alex Liu (@Mini-ghost)
    • Martins Zeltins (@martinszeltins)
    • Ivan Martianov (@ivansky)
    • Lorenzo Fiamingo (@lorenzofiamingo)
    • James (@Koshux)
    • Pooya Parsa (@pi0)
    • Kyohei Sonokawa (@kyohei-23)
    • Saeid Zareie (@Saeid-Za)
    • Bobbie Goede (@BobbieGoede)
    • Damian Głowala (@DamianGlowala)
    • Maxime Pauvert (@maximepvrt)
    • Leonid (@john-psina)
    • Wind (@productdevbook)
    • Arkadiusz Sygulski (@Aareksio)
    • Rohan Dhimal (@drowhannn)
    • Daniel Kelly (@danielkellyio)
    • Jeffrey van den Hondel (@jeffreyvdhondel)
    • Sébastien Chopin (@atinux)
    • Anthony Fu (@antfu)
    • Yizack Rangel (@Yizack)
    • Joaquín Sánchez (@userquin)
    • IlyaL (@ilyaliao)
    • Ben McCann (@benmccann)
    • Alexandru Ungureanu (@unguul)
    • Andrej Adamcik (@adamcikado)
    • Dennis Adriaansen (@dennisadriaans)
    • Guillaume Chau (@Akryum)
    • 翠 / green (@sapphi-red)
    • Johannes Buchholz (@jhony1104)
    • Claudiu (@sofuxro)
    • Anoesj Sadraee (@Anoesj)
    • Peter Radko (@Gwynerva)
    • Adam DeHaven (@adamdehaven)
    • Francesco Agnoletto (@Kornil)
    • imreegall (@imreegall)
    • Sam Blowes (@blowsie)
    • Nimit012 (@Nimit012)
    • Camille Coutens (@Kamsou)
    • Connor Pearson (@cjpearson)
    • Connor Roberts (@murshex)
    • Harlan Wilton (@harlan-zw)
    • dependabot[bot] (@dependabot[bot])
    • Kevin Deng 三咲智子 (@sxzz)
    • Maik Kowol (@94726)
    • Clayton Chew (@claytonchew)
    • awfulness (@awfulness)
    • Vahagn Zaqaryan (@Vahagn-Zaqaryan)
    • Idorenyin Udoh (@idorenyinudoh)
    • Jonas Thelemann (@dargmuesli)
    • Horu (@HigherOrderLogic)
    • Nolhan (@Nonolanlan1007)
    • Typed SIGTERM (@typed-sigterm)
    • Hans Tu (@ChiaHanTu)
    • David Marr (@marr)
    • Charlie ✨ (@CharleeWa)
    • Hussain Panahy (@HP8585)
    • Lansi (@lansi951)
    • Yauheni Vasiukevich (@EvgenyWas)
    • Alan Schio (@schirrel)
    • Zakhar Shymanchyk (@zakshyman)
    • Arturs Jansons (@iegik)
    • Peter Buglavecz (@buglavecz)
    • ikxin (@ikxin)
    • Guspan Tanadi (@guspan-tanadi)
    • Vuk Marjanovic (@vmrjnvc)
    • Clément Ollivier (@clemcode)
    • Anders Bootsmann Larsen (@bootsmann1995)
    • Nishant Aanjaney Jalan (@cybercoder-naj)
    • David Nahodyl (@Smef)
    • derHodrig (@skoenfaelt)
    • Matt (@matt-clegg)
    • Nikolay (@RokeAlvo)
    • bjoaquinc (@bjoaquinc)
    • wzc520pyfm (@wzc520pyfm)
    • Kraig Burrows (@zync09)
    • Sébastien LeBlanc (@mrleblanc101)
    • Teena (@franklin-tina)
    • skmedix (@skmedix)
    • Daniel Rentz (@danielrentz)
    • Inesh Bose (@ineshbose)
    • Felix Gabler (@felixgabler)
    • mianlang (@mianlang)
    • Tamás H. (@Tamas-hi)
    • Farnabaz (@farnabaz)
    • Jan-Niklas W. (@niklas-wortmann)
    • Gustavo Aquino Torres Teixeira (@guska8)
    • Stephanie Smith (@stephiescastle)
    • crisarji (@crisarji)
    • RBV1 (@RBV1)
    • Adrien Foulon (@Tofandel)
    • Efraim (@EfraimGENC)
    • Aurion SARL (@TonyFresneau)
    • Erik Lilja (@Lilja)
    • Markus Oberlehner (@maoberlehner)
    • Lukas Bauer (@luxterful)
    • Till Sanders (@tillsanders)
    • Nils (@BracketJohn)
    • Estéban (@Barbapapazes)
    • Cruz (@SparK-Cruz)
    • Taras Batenkov (@enkot)
    • Panopoulos Andreas (@b0ul17)
    • Dawit (@oneminch)
    • Ryoya (@harunari0928)
    • Alexander (@hywax)
    • Jelmer (@jelmerdemaat)
    • Christoph Heike (@cheike569)
    • Jeremy Graziani (@AcelisWeaven)
    • Domenik Reitzner (@dreitzner)
    • Jeel Rupapara (@zeelrupapara)
    • Leopold Kristjansson (@leopoldkristjansson)
    • Horváth Bálint (@horvbalint)
    • Bochkarev Ivan (@Ibochkarev)
    • Joschua (@selfire1)
    • Indrek Ardel (@Ingramz)
    • DarkVen0m (@DarkVen0m)
    • Ezra Ashenafi (@Eazash)
    • Artem Maslov (@Twocram)
    • Paulo Ricardo Severo (@prsevero)
    • Liran Tal (@lirantal)
    • Osama Abdallah Essa Haikal (@OsamaHaikal)
    • Gianluca Di Francesco (@gianlucadifrancesco)
    • Heb (@Hebilicious)
    • Eckhardt (Kaizen) Dreyer (@Eckhardt-D)
    • Ismail Sabet (@ismailsabet)
    • riskrole (@riskrole)
    • Thimo Sietsma (@th1m0)
    • felix-dolderer (@felix-dolderer)
    • Nicolas Payot (@nicolaspayot)
    • Kewin Szlezingier (@kewinzaq1)
    • Vasily Kuzin (@ExEr7um)
    • Gustav Odinger (@gustavwilliam)
    • Martin André (@Martichou)
    • Mike Laumann Bellika (@MikeBellika)
    • Son Tran (@trandaison)
    • rubyisrust (@rubyisrust)
    • Riley Ho (@rileychh)
    • Potter (@yxw007)
    • Martin Masevski (@Archetipo95)
    • BoogieBen. (@boogie-ben)
    • Tobias Diez (@tobiasdiez)
    • Yasser Lahbibi (@yassilah)
    • pan93412 (@pan93412)
    • AuroraTea (@AuroraTea)
    • nuxt-studio[bot] (@nuxt-studio[bot])
    • Vaci (@vacijj)
    • FELIPE COSTA DE OLIVEIRA (@FelipeO16)
    • Aleksei Nagovitsyn (@al3xnag)
    • Meo (@miaobuao)
    • Mohab Sameh (@mohab-sameh)
    • Quentin Macq (@quentinmcq)
    • Johan Krijt (@johankrijt)
    • arshcodemod (@arshcodemod)
    • Santiago A (@santiagoaloi)
    • Thomas (@ThomasWT)
    • Dominic (@rexhent)
    • Florian Metz (@Timeraa)
    • Daniel Flanagan (@FlantasticDan)
    • 山吹色御守 (@KazariEX)
    • izzy goldman (@izzygld)
    • Seno (@s-en-o)
    • Aviv Keller (@avivkeller)
    • Lucie (@lihbr)
    Open source →
  29. 4.0.0-015 May 2025pre-release

    Nothing published for this version

  30. 3.21.115 Aug 2026
    Release notes

    3.21.11 is a patch release.

    [!IMPORTANT] Nuxt v3 is now end-of-life. Please upgrade to Nuxt v4, or you may wish to check out our partner HeroDevs who provide never-ending support for end-of-life releases

    👉 Changelog

    compare changes

    🩹 Fixes

    • nuxt: Serialize island payloads for components with underscores in keys (#35807)
    • nitro: Dedupe island renders when prerendering (#35835)
    • nitro: Reject non-object island props (#35867)
    • nuxt: Re-check for preview mode after prerendered page hydration (#35886)
    • nuxt: Settle asyncData status when bailing (#35908)
    • kit: Clone resolved config with klona rather than klona/full (#35914)
    • nuxt: Use client-side navigation for links inside islands (#35806)
    • nuxt: Match route rules against decoded paths (81f86ac5e)

    🏡 Chore

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Samuel Burkhard (@samydoesit)
    • Alexander Lichter (@TheAlexLichter)
    Open source →
  31. 3.21.1027 Jul 2026
    Release notes

    ⚠️ This is a security release. We recommend upgrading as soon as possible with npx nuxt upgrade --dedupe.

    It fixes server-side RCE and unauthorized component instantiation via server island props, a route rule authorization bypass, server component DoS, and dev server path disclosure. Refreshing your lockfile also pulls in @nuxt/[email protected], which fixes a separate critical development-only RCE.

    If you already upgraded for the earlier route rule advisory (CVE-2026-53721), you still need this release: one of the fixes addresses a regression introduced by that fix.

    Full details: Nuxt Security Patch Releases and GitHub Security Advisories.

    👉 Changelog

    compare changes

    🩹 Fixes

    • nuxt: Clear hide/reset timeouts in set() (#35534)
    • nuxt: Preserve trailing slash in NuxtLink href when unset (#35501)
    • vite: Resolve SSR inlined CSS module class name mismatch (#35610)
    • nuxt: Sync layout meta during middleware on SSR (#35633)
    • nuxt: Update client URL to match SSR on fatal middleware error (#35637)
    • nuxt: Watch external component directories in development (#35652)
    • nuxt: Don't cross-pollute useAsyncData cache on reactive key change (#35656)
    • nuxt: Return global route for useRoute in detached effect scope (#35659)
    • nuxt: Ignore custom name or path when reusing an existing page in pages:extend (#35661)
    • nuxt: Preserve explicit useFetch method inference (#35671)
    • nuxt: Correct default export detection in plugin metadata (#35676)
    • nuxt: Reload real page module on HMR of JSX render-function pages (#35678)
    • vite: Ensure server sourcemap-preserver plugin actually runs (#35680)
    • nuxt: Resolve @unhead/vue/* from nuxt's dependency tree (#35690)
    • nuxt: Don't apply scroll behaviour after a subsequent nav (#35719)
    • vite: Preserve css suffix when extracting ssr inline styles (#35714)
    • nuxt: Don't exclude client entry module from style extraction (#35720)
    • kit: Avoid mutating layer configs when resolving options (#35729)
    • nuxt: Generate layout types even when pages module is disabled (#35717)
    • nitro: Skip resource hints for stylesheets already rendered as blocking links (#35691)
    • nuxt: Revalidate cached route payloads instead of using force-cache (#35672)
    • nuxt: Preserve query params in cached payload extraction (#35696)
    • rspack,webpack: Resolve loaders and runtime deps from nuxt dirs (#35568)
    • nuxt: Render client components in nested server components (#35669)
    • nuxt: Remove dev error overlay when error is cleared (#35821)
    • rspack,webpack: Resolve bundled postcss defaults from builder (#35823)
    • schema: Normalise slashes in app.buildAssetsDir (#35833)
    • nuxt: Case-fold route rule keys to match folded lookups (619963309)
    • nitro: Require loopback peer for chrome devtools workspace endpoint (00f71bb65)
    • nitro: Bound island props and v-for to prevent unauthenticated DoS (668cdfdfd)
    • nuxt: Reject reserved template island prop under runtime compiler (5b60017f7)
    • nuxt: Reject top-level as prop for islands (00a2b0494)

    📖 Documentation

    • Document relative baseURL workarounds (#34004)
    • Warn about runtimeCompiler security best practices (b76c1a8bd)
    • Warn about validating server component props (f6d72628d)

    ✅ Tests

    • Guard against transient undefined _route in gotoPath (5391e7e6a)
    • Raise route-HMR polling timeout to reduce e2e flakiness (cbc757c63)
    • kit: Scope loadNuxt temp dir so it doesn't delete sibling fixtures (72e4b5578)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Florian Heuberger (@Flo0806)
    • Matej Černý (@cernymatej)
    • bdbch (@bdbch)
    • Elecmonkey (@elecmonkey)
    • Ryota Watanabe (@wattanx)
    • kealan (@KealanAU)
    • Julien Huang (@huang-julien)
    • Luke Nelson (@luc122c)
    • Harlan Wilton (@harlan-zw)
    • Mateleo (@Mateleo)
    • lutejka (@lutejka)
    • Darlan José Batista do Prado (@DarlanPrado)
    • Max (@onmax)
    • Sushant (@sushantguri)
    • raminjafary (@raminjafary)
    Open source →
  32. 3.21.918 Jul 2026
    Release notes

    3.21.9 is the next patch release.

    👉 Changelog

    compare changes

    🩹 Fixes

    • vite: Use spa entry for vite-node fallback (3.x) (c8410a16a)
    • kit,nuxt: Pass error as cause when we re-throw (#35387)
    • vite: Inline CSS for lazy components imported from #components (#35215)
    • nuxt: Validate <ClientOnly> fallback tag name (#35325)
    • vite: Extract server page CSS when inlineStyles is disabled (#35209)
    • nitro: Include nested layers in nitro transforms (#35327)
    • nitro: Export empty styles object with ssr: false (#35330)
    • nuxt: Emit auto-import paths as files, not directories (#35333)
    • nuxt: Suppress spurious slot warning in NuxtPage during nav (#35335)
    • vite: Preserve backslash separators in windows named pipe path (#35336)
    • nuxt: Detach in-flight promise on useAsyncData teardown (#35328)
    • nuxt: Respect per-page keepalive set via definePageMeta (#34526)
    • nuxt: Align useFetch error type with runtime (#35346)
    • nuxt: Unwrap getter body in useFetch (#35343)
    • rspack,webpack: Strip invalid webpack PURE annotations (#35386)
    • nuxt: Guard against -1 when unregistering a router hook (#35391)
    • nuxt: Clean up load/error listeners in preloadPayload (#35392)
    • nuxt: Avoid idle wait when refreshing data after hydration (#35358)
    • nuxt: Ensure page:start finishes before page:finish starts (#35408)
    • nuxt: Preserve plugin navigation during app boot (#35344)
    • vite: Add extension to vite-node-runner virtual import (e81a0c484)
    • nuxt: Make virtual module IDs stable across hosts (#35317)
    • nuxt: Hash serialized island props (#35356)
    • vite: Avoid emitted ssr styles file name collisions (#35432)
    • nuxt: Avoid syncing route too early when reused page remounts (#35440)
    • nuxt: Keep nested layout on deferred route during suspended layout switch (#35443)
    • vite: Set define for NODE_ENV and __VUE_PROD_DEVTOOLS__ (#35444)
    • nuxt: Restore deferred query route before page is mounted (#35442)
    • nuxt: Make islands hash backwards-compatible (#35452)
    • nuxt: Pass nuxt rootDir to typed-router context (#35565)
    • nitro: Only reload nitro after initial nitro build (6ba8e26a5)
    • schema: Enable HMR for defineNuxtComponent in JSX (#35620)
    • schema: Resolve Vite cache directory from workspace (#35626)
    • nitro: Write prerender cache files atomically (#35619)
    • nuxt: Apply latest navigation on concurrent navigateTo in built-in router (#35631)

    📖 Documentation

    • Improving testing documentation for better understanding (#35526)
    • Add tip about prerendering registration for pages (#35635)
    • Clarify useFetch custom data error (#35647)
    • Drop reference to non-existent section (bd1943d04)
    • Update link to /3.x slug (71bdb972d)

    🏡 Chore

    • Allow node version updates (#35297)

    ✅ Tests

    • Assert dev css delivery transport for server pages (9851e993b)
    • Count only render-blocking stylesheet links for page styles (b0e895a7f)
    • Await expectNoClientErrors (afffe7f09)

    🤖 CI

    • Handle missing base branch (for stacked prs) (13a933f8a)
    • Unlink issues from autoclosed PRs (#35615)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Florian Heuberger (@Flo0806)
    • Mateleo (@Mateleo)
    • Luke Nelson (@luc122c)
    • Darlan José Batista do Prado (@DarlanPrado)
    • Julien Huang (@huang-julien)
    • skoenfaelt (@skoenfaelt)
    • Anoesj Sadraee (@Anoesj)
    • raminjafary (@raminjafary)
    • Kurt Medley (@HeavyMedl)
    • isksss (@isksss)
    • Alexander Lichter (@TheAlexLichter)
    • Damian Głowala (@DamianGlowala)
    • Sami El Achi (@samiashi)
    Open source →
  33. 3.21.88 Jun 2026
    Release notes

    3.21.8 is a hotfix release to address an issue running the dev server on MacOS.

    👉 Changelog

    compare changes

    🩹 Fixes

    • vite: Shorter socket name for macOs with tmp fallback (#35265)
    • kit: Respect type option in findPath (#35272)
    • deps: Update nuxt/scripts presets (ff6b060dd)

    📖 Documentation

    • Change null to undefined in data-fetching docs to match actual types (#35301)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Ali Mahmmoud (@AliMahmoudDev)
    • Quentin Macq (@quentinmcq)
    • Eduardo San Martin Morote (@posva)
    Open source →
  34. 3.21.72 Jun 2026
    Release notes

    3.21.7 is the a security hotfix release.

    👉 make sure to check https://github.com/nuxt/nuxt/security/advisories to view open advisories resolved by this release.

    👉 Changelog

    compare changes

    🩹 Fixes

    • nitro: Assign noSSR before deciding payload extraction (#35108)
    • vite: Avoid filtering out dirs with shared prefix from allowDirs (#35112)
    • nuxt: Use resolve from pathe for buildCache path boundary check (#35111)
    • nuxt: Prevent sibling-directory traversal in test component wrapper (#35110)
    • nitro: Pass event data to isValid in dev clipboard-copy listener (#35109)
    • nuxt: Validate protocols in reloadNuxtApp path before reload (#35115)
    • vite: Resolve vite clientServer with ssr: false (#34959)
    • vite: Prefix public asset virtuals with null byte (38d330179)
    • nuxt: Handle missing payload in chunkError listener (#35155)
    • vite: Close vite dev server on nuxt close (d007d7060)
    • kit,nuxt: Handle cancelling prompts to install packages (59821a5ca)
    • nuxt: Await in-lifght template generation when closing nuxt (#35181)
    • webpack: Surface compilation errors when stats.toString is empty (71dccff2b)
    • kit: Improve TS extension stripping/substitutions (#35233)
    • nuxt: Preserve .d.mts/.d.cts in resolveTypePaths (#35235)
    • nuxt: Reject prototype-chain keys in the island registry (#35205)
    • nitro: Gate chrome devtools workspace endpoint to local requests (#35201)
    • nuxt: Escape props in <NuxtClientFallback> ssr output (#35199)
    • nuxt: Apply isScriptProtocol guard to navigateTo open option (#35206)
    • rspack,webpack: Require loopback host when missing same-origin signals (#35200)
    • nuxt: Absolutely resolve defu in app config template (40bedf0db)
    • nuxt: Match route rules case-insensitively to mirror vue-router (3f3e3fa7b)
    • nuxt: Escape <NoScript> slot content (7fea9fd68)
    • nuxt: Block path-normalization open redirect in navigateTo (1f2dd5e78)
    • nuxt: Reject cross-origin paths in reloadNuxtApp (6497d99dd)
    • vite: Bind vite-node IPC to a permissioned filesystem socket (c293bf950)
    • nuxt: Reject script-capable protocols in <NuxtLink> href (53284043d)
    • nuxt: Clarify page and layout usage warnings (#35184)
    • nuxt: Do not absolutely resolve defu (d11d7b1b5)

    📖 Documentation

    • Edit for clarity and grammar (#35214)
    • Add dedicated module dependencies page (#35171)

    🏡 Chore

    • Use execFileSync for safety in release scripts (9a455a658)
    • Assert there is always a tag (8da21fba8)
    • Fix type in test (bc2837125)
    • Fix lychee dynamic composable exclude (#35119)
    • Add autofix action tag in comment (70eba297f)
    • Update renovate minimum release age (27a6821a1)

    ✅ Tests

    • Update test for js payload rendering (b51a80840)
    • Improve reliability of hmr test (0078499f0)

    🤖 CI

    • Always run all tests for 4.x/3.x (0519c0ade)
    • Update to agentscan v1.8.0 (#35120)
    • Automatically close PRs from automated accounts (#35161)
    • Migrate from tibdex (6277aedcb)
    • Disable provenance-change enforcement in dependency-review (1d4910eed)
    • Add zizmor github actions check (#35089)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Matej Černý (@cernymatej)
    • anton-gor-dev (@anton-gor-dev)
    • Julien Huang (@huang-julien)
    • David Stack (@davidstackio)
    • Noah3521 (@Noah3521)
    • Matteo Gabriele (@MatteoGabriele)
    • Mohit Kumar (@mohitkum4r)
    • Florian Heuberger (@Flo0806)
    Open source →
  35. 3.21.618 May 2026
    Release notes

    3.21.6 is the next patch release.

    👉 Changelog

    compare changes

    🩹 Fixes

    • nuxt: Prefer our own builder/server deps (#35029)
    • nitro: Add json extension to payload cache items (#35043)
    • nuxt: Handle errors fetching app manifest (#35050)
    • nuxt: Preserve setPageLayout props on same-path navigation (#35055)
    • vite: Don't strip buildAssetsDir from vite-node SSR ids (#35040)
    • nuxt: Mark useLoadingIndicator properties as readonly (#35062)
    • vite: Strip queries in css inline styles map (#35067)
    • nuxt: Encode html-significant characters in external redirect body (#35052)
    • nitro: Validate island request hash matches props (#35077)
    • nitro: Use regexp to strip query (042b615e6)
    • nitro: Use statusCode for nitro v2 compatibility (82dcd6a31)
    • nuxt: Render component-less parent routes during client-side nav (#35036)
    • nuxt: Run middleware for page islands (#35092)

    💅 Refactors

    • rspack,webpack: Extract same-origin check for dev middleware (#35051)

    📖 Documentation

    • Remove CSB, set node 22 and use steps for clarity (#35066)

    🏡 Chore

    ✅ Tests

    • Relax relative time assertion (256513eb0)
    • Move build assets dir fixture out of app/ (6d2ac69ff)

    🤖 CI

    • Clean up agent-scan workflow (31590cf07)
    • Continue autofix workflow when test:engines fails (958abb882)
    • Improve workflows (#35088)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Julien Huang (@huang-julien)
    • Damian Głowala (@DamianGlowala)
    • Sébastien Chopin (@atinux)
    • Adrien Foulon (@Tofandel)
    Open source →
  36. 3.21.510 May 2026
    Release notes

    3.21.5 is the next patch release.

    👉 Changelog

    compare changes

    🔥 Performance

    • kit: Cache layer roots and short-circuit isIgnored relative (#35015)

    🩹 Fixes

    • nitro: Correct payload route rule for / + override ssr: true (#34990)
    • nitro: Break recursive rendering deadlocks during prerender (#34939)
    • vite: Drop redundant css link when entry styles are inlined (#34950)
    • nuxt: Only force suspense remount after first resolve (#34949)
    • kit: Read .env before resolving nuxt schema (#34958)
    • nitro: Preserve serverHandlers array after nitro:config (#34985)
    • vite: Only consider CSS inlined when styles are actually emitted (#35006)
    • nuxt: Handle string presets in auto-imports (#35013)
    • nuxt: Correct island transform for server pages and 'deep' mode (#35005)
    • vite: Inline css for non-island children of server components (#35001)
    • nuxt: Defer head DOM updates until page transition finishes (#35016)
    • nuxt: Explicitly freeze head during island plugin phase (#35010)
    • vite: Inline css imported from non-vue js modules (#35020)
    • nitro: Remove unused middleware (fe857d36b)

    📖 Documentation

    • Add warning about routing in server components (#34994)

    🏡 Chore

    • Ignore pnpm cyclic workspace deps warn (#34998)
    • Remove jiti from build steps (#35004)
    • Fix lockfile (48e56a509)
    • nuxt: Cast to nitro event handler type (5b358ca19)

    ✅ Tests

    • Extract server components fixture + add some failing tests (#34995)
    • Isolate buildDir per matrix project for shared fixtures (#35007)
    • Split env testing into separate file (fd4019cf8)
    • Use 3.x style tsconfig (86625efad)
    • Use more 3.x style tsconfigs (4a9bde3f3)
    • Correct import path (133d5f6d7)
    • Update snapshots (9fc42f788)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Harlan Wilton (@harlan-zw)
    • Jonazzzz (@Bombastickj)
    • Damian Głowala (@DamianGlowala)
    • Florian Heuberger (@Flo0806)
    Open source →
  37. 3.21.429 Apr 2026

    Nothing published for this version

  38. 3.21.212 Mar 2026

    Nothing published for this version

  39. 3.21.17 Feb 2026
    Release notes

    3.21.1 is a regularly schedule patch release.

    👉 Changelog

    compare changes

    🩹 Fixes

    • nuxt: Correct reference format of server builder (#34177)
    • nuxt: Add status/statusText getters to NuxtError (#34188)
    • schema: Add direnv and vendor to default ignore (#34190)
    • nuxt: Focus hash links after navigation (#34193)
    • nuxt: Exclude head runtime from unhead imports transform (#34195)
    • kit: Include prereleases in semver satisfy check (#34210)
    • nuxt: Watch server/ for builder:watch hook (#34208)
    • nitro: Encode unicode paths in x-nitro-prerender header (#34202)
    • nitro: Preserve error.message for fatal errors (#34226)
    • Only enable dynamic imports when ts plugin (#34205)
    • webpack: Use H3Error for 403 in dev server (#34233)
    • nuxt: Ensure NuxtError extends Error type (#34242)
    • vite: Use H3Error for 404 in dev server (#34225)
    • nuxt: Add backwards compat for #app barrel export in keyed functions (#34199)
    • nuxt: Track + re-add custom routes on hmr (#32044)
    • nuxt: Keep vnode when leaving deeper nested route (#33778)
    • vite: Prevent CSS flickering in dev mode after config changes (#33856)
    • nuxt: Do not start view transition if there is no route (#33723)
    • nuxt: Call deferHydration done on NuxtPage unmount (#34152)
    • nuxt: Handle invalid datetime in <NuxtTime>` (#33992)
    • nuxt: Preserve middleware error status in 404 fallback (#34148)
    • nitro: Do not augment nuxt/schema (#34255)
    • nuxt: Cache manifest files to preserve buildId (#34002)
    • nuxt: Don't decode query string in SSR context URL (#34252)
    • nuxt: Allow specifying moduleDependencies by meta.name (#34263)
    • nuxt: Resolve #components import mapping conflict for packages outside rootDir (#34139)
    • vite,webpack: Use node.res to send 403/404 (#34266)
    • nitro,nuxt: Align path encoding with vue-router (#34265)
    • nitro: Augment nuxt/schema once more (9f5bb611d)

    💅 Refactors

    • nuxt: Prefer genObjectKey to omit unnecessary quotes (#34245)
    • nuxt: Use ComponentProps helper to extract layout props (#34248)

    📖 Documentation

    • Remove link to ai guide entirely (084b5d7f2)
    • Update roadmap dates (#34166)
    • Clarify shared type context limitations for custom imports (#34194)
    • Fix broken links (#34223)
    • Document payload extraction for ISR/SWR routes (#34222)
    • Update example of email validation (#34247)
    • Add documentation for keyedComposables (#34201)

    🏡 Chore

    • Remove px from width attribute (e80147f7d)
    • Add ai config in gitignore (#34220)

    ✅ Tests

    • Vitest v4 compatibility (70e147b71)
    • Add runtime tests for deeply nested <NuxtPage> navigation (707a9dc44)
    • Resolve merge issues in tests (85abddc54)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Matej Černý (@cernymatej)
    • Octavio Araiza (@8ctavio)
    • Muhammad Yasir Ghaffar (@M-YasirGhaffar)
    • Max (@onmax)
    • Bobbie Goede (@BobbieGoede)
    • 纸鹿/Zhilu (@L33Z22L11)
    • Florian Heuberger (@Flo0806)
    • 山吹色御守 (@KazariEX)
    • ExXTreMe315 (@ExXTreMe315)
    • Eugene (@FlexIDK)
    • abeer0 (@iiio2)
    • Jonas Thelemann (@dargmuesli)
    • Erwan Jugand (@erwanjugand)
    Open source →
  40. 3.21.022 Jan 2026
    Release notes

    3.21.0 is the next minor release.

    Nuxt 4.3 and 3.21 bring powerful new features for layouts, caching, and developer experience – plus significant performance improvements under the hood.

    📣 Some News

    Extended v3 Support

    Early this month, I opened a discussion to find out how the upgrade had gone from v3 to v4. I was really pleased to hear how well it had gone for most people.

    Having said that, we're committed to making sure no one gets left behind. And so we will continue to provide security updates and critical bug fix releases beyond the previously announced end-of-life date of January 31, 2026, meaning Nuxt v3 will meet its end-of-life on July 31, 2026.

    [!TIP] As usual, today also brings a minor release for v3, with many of the same improvements backported from v4.3.

    Preparing for Nuxt 5

    We're closer than ever to the releases of Nuxt v5 and Nitro v3. In the coming weeks, the main branch of the Nuxt repository will begin receiving initial commits for Nuxt 5. However, it's still business as usual.

    • Continue making pull requests to the main branch
    • We'll backport changes to the 4.x and 3.x branches

    Keep an eye out on the Upgrade Guide – we'll be adding details about how you can already start migrating your projects to prepare for Nuxt v4 with future.compatibilityVersion: 5.

    🗂️ Route Rule Layouts

    But that's enough about the future. We have a lot of good things for you today!

    First, you can now set layouts directly in route rules using the new appLayout property (#31092). This provides a centralized, declarative way to manage layouts across your application without scattering definePageMeta calls throughout your pages.

    export default defineNuxtConfig({
      routeRules: {
        '/admin/**': { appLayout: 'admin' },
        '/dashboard/**': { appLayout: 'dashboard' },
        '/auth/**': { appLayout: 'minimal' }
      }
    })
    

    This might be useful for:

    • Admin panels with a shared layout across many routes
    • Marketing pages that need a different layout from the app

    [!TIP] Plus, you can pass props to layouts now! See the setPageLayout improvements below.

    📦 ISR/SWR Payload Extraction

    Payload extraction now works with ISR (incremental static regeneration), SWR (stale-while-revalidate) and cache routeRules (#33467). Previously, only pre-rendered pages could generate _payload.json files.

    This means:

    • Client-side navigation to ISR/SWR pages can use cached payloads
    • CDNs (Vercel, Netlify, Cloudflare) can cache payload files alongside HTML
    • Fewer API calls during navigation – data can be prefetched and served from the cached payload
    export default defineNuxtConfig({
      routeRules: {
        '/products/**': { 
          isr: 3600, // Revalidate every hour
        }
      }
    })
    

    🧹 Dev Mode Payload Extraction

    Related to the above, payload extraction now also works in development mode (#30784). This makes it easier to test and debug payload behavior without needing to run a production build.

    [!IMPORTANT] Payload extraction works in dev mode with nitro.static set to true, or for individual pages which have isr, swr, prerender or cache route rules.

    🚫 Disable Modules from Layers

    When extending Nuxt layers, you can now disable specific modules that you don't need (#33883). Just pass false to the module's options:

    export default defineNuxtConfig({
      extends: ['../shared-layer'],
      // disable @nuxt/image from layer
      image: false,
    })
    

    🏷️ Route Groups in Page Meta

    Route groups (folders wrapped in parentheses like (protected)/) are now exposed in page meta (#33460). This makes it easy to check which groups a route belongs to in middleware or anywhere you have access to the route.

    <script setup lang="ts">
    // This page's meta will include: { groups: ['protected'] }
    useRoute().meta.groups
    </script>
    
    export default defineNuxtRouteMiddleware((to) => {
      if (to.meta.groups?.includes('protected') && !isAuthenticated()) {
        return navigateTo('/login')
      }
    })
    

    This provides a clean, convention-based approach to route-level authorization without needing to add definePageMeta to every protected page.

    🎨 Layout Props with setPageLayout

    The setPageLayout composable now accepts a second parameter to pass props to your layout (#33805):

    export default defineNuxtRouteMiddleware((to) => {
      setPageLayout('admin', {
        sidebar: true,
        theme: 'dark'
      })
    })
    
    <script setup lang="ts">
    defineProps<{
      sidebar?: boolean
      theme?: 'light' | 'dark'
    }>()
    </script>
    

    🔧 #server Alias

    A new #server alias provides clean imports within your server directory (#33870), similar to how #shared works:

    // Before: relative path hell
    import { helper } from '../../../../utils/helper'
    
    // After: clean and predictable
    import { helper } from '#server/utils/helper'
    

    The alias includes import protection – you can't accidentally import #server code from client or shared contexts.

    🪟 Draggable Error Overlay

    The development error overlay introduced in Nuxt 4.2 is now draggable and can be minimized (#33695). You can:

    • Drag it to any corner of the screen (it snaps to edges)
    • Minimize it to a small pill button when you want to keep working
    • Your position and minimized state persist across page reloads

    This is a quality-of-life improvement when you're iterating on fixes and don't want the overlay blocking your view.

    https://github.com/user-attachments/assets/nuxt_4-3_error_demo.mp4

    ⚙️ Async Plugin Constructors

    Module authors can now use async functions when adding build plugins (#33619):

    export default defineNuxtModule({
      async setup() {
        // Lazy load only when actually needed
        addVitePlugin(() => import('my-cool-plugin').then(r => r.default()))
        
        // No need to load webpack plugin if using Vite
        addWebpackPlugin(() => import('my-cool-plugin/webpack').then(r => r.default()))
      }
    })
    

    This enables true lazy loading of build plugins, avoiding unnecessary code loading when plugins aren't needed.

    🚀 Performance Improvements

    This release includes several performance optimizations for faster builds:

    • Hook filters - Internal plugins now use filters to avoid running hooks unnecessarily (#33898)
    • SSR styles optimization - The nuxt:ssr-styles plugin is now significantly faster (#33862, #33865)
    • Layer alias transform - Skipped when using Vite (it handles this natively) (#33864)
    • Route rules compilation - Route rules are now compiled into a client chunk using rou3, removing the need for radix3 in the client bundle and eliminating app manifest fetches (#33920)

    🎨 Inline Styles for Webpack/Rspack

    The inlineStyles feature now works with webpack and rspack builders (#33966), not just Vite. This enables critical CSS inlining for better Core Web Vitals regardless of your bundler choice.

    ⚠️ Deprecations

    statusCodestatus, statusMessagestatusText

    In preparation for Nitro v3 and H3 v2, we're moving to use Web API naming conventions (#33912). The old properties still work but are deprecated in advance of v5:

    - throw createError({ statusCode: 404, statusMessage: 'Not Found' })
    + throw createError({ status: 404, statusText: 'Not Found' })
    

    🐛 Bug Fixes

    Notable fixes in this release:

    • Fixed head component deduplication using key attribute (#33958, #33963)
    • Fixed async data properties not being reactive in Options API (#34119)
    • Fixed useCookie unsafe number parsing during decode (#34007)
    • Fixed NuxtPage not re-rendering when nested NuxtLayout has layouts disabled (#34078)
    • Fixed client-side pathname decoding for non-ASCII route aliases (#34043)
    • Fixed suspense remounting when navigating after pending state (#33991)
    • Fixed clipboard copy in error overlay (#33873)
    • Enabled allowArbitraryExtensions by default in TypeScript config (#34084)
    • Added noUncheckedIndexedAccess to server tsconfig for safer typing (#33985)

    [!IMPORTANT] Enabling noUncheckedIndexedAccess in the Nitro server TypeScript config improves type safety but may surface new type errors in your server code. This change was necessary because Nuxt's app context performs type checks on server routes (learn more).

    While we recommend keeping this enabled for better type safety, you can disable it if needed:

    export default defineNuxtConfig({
      nitro: {
        typescript: {
          tsConfig: {
            compilerOptions: {
              noUncheckedIndexedAccess: false
            }
          }
        }
      }
    })
    

    Note that disabling this may allow type errors to slip through that could cause runtime issues with indexed access.

    📚 Documentation

    • Improved module author guides with clearer structure (#33803)
    • Added MCP setup instructions for Claude Desktop (#33914)
    • Added layers directory documentation (#33967)
    • Added Deno package manager examples (#34070)
    • Clarified type-checking context limitations for server routes (#33964)

    🎉 Nuxt 3.21.0

    Alongside v4.3.0, we're releasing Nuxt v3.21.0 with many of the same improvements backported to the 3.x branch. This release includes:

    • All the same features: Route rule layouts, ISR payload extraction, layout props with setPageLayout, #server alias, draggable error overlay, and more
    • All performance improvements: SSR styles optimization, hook filters, and route rules compilation
    • Module disabling: Disable layer modules by setting options to false
    • Critical bug fixes: Async data reactivity in Options API, useCookie number parsing, head component deduplication, and more

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt@latest upgrade --dedupe --channel=v3
    

    This will deduplicate your lockfile and help ensure you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    [!TIP] Check out our upgrade guide if upgrading from an older version.

    👉 Changelog

    compare changes

    🚀 Enhancements

    • kit: Support async constructor for adding plugins (#33619)
    • kit: Export Nuxt major version type (#33700)
    • schema: Add #server alias for server directory imports (#33870)
    • schema: Hoist nitro crossws types (6ff79ea6c)
    • nitro,nuxt: Compile route rules into client chunk (#33920)
    • nuxt: Allow disabling modules by setting module options to false (#33883)
    • kit: Allow specifying moduleDependencies as an async function (#33504)
    • nuxt: Support appLayout in route rules (#31092)
    • nuxt: Add route groups to page meta (#33460)
    • nuxt: Enable payload extraction for ISR/SWR routes (#33467)
    • nuxt: Allow updating props with setPageLayout (#33805)
    • nuxt: Enable dragging and minimizing for error overlay (#33695)
    • nitro,nuxt: Add support for payload extraction in dev (#30784)
    • rspack,webpack: Add inline styles (#33966)
    • kit: Add forward-compatible nitro types (#34036)

    🔥 Performance

    • nuxt: Do not init layer alias transform when using vite (#33864)
    • vite: Add hook filters for ssr styles plugin (#33865)
    • vite: Optimize nuxt:ssr-styles plugin (#33862)
    • nuxt: Use filter for vfs plugin load (5bd8e81ed)
    • nuxt,vite: Use filters to avoid running hooks unnecessarily (e762a1e20)
    • nuxt,vite: Add more filters to internal plugins (#33898)

    🩹 Fixes

    • kit: Normalize local layer paths with trailing slashes (#33858)
    • nuxt: Avoid overwriting multiple head input in island handler (#33849)
    • nuxt: Update meta instead of calling router.replace in page hmr (#33897)
    • nuxt: Don't call page:loading:end in cache if already called (fbbe10133)
    • vite: Add error handling for parsing NUXT_VITE_NODE_OPTIONS (8abb7ef5b)
    • nuxt: Do not skip middleware when appMiddleware references invalid key (ed8bb68c5)
    • nitro: Clipboard copy in error overlay (#33873)
    • webpack,rspack: Resolve deep imports in virtual files (#33927)
    • webpack: Disable async chunks in dev mode (c4bfd0a49)
    • webpack: Correctly evaluate sourcemap name (93e3d92b9)
    • nuxt: Handle node10 resolution for nuxt/meta (b748840bc)
    • nuxt: Do not early return if component priorities conflict (#33955)
    • nuxt: Use key for tag deduplication in <Head> component (#33958)
    • schema,vite: Resolve build.transpile when initialising vite (#33868)
    • nuxt,rspack,webpack: Inject module identifiers for webpack builders (#33962)
    • nuxt: Add key to head components for proper deduplication (#33963)
    • nitro: Check prettyResponse.body type before error overlay (#33977)
    • nuxt: Don't URI-encode static route paths (#33990)
    • nuxt: Skip internal stub routes from prerender (#34001)
    • kit,schema: Align module onUpgrade arguments with types (#33988)
    • nuxt: Handle unsafe number parsing in useCookie decode (#34007)
    • nuxt: Do not externalise rou3 (7da94e8c3)
    • nitro: Add noUncheckedIndexedAccess to server tsconfig (#33985)
    • nuxt: Update global reference to globalThis in useRequestFetch (#33976)
    • vite: Configure hmr port for server build (#33929)
    • kit: Add forward compatible nitro v3 types (#34053)
    • nitro,nuxt: Do not import nitro deps in builders (#34054)
    • nitro: Add h3 types to auto-imports (#34035)
    • schema: Add some more directories to ignore (9cb9a19dd)
    • nitro: Also augment nuxt/schema (9b40196a6)
    • nuxt: Make asyncData properties reactive in Options API (#34119)
    • nuxt: Rerender NuxtPage when nested NuxtLayout has explicitly disabled layouts (#34078)
    • nuxt,schema: Clean up types (5ce351d0f)
    • nuxt: Allow user augmentation of runtime config (dd30410cb)
    • kit,nitro: Enable allowArbitraryExtensions by default (#34084)
    • nuxt: Decode client-side pathname for non-ASCII route aliases (#34043)
    • nuxt: Force remount suspense when navigating after pending (#33991)
    • nuxt: Add documentation link to server builder error message (#34122)
    • nuxt: Validate placeholder/fallback tags + warn about placeholder/fallback props (f7912d3f3)
    • nuxt: Force flush useAsyncData debounced execute post watcher flush (#34125)
    • nitro: Process isr/swr/cache keys (7f2bf4d13)
    • nuxt: Add typeFrom support for imports.d.ts template exports (#34135)
    • nuxt: Ensure we inline styles for hydrate-never components (#34132)

    💅 Refactors

    • kit: Add explicit return types for kit utilities (ec2239cb4)
    • nitro,nuxt,schema,vite: Provide explicit return types (2564002de)
    • kit,nuxt,schema: Use named imports from defu + consola (e31668f67)
    • Add explicit .ts file extensions to relative imports (458f3c9b6)
    • kit,nitro,nuxt,schema: Reduce barrels + move <> to as (08f72881e)
    • nitro,nuxt: Use ~ prefix for internal ssrContext properties (#33896)
    • nitro: Add explicit return types for runtime utils (74bb6ddeb)
    • nitro: Move tree-shaken flags from replace plugin -> vfs (#33907)
    • nitro,nuxt,vite,webpack: Use status/statusText + deprecate old props (#33912)
    • webpack: Use RuntimeModule API for chunk preloads (#33930)
    • nuxt: Use AST-aware function key injection (#33446)
    • nitro,nuxt,schema: Use augments for nitro schema types (#34039)
    • nitro,rspack,vite,webpack: Move cors handling -> nitro builder (#34048)
    • nitro: Move to nitropack/runtime namespace (b06d53166)
    • nitro,nuxt: Move to nitropack/runtime namespace (897a2259f)

    📖 Documentation

    • Fix useHead return type (#33857)
    • Add correct instructions to upgrade to latest Nuxt 3.x (#33866)
    • Improve grammar (#34093)
    • Use h2 for nuxt add command page (a0a1763d5)
    • Update links to module guide (c9c1282f8)
    • Split and improve Module Author Guides (#33803)
    • Split directory structure and re-order guides (v4) (#33691)
    • Add mcp server and llms.txt (#33371)
    • Add note that middleware doesn't run when rendering islands (d22cf7903)
    • Add note on default branch for layers (#33919)
    • Add mcp setup instructions for claude desktop (#33914)
    • Mention deno as package manager (#33875)
    • Clarify purpose of statusText (#32834)
    • Update lychee config and remove medium article link (36c19ce73)
    • Update module count and fix typo (#33950)
    • Add DeepWiki badge (#33508)
    • Give example of usage of defineWrappedResponseHandler (#33952)
    • Provide cleaner example code for vitest projects (#33960)
    • Update yarn create command (b30432979)
    • Update roadmap with a11y (7ea35137c)
    • Add a11y release (#34041)
    • Remove Nuxtr from recommendations (#34045)
    • Remove duplicate feature (#34058)
    • Provide deno package manager examples (#34070)
    • Make custom wrapper recipe link more prominent (#34085)
    • nuxt: Mention custom serializers in useState docs (#34105)
    • Clarify module setups in .nuxtrc example (#34107)
    • Add layers directory documentation (#33967)
    • Add a tip for appLayout (9b78698c3)
    • Add docs for disabling modules by passing false to its options (18500730c)
    • Add info about caching payloads with isr/swr (4b055548e)
    • Add example for async addVitePlugin (4407f6862)
    • Add example of passing props to layouts (401aa90ab)
    • Mark vite plugin as not typed (25eae7699)
    • Add warning about source from <NuxtIsland> (08778c98c)
    • Sync with main branch (e8c04aaa6)
    • Fix ai guide link (01c173b78)

    📦 Build

    • Remove babel debugging plugin from jiti stub options (1ec010681)
    • vite: Add build entries for vite-node entrypoints (#33893)
    • nuxt: Tidy up subpath export types (fe92e9c17)
    • Use obuild except for nuxt + nitro-server packages (#34049)
    • schema: Fix /builder-env subpath types (1951648fa)

    🏡 Chore

    ✅ Tests

    • Update tests for new version of nuxt/test-utils (#33842)
    • Avoid unnecessary tick (fb4720840)
    • Add regression test for asyncData HMR (#32182)
    • Add test for page hmr resetting state (#32418)
    • Add reproduction for vite pre-transform error (#31574)
    • Add regression test for #32154 (#32154)
    • Use vi.hoisted for klona mock (#34113)
    • Update bundle size (e6c8d10c6)
    • Fix paths in hmr test (3b8b2138a)
    • Update snapshots (51c83b8ec)
    • Update bundle size (22708c05c)

    🤖 CI

    • Directly call webhook url (4eedbcae5)
    • Use new reusable triage workflows (#34072)
    • Use new shared dependency review workflow (9e6770f18)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Florian Heuberger (@Flo0806)
    • Octavio Araiza (@8ctavio)
    • Robin (@OrbisK)
    • shaheer-arbisoft (@shaheer-arbisoft)
    • Francesco Mussoni (@solidusite)
    • Danila Poyarkov (@dannote)
    • Teages (@Teages)
    • Anthony Fu (@antfu)
    • Eli Sterken (@eli-sterk)
    • Ryota Watanabe (@wattanx)
    • edison (@edison1105)
    • Max (@onmax)
    • Rahul Dogra (@rahuld109)
    • abeer0 (@iiio2)
    • Philipp Wagner (@imphil)
    • Maxime Pauvert (@maximepvrt)
    • Wind (@productdevbook)
    • Agatem (@agatemosu)
    • Pavel (@eL1fe)
    • Lucie (@lihbr)
    • Sergiu Ravliuc (@YoSoySergio)
    • Julien Huang (@huang-julien)
    • Saeid Zareie (@Saeid-Za)
    • Alireza Jahandideh (@Youhan)
    • kikuchan (@kikuchan)
    • Ragura (@Ragura)
    • Josh Deltener (@hecktarzuli)
    • Teena (@franklin-tina)
    • Matej Černý (@cernymatej)
    • Frederik Bußmann (@freb97)
    • Benjamin Oddou (@BenjaminOddou)
    • Mukund Shah (@mukundshah)
    • Jessé Correia Lins (@linspw)
    • Jannik Sohn (@janniksohn)
    • Dawit (@oneminch)
    • Ali Sokkar (@NyllRE)
    • Horu (@HigherOrderLogic)
    • Hugo (@HugoRCD)
    • Sébastien Chopin (@atinux)
    • David Stack (@davidstackio)
    • Ruslan Stelmachenko (@xak2000)
    • Harlan Wilton (@harlan-zw)
    • Alexander Lichter (@TheAlexLichter)
    • Ryan Wilson (@rywils)
    • yamachi4416 (@yamachi4416)
    Open source →
  41. 3.20.29 Dec 2025
    Release notes

    3.20.2 is the next patch release.

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe --channel=v3
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    [!NOTE] This will only work if you already have a version of @nuxt/cli which has the --channel flag. If this does not work, you can instead run npx nuxi@latest for the initial upgrade.

    👉 Changelog

    compare changes

    🩹 Fixes

    • nitro: Do not show pretty error handler when testing (cc75ce409)
    • nuxt: Generate valid references for component declaration items (#33388)
    • nuxt: Sync internal route before calling page:finish hook (#33707)
    • nitro: Ensure html is a string before injecting error handler (6f51a25e9)
    • nitro: Include layer server directories in tsconfig.server.json (#33510)
    • nuxt: Ensure deduped async data executions return latest promise (#33740)
    • kit,nuxt: Type + respect moduleDependencies by meta name (#33774)
    • nuxt,schema: Ignore .d.vue.ts declarations (9a6a770ab)
    • kit,nuxt: Protect against resolved nuxt module subpath (#33767)
    • nuxt: Re-execute callOnce during HMR (#33810)
    • nuxt: Resolve watch callback after reactive key change in useAsyncData (#33802)
    • nuxt: Escape HTML in development error page stack trace (#33820)
    • kit: Do not add resolved rootDir to cached layer config (#33779)
    • kit,schema: Add moduleDependencies -> installModule (#33689)

    💅 Refactors

    • nuxt: Improve type safety within callOnce function (#33825)

    📖 Documentation

    • Split directory structure and re-order guides (v3) (#33690)
    • Fix link (016ef66e3)
    • Add hints release (#33701)
    • Fix link to vitest globals config (#33702)
    • Fix 404 link (5543b7cf7)
    • Text consistency (#33709)
    • Type error as non-optional prop (#33763)

    🏡 Chore

    • Update pnpm to 10.21 and enable trust policy (1cb55efc0)
    • Revert pnpm trust policy and restore provenance action (103ae1351)
    • Update markdownlint config to ignore mdc issues (d4933e26e)
    • Pin to single version of unstorage (619956e7f)

    ✅ Tests

    • Add patchProp and nodeOps to excluded Vue helpers (#33754)
    • Use fake timers for watch params test (58607fbea)
    • Update test for v3 defaults (daa002638)

    🤖 CI

    • Add --pnpm flag to correctly publish prerelease (#33688)
    • Update action lint config (#33710)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Alexander Lichter (@TheAlexLichter)
    • Florian Heuberger (@Flo0806)
    • Konstantin Telyakov (@kTelyakov)
    • abeer0 (@iiio2)
    • Julien Huang (@huang-julien)
    • Robin (@OrbisK)
    • Dheeraj Joshi (@dheeraj3587)
    • Edwin Samodra (@edwinsamodra)
    • edison (@edison1105)
    • 山吹色御守 (@KazariEX)
    • Sébastien Chopin (@atinux)
    • pierreoa (@pierreoa)
    • Maxime Pauvert (@maximepvrt)
    Open source →
  42. 3.20.16 Nov 2025
    Release notes

    3.20.1 is the next patch release.

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe --channel=v3
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🩹 Fixes

    • vite: Unset optimizeDeps.include for server environment (#33550)
    • kit,nuxt,schema: Deprecate ImportPresetWithDeprecation (#33596)
    • nuxt: Correct warning message for prefetch/noPrefetch conflict (#33617)
    • nitro: Remove <nuxt-error-overlay> iframe border (#33625)
    • vite: Use rolldown replace only in build (#33615)
    • nitro: Use directory paths in moduleEntryPaths (#33628)
    • nitro: Start error overlay minimized based on status code (#33658)
    • vite: Ensure optimizeDeps config is applied before other plugins (#33586)
    • nuxt: Respect layer priority order for scanned components (#33654)
    • nuxt: Process prerender routes on pages:resolved (#33662)
    • nuxt: Remove abort signal event listeners after render (#33665)
    • nuxt: Cleanup event listener with cleanup signal (#33667)
    • vite: Respect vite proxy in dev middleware (#33670)

    💅 Refactors

    • kit,nitro,nuxt,schema,vite: Explicitly import process/performance (#33650)

    📖 Documentation

    • Fix typo in eslint flat config description (#33569)
    • Add signal support to useAsyncData examples (#33601)
    • Note that cookieStore is true by default (#33572)
    • Document pending as alias of status === 'pending' (#33221)
    • Clarify route middleware doesn't affect API routes (#33643)
    • Improve docs for useHead/useHydration/useLazy* (#33626)
    • Typo (#33655)

    🏡 Chore

    🤖 CI

    • Disable cache in release action (885df65f4)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Robin (@OrbisK)
    • abeer0 (@iiio2)
    • Bobbie Goede (@BobbieGoede)
    • Florian Heuberger (@Flo0806)
    • Matej Černý (@cernymatej)
    • Peter Budai (@peterbud)
    • Julien Huang (@huang-julien)
    • Max (@onmax)
    • 纸鹿/Zhilu (@L33Z22L11)
    • Hinata Oishi (@te19oishi)
    • Damian Głowala (@DamianGlowala)
    • Maxime Pauvert (@maximepvrt)
    • Raed Abdennadher (@RaedAbr)
    Open source →
  43. 3.20.028 Oct 2025
    Release notes

    3.20.0 is the next minor release.

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe --channel=v3
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🚀 Enhancements

    • nuxt: Allow specifying component declarationPath (#33419)
    • kit: Add extensions option for resolveModule (#33328)
    • nuxt: Add abortController option to useAsyncData (#32531)
    • nuxt: Display youch error page w/ user error page in dev (#33359)
    • nuxt: Experimental typescript plugin support (#33314)
    • nuxt,schema: Extract asyncData handlers to chunks (#33131)
    • kit: Add setGlobalHead utility (#33512)
    • kit,vite: Allow enabling vite environment api (#33492)

    🔥 Performance

    • nuxt: Precompute renderer dependencies at build time (#33361)
    • kit,schema: Remove some unnecessary dependencies (bdf34c263)

    🩹 Fixes

    • nuxt: Preserve hash with redirecting based on routeRules (#33222)
    • kit: Safely cleanup loadNuxtConfig in concurrent calls (#33420)
    • nuxt: Allow object-format href in <NuxtLink> (b97ae2f70)
    • nuxt: Remove mergeModels from auto imports (#33344)
    • nuxt: Add back shortPath property (#33384)
    • nuxt: Do not allow native attrs to shadow nuxt link props (0981990a7)
    • nuxt: Remove declarationPath from component dirs (e384ba3cb)
    • nuxt: Preserve root route in isPrerendered check (#33476)
    • nuxt: Exempt webpack vfs from pkg lookup (4df1e8275)
    • nitro: Exempt nightly release from import protections (272d9abbe)
    • webpack,rspack: Preserve prerender + nitro flags in server builds (#33503)
    • nuxt: Support component auto-imports as arguments of h() (#33509)
    • vite: Prevent assignment for rolldown's replacement plugin (#33526)
    • nuxt: Use sha256 hash for prerender cache keys (#33505)
    • nuxt: Add NuxtTime relative time numeric prop (#33552)
    • nuxt: Add NuxtTime relative time relativeStyle prop (#33557)
    • nuxt: Handle arrays in app config correctly during HMR (#33555)

    💅 Refactors

    • Remove obsolete shortPath property (#33384)
    • kit: Extract trace utilities (ddaedfa51)
    • nuxt,vite,webpack: Allow builders to augment types (#33427)
    • schema: Deprecate extend, extendConfig, and configResolved hooks (932a80dc6)
    • nitro,nuxt: Extract @nuxt/nitro-server package (#33462)
    • nuxt: Use RouteLocationNormalizedLoadedGeneric internally (aa211fb4f)
    • vite: Make vite plugins environment-compatible (#33445)

    📖 Documentation

    • Add nuxt module addServerPlugin note (#33409)
    • Remove deprecated node version (#33411)
    • Update declarationPath in addComponent (#33380)
    • Add some notes/deprecations for vite hooks (2c6912d2f)
    • Fix incorrect ESM module field info (#33451)
    • Recommend getLayerDirectories() instead of nuxt.options._layers (#33484)
    • Add docs for moduleDependencies (#33499)
    • Pin codemod to v0.18.7 for migration recipe (#33522)

    🏡 Chore

    • Migrate gitpod to ona (#33159)
    • Use native node to run test:prepare (cbad63c02)
    • Do not use native node to run test:prepare (672c09423)
    • Update valid semantic scopes (4ca29168b)
    • Ignore nitro templates (ec59aceeb)
    • Remove vue-demi from ignoredBuiltDependencies (#33494)
    • Update vscode url (#33360)
    • Correct jsdoc location for function used as parameters (#33507)
    • Remove code comment (#33515)
    • Patch changelogen for large numbers of commits (b6530b5b6)
    • Filter out commits before last tag when constructing changelog (257049712)
    • Ignore @rollup/plugin-commonjs (c2bd323b8)
    • Pin @rollup/plugin-commonjs (a524522ea)

    ✅ Tests

    • Update runtime test to use asyncDataDefaults.errorValue (b6f1c9b0d)
    • Refactor suite to use common matrix utils (#33483)
    • Update typed router test (c55db2854)

    🤖 CI

    • Publish @nuxt/nitro-server on pkg-pr-new (d37ef17b0)
    • Remove nitro-server publish until v4.2 is released (e34c2f52f)
    • For now, use tag push to trigger release (0705b835f)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • 山吹色御守 (@KazariEX)
    • Matej Černý (@cernymatej)
    • Trung Dang (@NamesMT)
    • 纸鹿/Zhilu (@L33Z22L11)
    • Florian Heuberger (@Flo0806)
    • Alexander Lichter (@TheAlexLichter)
    • Julien Huang (@huang-julien)
    • abeer0 (@iiio2)
    • Max (@onmax)
    • Octavio Araiza (@8ctavio)
    • Bobbie Goede (@BobbieGoede)
    • DipakHalkude (@DipakHalkude)
    • Aleksander Błaszkiewicz (@ablaszkiewicz)
    Open source →
  44. 3.19.36 Oct 2025
    Release notes

    3.19.3 is a regularly scheduled patch release.

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🔥 Performance

    • vite: Use rolldown's replace plugin when applicable (#33258)

    🩹 Fixes

    • nuxt: Make lazy component types compatible with h (#33046)
    • vite: Deduplicate inlined server style chunks (#33308)
    • nuxt: Support head option on useHead (#33318)
    • nuxt: Do not relativise importmap if cdnURL is set (#33333)
    • nuxt: Resolve aliases in imports.dirs (#33334)
    • nuxt: Add missing element/vnode props for <NuxtLink> (#33335)
    • nuxt: Do not generate server placeholder components (#33345)
    • nuxt: Dedupe generated component names (#33346)
    • webpack: Test watch instance before closing it (3314bc9a1)
    • nuxt: Correctly handle island rendering error (#33302)
    • nuxt: Support v-slot:fallback longform syntax in <DevOnly> (#33368)
    • nuxt: Support typeFrom when generating auto-import type templates (#33373)
    • nuxt: Don't trigger scroll when changing trailing slash (#33358)
    • nuxt: Add stubs for new scripts from @nuxt/scripts (057ade490)
    • nuxt: Prevent duplicate execution on key change in useAsyncData (#33325)
    • nuxt: Make middleware _path property configurable for HMR (#33379)
    • nuxt: Handle non-immediate useAsyncData with different key on ssr (#33341)

    💅 Refactors

    • nuxt: Improve implementation of error composables (#33234)
    • nuxt: Resolve path of typed-router.d.ts early for consistency (#33285)
    • nuxt: Place filename into componentsIslandsTemplate definition (#33394)
    • nuxt,vite: Use environment-api compatible plugins (#33403)

    📖 Documentation

    • Update usage instructions for Windows users (#33284)
    • Remove d suffix in example (#33298)
    • Move directory structure to top-level (#33299)
    • Add 3.x prefix to all internal links (0fef864d6)
    • Add information about useFetch reactivity (#33317)
    • Lint code samples within docs (#33271)
    • Note prepare command NODE_ENV behavior (#33330)
    • Update nuxt command pages (#33336)

    🏡 Chore

    ✅ Tests

    • nuxt: Set locale to en for nuxt-time tests (#33343)
    • Double gotoPath timeout in CI (9d336cc76)

    🤖 CI

    • Add provenance action to check for downgrades in provenance (18ab6e5fa)
    • Pass commit sha when triggering ecosystem ci (7b2949a3c)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • 山吹色御守 (@KazariEX)
    • Julien Huang (@huang-julien)
    • Florian Heuberger (@Flo0806)
    • Ondrej Brendy (@bandiasek)
    • Octavio Araiza (@8ctavio)
    • Alex Liu (@Mini-ghost)
    • Bobbie Goede (@BobbieGoede)
    • abeer0 (@iiio2)
    • Harlan Wilton (@harlan-zw)
    • Alexander Lichter (@TheAlexLichter)
    • Sébastien Chopin (@atinux)
    • Ben Hong (@bencodezen)
    • Huseyn Guliyev (@husayt)
    Open source →
  45. 3.19.212 Sept 2025
    Release notes

    3.19.2 is a regularly scheduled patch release.

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🔥 Performance

    • kit: Do not normalise templates in loop if dst is present (#33200)
    • nuxt: Remove watcher from hydrate-when lazy hydration strategy (#33199)
    • nuxt,schema: Normalise components + directories more efficiently (#33207)
    • kit,nuxt: Reduce unnecessary iteration in nuxt code (#33212)
    • nuxt: Skip running lazy hydration transform with filter (#33213)

    🩹 Fixes

    • schema: Add pkg-types to dependencies (a6e5dd756)
    • nuxt: Ignore errors when treeshaking composables within other composables (e3e42ac77)
    • nuxt: Do not tree-shake composables within other composables (#33153)
    • kit: Ensure module dependencies are typed correctly (ea16d182a)
    • nuxt: Prevent Infinity backgroundSize in loading indicator (#33211)
    • nuxt: Remove unused enabled from components dir options (#32844)
    • nuxt: Sync watch request in useAsyncData (#33192)
    • nuxt: Move key imports logic after all modules run (#33214)

    📖 Documentation

    • Update language on bridge head migration (32e76f609)

    🏡 Chore

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Adrien Foulon (@Tofandel)
    • Matej Černý (@cernymatej)
    • Антон Стасюк (@11Alone11)
    • wuiyang (@wuiyang)
    Open source →
  46. 3.19.15 Sept 2025
    Release notes

    v3.19.1 is a regularly scheduled patch release

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🩹 Fixes

    • nuxt: Correct relative path of auto imported components (#33122)
    • nuxt: Prefer accessing globalThis over window (#33125)
    • nuxt: Migrate to AST-aware tree-shaking + route injection (#33128)
    • nuxt: Ignore #components import mapping inside packages that use it internally (#33049)
    • vite: Remove explicit vite-node configuration of deps.inline (#33133)
    • nuxt: Include trace in dev-time useRoute usage warning (#33039)
    • nuxt: Print route middleware path in warning (#33136)
    • nuxt: Include core auto-imports from imports:sources in override warning (#33050)
    • nuxt: Render relative importmap entry path if required (#33146)

    📖 Documentation

    • Add documentation for module lifecycle hooks (#33115)
    • Add -- to bun create command (ab6aa8ee5)
    • Add JSDoc for navigateTo (#21442)

    🏡 Chore

    ✅ Tests

    🤖 CI

    • Remove default discord reactions from thread (more noise than it's worth) (2e3c91e0c)
    • Rewrite release workflow in ts + support multiple tags (478c64342)
    • Pass correct flag (a954f383f)
    • Pass tag via env variable (dcfc82688)
    • Drop 4x tags from releases (e3aa50d11)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Matej Černý (@cernymatej)
    • Bobbie Goede (@BobbieGoede)
    • Octavio Araiza (@8ctavio)
    • Michael Brevard (@GalacticHypernova)
    • abeer0 (@iiio2)
    • 山吹色御守 (@KazariEX)
    Open source →
  47. 3.19.02 Sept 2025
    Release notes

    👀 Highlights

    Please see the release notes for Nuxt v4.1 for full details on the features and fixes in Nuxt v3.19.

    ✅ Upgrading

    As usual, our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe
    

    This will refresh your lockfile and pull in all the latest dependencies that Nuxt relies on, especially from the unjs ecosystem.

    👉 Changelog

    compare changes

    🚀 Enhancements

    • kit: Add ignore option to resolveFiles (#32858)
    • kit: Add onInstall and onUpgrade module hooks (#32397)
    • nuxt,vite: Add experimental support for rolldown-vite (#31812)
    • nuxt: Extract defineRouteRules to page rules property (#32897)
    • nuxt,vite: Use importmap to increase chunk stability (#33075)
    • nuxt: Lazy hydration macros without auto-imports (#33037)
    • kit,nuxt,schema: Allow modules to specify dependencies (#33063)
    • kit,nuxt: Add getLayerDirectories util and refactor to use it (#33098)

    🔥 Performance

    • nuxt: Clear inline route rules cache when pages change (#32877)
    • nuxt: Stop watching app manifest once a change has been detected (#32880)

    🩹 Fixes

    • nuxt: Handle satisfies in page augmentation (#32902)
    • nuxt: Type response in useFetch hooks (#32891)
    • nuxt: Add TS parenthesis and as expression for page meta extraction (#32914)
    • nuxt: Use correct unit thresholds for relative time (#32893)
    • nuxt: Handle uncached current build manifests (#32913)
    • kit: Resolve directories in resolvePath and normalize file extensions (#32857)
    • schema,vite: Bump requestTimeout + allow configuration (#32874)
    • nuxt: Deep merge extracted route meta (#32887)
    • nuxt: Do not expose app components until fully resolved (#32993)
    • kit: Only exclude node_modules/ if no custom srcDir (#32987)
    • nuxt: Compare final matched routes when syncing route object (#32899)
    • nuxt: Make vue server warnings much less verbose in dev mode (#33018)
    • schema: Allow disabling cssnano/autoprefixer postcss plugins (#33016)
    • kit: Ensure local layers are prioritised alphabetically (#33030)
    • kit,nuxt: Expose global types to vue compiler (#33026)
    • nuxt: Support config type inference for defineNuxtModule().with() (#33081)
    • nuxt: Search for colliding names in route children (31a9282c2)
    • nuxt: Delete nuxtApp._runningTransition on resolve (#33025)
    • nuxt: Add validation for nuxt island reviver key (#33069)
    • kit: Prioritise local layers over extended layers (ae8b0d2b8)
    • kit: Address merge conflict (89ccbbebb)
    • kit: Do not resolve public dir aliases (5d87d3a80)

    💅 Refactors

    • nuxt: Simplify page segment parsing (#32901)
    • nuxt: Remove unnecessary async/await in afterEach (#32999)
    • vite: Simplify inline chunk iteration (9ea90fc33)
    • kit,nuxt,ui-templates,vite: Address deprecations + improve regexp perf (#33093)

    📖 Documentation

    • Add a section about augmenting types with TS project references (#32843)
    • Switch example to use vitest projects (#32863)
    • Update testing setupTimeout and add teardownTimeout (#32868)
    • Add middleware to layers guide (fa516d440)
    • Add documentation for --nightly command (#32907)
    • Update package information in roadmap section (#32881)
    • Add more info about nuxt spa loader element attributes (#32871)
    • Correct filename in example (#33000)
    • Add more information about using useRoute and accessing route in middleware (#33004)
    • Avoid variable shadowing in locale example (#33031)

    🏡 Chore

    • Remove stray test file (42fd247a4)
    • Ignore webpagetest.org when scanning links (cb18f4960)
    • Add type: 'module' in playground (#33099)

    ✅ Tests

    • Add failing test for link component duplication (#32792)
    • Simplify module hook tests (#32950)
    • Refactor stubbing of import.meta.dev (#33023)
    • Use findWorkspaceDir rather than relative paths to repo root (c4c3ada96)
    • Improve router test for global transitions (7e6a6fc35)
    • Use expect.poll (f4354203a)
    • Use expect.poll instead of expectWithPolling (15ca5be95)
    • Use vi.waitUntil instead of custom retry logic (4c8c13090)
    • Update test for app creation (9a3b44515)
    • Update bundle size snapshot (76988ce97)

    🤖 CI

    • Remove double set of tests for docs prs (14c006ac4)
    • Add workflow for discord team discussion threads (f14854fc3)
    • Fix some syntax issues with discord + github integrations (c059f7cd1)
    • Use token for adding issue to project (51661bac3)
    • Use discord bot to create thread automatically (37f9eb27b)
    • Only use discord bot (38ce2dcbb)
    • Update format of discord message (0047b3059)
    • Try bolding entire line (6e9f40eb9)
    • Oops (8b044cad2)
    • Add delay after adding each reaction (37b7e2108)
    • Use last lts node version for testing (98719c065)
    • Try npm trusted publisher (ea33502c3)
    • Use npm trusted publisher for main releases (31a55437f)
    • Change wording (#32979)
    • Add github ai moderator (#33077)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • abeer0 (@iiio2)
    • Julien Huang (@huang-julien)
    • kyumoon (@kyumoon)
    • Alexander Lichter (@TheAlexLichter)
    • Bobbie Goede (@BobbieGoede)
    • mustafa60x (@mustafa60x)
    • Matej Černý (@cernymatej)
    • Alex Liu (@Mini-ghost)
    • Amitav Chris Mostafa (@semibroiled)
    • Romain Hamel (@romhml)
    • Jacky Lam (@jackylamhk)
    • Mukund Shah (@mukundshah)
    • Luke Nelson (@luc122c)
    • letianpailove (@letianpailove)
    • Erwan Jugand (@erwanjugand)
    • Alexander (@TheColorman)
    • Ryota Watanabe (@wattanx)
    • Yizack Rangel (@Yizack)
    Open source →
  48. 3.18.15 Aug 2025
    Release notes

    3.18.1 is a regularly scheduled patch release.

    👉 Changelog

    compare changes

    🔥 Performance

    • kit: Get absolute path from tinyglobby in resolveFiles (#32846)

    🩹 Fixes

    • nuxt: Do not throw undefined error variable (#32807)
    • vite: Include tsconfig references during typeCheck (#32835)
    • nuxt: Add sourcemap path transformation for client builds (#32313)
    • nuxt: Add warning for lazy-hydration missing prefix (#32832)
    • nuxt: Trigger call once navigation even when no suspense (#32827)
    • webpack: Handle null result from webpack call (65aa17158)
    • kit,nuxt: Use reverseResolveAlias for better errors (#32853)

    📖 Documentation

    • Update nightly version references (#32776)
    • Improve explanation of global middleware (#32855)

    🏡 Chore

    • Update reproduction help text links (#32803)
    • Update pnpm ignored build scripts (#32849)
    • Improve internal types (f271c66c4)

    ✅ Tests

    • Move tests for defineNuxtComponent out of e2e test (#32848)

    🤖 CI

    • Move nightly releases into different concurrency group (26f9baa6a)

    ❤️ Contributors

    • RDistinct (@RDistinct)
    • Daniel Roe (@danielroe)
    • Oskar Lebuda (@OskarLebuda)
    • Peter Budai (@peterbud)
    • Matej Černý (@cernymatej)
    • Damian Głowala (@DamianGlowala)
    • Bobbie Goede (@BobbieGoede)
    • Robin (@OrbisK)
    • Bobby (@xanzhu)
    Open source →
  49. 3.18.029 Jul 2025
    Release notes

    3.18.0 is the next minor release.

    👀 Highlights

    A huge thank you to everyone who's been a part of this release, which is mostly about backporting features + bugfixes from Nuxt v4.

    Over the next six months, we'll continue backporting compatible v4 features and bug fixes, so please keep the feedback coming! ❤️

    🧪 Lazy Hydration Macros

    Building on the delayed hydration support from v3.16, we now support lazy hydration macros (#31192)! These provide a more ergonomic way to control component hydration:

    <script setup lang="ts">
    const LazyHydrationMyComponent = defineLazyHydrationComponent(
      'visible',
      () => import('./components/MyComponent.vue')
    )
    </script>
    <template>
      <div>
        <!-- 
          Hydration will be triggered when
          the element(s) is 100px away from entering the viewport.
        -->
        <LazyHydrationMyComponent :hydrate-on-visible="{ rootMargin: '100px' }" />
      </div>
    </template>
    

    These macros make it possible to use Nuxt's lazy hydration utilities alongside explicit component imports.

    ♿️ Accessibility Improvements

    We've enhanced accessibility by including <NuxtRouteAnnouncer> in the built-in app.vue (#32621). This means page changes will be announced to screen readers, making navigation more accessible for users with visual impairments. (This only applies if you do not have an app.vue in your project. If you do, please keep <NuxtRouteAnnouncer> in your app.vue!)

    🛠️ Enhanced Development Experience

    Chrome DevTools Workspace Integration

    We've added Chrome DevTools workspace integration (#32084), allowing you to edit your Nuxt source files directly from Chrome DevTools. This creates a better debugging experience where changes made in DevTools are reflected in your actual source files.

    Better Component Type Safety

    Component type safety has been improved with:

    • Typed slots for <ClientOnly> and <DevOnly> (#32707) - better IntelliSense and error checking
    • Exported <NuxtTime> prop types (#32547) - easier to extend and customize

    New Auto-Import: onWatcherCleanup

    The onWatcherCleanup function from vue is now available as an auto-import (#32396), making it easier to clean up watchers and prevent memory leaks:

    const { data } = useAsyncData('users', fetchUsers)
    
    watch(data, (newData) => {
      const interval = setInterval(() => {
        // Some periodic task
      }, 1000)
      
      // Clean up when the watcher is stopped
      onWatcherCleanup(() => {
        clearInterval(interval)
      })
    })
    

    📊 Observability Enhancements

    Page routes are now exposed to Nitro for observability (#32617), enabling better monitoring and analytics integration with supported platforms. This allows observability tools to track page-level metrics more effectively.

    🔧 Module Development Improvements

    Module authors get several quality-of-life improvements:

    Simplified Server Imports

    The addServerImports kit utility now supports single imports (#32289), making it easier to add individual server utilities:

    // Before: had to wrap in array
    addServerImports([{ from: 'my-package', name: 'myUtility' }])
    
    // Now: can pass directly
    addServerImports({ from: 'my-package', name: 'myUtility' })
    

    TypeScript Configuration

    Modules can now add to typescript.hoist (#32601), giving them more control over TypeScript configuration and type generation.

    ⚡️ Performance Improvements

    We've made several performance optimizations:

    • Improved Vite-node communication via internal socket (#32417) for faster development builds
    • Migration to oxc-walker (#32250) and oxc for onPrehydrate transforms (#32045) for faster code transformations

    🐛 Bug Fixes

    This release also includes several important fixes:

    • Improved data fetching: When computed keys change, old data is now properly retained (#32616)
    • Better scroll behavior: scrollBehaviorType is now only used for hash scrolling (#32622)
    • Fixed directory aliases: Added trailing slashes to some directory aliases for better consistency (#32755)

    ✅ Upgrading

    As usual, our recommendation for upgrading is to run:

    npx nuxi@latest upgrade --dedupe
    

    This refreshes your lockfile and pulls in all the latest dependencies that Nuxt relies on, especially from the unjs ecosystem.

    👉 Changelog

    compare changes

    🚀 Enhancements

    • nuxt: Expose page routes to nitro for o11y (#32617)
    • nuxt: Export <NuxtTime> prop types (#32547)
    • nuxt: Add integration with chrome devtools workspaces (#32084)
    • kit: Support single import in addServerImports (#32289)
    • nuxt: Add onWatcherCleanup to imports presets (#32396)
    • nuxt: Add route announcer to default app.vue (#32621)
    • nuxt: Support lazy hydration macros (#31192)

    🔥 Performance

    • vite: Communicate with vite-node via internal socket (#32417)
    • kit: Update env expansion regex to match nitro (#30766)

    🩹 Fixes

    • nuxt: Allow modules to add to typescript.hoist (#32601)
    • nuxt: Retain old data when computed key changes (#32616)
    • nuxt: Only use scrollBehaviorType for hash scrolling (#32622)
    • nuxt: Add missing async (fd312af03)
    • nuxt: Fix transform/minify types + bump oxc-transform (d2ba19963)
    • nuxt: Provide typed slots for <ClientOnly> and <DevOnly> (#32707)
    • kit,nuxt,schema: Add trailing slash to some dir aliases (#32755)
    • nuxt: Include source base url for remote islands (#32772)
    • vite: Use vite node server to transform requests (#32791)
    • kit: Use mlly to parse module paths (#32386)
    • nuxt: Execute all plugins after error rendering error.vue (#32744)

    💅 Refactors

    • nuxt: Migrate to oxc-walker (#32250)
    • nuxt,schema: Use oxc for onPrehydrate transform (#32045)
    • nuxt: Pass file language directly to parser options (#32665)
    • nuxt: Use direct import of installNuxtModule (228e3585e)

    📖 Documentation

    • Pass v3 template to create nuxt examples (03182202f)
    • Add reference to useNuxtData in data fetching composable pages (#32589)
    • Document the --modules flag in the init command (#32599)
    • Added new Shared folder to the example of v4 folder structure (#32630)
    • Improve grammar (#32640)
    • Typos (#32567)
    • Fix abbreviation (#32613)
    • Reference noUncheckedIndexedAccess rule change in v4 guide (#32643)
    • Fix links to Nitro docs (#32691)
    • Add best practices section (#31609)
    • Correct alias for local fonts in styling guide (#32680)
    • Update nuxt.new links to v4 (#32639)
    • Set correct default value for deep option in usefetch (#32724)
    • Fix link to issue (ca03f533f)
    • Add AI-assisted contribution guidelines (#32725)
    • Update Nuxt installation command to use npm create nuxt@latest (#32726)
    • Hydration best practice (#32746)
    • Add example for module .with() (#32757)
    • Replace dead Vue Router docs links (#32779)

    🏡 Chore

    • Handle missing commit details (0af98763d)
    • Update reproduction links for bug-report template (#32722)
    • Update unbuild and use absolute path in dev stubs (#32759)

    ✅ Tests

    🤖 CI

    • Trigger website redeploy on main branch (#32695)
    • Release pkg.pr.new for main/3.x branches as well (ca4f0b1da)
    • Apply 3x tag to latest v3 release (5e8dfc150)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Bobbie Goede (@BobbieGoede)
    • Damian Głowala (@DamianGlowala)
    • Dog (@dgxo)
    • Julien Huang (@huang-julien)
    • Yauheni Vasiukevich (@EvgenyWas)
    • Alex Liu (@Mini-ghost)
    • Robin (@OrbisK)
    • Mateleo (@Mateleo)
    • Stephen Jason Wang (@stephenjason89)
    • Maurits Meester (@mmeester)
    • Igor Kononenko (@igorexa34314)
    • Alex (@hywax)
    • Matej Černý (@cernymatej)
    • Alexander Lichter (@TheAlexLichter)
    • Hashim Kalam (@hashimkalam)
    • Alois Sečkár (@AloisSeckar)
    • Haythem Frikha (@Flamenate)
    • abeer0 (@iiio2)
    • Thomas (@ThomasWT)
    • Connor Pearson (@cjpearson)
    • dwood-csi (@dwood-csi)
    Open source →
  50. 3.17.713 Jul 2025
    Release notes

    3.17.7 is the last patch release before v3.18.

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🩹 Fixes

    • nuxt: Safe-guard extraPageMetaExtractionKeys (#32510)
    • nuxt: Expose loadBuilder error cause (8f13ce3c2)
    • vite: Handle resolving string vite input (#32527)
    • nuxt: Wrap only server components with island generic (#32540)
    • vite: Ignore when client entry cannot be resolved (19a292f34)
    • nuxt: Normalize segment catchall pattern before checking for parent (#32413)
    • nuxt: Update warning message to warn against null values (c1b83eab5)
    • nuxt: Ensure semver.satisfies returns true for pre-release versions (#32574)
    • nuxt: Scroll to anchor if present when changing page without saved position (#32376)
    • nuxt: Handle execute being passed to watch` (#32591)

    📖 Documentation

    • Update fetch types (#32522)
    • Clarify that runtime env variables must start with NUXT_ (#32223)
    • Fix key change behavior in useAsyncData and useFetch migration (#32560)
    • Change return type of async data from undefined to null in v3 docs (#32562)
    • Add section on custom hooks for Nuxt modules (#32586)
    • Provide async keyword (#32587)
    • Move augmenting hook types in hooks page (#32595)
    • Add section about module loading order (#32597)

    ✅ Tests

    • Reenable skipped unit tests (8fc9b9ee9)
    • Update test snapshot for generateTypes (c0855439d)
    • Improve page scanning test stability (84b96f3de)
    • Pass timeZone in to <NuxtTime> test (#32558)
    • Add more useAsyncData + useFetch tests (#32585)
    • Avoid hard-coding async-data keys (bfca95118)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Julien Huang (@huang-julien)
    • abeer0 (@iiio2)
    • Bobbie Goede (@BobbieGoede)
    • Damian Głowala (@DamianGlowala)
    • Nestor Vera (@hacknug)
    • Ezra Ashenafi (@Eazash)
    • Mike Laumann Bellika (@MikeBellika)
    • Maxime Pauvert (@maximepvrt)
    • Chriest Yu (@jcppman)
    • Andrei Hudalla (@paranoidPhantom)
    • Sigrid Huemer (@s1gr1d)
    • xjccc (@xjccc)
    Open source →
  51. 3.17.61 Jul 2025
    Release notes

    3.17.6 is a regularly scheduled patch release.

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🔥 Performance

    • nuxt: Decrease if checks when prerendering (#32455)

    🩹 Fixes

    • nuxt: Generate correct types for async data defaults based on nuxt.config (#32324)
    • nuxt: Reload at base URL in nuxt:chunk-reload-immediate (#32382)
    • nuxt: Use rollup to calculate island component filenames (#32421)
    • nuxt: Append set-cookie headers in error handler (#32483)
    • nuxt: Ensure asyncData runs if changing key while fetcher is running (#32466)
    • nuxt: Handle pure hash link clicks with navigateTo (#32393)
    • nuxt: Skip external <NuxtLink>'s custom on click handler (#32499)
    • nuxt: Update component loader regexp for minified code (#32298)
    • nuxt: Allow camelCase for lazy hydration attributes (#32297)
    • nuxt: Respect inheritAttrs: false in createClientOnly fn (#32323)
    • kit: Do not double-urlify file urls when resolving schema (#32354)
    • nuxt: Align scroll behavior with page transition completion (#32239)
    • nuxt: Set output.generatedCode.symbols for nitro build (#32358)
    • nuxt: Lazily access runtimeConfig (#32428)

    💅 Refactors

    • vite: Migrate plugins internally to vite environments (#32461)

    📖 Documentation

    • Clarify where logging tag is displayed (#32440)
    • Remove kit playground auto-import note (#32415)
    • Remove webstorm warning (#32513)
    • Migrate to h3js (#32243)
    • Update the fetch clear function description (#32287)
    • defineNuxtPlugin function documentation (#32328)
    • Mention that <NuxtLink> encodes query params (#32361)
    • Enhance documentation for Nuxt composables (#32218)
    • Adjust wording to reduce confusion in lifecycle section (#32503)
    • Improve useCookie example (367b85405)
    • Capitalise title (#32426)
    • Mention bun.lock for lockfile (#32427)

    🏡 Chore

    • Update stackblitz reproduction link (6ab5bac66)
    • Update copilot instructions (220439055)
    • Rename deprecated vitest workspace to projects (#32388)
    • Remove space in URL in comment (#32394)
    • Allow setting TAG on commandline (d387e07a3)

    ✅ Tests

    • nuxt: Add case for key only changes with immediate: false (#32473)
    • Separate nuxt legacy runtime tests (#32481)

    🤖 CI

    • Set correct base branch label (#32325)

    ❤️ Contributors

    • Mihailo Bursac (@djixadin)
    • Daniel Roe (@danielroe)
    • abeer0 (@iiio2)
    • 翠 (@sapphi-red)
    • Robin (@OrbisK)
    • Alex Liu (@Mini-ghost)
    • Damian Głowala (@DamianGlowala)
    • Julien Huang (@huang-julien)
    • Ibrahimm (@Ibra-cesar)
    • Peter Budai (@peterbud)
    • Ali Soueidan (@lazercaveman)
    • Vachmara (@vachmara)
    • xjccc (@xjccc)
    • Paul Melero (@paulmelero)
    • David Stack (@davidstackio)
    Open source →
  52. 3.17.53 Jun 2025
    Release notes

    3.17.5 is a regularly scheduled patch release.

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxt upgrade --dedupe
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🔥 Performance

    • nuxt: Replace remaining instance of globby (#31688)

    🩹 Fixes

    • nuxt: Export useScriptRybbitAnalytics from script stubs (d275ae1a0)
    • nuxt: Remove unneeded pattern from regexp (2954c092c)
    • nuxt: Ensure appConfig sources are not duplicated (#32216)
    • nuxt: Wrap slot with h() in ClientOnly (#30664)
    • kit: Ensure template filename uses safe patterns (4372b24dd)
    • nuxt: Access asyncData state from nuxt app instance (#32232)
    • nuxt: Make patterns relative to srcDir in buildCache (#32260)
    • nuxt: Return non-existent route component in RouteProvider (#32266)
    • nuxt: Use single asyncData watcher (#32247)
    • vite: Use arrow functions in dynamic imports (#32285)
    • webpack: Use plugin for rollup-compatible dynamic imports (#32281)

    📖 Documentation

    • Update addRouteMiddleware path in example (#32171)
    • Narrow link to just middleware (#32203)
    • Use optional chaining in error example (#32214)
    • Give example of using --env-file (29f6392cd)
    • Recommend nuxt command consistently (#32237)
    • Fix typos (#30413)
    • Add props to special metadata (#29708)
    • Fix wrong alert with warning in /guide/pages (#32270)
    • Update upgrade guide + roadmap (0040ee5e7)

    📦 Build

    🏡 Chore

    ✅ Tests

    • Add regression test for useAsyncData + transition (29f7c8cb4)
    • Ensure builder tests run sequentially (defa32829)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Julien Huang (@huang-julien)
    • Hugo Richard (@HugoRCD)
    • mxmxmmgg (@mxmxmmgg)
    • xjccc (@xjccc)
    • Horu (@HigherOrderLogic)
    • Baptiste Leproux (@larbish)
    • Phojie Rengel (@phojie)
    • duolaameng (@1411430556)
    • David Stack (@davidstackio)
    Open source →
  53. 3.17.420 May 2025
    Release notes

    3.17.4 is a regularly-scheduled patch release.

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxi@latest upgrade --dedupe
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🔥 Performance

    • nuxt: Use Set for circular dep plugin (#32110)
    • Refactor Array.includes checks to use Sets (#32133)
    • nuxt: Use shallowRef for primitive values (#32152)
    • nuxt: Skip route rules processing for empty child array (#32166)
    • nuxt: Use Intl.Collator instead of localeCompare (#32167)

    🩹 Fixes

    • nuxt: Do not await lazy asyncData inside <ClientOnly> (#32101)
    • nuxt: Respect cachedData with multiple asyncData calls (#32099)
    • nuxt: Clear async data after a tick (#32096)
    • nuxt: Support reactive keys in useLazyAsyncData (#32092)
    • rspack: Use ts-checker-rspack-plugin (#32115)
    • nuxt: Clear previous head in island-renderer (#32100)
    • nuxt: Handle virtual files prefixed with / (#32129)
    • schema: Remove nitro options from DeepPartial (#31990)
    • nuxt: Ensure legacy async data remains reactive (#32134)
    • nuxt: Pass attrs down to single child of <ClientOnly> (#32131)
    • nuxt: Fix merge conflicts (7044450d4)
    • nuxt: Clone vnode when passing attrs down to client-only (b3acf0c78)
    • vite: Do not replace global with globalThis (#32130)
    • nuxt: Suppress client-side errors by crawlers (#32137)
    • nuxt: Use fresh route when <NuxtLayout> first renders (#24673)
    • nuxt: Add additional logging when skipping error page for bot (68c270083)
    • nuxt: Add watch paths outside srcDir to parcel strategy (#32139)

    📖 Documentation

    • Use emphasis instead of quotes (#32078)
    • Update useNuxtData default return to undefined (#32054)
    • Capitalise headings (#32095)
    • Prefix imports.dirs with alias (0dbf314d9)
    • Mention node v20 is minimum requirement for nuxt setup (#32148)
    • Use more descriptive link text (d0b1b9d35)

    🏡 Chore

    • Remove unneeded JSdoc comments (#32090)
    • Use vitest workspaces for tests (#32121)

    ✅ Tests

    • Add universal routing tests + clean up output (64178b6f4)
    • nuxt: Add unit tests for watch strategies (#32138)
    • Resolve watch path (8fb562c04)
    • Use fake timers instead of setTimeout mock (#32142)

    🤖 CI

    ❤️ Contributors

    • John Tanzer (@moshetanzer)
    • Daniel Roe (@danielroe)
    • Robin (@OrbisK)
    • @beer (@iiio2)
    • Julien Huang (@huang-julien)
    • हिमांशु (@CodeMan62)
    • Norbiros (@Norbiros)
    • watsonhaw5566 (@watsonhaw5566)
    • xjccc (@xjccc)
    Open source →
  54. 3.17.312 May 2025
    Release notes

    3.17.3 is a regularly-scheduled patch release.

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxi@latest upgrade --dedupe
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🔥 Performance

    • nuxt: Pre-calculate extension glob before app resolution (#32052)
    • nuxt: Improve islands client components chunks (#32015)

    🩹 Fixes

    • nuxt: Preload async layouts (#32002)
    • nuxt: Handle File within FormData (#32013)
    • schema: Respect user-provided ignore patterns (#32020)
    • nuxt: Allow loading virtual files with query params (#32022)
    • nuxt: Don't use reactive key for useFetch with watch: false (#32019)
    • nuxt: Do not clear data if custom getCachedData is provided (#32003)
    • nuxt: Provide nuxtApp for asyncData functions run on server (#32038)
    • vite: Strip queries when skipping vite transform middleware (#32041)
    • nuxt: Sort hash sources and files (#32048)
    • nuxt: Do not suppress chunk import error (#32064)

    💅 Refactors

    • nuxt: Directly access initialised asyncData (e779d6cd5)

    📖 Documentation

    • Fix module initialization command for pnpm (#32024)
    • Provide nuxt installation guide with deno (#32029)
    • Add codeblock closing tag (#32043)
    • Tweak nuxt doc (#32063)
    • Add space between sentences (#32069)

    🤖 CI

    • Convert bug/enhancement labels to issue types (3ff743fe0)
    • Update payload for issue types (791e5f443)

    ❤️ Contributors

    • Ryota Watanabe (@wattanx)
    • Julien Huang (@huang-julien)
    • John Tanzer (@moshetanzer)
    • @beer (@iiio2)
    • Daniel Roe (@danielroe)
    • xjccc (@xjccc)
    • Max (@onmax)
    Open source →
  55. 3.17.25 May 2025
    Release notes

    3.17.2 is a regularly-scheduled patch release.

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxi@latest upgrade --dedupe
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🔥 Performance

    • nuxt: Tree-shake router's handleHotUpdate in production (#31971)

    🩹 Fixes

    • nuxt: Ensure asyncData is initialised before effects run (#31946)
    • nuxt: Skip view transition if user agent provides one before defining transition (#31945)
    • nuxt: Improve hashing for complex body in useFetch (#31963)
    • nuxt: Immediately call asyncData within client-only components (#31964)
    • nuxt: Don't render errors if event is already handled (#31966)
    • nuxt: Track whether need to reinit asyncData separately from deps (#31965)
    • nuxt: Preserve params/meta/matched with universal router (#31950)
    • nuxt: Respect scroll behavior set by scrollToTop (#31914)
    • nuxt: Load live data from vfs even if a file exists in buildDir (#31969)
    • nuxt: Short circuit middleware when validate returns false (#31967)
    • nuxt: Ensure useAsyncData reactive to key changes when immediate: false (#31987)
    • nuxt: Resolve real paths imported into virtual files (0bb07f129)
    • webpack: Broaden WarningFilter type (2a79dbd68)
    • schema: Broaden warningIgnoreFilters (a62e808ac)

    📖 Documentation

    • Add missing article (#31952)
    • Improve @nuxt/kit documentation (#31793)
    • Fix type issues in twoslash blocks (85ab105b8)
    • Add events page (#31977)

    🏡 Chore

    ✅ Tests

    🤖 CI

    • Run docs workflow against pull requests (08f968903)
    • Run tests against node v20 (3c97d3493)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Alex Liu (@Mini-ghost)
    • Martins Zeltins (@martinszeltins)
    • Ivan Martianov (@ivansky)
    • Lorenzo Fiamingo (@lorenzofiamingo)
    • James (@Koshux)
    Open source →
  56. 3.17.129 Apr 2025
    Release notes

    3.17.1 is the next patch release.

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxi@latest upgrade --dedupe
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🩹 Fixes

    • nuxt: Check if match exists with new unplugin filter (#31929)
    • nuxt: Reinitialise stale async data (#31940)
    • nuxt: Skip view transition if user agent is providing one (#31938)
    • nuxt: Trigger execute when non-immediate fetch key changes (#31941)
    • nuxt: Don't redirect when route has trailing slash (#31902)
    • ui-templates: Use escapeHTML from vue (8e4b8d62f)
    • schema: Add @vue/shared dependency (7d445c963)

    📦 Build

    • Copy README/LICENSE from repo root (8e287d556)

    🏡 Chore

    ✅ Tests

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Pooya Parsa (@pi0)
    • Kyohei Sonokawa (@kyohei-23)
    • Lorenzo Fiamingo (@lorenzofiamingo)
    Open source →
  57. 3.17.027 Apr 2025
    Release notes

    👀 Highlights

    This release brings a major reworking of the async data layer, a new built-in component, better warnings, and performance improvements!

    📊 Data Fetching Improvements

    A major reorganization of Nuxt's data fetching layer brings significant improvements to useAsyncData and useFetch.

    Although we have aimed to maintain backward compatibility and put breaking changes behind the experimental.granularCachedData flag (disabled by default), we recommend testing your application thoroughly after upgrading. You can also disable experimental.purgeCachedData to revert to the previous behavior if you are relying on cached data being available indefinitely after components using useAsyncData are unmounted.

    👉 Read the the original PR for full details (#31373), but here are a few highlights.

    Consistent Data Across Components

    All calls to useAsyncData or useFetch with the same key now share the underlying refs, ensuring consistency across your application:

    <!-- ComponentA.vue -->
    <script setup>
    const { data: users, pending } = useAsyncData('users', fetchUsers)
    </script>
    
    <!-- ComponentB.vue -->
    <script setup>
    // This will reference the same data state as ComponentA
    const { data: users, status } = useAsyncData('users', fetchUsers)
    // When either component refreshes the data, both will update consistently
    </script>
    

    This solves various issues where components could have inconsistent data states.

    Reactive Keys

    You can now use computed refs, plain refs, or getter functions as keys:

    const userId = ref('123')
    const { data: user } = useAsyncData(
      computed(() => `user-${userId.value}`),
      () => fetchUser(userId.value)
    )
    
    // Changing the userId will automatically trigger a new data fetch
    // and clean up the old data if no other components are using it
    userId.value = '456'
    

    Optimized Data Refetching

    Multiple components watching the same data source will now trigger only a single data fetch when dependencies change:

    // In multiple components:
    const { data } = useAsyncData(
      'users', 
      () => $fetch(`/api/users?page=${route.query.page}`),
      { watch: [() => route.query.page] }
    )
    
    // When route.query.page changes, only one fetch operation will occur
    // All components using this key will update simultaneously
    

    🎭 Built-In Nuxt Components

    <NuxtTime> - A new component for safe time display

    We've added a new <NuxtTime> component for SSR-safe time display, which resolves hydration mismatches when working with dates (#31876):

    <template>
      <NuxtTime :datetime="Date.now()" />
    </template>
    

    The component accepts multiple time formats and gracefully handles both client and server rendering.

    Enhanced <NuxtErrorBoundary>

    The <NuxtErrorBoundary> component has been converted to a Single File Component and now exposes error and clearError from the component - as well as in the error slot types, giving you greater ability to handle errors in your templates and via useTemplateRef (#31847):

    <NuxtErrorBoundary @error="handleError">
      <template #error="{ error, clearError }">
        <div>
          <p>{{ error.message }}</p>
          <button @click="clearError">Try again</button>
        </div>
      </template>
      
      <!-- Content that might error -->
      <MyComponent />
    </NuxtErrorBoundary>
    

    🔗 Router Improvements

    <NuxtLink> now accepts a trailingSlash prop, giving you more control over URL formatting (#31820):

    <NuxtLink to="/about" trailing-slash>About</NuxtLink>
    <!-- Will render <a href="/about/"> -->
    

    🔄 Loading Indicator Customization

    You can now customize the loading indicator with new props directly on the component (#31532):

    • hideDelay: Controls how long to wait before hiding the loading bar
    • resetDelay: Controls how long to wait before resetting loading indicator state
    <template>
      <NuxtLoadingIndicator :hide-delay="500" :reset-delay="300" />
    </template>
    

    📚 Documentation as a Package

    The Nuxt documentation is now available as an npm package! You can install @nuxt/docs to access the raw markdown and YAML content used to build the documentation website (#31353).

    💻 Developer Experience Improvements

    We've added several warnings to help catch common mistakes:

    • Warning when server components don't have a root element #31365
    • Warning when using the reserved runtimeConfig.app namespace #31774
    • Warning when core auto-import presets are overridden #29971
    • Error when definePageMeta is used more than once in a file #31634

    🔌 Enhanced Module Development

    Module authors will be happy to know:

    • A new experimental.enforceModuleCompatibility allows Nuxt to throw an error when a module is loaded that isn't compatible with it (#31657). It will be enabled by default in Nuxt v4.
    • You can now automatically register every component exported via named exports from a file with addComponentExports #27155

    🔥 Performance Improvements

    Several performance improvements have been made:

    • Switched to tinyglobby for faster file globbing #31668
    • Excluded .data directory from type-checking for faster builds #31738
    • Improved tree-shaking by hoisting the purgeCachedData check #31785

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxi@latest upgrade --dedupe
    

    This refreshes your lockfile and pulls in all the latest dependencies that Nuxt relies on, especially from the unjs ecosystem.

    👉 Changelog

    compare changes

    🚀 Enhancements

    • nuxt: Accept hideDelay and resetDelay props for loading indicator (#31532)
    • nuxt: Warn server components need root element (#31365)
    • docs: Publish raw markdown/yaml docs as @nuxt/docs (#31353)
    • kit,nuxt: Pass dotenv values from loadNuxtConfig to nitro (#31680)
    • nuxt,vite: Support disabling scripts in dev mode (#31724)
    • nuxt: Warn if user uses reserved runtimeConfig.app namespace (#31774)
    • kit,schema: Allow throwing error if modules aren't compatible (#31657)
    • nuxt: Extract middleware when scanning page metadata (#30708)
    • nuxt: Warn if core auto-import presets are overridden (#29971)
    • nuxt: Scan named exports with addComponentExports (#27155)
    • nuxt: Convert <NuxtErrorBoundary> to SFC + expose error/clearError (#31847)
    • nuxt: Add <NuxtTime> component for ssr-safe time display (#31876)
    • nuxt: Add trailingSlash prop to <NuxtLink> (#31820)

    🔥 Performance

    • kit,rspack,webpack: Switch to tinyglobby (#31668)
    • kit: Exclude .data directory from type-checking (#31738)
    • nuxt: Hoist purgeCachedData check to improve tree-shaking (#31785)
    • nuxt: Remove oxc-parser manual wasm fallback logic (#31484)
    • nuxt: Remove unecessary type check for useFetch (#31910)

    🩹 Fixes

    • kit,vite: Ensure all modulesDir paths are added to fs.allow (#31540)
    • nuxt: Pass slots through to lazy hydrated components (#31649)
    • vite: Do not return 404 for dev server handlers which shadow /_nuxt/ (#31646)
    • nuxt: Sync error types for useLazyAsyncData (#31676)
    • nuxt: Strip base url from error.url (#31679)
    • nuxt: Render inline styles before app:rendered is called (#31686)
    • nuxt: Update nitro imports (0bec0bd26)
    • nuxt: Check for fallback attribute when stripping <DevOnly> (c1d735c27)
    • vite: Invalidate files not present in module graph (ecae2cd54)
    • nuxt: Do not add manifest preload when noScripts (c9572e953)
    • nuxt: Do not prompt to update compatibilityDate (#31725)
    • nuxt: Show brotli size by default when analyzing bundle (#31784)
    • nuxt: Always pass statusMessage when rendering html error (#31761)
    • nuxt: Error when definePageMeta is used more than once (#31634)
    • nuxt: Parse error.data before rendering error.vue (#31571)
    • nuxt: Use single synced asyncdata instance per key (#31373)
    • nuxt: Use useAsyncData in console log (#31801)
    • nuxt: Wait for suspense to resolve before handling NuxtErrorBoundary error (#31791)
    • vite: Disable preserveModules (#31839)
    • nuxt: Align pending with status value for v4 (#25864)
    • nuxt: Consider full path when de-duplicating routes (#31849)
    • nuxt: Augment nuxt/app in generated middleware and layouts declarations (#31808)
    • nuxt: Correct order of args passed to withoutBase (f956407bb)
    • vite: Dedupe vue in vite-node dev server (f3882e004)
    • ui-templates: Pass pointer events through spotlight div in error dev template (#31887)
    • kit: Include user-defined types before internal ones in tsconfig.json (#31882)
    • nuxt: Do not purge nuxt data if active useNuxtData (#31893)
    • nuxt: Do not include components of key in useFetch watch sources (#31903)
    • nuxt: Use first existing modulesDir to store build cache files (#31907)

    💅 Refactors

    • nuxt: Use shallowRef for primitives as well (#31662)
    • nuxt: Move island renderer into its own event handler (#31386)
    • nuxt: Remove unneeded import (#31750)
    • nuxt: Use _replaceAppConfig when applying hmr (#31786)
    • nuxt: Use new unplugin filter options (#31868)
    • schema: Do not generate types for ConfigSchema (#31894)

    📖 Documentation

    • Add note on extending auto-imports (#31640)
    • Improve description of app.vue (#31645)
    • Use video-accordion video and add more videos (#31655)
    • Add description of templateParams to seo docs (#31583)
    • Refine auto-imports documentation (#31700)
    • Fix nuxt logo on website badge (#31704)
    • Update tailwindcss link (b5741cb5a)
    • Adjust description of useHydration (#31712)
    • Remove trailing slash (#31751)
    • Remove comment about callOnce returning value (#31747)
    • Use vs. consistently (#31760)
    • Update nitro addServerHandler example (#31769)
    • Add supporting shared folder video (#31651)
    • Update example for component auto-import in nuxt modules (#31757)
    • Refine nuxt kit components documentation (#31714)
    • Use trailing slash for vitest link (82de8bcf8)
    • Fix casing (#31805)
    • Add discord and nuxters links (#31888)
    • Fix typos (#31898)

    📦 Build

    • nuxt: Use vue-sfc-transformer to process sfcs (#31691)

    🏡 Chore

    ✅ Tests

    • nuxt: Add customizable test api for pages tests (#31619)
    • kit: Fix tests when running on Windows (#31694)
    • Update page metadata snapshot (89a596075)
    • Add basic runtime tests for <NuxtErrorBoundary> (4df92c45f)
    • Add version to mock nuxt (915fae2fd)
    • Update assertion for pendingWhenIdle (08f2224c8)
    • Remove incorrect assertions (fdc4b5343)
    • Update tests for purgeCachedData (c6411eb17)

    🤖 CI

    • Add notify-nuxt-website workflow (#31726)

    ❤️ Contributors

    • @beer (@iiio2)
    • Julien Huang (@huang-julien)
    • Daniel Roe (@danielroe)
    • Saeid Zareie (@Saeid-Za)
    • Bobbie Goede (@BobbieGoede)
    • Damian Głowala (@DamianGlowala)
    • Maxime Pauvert (@maximepvrt)
    • Leonid (@john-psina)
    • Wind (@productdevbook)
    • Arkadiusz Sygulski (@Aareksio)
    • Rohan Dhimal (@drowhannn)
    • xjccc (@xjccc)
    • Robin (@OrbisK)
    • Alex Liu (@Mini-ghost)
    • Daniel Kelly (@danielkellyio)
    • Jeffrey van den Hondel (@jeffreyvdhondel)
    • Alexander Lichter (@TheAlexLichter)
    • Sébastien Chopin (@atinux)
    • Yizack Rangel (@Yizack)
    • Joaquín Sánchez (@userquin)
    • IlyaL (@ilyaliao)
    • Ben McCann (@benmccann)
    • Anthony Fu (@antfu)
    • Alexandru Ungureanu (@unguul)
    Open source →
  58. 3.16.21 Apr 2025
    Release notes

    3.16.2 is the next patch release.

    ✅ Upgrading

    Our recommendation for upgrading is to run:

    npx nuxi@latest upgrade --dedupe
    

    This will deduplicate your lockfile as well, and help ensure that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

    👉 Changelog

    compare changes

    🔥 Performance

    • nuxt: Improve tree-shaking of useRequestEvent on client (#31586)

    🩹 Fixes

    • nuxt: Pass down attrs to <Body> and <Html> (#31513)
    • nuxt: Use greedy catchall when /index is the last segment (#31528)
    • nuxt: Reset page:loading:end hook before navigation (#31504)
    • nuxt: Write initial cookie value if different from document.cookie (#31517)
    • nuxt: Support template string quotes in resolveComponent (#31526)
    • nuxt: Show fatal errors thrown in middleware (#31518)
    • nuxt: Use name to index route providers in dev (#31544)
    • nuxt: Improve default scroll behaviour (#31545)
    • vite: Return 404 for non-existent _nuxt/ paths in development (#31543)
    • nuxt: Pass error data to error.vue (#31573)
    • nuxt: Use unhead v2 api in default welcome + error pages (#31584)
    • nuxt: Improve consistency of page metadata extraction (#31306)
    • nuxt: Do not remove meta when scanPageMeta is disabled (0ba454b21)

    💅 Refactors

    • nuxt: Simplify conditional branches of <NuxtPage> (#31561)
    • Replace useServerHead in onPrehydrate with useHead (#31585)

    📖 Documentation

    • Move custom directories note to the correct place (#29100)
    • Update example to useTemplateRef (#31458)
    • Provide async function for $fetch (#31459)
    • Mention the possibility to scan pages based on a pattern (#31462)
    • Add dedupe flag (#31467)
    • Improve refreshNuxtData docs (#31448)
    • Add missing -- before --template (#31469)
    • Migrate to @nuxt/content v3 (#31150)
    • Fix icon for main docs (e7828d9c6)
    • Save selected package manager (#31520)
    • Improve refresh nuxt data example (#31487)
    • Note that middleware runs on error pages as well (df14c0263)
    • Replace all 'Nuxt 3' with 'Nuxt' in documentation (#31519)
    • resolveComponent only auto-imports components with literal strings (#31511)
    • Add ticks around tsconfig.json (#31473)
    • Capitalize heading (#31523)
    • Update links to unhead.unjs.io (1913febbb)
    • Document that props are passed via server components via query (db7688219)
    • Improve description of page:start and page:finish hooks (#31570)

    🏡 Chore

    ✅ Tests

    • Avoid invalid nested font face (#31524)
    • Add test for loading indicator with custom key (25ca9b819)
    • Add test for custom prop + loading indicator (94bfed031)
    • Update snapshot (55134fc2a)

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Julien Huang (@huang-julien)
    • Bobbie Goede (@BobbieGoede)
    • Alex Liu (@Mini-ghost)
    • Dennis Adriaansen (@dennisadriaans)
    • Guillaume Chau (@Akryum)
    • @beer (@iiio2)
    • 翠 / green (@sapphi-red)
    • xjccc (@xjccc)
    • Hugo Richard (@HugoRCD)
    • Sébastien Chopin (@atinux)
    • Johannes Buchholz (@jhony1104)
    • Alexander Lichter (@TheAlexLichter)
    • Matej Černý (@cernymatej)
    • Claudiu (@sofuxro)
    Open source →
  59. 3.16.119 Mar 2025
    Release notes

    compare changes

    🔥 Performance

    • nuxt: Use browser cache for payloads (#31379)

    🩹 Fixes

    • nuxt: Restore nuxt aliases to nitro compilerOptions.paths (#31278)
    • nuxt: Use new mocked-exports (#31295)
    • nuxt: Check resolved options for polyfills (#31307)
    • nuxt: Render style component html (#31337)
    • nuxt: Add missing lazy hydration prop in regex (#31359)
    • nuxt: Fully resolve nuxt dependencies (#31436)
    • vite: Don't show interim vite build output files (#31439)
    • nuxt: Ignore prerendering unprefixed public assets (151912ec3)
    • nuxt: Use more performant router catchall pattern (#31450)
    • nuxt: Prevent param duplication in typedPages implementation (#31331)
    • nuxt: Sort route paths before creating route tree (#31454)

    📖 Documentation

    • Update link to vercel edge network (ec20802a5)
    • Improve HMR performance note for Windows users (#31301)
    • Correct WSL note phrasing (#31322)
    • Fix typo (#31341)
    • Adjust app.head example (#31350)
    • Include package manager options in update script (#31346)
    • Add missing comma (#31362)
    • Add mention of addServerTemplate to modules guide (#31369)
    • Add rspack and remove test-utils for monorepo guide (#31371)
    • Adjust example (#31372)
    • Update experimental docs (#31388)
    • Use ini syntax block highlighting for .env files (f79fabe46)
    • Improve useHydration docs (#31427)
    • Update broken docs links (#31430)
    • Mention possibility of prerendering api routes (#31234)

    🏡 Chore

    ✅ Tests

    • Migrate runtime compiler test to playwright (+ add test cases) (#31405)
    • Migrate spa preloader tests to playwright (#31273)
    • Use srvx and random port for remote provider (#31432)

    🤖 CI

    ❤️ Contributors

    • Daniel Roe (@danielroe)
    • Anoesj Sadraee (@Anoesj)
    • Peter Radko (@Gwynerva)
    • Adam DeHaven (@adamdehaven)
    • Alex Liu (@Mini-ghost)
    • Julien Huang (@huang-julien)
    • Francesco Agnoletto (@Kornil)
    • Guillaume Chau (@Akryum)
    • imreegall (@imreegall)
    • xjccc (@xjccc)
    • Sam Blowes (@blowsie)
    • Nimit012 (@Nimit012)
    • Camille Coutens (@Kamsou)
    Open source →
  60. 3.16.07 Mar 2025
    Release notes

    👀 Highlights

    There's a lot in this one!

    ⚡️ A New New Nuxt

    Say hello to create-nuxt, a new tool for starting Nuxt projects (big thanks to @devgar for donating the package name)!

    It's a streamlined version of nuxi init - just a sixth of the size and bundled as a single file with all dependencies inlined, to get you going as fast as possible.

    Starting a new project is as simple as:

    npm create nuxt
    

    Special thanks to @cmang for the beautiful ASCII-art. ❤️

    Want to learn more about where we're headed with the Nuxt CLI? Check out our roadmap here, including our plans for an interactive modules selector.

    🚀 Unhead v2

    We've upgraded to unhead v2, the engine behind Nuxt's <head> management. This major version removes deprecations and improves how context works:

    • For Nuxt 3 users, we're shipping a legacy compatibility build so nothing breaks
    • The context implementation is now more direct via Nuxt itself
    // Nuxt now re-exports composables while properly resolving the context
    export function useHead(input, options = {}) {
      const unhead = injectHead(options.nuxt)
      return head(input, { head: unhead, ...options })
    }
    

    If you're using Unhead directly in your app, keep in mind:

    1. Import from Nuxt's auto-imports or #app/composables/head instead of @unhead/vue
    2. Importing directly from @unhead/vue might lose async context

    Don't worry though - we've maintained backward compatibility in Nuxt 3, so most users won't need to change anything!

    If you've opted into compatibilityVersion: 4, check out our upgrade guide for additional changes.

    🔧 Devtools v2 Upgrade

    Nuxt Devtools has leveled up to v2 (#30889)!

    You'll love the new features like custom editor selection, Discovery.js for inspecting resolved configs (perfect for debugging), the return of the schema generator, and slimmer dependencies.

    One of our favorite improvements is the ability to track how modules modify your Nuxt configuration - giving you X-ray vision into what's happening under the hood.

    👉 Discover all the details in the Nuxt DevTools release notes.

    ⚡️ Performance Improvements

    We're continuing to make Nuxt faster, and there are a number of improvements in v3.16:

    1. Using exsolve for module resolution (#31124) along with the rest of the unjs ecosystem (nitro, c12, pkg-types, and more) - which dramatically speeds up module resolution
    2. Smarter module resolution paths (#31037) - prioritizes direct imports for better efficiency
    3. Eliminated duplicated Nitro alias resolution (#31088) - leaner file handling
    4. Streamlined loadNuxt by skipping unnecessary resolution steps (#31176) - faster startups
    5. Adopt oxc-parser for parsing in Nuxt plugins (#30066)

    All these speed boosts happen automatically - no configuration needed!

    Shout out to CodSpeed with Vitest benchmarking to measure these improvements in CI - it has been really helpful.

    To add some anecdotal evidence, my personal site at roe.dev loads 32% faster with v3.16, and nuxt.com is 28% faster. I hope you see similar results! ⚡️

    🕰️ Delayed Hydration Support

    We're very pleased to bring you native delayed/lazy hydration support (#26468)! This lets you control exactly when components hydrate, which can improve initial load performance and time-to-interactive. We're leveraging Vue's built-in hydration strategies - check them out in the Vue docs.

    <template>
      <!-- Hydrate when component becomes visible in viewport -->
      <LazyExpensiveComponent hydrate-on-visible />
      
      <!-- Hydrate when browser is idle -->
      <LazyHeavyComponent hydrate-on-idle />
      
      <!-- Hydrate on interaction (mouseover in this case) -->
      <LazyDropdown hydrate-on-interaction="mouseover" />
      
      <!-- Hydrate when media query matches -->
      <LazyMobileMenu hydrate-on-media-query="(max-width: 768px)" />
      
      <!-- Hydrate after a specific delay in milliseconds -->
      <LazyFooter :hydrate-after="2000" />
    </template>
    

    You can also listen for when hydration happens with the @hydrated event:

    <LazyComponent hydrate-on-visible @hydrated="onComponentHydrated" />
    

    Learn more about lazy hydration in our components documentation.

    🧩 Advanced Pages Configuration

    You can now fine-tune which files Nuxt scans for pages (#31090), giving you more control over your project structure:

    export default defineNuxtConfig({
      pages: {
        // Filter specific files or directories
        pattern: ['**/*.vue'],
      }
    })
    

    🔍 Enhanced Debugging

    We've made debugging with the debug option more flexible! Now you can enable just the debug logs you need (#30578):

    export default defineNuxtConfig({
      debug: {
        // Enable specific debugging features
        templates: true,
        modules: true,
        watchers: true,
        hooks: {
          client: true,
          server: true,
        },
        nitro: true,
        router: true,
        hydration: true,
      }
    })
    

    Or keep it simple with debug: true to enable all these debugging features.

    🎨 Decorators Support

    For the decorator fans out there (whoever you are!), we've added experimental support (#27672). As with all experimental features, feedback is much appreciated.

    export default defineNuxtConfig({
      experimental: {
        decorators: true
      }
    })
    
    function something (_method: () => unknown) {
      return () => 'decorated'
    }
    
    class SomeClass {
      @something
      public someMethod () {
        return 'initial'
      }
    }
    
    const value = new SomeClass().someMethod()
    // returns 'decorated'
    

    📛 Named Layer Aliases

    It's been much requested, and it's here! Auto-scanned local layers (from your ~~/layers directory) now automatically create aliases. You can access your ~~/layers/test layer via #layers/test (#30948) - no configuration needed.

    If you want named aliases for other layers, you can add a name to your layer configuration:

    export default defineNuxtConfig({
      $meta: {
        name: 'example-layer',
      },
    })
    

    This creates the alias #layers/example-layer pointing to your layer - making imports cleaner and more intuitive.

    🧪 Error Handling Improvements

    We've greatly improved error messages and source tracking (#31144):

    1. Better warnings for undefined useAsyncData calls with precise file location information
    2. Error pages now appear correctly on island page errors (#31081)

    Plus, we're now using Nitro's beautiful error handling (powered by youch) to provide more helpful error messages in the terminal, complete with stacktrace support.

    Nitro now also automatically applies source maps without requiring extra Node options, and we set appropriate security headers when rendering error pages.

    📦 Module Development Improvements

    For module authors, we've added the ability to augment Nitro types with addTypeTemplate (#31079):

    // Inside your Nuxt module
    export default defineNuxtModule({
      setup(options, nuxt) {
        addTypeTemplate({
          filename: 'types/my-module.d.ts',
          getContents: () => `
            declare module 'nitropack' {
              interface NitroRouteConfig {
                myCustomOption?: boolean
              }
            }
          `
        }, { nitro: true })
      }
    })
    

    ⚙️ Nitro v2.11 Upgrade

    We've upgraded to Nitro v2.11. There are so many improvements - more than I can cover in these brief release notes.

    👉 Check out all the details in the Nitro v2.11.0 release notes.

    📦 New unjs Major Versions

    This release includes several major version upgrades from the unjs ecosystem, focused on performance and smaller bundle sizes through ESM-only distributions:

    • unenv upgraded to v2 (full rewrite)
    • db0 upgraded to v0.3 (ESM-only, native node:sql, improvements)
    • ohash upgraded to v2 (ESM-only, native node:crypto support, much faster)
    • untyped upgraded to v2 (ESM-only, smaller install size)
    • unimport upgraded to v4 (improvements)
    • c12 upgraded to v3 (ESM-only)
    • pathe upgraded to v2 (ESM-only)
    • cookie-es upgraded to v2 (ESM-only)
    • esbuild upgraded to v0.25
    • chokidar upgraded to v4

    ✅ Upgrading

    As usual, our recommendation for upgrading is to run:

    npx nuxi@latest upgrade --dedupe
    

    This refreshes your lockfile and pulls in all the latest dependencies that Nuxt relies on, especially from the unjs ecosystem.

    👉 Changelog

    compare changes

    🚀 Enhancements

    • nuxt: Upgrade @nuxt/devtools to v2 (#30889)
    • nuxt: Granular debug options (#30578)
    • nuxt: Add type hints for NuxtPage (#30704)
    • nuxt: Support tracking changes to nuxt options by modules (#30555)
    • nuxt: Allow disabling auto-imported polyfills (#30332)
    • schema: Add runtime + internal type validation (#30844)
    • kit,nuxt,schema: Support experimental decorators syntax (#27672)
    • kit,nuxt: Allow multiple nuxts to run in one process (#30510)
    • kit: Add named layer aliases (#30948)
    • kit,nuxt,vite: directoryToURL to normalise paths (#30986)
    • nuxt: Allow forcing start/set in loading indicator (#30989)
    • nuxt: Allow specifying glob patterns for scanning pages/ (#31090)
    • nuxt: Add types for default NuxtLink slot (#31104)
    • nuxt: Delayed/lazy hydration support (#26468)
    • vite: Add vite's modulepreload polyfill (#31164)
    • nuxt: Show source file when warning about undefined useAsyncData (#31144)
    • kit,nuxt: Augment nitro types with addTypeTemplate (#31079)
    • kit,nuxt: Resolve template imports from originating module (#31175)
    • nuxt: Use oxc-parser instead of esbuild + acorn (#30066)
    • nuxt: Upgrade to unhead v2 (#31169)
    • nuxt: Align nuxt error handling with nitro (#31230)

    🔥 Performance

    • nuxt: Remove duplicated nitro alias resolution (#31088)
    • kit: Try non-subpath routes first to resolve nuxt modules (#31037)
    • nuxt: Migrate to use exsolve for module resolution (#31124)
    • kit: Skip extra module resolution step in loadNuxt (#31176)

    🩹 Fixes

    • nuxt: Ensure <NuxtLayout> fallback prop is typed (#30832)
    • nuxt: Assign slot to be rendered for client components (#30768)
    • nuxt,vite: Do not override vite import conditions (#30887)
    • nuxt: Prevent keepalive cache reset (#30807)
    • nuxt: Remove div wrapper in client-only pages (#30425)
    • schema: Update type import to nitropack (aba75bd5a)
    • vite: Use resolveId from vite-node to resolve deps (#30922)
    • schema: Normalise additional experimental options (63e0c342c)
    • nuxt: Delete existing properties in app config HMR (#30918)
    • schema: Return null from resolve functions (d68e8ce57)
    • schema: Check if app.head.meta values are undefined (#30959)
    • nuxt: Make shared/ directories available within layers (#30843)
    • kit: Ensure nuxt is loaded from cwd rather than parent dir (#30910)
    • ui-templates: Remove extra <pre> when rendering dev errors (9aab69ec4)
    • nuxt: Use tsx loader for jsx blocks as well (#31014)
    • Remove unimplemented page:transition:start type (#31040)
    • kit: Expose module dependency errors (#31035)
    • nuxt: Deprioritise layer css imports (#31020)
    • nuxt: Ensure provide / inject work in setup of defineNuxtComponent (#30982)
    • nuxt: Decode URI components in cache driver methods (#30973)
    • nuxt: Use _ for NuxtIsland name on server pages (#31072)
    • nuxt: Use ohash to calculate legacy async data key without hash (#31087)
    • nuxt,schema: Resolve shared dir from config (#31091)
    • kit,schema: Set esbuild target for experimental decorators (#31089)
    • nuxt: Set nuxt.options.pages to detected configuration (#31101)
    • nuxt: Warn when definePageMeta does not receive an object (#31156)
    • nuxt: Fix nitro import statements for v2 (151cf7d49)
    • nuxt: Update path to no-ssr middleware handler (a99c59fbd)
    • nuxt: Align type of custom navigate with vue-router (7a1934509)
    • nuxt: Show error page on island page error (#31081)
    • nuxt: Do not render payloads if disabled, and correct regexp (#31167)
    • nuxt: Add backwards-compatible serialisation for nuxt.options.pages (fa480e0a0)
    • ui-templates: Escape inline scripts correctly in ui templates (39c2b0a2c)
    • nuxt: Add back fallback nuxtlink type signature (a8856de59)
    • kit: Provide default extensions in resolveModule (6fb5c9c15)
    • nuxt: Provide default extensions in resolveTypePath (a0f9ddfe2)
    • nuxt: Strip query before generating payload url (34ddc2d2f)
    • schema: Resolve workspaceDir to closest git config (7a2fbce01)
    • kit: Include declaration files when resolving compilerOptions.paths (835e89404)
    • nuxt: Consolidate head component context (#31209)
    • nuxt: Resolve shared externals to absolute paths (#31227)
    • nuxt: Skip deep merge in dev mode for prototype keys (#31205)
    • schema: Use RawVueCompilerOptions for unresolved tsconfig (#31202)
    • nuxt: Ensure externals are resolved first (#31235)
    • nuxt: Ensure we strip all chars in payload url (4f067f601)
    • nuxt: Exempt nitro from import protections (#31246)
    • nuxt: Normalise error url to pathname (87b69c9ae)
    • nuxt: Ensure head components are reactive (#31248)
    • nuxt: Preserve query/hash when calling navigateTo with replace (#31244)
    • nuxt: Apply ignore rules to nitro devStorage (#31233)
    • nuxt: Fall back to wasm if oxc native bindings are missing (#31190)
    • nuxt: Pass useFetch function name on server for warning (#31213)
    • vite: Prevent overriding server build chunks (89a29e760)
    • nuxt: Strip query in x-nitro-prerender header (2476cab9a)

    💅 Refactors

    • nuxt: Prefer logical assignment operators (#31004)
    • nuxt: Use isEqual from ohash/utils (2e27cd30c)
    • nuxt: Update to noScripts route rule (#31083)
    • nuxt: Re-organize internal runtime/nitro files (#31131)
    • nuxt: Explicitly type internal request fetch (54cb80319)
    • nuxt: Use relative imports (1bce3dc3b)
    • nuxt: Early return island response (#31094)

    📖 Documentation

    • Tiny typo (#30799)
    • Fix typo (#30817)
    • Remove backslashes in spaLoadingTemplate example (#30830)
    • Update path to nuxt binary (8992c4ea0)
    • Add nuxt lifecycle (#30726)
    • Add additional information about NuxtPage (#30781)
    • Improve navigateTo docs with clearer structure and examples (#30876)
    • Add auto import info about shared utils (#30858)
    • Fix typo and improve data fetching examples (#30935)
    • Clarify that local layers are scanned from rootDir (27e356fe6)
    • Fix typo (#30963)
    • Update links to unhead sources (6c520ef74)
    • Fix typo (#30971)
    • Add tips on how to override layers aliases (#30970)
    • Add description for vue:setup and app:data:refresh hooks (#31001)
    • Mention requirement to wrap middleware in defineNuxtRouteMiddleware (#31005)
    • Add port option to preview command (#30999)
    • Remove link to deleted nuxt 2 section (#31077)
    • Link to the scripts releases page (#31095)
    • Add .nuxtrc documentation (#31093)
    • Fix typo in example command (#31112)
    • Explain why headers not forwarded when using $fetch on the server (#31114)
    • Fix links to nitro directory structure (5a696176d)
    • Update to use create nuxt command (fe82af4c9)
    • Update getCachedData types (#31208)
    • Update code example for nightly release to default to 3x (a243f8fcf)
    • Clarify lifecycle behavior of <NuxtPage> during page changes (#31116)
    • Mention workaround for typedPages in unhoisted pnpm setups (#31262)

    📦 Build

    • nuxt: Add subpath imports for type support (8ef3fcc4d)

    🏡 Chore

    ✅ Tests

    • Add benchmarks for dev server initial build (#30742)
    • Exclude urls from lychee crawler used in test suite (8e2d9a640)
    • Prepare environment to ensure more reproducible dev tests (bc89ef867)
    • Update unit test (5a71ef8ac)
    • Add major version to unit test (676447239)
    • Slightly improve coverage (d992c0da9)
    • Bump timeout for route hmr (cbe38cf52)
    • Update unit test snapshot for jsx (4910959b9)
    • Disable codspeed outside of ci (71de708a0)
    • Add some more stability in hmr tests (9a9fcdab5)
    • Skip testing spa-preloader in dev (6cf97bfe5)
    • Fix time-based hydration test (da3b39d67)
    • Simplify further (ad306f472)
    • Filter out dev server logs 🙈 (ee040eea3)
    • Update unit test snapshot (97ec3143a)
    • Provide nuxt extensions in unit test (358729e96)
    • Add benchmark for vite client build (#31118)
    • Update build benchmark (82ca08f93)
    • Ensure dev tests have separate buildDirs (d7623f884)
    • Update nitro type import (8f61d0090)
    • Update import to #internal/nitro/app (a1b855cc5)
    • Try to improve dev test stability (#31218)
    • Migrate hmr test to use playwright runner (#31241)

    ❤️ Contributors

    • Anoesj Sadraee (@Anoesj)
    • Daniel Roe (@danielroe)
    • John Tanzer (@moshetanzer)
    • Connor Pearson (@cjpearson)
    • Connor Roberts (@murshex)
    • Harlan Wilton (@harlan-zw)
    • Alex Liu (@Mini-ghost)
    • Kevin Deng 三咲智子 (@sxzz)
    • xjccc (@xjccc)
    • Julien Huang (@huang-julien)
    • Michael Brevard (@GalacticHypernova)
    • Maik Kowol (@94726)
    • Anthony Fu (@antfu)
    • Bobbie Goede (@BobbieGoede)
    • Clayton Chew (@claytonchew)
    • awfulness (@awfulness)
    • Sébastien Chopin (@atinux)
    • Saeid Zareie (@Saeid-Za)
    • Vahagn Zaqaryan (@Vahagn-Zaqaryan)
    • Idorenyin Udoh (@idorenyinudoh)
    • Jonas Thelemann (@dargmuesli)
    • Ryota Watanabe (@wattanx)
    • Horu (@HigherOrderLogic)
    • Nolhan (@Nonolanlan1007)
    • Typed SIGTERM (@typed-sigterm)
    • Hans Tu (@ChiaHanTu)
    • Damian Głowala (@DamianGlowala)
    • David Marr (@marr)
    • Camille Coutens (@Kamsou)
    • Charlie ✨ (@CharleeWa)
    • Hussain Panahy (@HP8585)
    • @beer (@iiio2)
    Open source →