NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #4082 most downloaded on npm
Toolkit for authoring modules and interacting with Nuxt
Last release 2 months ago
05 Aug 2026
Ships fairly regularly
a new release about every 3 weeks
Nearly every release is documented
notes for 55 of the last 60 stable releases
12 versions withdrawn
withdrawn after publishing
6 years old
151 releases · first in 2021
One column per quarter.
> 4.5.2 is the next patch release.
4.5.2 is the next patch release.
v-for islands transform (#35877)apply and applyToEnvironment in vite wrapper (#35899)enforce in vite wrapper (#35916)vite-node (#35758)<NuxtPage> on nav + with slot (#35948)prepend is set (#35942)import.meta.test for server code (#35987)vue-component-type-helpers instead of locally maintained helpers (#35840)isReferenceIdentifier in page-meta plugin (#35882)defineVitestProject in e2e tests (#35926)@nuxt/devtools to v3.4.0 (#35892)toFsUrl (a5ad667f7)permissions: {} to workflows (2e1a1cbeb)> ⚠️ This is a security release. We recommend upgrading as soon as possible with npx nuxt upgrade --dedupe.
⚠️ 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/devtools@3.3.1, 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.
vue.optionsApi and disable it for v5+ (#35791)ssr: false (#35782)useRoute in detached effect scope (#35659)name or path when reusing an existing page in pages:extend (#35661)useFetch method inference (#35671)force-cache (#35672).mts file extension in resolver (#33845)@unhead/vue/* from nuxt's dependency tree (#35690)$fetch with nitro's $Fetch (#35704)vue-router when there are island pages (#35739)h3 that pins it to the version nuxt depends on (#35774)from cannot be resolved (#35799)app.buildAssetsDir (#35833)template island prop under runtime compiler (ee6c84633)as prop for islands (581651ff3)semver with verkit (#35713)codeSplitting: false (#35683)onPrehydrate example comment (#35684)runtimeConfig env var casting edge cases (#35709)nuxt rather than nuxi (8891e179c)runtimeCompiler security best practices (449b63ab1).ts file extension from runtime/ imports (#35689)@nuxt/telemetry in knip (9824d4f10)@nuxt/devtools to v3.3.1 (#35815)_route in gotoPath (ca92d082b)knip job (58f68bd64)> 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…
4.5.0 is the next minor release.
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 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.
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. ☕️
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.configtweaks, or ecosystem plugins that pin a Vite version), make sure those are compatible before upgrading in production.
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:
webpack-dev-middleware and webpack-hot-middleware (#35575).[!NOTE] This is the foundation for first-class Rsbuild support. We kept the builder named
rspackfor now so nothing breaks, but the internals are now Rsbuild all the way down.
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.
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 ComposableThere'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.
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 name@view.vue convention:
# Directory Structure
-| pages/
---| parent/
-----| child.vue
-----| child@sidebar.vue
---| 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 child@sidebar.vue 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]
definePageMetais 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).
enabled Option for useFetch and useAsyncDataYou 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.
NuxtLink Prefetch Control for Custom SlotsWhen 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.
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.envNameThe 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
}
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.
unhead v3Nuxt'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]
unheadv3 introduces type-narrowing foruseHead, 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 v3We'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.
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.
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).
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
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:
getIslandHash and hashKey now exposed (#35583).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).HTTP_PROXY / HTTPS_PROXY environment variables in the builder environment (#35183).defineNuxtComponent in JSX (#35620).As mentioned above, this release includes three major dependency bumps. For most apps they're transparent, but they're worth a moment of attention:
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.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. 💚
import.meta (#34844)allowImportingTsExtensions (87c214b34)nuxt/* build output contract (#35463)NuxtLink prefetch props for custom slot (#34539)enabled option to AsyncData (#33260)getIslandHash + hashKey + improve hash for keys (#35583)useLayout composable for accessing the resolved route layout (#35623)enabled option in useFetch (#35627)~, @) (#35641)updateAppConfig util for module authors (#35651)experimental.watcher (#35143)rolldown-string (#35058)ready event for vite watcher (6fe539f52)cause when we re-throw (#35387)#components (#35215)<ClientOnly> fallback tag name (#35325)inlineStyles is disabled (#35209)ssr: false (#35330)NuxtPage during nav (#35335)useAsyncData teardown (#35328)definePageMeta (#34526)body in useFetch (#35343)page:start finishes before page:finish starts (#35408)NODE_ENV and __VUE_PROD_DEVTOOLS__ (#35444)$fetch where possible (#35581).mjs runtime output (#35263)head.push for client side (#35498)rootDir to typed-router context (#35565)__nuxt_error marker on NuxtError (06e976d2e)noUncheckedSideEffectImports (v5) + disable libReplacement (#35548)unctx transform marker through magic-string (#35618)node:process in diagnostics (d73b5df6d)navigateTo in built-in router (#35631)nuxt prepare (#35141)clearNuxtData & clearNuxtState (#35142)fsCache instead of deprecated cache (#35268)#vite-node types from source (#35334)rolldown/utils instead of oxc-* dependencies (#34983)ssrStyles build output => lazy code provider (#35601)rsbuild to power rspack builder (#35489)useAsyncData and useFetch (#35528)enabled from useFetch docs (bf7810600)useFetch keys are unique per call site (#35645)tsdown to build project (#35179)vp in nightly release script (97b56d98d)loadNuxt startup (#35382)experimental.attachDebugInfo (7c2397ae6)test mode for bundle size tests (#35558)expectNoClientErrors (9f3123f60)> 4.4.8 is a hotfix release to address an issue running the dev server on MacOS.
4.4.8 is a hotfix release to address an issue running the dev server on MacOS.
type option in findPath (#35272)null to undefined in data-fetching docs to match actual types (#35301)> 4.4.7 is a security hotfix release.
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.
noSSR before deciding payload extraction (#35108)allowDirs (#35112)pathe for buildCache path boundary check (#35111)isValid in dev clipboard-copy listener (#35109)reloadNuxtApp path before reload (#35115)getCachedData after initial fetch (#35122)useFetch/useAsyncData factory types (#35133)isScriptProtocol guard to navigateTo open option (#35206)<NuxtPage> (#35198)<NuxtClientFallback> ssr output (#35199).d.mts/.d.cts in resolveTypePaths (#35235)<NoScript> slot content (4b054e9d9)vue-router (07e39cd6f)<NuxtLink> href (0103ce06f)navigateTo (2cce6fb02)reloadNuxtApp (e447a793c)es2023 array methods (#34980)runInNewContext with AST walker (d72a89ef4)execFileSync for safety in release scripts (1d7baaf01)> 4.4.6 is the next patch release.
4.4.6 is the next patch release.
resolveComponent calls in jsx blocks (#35028)useFetch key even with watch: false (#35002)@babel/plugin-syntax-typescript as optional peer dep (#35041)setPageLayout props on same-path navigation (#35055)useLoadingIndicator properties as readonly (#35062)statusCode for nitro v2 compatibility (952f6841e)tsConfig.exclude in legacy tsconfig.json (#35079)test:engines fails (3025e561e)> 4.4.5 is the next patch release.
4.4.5 is the next patch release.
isIgnored relative (#35015)clientServer with ssr: false (#34959)/ + override ssr: true (#34990)optimizeDeps.include in pre-bundle hint (#34976).env before resolving nuxt schema (#34958)serverHandlers array after nitro:config (#34985)getCachedData for concurrent callers sharing a key (#34999)useFetch (#35003)jiti (c8102228f)@vue/compiler-sfc (cd404a14c)buildDir per matrix project for shared fixtures (#35007)Nothing published for this version
Nothing published for this version
Nothing published for this version
> 4.3.1 is a regularly scheduled patch release.
4.3.1 is a regularly scheduled patch release.
x-nitro-prerender header (#34202)server/ for builder:watch hook (#34208)error.message for fatal errors (#34226)#app barrel export in keyed functions (#34199)datetime in <NuxtTime>` (#33992)nuxt/schema (#34255)meta.name (#34263)#components import mapping conflict for packages outside rootDir (#34139)nuxt/schema once more (552bbd8d1)genObjectKey to omit unnecessary quotes (#34245)ComponentProps helper to extract layout props (#34248)nitroAutoImports (#34182)#server and rootDir (#34259)keyedComposables (#34201)<NuxtPage> navigation (048efc030)The old properties still work but are deprecated in advance of v5:
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.
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.
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.
main branch4.x and 3.x branchesKeep 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.
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:
[!TIP] Plus, you can pass props to layouts now! See the
setPageLayoutimprovements below.
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:
export default defineNuxtConfig({
routeRules: {
'/products/**': {
isr: 3600, // Revalidate every hour
}
}
})
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.staticset totrue, or for individual pages which haveisr,swr,prerenderorcacheroute rules.
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 (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.
setPageLayoutThe 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 AliasA 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.
The development error overlay introduced in Nuxt 4.2 is now draggable and can be minimized (#33695). You can:
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
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.
This release includes several performance optimizations for faster builds:
nuxt:ssr-styles plugin is now significantly faster (#33862, #33865)rou3, removing the need for radix3 in the client bundle and eliminating app manifest fetches (#33920)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.
statusCode → status, statusMessage → statusTextIn 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' })
Notable fixes in this release:
key attribute (#33958, #33963)useCookie unsafe number parsing during decode (#34007)NuxtPage not re-rendering when nested NuxtLayout has layouts disabled (#34078)allowArbitraryExtensions by default in TypeScript config (#34084)noUncheckedIndexedAccess to server tsconfig for safer typing (#33985)[!IMPORTANT] Enabling
noUncheckedIndexedAccessin 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.
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:
setPageLayout, #server alias, draggable error overlay, and morefalseuseCookie number parsing, head component deduplication, and moreOur 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.
#server alias for server directory imports (#33870)crossws types (5b16a51f5)false (#33883)moduleDependencies as an async function (#33504)appLayout in route rules (#31092)setPageLayout (#33805)nuxt:ssr-styles plugin (#33862)router.replace in page hmr (#33897)page:loading:end in cache if already called (7789f73bd)NUXT_VITE_NODE_OPTIONS (41a564d23)appMiddleware references invalid key (323f27bc8)nuxt/meta (01c2c9b13)key for tag deduplication in <Head> component (#33958)build.transpile when initialising vite (#33868)onUpgrade arguments with types (#33988)rou3 (2df4e1ae3)noUncheckedIndexedAccess to server tsconfig (#33985)shared/ context (#33978)useRequestFetch (#33976)h3 types to auto-imports (#34035)nuxt/schema (a6a044d81)NuxtPage when nested NuxtLayout has explicitly disabled layouts (#34078)allowArbitraryExtensions by default (#34084)useAsyncData debounced execute post watcher flush (#34125)typeFrom support for imports.d.ts template exports (#34135)hydrate-never components (#34132)defu + consola (322dae3e0).ts file extensions to relative imports (80778c0cd)<> to as (f1713850c)~ prefix for internal ssrContext properties (#33896)status/statusText + deprecate old props (#33912)Module Author Guides (#33803)useHead return type (#33857)statusText (#32834)defineWrappedResponseHandler (#33952)addImports example (#34011)config.experimental properties (#34069)null from getCachedData trigger (f7cf3747e)useState docs (#34105).nuxtrc example (#34107)addServerHandler (#34060)appLayout (beda47955)false to its options (cdad9310c)source from <NuxtIsland> (1586bbb6e)vite-node entrypoints (#33893)obuild except for nuxt + nitro-server packages (#34049)/builder-env subpath types (7f5034288)build:stub command for those that need it (3e3d3d37a)node:process (#33982)vi.hoisted for klona mock (#34113)> 4.2.2 is the next patch release.
4.2.2 is the next patch release.
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.
page:finish hook (#33707)tsconfig.server.json (#33510)moduleDependencies by meta name (#33774).d.vue.ts declarations (1c73525a2)callOnce during HMR (#33810)useAsyncData (#33802)rootDir to cached layer config (#33779)moduleDependencies -> installModule (#33689)callOnce function (#33825)error as non-optional prop (#33763)patchProp and nodeOps to excluded Vue helpers (#33754)kit,nuxt,schema: Deprecate ImportPresetWithDeprecation
4.2.1 is the next patch release.
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.
ImportPresetWithDeprecation (#33596)<nuxt-error-overlay> iframe border (#33625)moduleEntryPaths (#33628)optimizeDeps config is applied before other plugins (#33586)pages:resolved (#33662)vite-node (#33663)pending as alias of status === 'pending' (#33221)cookieStore is true by default (#33572)useHead/useHydration/useLazy* (#33626)verifyDepsBeforeRun: install (#33603)This is also the first breaking change for Nuxt v5. You can opt in to these breaking changes by setting compatibilityVersion to 5:
4.2.0 is the next minor release.
We're excited to announce Nuxt 4.2, bringing new capabilities for better TypeScript DX, enhanced error handling, and improved control over 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()
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.
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!
@nuxt/nitro-server PackageWe'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.
We've also shipped several performance enhancements:
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.
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:
import(\~/assets/${name}.webp`)`$fetch, useFetch, useLazyFetch)@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".
declarationPath – You can now specify a custom declaration path for components (#33419)resolveModule now accepts an extensions option (#33328)setGlobalHead utility in kit for easier head management (#33512)routeRules (#33222)loadNuxtConfig with proper cleanup (#33420)href now works correctly in <NuxtLink> (c69e4c30d)h() function (#33509)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.
declarationPath (#33419)extensions option for resolveModule (#33328)useAsyncData (#32531)future.compatibilityVersion to 5 (22f4693a1)setGlobalHead utility (#33512)routeRules (#33222)loadNuxtConfig in concurrent calls (#33420)href in <NuxtLink> (c69e4c30d)mergeModels from auto imports (#33344)shortPath property (#33384)declarationPath from component dirs (191bcb7e9)isPrerendered check (#33476)h() (#33509)NuxtTime relative time numeric prop (#33552)NuxtTime relative time relativeStyle prop (#33557)optimizeDeps.include for server environment (#33550)shortPath property (#33384)extend, extendConfig, and configResolved hooks (e060b9695)@nuxt/nitro-server package (#33462)RouteLocationNormalizedLoadedGeneric internally (b51cb3067)addServerPlugin note (#33409)declarationPath in addComponent (#33380)getLayerDirectories() instead of nuxt.options._layers (#33484)4.x prefix (5c0bb9285)moduleDependencies (#33499)test:prepare (6ef632b82)test:prepare (eca36cfe5)vue-demi from ignoredBuiltDependencies (#33494)since in nightly releases (74ca73ca1)@rollup/plugin-commonjs (cd12980ce)@nuxt/nitro-server on pkg-pr-new (b7ccf17bf)> 4.1.3 is a regularly scheduled patch release.
4.1.3 is a regularly scheduled patch release.
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.
prepare:types hook (#33239)h (#33046)head option on useHead (#33318)cdnURL is set (#33333)imports.dirs (#33334)<NuxtLink> (#33335)v-slot:fallback longform syntax in <DevOnly> (#33368)typeFrom when generating auto-import type templates (#33373)@nuxt/scripts (bed410d60)useAsyncData (#33325)_path property configurable for HMR (#33379)useAsyncData with different key on ssr (#33341)typed-router.d.ts early for consistency (#33285)nitro:prepare:types hook (#33286)filename into componentsIslandsTemplate definition (#33394)4.x prefix to all internal links (#33264)useFetch reactivity (#33317)4.x prefixes in urls (47ea684c7)nuxt.config page (b438d44e1)prepare command NODE_ENV behavior (#33330)nuxt command pages (#33336).npmrc (14514329b)> 4.1.2 is a regularly scheduled patch release.
4.1.2 is a regularly scheduled patch release.
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.
dst is present (#33200)hydrate-when lazy hydration strategy (#33199)pkg-types to dependencies (9fe2541ca)backgroundSize in loading indicator (#33211)enabled from components dir options (#32844)app/ suffix to a few links (#33217)> v4.1.1 is a regularly scheduled patch release
v4.1.1 is a regularly scheduled patch release
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.
globalThis over window (#33125)deps.inline (#33133)useRoute usage warning (#33039)imports:sources in override warning (#33050)-- to bun create command (5e661f0ca)app/ prefix in lots of cases (#33117)navigateTo (#21442)rou3 github url (#33130).ts extension (db9d840e1)4x tags from releases (1cd8a6857)This replaces the deprecated installModule function and provides a more robust way to handle module dependencies with version constraints and configur…
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:
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
}
})
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.
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.
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.
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 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.
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__/**']
})
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
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' })
This release includes several internal performance optimizations:
useFetch hook typing (#32891)<NuxtTime> (#32893)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.
ignore option to resolveFiles (#32858)onInstall and onUpgrade module hooks (#32397)rolldown-vite (#31812)defineRouteRules to page rules property (#32897)getLayerDirectories util and refactor to use it (#33098)satisfies in page augmentation (#32902)useFetch hooks (#32891)resolvePath and normalize file extensions (#32857)requestTimeout + allow configuration (#32874)node_modules/ if no custom srcDir (#32987)route object (#32899)defineNuxtModule().with() (#33081)nuxtApp._runningTransition on resolve (#33025)async/await in afterEach (#32999)setupTimeout and add teardownTimeout (#32868)webRoot to use new app directory (df7177bff)app/ directory in layer guide (eee55ea41)--nightly command (#32907)features.inlineStyles default value (6ff3fbebb)useRoute and accessing route in middleware (#33004)type: 'module' in playground (#33099)import.meta.dev (#33023)findWorkspaceDir rather than relative paths to repo root (a6dec5bd9)expect.poll (53fb61d5d)expect.poll instead of expectWithPolling (357492ca7)vi.waitUntil instead of custom retry logic (611e66a47)> 4.0.3 is a regularly scheduled patch release.
4.0.3 is a regularly scheduled patch release.
tinyglobby in resolveFiles (#32846)error variable (#32807)typeCheck (#32835)null result from webpack call (84816d8a1)reverseResolveAlias for better errors (#32853)bun.lock for lockfile (#32820)defineNuxtComponent out of e2e test (#32848)> 4.0.2 is the next patch release.
4.0.2 is the next patch release.
Timetable: 28 July.
<ClientOnly> and <DevOnly> (#32707)defineAppConfig type (#32760)app context (#32758)mlly to parse module paths (#32386)npm create nuxt@latest (#32726).with() (#32757)unbuild and use absolute path in dev stubs (#32759)module.exports export (c4317e057)pkg.pr.new for main/3.x branches as well (b0f289550)3x tag to latest v3 release (5f6c27509)> v4.0.1 is the first regularly scheduled patch release of v4
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.
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.
nuxt.schema files to node tsconfig context (#32644)nitropack (ed5ad64ad)shared/ dir (#32676)-t v4 tag from getting started (343f59235)noUncheckedIndexedAccess rule change in v4 guide (#32643)nitropack types as external (39be1b3a9)This is a stability-focused major release, introducing a few thoughtful breaking changes in order to improve development experience.
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.
Nuxt 4 is all about making your development experience smoother:
app/ directory structureshared/ folder, and configurationWhy 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.
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.
Nuxt’s starter templates have an all new look, with improved accessibility, default titles, and template polish (#27843).
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.
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.jsonfile 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. 🙏
In parallel with the release of v4, we've been working on speeding up @nuxt/cli.
fs.watch APIs for fewer system resourcesThese improvements combined can make a really noticeable difference in your day-to-day development experience, and we have more planned.
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/kit. (This will particularly affect module authors.)Don't worry though — for most breaking changes, there are configuration options to revert to the old behavior while you adjust.
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.
We’ve also partnered with Codemod to automate many, though not all, migration steps:
npx codemod@latest nuxt/4/migration-recipe
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.
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.
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! 🚀
mlly (#28012)addServerImports (#32289)onWatcherCleanup to imports presets (#32396)<NuxtTime> prop types (#32547)render:html for server islands (#27889)compatibilityVersion: 4 (#27710)builder:watch hook (#27709)asyncData value behaviour (#27718)__NUXT__ after hydration (#27745)4 (7aae4033b)resolvePath utils as sync (655e1473d)tryResolveModule (2d136e04c)requireModule and tryRequireModule (#28013)useScriptCrisp scripts stub (0c3cc4cf3)globalName property (#28391)updateAppConfig in HMR (#28349)ssr: false (#28488)window access (d874726ff)resolveId from vite-node to resolve deps (#30922)isEqual from main ohash export (3ec1a1e5e)output.preserveModules (ce49734aa)#app-manifest import in dev mode (#31539)purgeCachedData until v4 (7aa3a01ae)purgeCachedData by default (06745604c).execute (d79e14612)compatibilityVersion: 3 (#32255)useAsyncData (#32170)errorValue/value to be undefined (7e4eac655)srcDir (#32487)@nuxt/cli (#32488)tsConfig doesn't exclude too many types (#32528)app/ and server/ folders into tsconfigs (#32592)typescript.hoist (#32601)tsconfig.server.json (#32594)compatibilityDate to 2025-07-15 (e35e1ccb9)scrollBehaviorType for hash scrolling (#32622)#app/components/layout -> #app/components/nuxt-layout (209e81b60)dedupe option (#28151)installNuxtModule (501ccc375)oxc-walker (#32250)onPrehydrate transform (#32045)useAsyncData must return (#28259)deep default for useAsyncData & useFetch (#28564)deep option (bec85dfcd).nuxtignore examples for v4 structure (#32489)useNuxtData in data fetching composable pages (#32589)vite-plugin-checker separately (02d46dd3d)engines.node compatibility (a26322f5f)nuxi (9aa4c7c3b)nuxi version again (#30547)oxc-parser updates temporarily (1cd0fb5cb)nitro/templates directory (e531477f8)attw test for built packages (#30206)configResolved (8d3bd4f9f)render:html for server islands (#27889)compatibilityVersion: 4 (#27710)builder:watch hook (#27709)asyncData value behaviour (#27718)__NUXT__ after hydration (#27745)4 (7aae4033b)globalName property (#28391)compatibilityVersion: 3 (#32255)useAsyncData (#32170)compatibilityDate to 2025-07-15 (e35e1ccb9)#app/components/layout -> #app/components/nuxt-layout (209e81b60)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 unexpect…
4.0.0-rc.0 is our first release candidate.
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
> 4.0.0-alpha.4 is the fourth alpha release of Nuxt 4 for early testing
4.0.0-alpha.4 is the fourth alpha release of Nuxt 4 for early testing
👉 Read more at https://nuxt.com/blog/roadmap-v4
asyncData runs if changing key while fetcher is running (#32466)srcDir (#32487)@nuxt/cli (#32488).nuxtignore examples for v4 structure (#32489)Rename deprecated vitest workspace to projects
4.0.0-alpha.3 is the third alpha release of Nuxt 4 for early testing
👉 Read more at https://nuxt.com/blog/roadmap-v4
onWatcherCleanup to imports presets (#32396)navigateTo (#32393)output.generatedCode.symbols for nitro build (#32358)nuxt:chunk-reload-immediate (#32382)set-cookie headers in error handler (#32483)bun.lock for lockfile (#32427)h3js (#32243)clear function description (#32287)defineNuxtPlugin function documentation (#32328)<NuxtLink> encodes query params (#32361)workspace to projects (#32388)immediate: false (#32473)> 4.0.0-alpha.2 is the second alpha release of Nuxt 4 for early testing
4.0.0-alpha.2 is the second alpha release of Nuxt 4 for early testing
👉 Read more at https://nuxt.com/blog/roadmap-v4
addServerImports (#32289)inheritAttrs: false in createClientOnly fn (#32323)> 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 p…
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:
3.x, 4.x and (soon) 5.x documentation.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
mlly (#28012)render:html for server islands (#27889)globby (#31688)compatibilityVersion: 4 (#27710)builder:watch hook (#27709)asyncData value behaviour (#27718)__NUXT__ after hydration (#27745)4 (7aae4033b)resolvePath utils as sync (655e1473d)tryResolveModule (2d136e04c)requireModule and tryRequireModule (#28013)useScriptCrisp scripts stub (0c3cc4cf3)globalName property (#28391)updateAppConfig in HMR (#28349)ssr: false (#28488)window access (d874726ff)h() in ClientOnly (#30664)resolveId from vite-node to resolve deps (#30922)isEqual from main ohash export (3ec1a1e5e)output.preserveModules (ce49734aa)#app-manifest import in dev mode (#31539)purgeCachedData until v4 (7aa3a01ae)purgeCachedData by default (06745604c).execute (d79e14612)appConfig sources are not duplicated (#32216)compatibilityVersion: 3 (#32255)asyncData state from nuxt app instance (#32232)srcDir in buildCache (#32260)useAsyncData (#32170)errorValue/value to be undefined (7e4eac655)asyncData watcher (#32247)#app/components/layout -> #app/components/nuxt-layout (209e81b60)dedupe option (#28151)installNuxtModule (501ccc375)oxc-walker (#32250)onPrehydrate transform (#32045)useAsyncData must return (#28259)deep default for useAsyncData & useFetch (#28564)addRouteMiddleware path in example (#32171)--env-file (15fb7b30f)nuxt command consistently (#32237)deep option (bec85dfcd)alert with warning in /guide/pages (#32270)vite-plugin-checker separately (02d46dd3d)engines.node compatibility (a26322f5f)nuxi (9aa4c7c3b)nuxi version again (#30547)oxc-parser updates temporarily (1cd0fb5cb)nitro/templates directory (e531477f8)attw test for built packages (#30206)configResolved (8d3bd4f9f)render:html for server islands (#27889)compatibilityVersion: 4 (#27710)builder:watch hook (#27709)asyncData value behaviour (#27718)__NUXT__ after hydration (#27745)4 (7aae4033b)globalName property (#28391)compatibilityVersion: 3 (#32255)useAsyncData (#32170)#app/components/layout -> #app/components/nuxt-layout (209e81b60)Nothing published for this version
> 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
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
oxc-walker (a6c9dc6d3)> ⚠️ This is a security release. We recommend upgrading as soon as possible with npx nuxt upgrade --dedupe.
⚠️ 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/devtools@3.3.1, 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.
useRoute in detached effect scope (#35659)name or path when reusing an existing page in pages:extend (#35661)useFetch method inference (#35671)@unhead/vue/* from nuxt's dependency tree (#35690)force-cache (#35672)app.buildAssetsDir (#35833)template island prop under runtime compiler (5b60017f7)as prop for islands (00a2b0494)runtimeCompiler security best practices (b76c1a8bd)_route in gotoPath (5391e7e6a)> 3.21.9 is the next patch release.
3.21.9 is the next patch release.
cause when we re-throw (#35387)#components (#35215)<ClientOnly> fallback tag name (#35325)inlineStyles is disabled (#35209)ssr: false (#35330)NuxtPage during nav (#35335)useAsyncData teardown (#35328)definePageMeta (#34526)body in useFetch (#35343)page:start finishes before page:finish starts (#35408)NODE_ENV and __VUE_PROD_DEVTOOLS__ (#35444)rootDir to typed-router context (#35565)navigateTo in built-in router (#35631)expectNoClientErrors (afffe7f09)> 3.21.8 is a hotfix release to address an issue running the dev server on MacOS.
3.21.8 is a hotfix release to address an issue running the dev server on MacOS.
type option in findPath (#35272)null to undefined in data-fetching docs to match actual types (#35301)> 3.21.7 is the a security hotfix release.
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.
noSSR before deciding payload extraction (#35108)allowDirs (#35112)pathe for buildCache path boundary check (#35111)isValid in dev clipboard-copy listener (#35109)reloadNuxtApp path before reload (#35115)clientServer with ssr: false (#34959).d.mts/.d.cts in resolveTypePaths (#35235)<NuxtClientFallback> ssr output (#35199)isScriptProtocol guard to navigateTo open option (#35206)defu in app config template (40bedf0db)vue-router (3f3e3fa7b)<NoScript> slot content (7fea9fd68)navigateTo (1f2dd5e78)reloadNuxtApp (6497d99dd)<NuxtLink> href (53284043d)defu (d11d7b1b5)execFileSync for safety in release scripts (9a455a658)> 3.21.6 is the next patch release.
3.21.6 is the next patch release.
setPageLayout props on same-path navigation (#35055)useLoadingIndicator properties as readonly (#35062)statusCode for nitro v2 compatibility (82dcd6a31)test:engines fails (958abb882)> 3.21.5 is the next patch release.
3.21.5 is the next patch release.
isIgnored relative (#35015)/ + override ssr: true (#34990).env before resolving nuxt schema (#34958)serverHandlers array after nitro:config (#34985)buildDir per matrix project for shared fixtures (#35007)Nothing published for this version
Nothing published for this version
> 3.21.1 is a regularly schedule patch release.
3.21.1 is a regularly schedule patch release.
server/ for builder:watch hook (#34208)x-nitro-prerender header (#34202)error.message for fatal errors (#34226)#app barrel export in keyed functions (#34199)datetime in <NuxtTime>` (#33992)nuxt/schema (#34255)meta.name (#34263)#components import mapping conflict for packages outside rootDir (#34139)nuxt/schema once more (9f5bb611d)genObjectKey to omit unnecessary quotes (#34245)ComponentProps helper to extract layout props (#34248)keyedComposables (#34201)<NuxtPage> navigation (707a9dc44)The old properties still work but are deprecated in advance of v5:
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.
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.
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.
main branch4.x and 3.x branchesKeep 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.
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:
[!TIP] Plus, you can pass props to layouts now! See the
setPageLayoutimprovements below.
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:
export default defineNuxtConfig({
routeRules: {
'/products/**': {
isr: 3600, // Revalidate every hour
}
}
})
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.staticset totrue, or for individual pages which haveisr,swr,prerenderorcacheroute rules.
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 (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.
setPageLayoutThe 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 AliasA 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.
The development error overlay introduced in Nuxt 4.2 is now draggable and can be minimized (#33695). You can:
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
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.
This release includes several performance optimizations for faster builds:
nuxt:ssr-styles plugin is now significantly faster (#33862, #33865)rou3, removing the need for radix3 in the client bundle and eliminating app manifest fetches (#33920)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.
statusCode → status, statusMessage → statusTextIn 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' })
Notable fixes in this release:
key attribute (#33958, #33963)useCookie unsafe number parsing during decode (#34007)NuxtPage not re-rendering when nested NuxtLayout has layouts disabled (#34078)allowArbitraryExtensions by default in TypeScript config (#34084)noUncheckedIndexedAccess to server tsconfig for safer typing (#33985)[!IMPORTANT] Enabling
noUncheckedIndexedAccessin 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.
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:
setPageLayout, #server alias, draggable error overlay, and morefalseuseCookie number parsing, head component deduplication, and moreOur 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.
#server alias for server directory imports (#33870)crossws types (6ff79ea6c)false (#33883)moduleDependencies as an async function (#33504)appLayout in route rules (#31092)setPageLayout (#33805)nuxt:ssr-styles plugin (#33862)router.replace in page hmr (#33897)page:loading:end in cache if already called (fbbe10133)NUXT_VITE_NODE_OPTIONS (8abb7ef5b)appMiddleware references invalid key (ed8bb68c5)nuxt/meta (b748840bc)key for tag deduplication in <Head> component (#33958)build.transpile when initialising vite (#33868)onUpgrade arguments with types (#33988)rou3 (7da94e8c3)noUncheckedIndexedAccess to server tsconfig (#33985)useRequestFetch (#33976)h3 types to auto-imports (#34035)nuxt/schema (9b40196a6)NuxtPage when nested NuxtLayout has explicitly disabled layouts (#34078)allowArbitraryExtensions by default (#34084)useAsyncData debounced execute post watcher flush (#34125)typeFrom support for imports.d.ts template exports (#34135)hydrate-never components (#34132)defu + consola (e31668f67).ts file extensions to relative imports (458f3c9b6)<> to as (08f72881e)~ prefix for internal ssrContext properties (#33896)status/statusText + deprecate old props (#33912)nitropack/runtime namespace (b06d53166)nitropack/runtime namespace (897a2259f)useHead return type (#33857)Module Author Guides (#33803)statusText (#32834)defineWrappedResponseHandler (#33952)useState docs (#34105).nuxtrc example (#34107)appLayout (9b78698c3)false to its options (18500730c)source from <NuxtIsland> (08778c98c)vite-node entrypoints (#33893)obuild except for nuxt + nitro-server packages (#34049)/builder-env subpath types (1951648fa)build:stub command for those that need it (c682b2681)node:process (#33982).nuxtrc with test-utils setup (b5879351f)vite-node separately from vitest (8114e886f)vi.hoisted for klona mock (#34113)> 3.20.2 is the next patch release.
3.20.2 is the next patch release.
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/cliwhich has the--channelflag. If this does not work, you can instead runnpx nuxi@latestfor the initial upgrade.
page:finish hook (#33707)tsconfig.server.json (#33510)moduleDependencies by meta name (#33774).d.vue.ts declarations (9a6a770ab)callOnce during HMR (#33810)useAsyncData (#33802)rootDir to cached layer config (#33779)moduleDependencies -> installModule (#33689)callOnce function (#33825)error as non-optional prop (#33763)patchProp and nodeOps to excluded Vue helpers (#33754)kit,nuxt,schema: Deprecate ImportPresetWithDeprecation
3.20.1 is the next patch release.
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.
optimizeDeps.include for server environment (#33550)ImportPresetWithDeprecation (#33596)<nuxt-error-overlay> iframe border (#33625)moduleEntryPaths (#33628)optimizeDeps config is applied before other plugins (#33586)pages:resolved (#33662)cookieStore is true by default (#33572)pending as alias of status === 'pending' (#33221)useHead/useHydration/useLazy* (#33626)verifyDepsBeforeRun: install (#33603)schema: Deprecate extend, extendConfig, and configResolved hooks
3.20.0 is the next minor release.
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.
declarationPath (#33419)extensions option for resolveModule (#33328)useAsyncData (#32531)setGlobalHead utility (#33512)routeRules (#33222)loadNuxtConfig in concurrent calls (#33420)href in <NuxtLink> (b97ae2f70)mergeModels from auto imports (#33344)shortPath property (#33384)declarationPath from component dirs (e384ba3cb)isPrerendered check (#33476)h() (#33509)NuxtTime relative time numeric prop (#33552)NuxtTime relative time relativeStyle prop (#33557)shortPath property (#33384)extend, extendConfig, and configResolved hooks (932a80dc6)@nuxt/nitro-server package (#33462)RouteLocationNormalizedLoadedGeneric internally (aa211fb4f)addServerPlugin note (#33409)declarationPath in addComponent (#33380)getLayerDirectories() instead of nuxt.options._layers (#33484)moduleDependencies (#33499)test:prepare (cbad63c02)test:prepare (672c09423)vue-demi from ignoredBuiltDependencies (#33494)@rollup/plugin-commonjs (c2bd323b8)@rollup/plugin-commonjs (a524522ea)asyncDataDefaults.errorValue (b6f1c9b0d)@nuxt/nitro-server on pkg-pr-new (d37ef17b0)> 3.19.3 is a regularly scheduled patch release.
3.19.3 is a regularly scheduled patch release.
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.
h (#33046)head option on useHead (#33318)cdnURL is set (#33333)imports.dirs (#33334)<NuxtLink> (#33335)v-slot:fallback longform syntax in <DevOnly> (#33368)typeFrom when generating auto-import type templates (#33373)@nuxt/scripts (057ade490)useAsyncData (#33325)_path property configurable for HMR (#33379)useAsyncData with different key on ssr (#33341)typed-router.d.ts early for consistency (#33285)filename into componentsIslandsTemplate definition (#33394)3.x prefix to all internal links (0fef864d6)useFetch reactivity (#33317)prepare command NODE_ENV behavior (#33330)nuxt command pages (#33336).npmrc (101682a6b)> 3.19.2 is a regularly scheduled patch release.
3.19.2 is a regularly scheduled patch release.
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.
dst is present (#33200)hydrate-when lazy hydration strategy (#33199)pkg-types to dependencies (a6e5dd756)backgroundSize in loading indicator (#33211)enabled from components dir options (#32844)> v3.19.1 is a regularly scheduled patch release
v3.19.1 is a regularly scheduled patch release
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.
globalThis over window (#33125)deps.inline (#33133)useRoute usage warning (#33039)imports:sources in override warning (#33050)-- to bun create command (ab6aa8ee5)navigateTo (#21442)4x tags from releases (e3aa50d11)kit,nuxt,ui-templates,vite: Address deprecations + improve regexp perf
Please see the release notes for Nuxt v4.1 for full details on the features and fixes in Nuxt v3.19.
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.
ignore option to resolveFiles (#32858)onInstall and onUpgrade module hooks (#32397)rolldown-vite (#31812)defineRouteRules to page rules property (#32897)getLayerDirectories util and refactor to use it (#33098)satisfies in page augmentation (#32902)useFetch hooks (#32891)resolvePath and normalize file extensions (#32857)requestTimeout + allow configuration (#32874)node_modules/ if no custom srcDir (#32987)route object (#32899)defineNuxtModule().with() (#33081)nuxtApp._runningTransition on resolve (#33025)async/await in afterEach (#32999)setupTimeout and add teardownTimeout (#32868)--nightly command (#32907)useRoute and accessing route in middleware (#33004)type: 'module' in playground (#33099)import.meta.dev (#33023)findWorkspaceDir rather than relative paths to repo root (c4c3ada96)expect.poll (f4354203a)expect.poll instead of expectWithPolling (15ca5be95)vi.waitUntil instead of custom retry logic (4c8c13090)> 3.18.1 is a regularly scheduled patch release.
3.18.1 is a regularly scheduled patch release.
tinyglobby in resolveFiles (#32846)error variable (#32807)typeCheck (#32835)null result from webpack call (65aa17158)reverseResolveAlias for better errors (#32853)defineNuxtComponent out of e2e test (#32848)> 3.18.0 is the next minor release.
3.18.0 is the next minor release.
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! ❤️
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.
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!)
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.
Component type safety has been improved with:
<ClientOnly> and <DevOnly> (#32707) - better IntelliSense and error checking<NuxtTime> prop types (#32547) - easier to extend and customizeonWatcherCleanupThe 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)
})
})
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 authors get several quality-of-life improvements:
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' })
Modules can now add to typescript.hoist (#32601), giving them more control over TypeScript configuration and type generation.
We've made several performance optimizations:
oxc-walker (#32250) and oxc for onPrehydrate transforms (#32045) for faster code transformationsThis release also includes several important fixes:
scrollBehaviorType is now only used for hash scrolling (#32622)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.
<NuxtTime> prop types (#32547)addServerImports (#32289)onWatcherCleanup to imports presets (#32396)typescript.hoist (#32601)scrollBehaviorType for hash scrolling (#32622)async (fd312af03)<ClientOnly> and <DevOnly> (#32707)mlly to parse module paths (#32386)oxc-walker (#32250)onPrehydrate transform (#32045)installNuxtModule (228e3585e)v3 template to create nuxt examples (03182202f)useNuxtData in data fetching composable pages (#32589)noUncheckedIndexedAccess rule change in v4 guide (#32643)npm create nuxt@latest (#32726).with() (#32757)unbuild and use absolute path in dev stubs (#32759)module.exports export (ac8b02d09)pkg.pr.new for main/3.x branches as well (ca4f0b1da)3x tag to latest v3 release (5e8dfc150)> 3.17.7 is the last patch release before v3.18.
3.17.7 is the last patch release before v3.18.
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.
extraPageMetaExtractionKeys (#32510)loadBuilder error cause (8f13ce3c2)null values (c1b83eab5)semver.satisfies returns true for pre-release versions (#32574)execute being passed to watch` (#32591)NUXT_ (#32223)useAsyncData and useFetch migration (#32560)undefined to null in v3 docs (#32562)async keyword (#32587)generateTypes (c0855439d)<NuxtTime> test (#32558)Rename deprecated vitest workspace to projects
3.17.6 is a regularly scheduled patch release.
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.
nuxt.config (#32324)nuxt:chunk-reload-immediate (#32382)set-cookie headers in error handler (#32483)asyncData runs if changing key while fetcher is running (#32466)navigateTo (#32393)<NuxtLink>'s custom on click handler (#32499)inheritAttrs: false in createClientOnly fn (#32323)output.generatedCode.symbols for nitro build (#32358)h3js (#32243)clear function description (#32287)defineNuxtPlugin function documentation (#32328)<NuxtLink> encodes query params (#32361)bun.lock for lockfile (#32427)workspace to projects (#32388)immediate: false (#32473)> 3.17.5 is a regularly scheduled patch release.
3.17.5 is a regularly scheduled patch release.
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.
globby (#31688)useScriptRybbitAnalytics from script stubs (d275ae1a0)appConfig sources are not duplicated (#32216)h() in ClientOnly (#30664)asyncData state from nuxt app instance (#32232)srcDir in buildCache (#32260)asyncData watcher (#32247)addRouteMiddleware path in example (#32171)--env-file (29f6392cd)nuxt command consistently (#32237)alert with warning in /guide/pages (#32270)> 3.17.4 is a regularly-scheduled patch release.
3.17.4 is a regularly-scheduled patch release.
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.
shallowRef for primitive values (#32152)Intl.Collator instead of localeCompare (#32167)<ClientOnly> (#32101)useLazyAsyncData (#32092)ts-checker-rspack-plugin (#32115)/ (#32129)DeepPartial (#31990)<ClientOnly> (#32131)global with globalThis (#32130)<NuxtLayout> first renders (#24673)srcDir to parcel strategy (#32139)useNuxtData default return to undefined (#32054)imports.dirs with alias (0dbf314d9)setTimeout mock (#32142)> 3.17.3 is a regularly-scheduled patch release.
3.17.3 is a regularly-scheduled patch release.
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.
FormData (#32013)ignore patterns (#32020)useFetch with watch: false (#32019)getCachedData is provided (#32003)nuxtApp for asyncData functions run on server (#32038)asyncData (e779d6cd5)bug/enhancement labels to issue types (3ff743fe0)> 3.17.2 is a regularly-scheduled patch release.
3.17.2 is a regularly-scheduled patch release.
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.
handleHotUpdate in production (#31971)transition (#31945)useFetch (#31963)scrollToTop (#31914)vfs even if a file exists in buildDir (#31969)useAsyncData reactive to key changes when immediate: false (#31987)WarningFilter type (2a79dbd68)warningIgnoreFilters (a62e808ac)@nuxt/kit documentation (#31793)asyncDataDefaults.value (91568c5da)> 3.17.1 is the next patch release.
3.17.1 is the next patch release.
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.
execute when non-immediate fetch key changes (#31941)escapeHTML from vue (8e4b8d62f)@vue/shared dependency (7d445c963)Although we have aimed to maintain backward compatibility and put breaking changes behind the experimental.granularCachedData flag (disabled by defaul…
This release brings a major reworking of the async data layer, a new built-in component, better warnings, and performance 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.
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.
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'
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
<NuxtTime> - A new component for safe time displayWe'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.
<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>
<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/"> -->
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 barresetDelay: Controls how long to wait before resetting loading indicator state<template>
<NuxtLoadingIndicator :hide-delay="500" :reset-delay="300" />
</template>
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).
We've added several warnings to help catch common mistakes:
runtimeConfig.app namespace #31774definePageMeta is used more than once in a file #31634Module authors will be happy to know:
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.addComponentExports #27155Several performance improvements have been made:
tinyglobby for faster file globbing #31668.data directory from type-checking for faster builds #31738purgeCachedData check #31785Our 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.
hideDelay and resetDelay props for loading indicator (#31532)@nuxt/docs (#31353)loadNuxtConfig to nitro (#31680)runtimeConfig.app namespace (#31774)middleware when scanning page metadata (#30708)addComponentExports (#27155)<NuxtErrorBoundary> to SFC + expose error/clearError (#31847)<NuxtTime> component for ssr-safe time display (#31876)trailingSlash prop to <NuxtLink> (#31820)tinyglobby (#31668).data directory from type-checking (#31738)purgeCachedData check to improve tree-shaking (#31785)oxc-parser manual wasm fallback logic (#31484)modulesDir paths are added to fs.allow (#31540)/_nuxt/ (#31646)useLazyAsyncData (#31676)error.url (#31679)app:rendered is called (#31686)fallback attribute when stripping <DevOnly> (c1d735c27)noScripts (c9572e953)compatibilityDate (#31725)statusMessage when rendering html error (#31761)definePageMeta is used more than once (#31634)error.data before rendering error.vue (#31571)useAsyncData in console log (#31801)NuxtErrorBoundary error (#31791)preserveModules (#31839)pending with status value for v4 (#25864)nuxt/app in generated middleware and layouts declarations (#31808)withoutBase (f956407bb)vue in vite-node dev server (f3882e004)tsconfig.json (#31882)useNuxtData (#31893)useFetch watch sources (#31903)modulesDir to store build cache files (#31907)shallowRef for primitives as well (#31662)_replaceAppConfig when applying hmr (#31786)ConfigSchema (#31894)app.vue (#31645)templateParams to seo docs (#31583)useHydration (#31712)callOnce returning value (#31747)vs. consistently (#31760)addServerHandler example (#31769)vue-sfc-transformer to process sfcs (#31691)<NuxtErrorBoundary> (4df92c45f)pendingWhenIdle (08f2224c8)> 3.16.2 is the next patch release.
3.16.2 is the next patch release.
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.
useRequestEvent on client (#31586)<Body> and <Html> (#31513)/index is the last segment (#31528)page:loading:end hook before navigation (#31504)document.cookie (#31517)resolveComponent (#31526)_nuxt/ paths in development (#31543)error.vue (#31573)unhead v2 api in default welcome + error pages (#31584)scanPageMeta is disabled (0ba454b21)<NuxtPage> (#31561)useServerHead in onPrehydrate with useHead (#31585)useTemplateRef (#31458)$fetch (#31459)dedupe flag (#31467)refreshNuxtData docs (#31448)-- before --template (#31469)resolveComponent only auto-imports components with literal strings (#31511)tsconfig.json (#31473)page:start and page:finish hooks (#31570)nuxt: Use browser cache for payloads
mocked-exports (#31295)typedPages implementation (#31331)app.head example (#31350)addServerTemplate to modules guide (#31369)rspack and remove test-utils for monorepo guide (#31371)ini syntax block highlighting for .env files (f79fabe46)useHydration docs (#31427)srvx and random port for remote provider (#31432)We've upgraded to unhead v2, the engine behind Nuxt's management. This major version removes deprecations and improves how context works:
There's a lot in this one!
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.
We've upgraded to unhead v2, the engine behind Nuxt's <head> management. This major version removes deprecations and improves how context works:
// 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:
#app/composables/head instead of @unhead/vue@unhead/vue might lose async contextDon'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.
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.
We're continuing to make Nuxt faster, and there are a number of improvements in v3.16:
exsolve for module resolution (#31124) along with the rest of the unjs ecosystem (nitro, c12, pkg-types, and more) - which dramatically speeds up module resolutionloadNuxt by skipping unnecessary resolution steps (#31176) - faster startupsoxc-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! ⚡️
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.
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'],
}
})
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.
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'
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.
We've greatly improved error messages and source tracking (#31144):
useAsyncData calls with precise file location informationPlus, 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.
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 })
}
})
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.
unjs Major VersionsThis release includes several major version upgrades from the unjs ecosystem, focused on performance and smaller bundle sizes through ESM-only distributions:
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.
@nuxt/devtools to v2 (#30889)NuxtPage (#30704)directoryToURL to normalise paths (#30986)start/set in loading indicator (#30989)pages/ (#31090)NuxtLink slot (#31104)addTypeTemplate (#31079)oxc-parser instead of esbuild + acorn (#30066)exsolve for module resolution (#31124)loadNuxt (#31176)<NuxtLayout> fallback prop is typed (#30832)keepalive cache reset (#30807)div wrapper in client-only pages (#30425)nitropack (aba75bd5a)null from resolve functions (d68e8ce57)app.head.meta values are undefined (#30959)shared/ directories available within layers (#30843)<pre> when rendering dev errors (9aab69ec4)page:transition:start type (#31040)provide / inject work in setup of defineNuxtComponent (#30982)_ for NuxtIsland name on server pages (#31072)ohash to calculate legacy async data key without hash (#31087)shared dir from config (#31091)nuxt.options.pages to detected configuration (#31101)definePageMeta does not receive an object (#31156)no-ssr middleware handler (a99c59fbd)navigate with vue-router (7a1934509)nuxt.options.pages (fa480e0a0)resolveModule (6fb5c9c15)resolveTypePath (a0f9ddfe2)compilerOptions.paths (835e89404)RawVueCompilerOptions for unresolved tsconfig (#31202)navigateTo with replace (#31244)devStorage (#31233)useFetch function name on server for warning (#31213)x-nitro-prerender header (2476cab9a)isEqual from ohash/utils (2e27cd30c)noScripts route rule (#31083)runtime/nitro files (#31131)spaLoadingTemplate example (#30830)NuxtPage (#30781)navigateTo docs with clearer structure and examples (#30876)rootDir (27e356fe6)vue:setup and app:data:refresh hooks (#31001)defineNuxtRouteMiddleware (#31005)port option to preview command (#30999).nuxtrc documentation (#31093)$fetch on the server (#31114)create nuxt command (fe82af4c9)3x (a243f8fcf)<NuxtPage> during page changes (#31116)typedPages in unhoisted pnpm setups (#31262)errx dependency (566418177)@nuxtjs/mdc typechecking dep (f23683b26)nitro/renderer templates (b29c0e86b)#internal/nitro/app (a1b855cc5)Your coding agent can read these notes before it upgrades. Set up the MCP server →