# Nuxt Changelog

> Latest releases from Nuxt and official modules.

## v4.3.4 (nuxt/test-utils) - 2026-10-16

[Release notes](https://github.com/nuxt/test-utils/releases/tag/v4.3.4)

> v4.3.4 is the next patch release.

## 👉 Changelog

[compare changes](https://github.com/nuxt/test-utils/compare/v4.3.3...v4.3.4)

### 🩹 Fixes

- **runtime:** test failure when module cached (#1856)
- **runtime-utils:** support registerEndpoint with FormData in jsdom (#1846)
- **e2e:** restore test context before running `setup` hooks (#1855)
- **e2e:** apply `nuxtConfig` overrides to dev server (#1851)
- **config:** prefer `h3` version from nitro path (#1844)
- **module:** apply vitest setup only when loaded from vitest config (#1834)
- **config:** respect default resolve conditions in vitest browser mode (#1843)
- **module:** pass required token to open vitest ui in devtools (#1841)

### 💅 Refactors

- **module:** use `package-manager-detector` workspace + deno handling ([`1d59009c7`](https://github.com/nuxt/test-utils/commit/1d59009c7))

### 🏡 Chore

- cleanup example deps, unify vitest, and update knip config (#1840)

### ❤️ Contributors

- Yoshihiro Yamaguchi (@yamachi4416)
- Daniel Roe (@danielroe)

---

## v4.6.2 (nuxt/nuxt) - 2026-10-16

[Release notes](https://github.com/nuxt/nuxt/releases/tag/v4.6.2)

> v4.6.2 is the next patch release.

## 👉 Changelog

[compare changes](https://github.com/nuxt/nuxt/compare/v4.6.1...v4.6.2)

### 🩹 Fixes

- **nitro:** apply `useHeadSafe` rules to server island head ([`493565e99`](https://github.com/nuxt/nuxt/commit/493565e99))
- **nitro-server:** read router params from the path h3 matched ([`010f6b43d`](https://github.com/nuxt/nuxt/commit/010f6b43d))
- **nitro:** match server route rules case-insensitively unless routing is sensitive ([`f6cfee52c`](https://github.com/nuxt/nuxt/commit/f6cfee52c))
- **nuxt:** resolve rooted paths through the URL parser (#36617)
- **nuxt:** resolve empty route types in shared context (#36576)
- **nitro:** preserve server tsconfig with relocated build dir (#36494)
- **nuxt:** fix scroll offset for IDs starting with numbers (#36524)
- **kit:** do not exclude module directories with a dot in their name from app tsconfig (#36331)
- **nuxt:** detect vapor slots with `rawVaporSlotKey` from vue (#36614)
- **nuxt:** keep middleware layout when restoring deferred prerendered route (#36560)
- **schema:** provide default value for `experimental.typescriptPlugin` (#36561)
- **vite:** only replay compile error overlays to newly loaded pages (#36611)
- **nuxt:** re-export `AnyFetchPath` for emitted server route types (#36610)
- **vite:** warm up the dev ssr entry from a nitro plugin (#36615)
- **nitro:** avoid unused h3 imports in nuxt/server runtime (#36609)
- **vite-server:** scope asset url helpers to the build (#36591)
- **nuxt:** resolve `nuxt/app` to the app's runtime (#36587)
- **kit:** lowercase filename-derived handler method on nitro v2 (#36567)
- **nuxt,nitro:** normalise string/array `appMiddleware` (#36565)
- **nitro:** pass response headers to `render:response` listeners (#36583)
- **vite:** resolve inlined `vue` to its bundler build in dev (#36569)
- **nuxt:** don't start a page transition with no page to leave (#36535)
- **nuxt:** preserve error state on aborted or cancelled navigation (#36546)
- **vite,nitro:** link null-byte virtual css through `/@id/` in dev (#36549)
- **kit:** resolve module dependencies from the declaring module (#36542)
- **nitro:** only disable h3 + nitro presets when `nitroAutoImports` is off (#36548)
- **nitro,vite:** don't access unspecified dependencies (#36541)
- **nitro:** don't inline deps under absolute transpile dirs (#36540)
- **vite-server:** respect spa loading template location (#36536)

### 💅 Refactors

- **webpack,rspack:** inline friendly errors plugin (#36568)

### 📖 Documentation

- remove DeepWiki badge (#36616)
- rename `H(TTP)` to `HTTP` (#36559)
- mention `proxy` route rule ([`4a529be68`](https://github.com/nuxt/nuxt/commit/4a529be68))
- reference `definePlugin` and `defineNitroPlugin` in server plugin tip ([`64b8e0334`](https://github.com/nuxt/nuxt/commit/64b8e0334))
- open a PR to list a module ([`e551df267`](https://github.com/nuxt/nuxt/commit/e551df267))
- clarify testing environments, runners, and config (#32963)
- align spa loading template references (#36552)
- explain how to disable iOS Safari phone number detection (#36539)
- fix outdated internal links (#36550)
- explain how to restore nitro auto-imports with compat v5 ([`7499a445b`](https://github.com/nuxt/nuxt/commit/7499a445b))
- add spa-loading-template documentation (#36537)

### 🏡 Chore

- keep @nuxt/telemetry ignore for production mode 😭 ([`3110d6947`](https://github.com/nuxt/nuxt/commit/3110d6947))
- fix knip, eslint and type import failures in ci ([`fb01db4eb`](https://github.com/nuxt/nuxt/commit/fb01db4eb))
- exclude `nuxt/app` entry shim from root typecheck ([`c65cef3a8`](https://github.com/nuxt/nuxt/commit/c65cef3a8))
- animate readme banner (#36593)
- actually exclude fixtures from `test:engines` ([`6ce412822`](https://github.com/nuxt/nuxt/commit/6ce412822))
- resolve `#build/server-routes` stub via root tsconfig paths ([`8235dd605`](https://github.com/nuxt/nuxt/commit/8235dd605))

### ✅ Tests

- wait for scroll to settle in route-scroll e2e ([`ca784deb7`](https://github.com/nuxt/nuxt/commit/ca784deb7))

### 🤖 CI

- comment nuxt.com preview links on docs pull requests (#36594)
- regenerate kit `inlinedDependencies` in autofix ([`4b6da3a29`](https://github.com/nuxt/nuxt/commit/4b6da3a29))
- remove docs deploy triggers ([`917bdf218`](https://github.com/nuxt/nuxt/commit/917bdf218))

### 🎉 New Contributors

- Sandro Circi (@sandros94)
- Yunus Ozen (@ozenyunus35)
- Vladislav (@dsfcoll)
- AXH-xecoy (@axh-xecoy)
- Jess (@JessicaSachs)
- Gareth (@0xgdr)

### ❤️ Contributors

- Daniel Roe (@danielroe)
- Jonas Thelemann (@dargmuesli)
- Sandro Circi (@sandros94)
- Yunus Ozen (@ozenyunus35)
- Vladislav (@dsfcoll)
- Sébastien Chopin (@atinux)
- Kazbek Askarov (@kazbekaskarov)
- Nicholas (@Neekoras)
- Peter (@tada5hi)
- Baptiste Leproux (@larbish)
- Hugo (@HugoRCD)
- Harlan Wilton (@harlan-zw)
- AXH-xecoy (@axh-xecoy)
- Jess (@JessicaSachs)
- Alex Liu (@Mini-ghost)
- Gareth (@0xgdr)
- Florian Heuberger (@Flo0806)

---

## v4.12.0 (nuxt/ui) - 2026-10-15

[Release notes](https://github.com/nuxt/ui/releases/tag/v4.12.0)

## :sparkles: Highlights

### :bar_chart: Chart component

A new [`Chart`](https://ui.nuxt.com/docs/components/chart) component built on [TanStack Charts](https://tanstack.com/charts/latest) renders `line`, `area`, `bar` and `donut` charts as an SVG on the server. Series colors follow your theme and color mode through the new `--ui-chart-*` CSS variables:

```vue
<script setup lang="ts">
const data = [
  { month: 'January', desktop: 186, mobile: 80 },
  { month: 'February', desktop: 305, mobile: 200 },
  { month: 'March', desktop: 237, mobile: 120 }
]
</script>

<template>
  <UChart
    type="bar"
    :data="data"
    index="month"
    :categories="[{ key: 'desktop', label: 'Desktop' }, { key: 'mobile', label: 'Mobile' }]"
    stacked
  />
</template>
```

> [!NOTE]
> `@tanstack/charts` is an optional peer dependency, install it to use the component. When the props are not enough, the `definition` prop takes a full TanStack chart definition.

### :globe_with_meridians: Automatic locale with `@nuxtjs/i18n`

When `@nuxtjs/i18n` is installed, the [`App`](https://ui.nuxt.com/docs/components/app) component now follows the current i18n locale, and only the Nuxt UI locales matching your `i18n.locales` are bundled. You can drop the `import * as locales` pattern, which shipped every locale in the entry chunk:

```diff
- <script setup lang="ts">
- import * as locales from '@nuxt/ui/locale'
-
- const { locale } = useI18n()
- </script>
-
  <template>
-   <UApp :locale="locales[locale]">
+   <UApp>
      <NuxtPage />
    </UApp>
  </template>
```

> [!TIP]
> An explicit `locale` prop still wins, see the [i18n guide](https://ui.nuxt.com/docs/getting-started/integrations/i18n/nuxt#automatic-locale).

### :zap: Lighter and faster pages

Pages now load up to 27% less JavaScript. A page no longer loads the code of components only other pages use, and overlays are lazy loaded: the menu of `Header`, `Sidebar` and `DashboardSidebar`, the command palette of `DashboardSearch` and `ContentSearch`, and the toasts of `Toaster`.

| | v4.11.3 | v4.12.0 |
| --- | --: | --: |
| JS | 871.6 kB | 549.6 kB |
| JS (gzip) | 251.9 kB | 183.9 kB |

> [!NOTE]
> `UButton` also mounts about 38% faster and each item of an open `DropdownMenu` about 30% faster, since link props are now picked without a reactive proxy.

## :rocket: Features

* **App:** follow the `@nuxtjs/i18n` locale ([#7152](https://github.com/nuxt/ui/issues/7152)) ([43ba8a0](https://github.com/nuxt/ui/commit/43ba8a07ee6561613045c36c6e3015ceecf873c9))
* **Calendar:** add `yearsPerPage` prop ([#7138](https://github.com/nuxt/ui/issues/7138)) ([cc4acae](https://github.com/nuxt/ui/commit/cc4acae75c9e18705e97ff0b7af9b2dd5af3f290))
* **Chart:** new component ([#7022](https://github.com/nuxt/ui/issues/7022)) ([8b37286](https://github.com/nuxt/ui/commit/8b372869000484efbb9f687f9095782351ab2acf))
* **ChatReasoning:** add `autoOpen` prop ([#7049](https://github.com/nuxt/ui/issues/7049)) ([dad748e](https://github.com/nuxt/ui/commit/dad748e230314aed88fc555da93089185d49c1a3))
* **CheckboxGroup:** add `max` prop ([#7145](https://github.com/nuxt/ui/issues/7145)) ([63a0c05](https://github.com/nuxt/ui/commit/63a0c0563ea225d31d32019ccf3fdc9a455bb44c))
* **components:** add `loop` prop ([#7128](https://github.com/nuxt/ui/issues/7128)) ([a96f56f](https://github.com/nuxt/ui/commit/a96f56f7649b0794dba5337a4d483efeb228d58b))
* **components:** allow controlling heading element via `as` prop ([#7048](https://github.com/nuxt/ui/issues/7048)) ([623d6d2](https://github.com/nuxt/ui/commit/623d6d2bc35ad0d1e4afbc3dca039786aa3be240))
* **ContextMenu:** add `open` and `pressOpenDelay` props ([#7148](https://github.com/nuxt/ui/issues/7148)) ([73c489b](https://github.com/nuxt/ui/commit/73c489b64460430a0924e7897cfc33145e1458d0))
* **FileUpload:** add `reject` event for dropped files ([#7164](https://github.com/nuxt/ui/issues/7164)) ([c8f5ffc](https://github.com/nuxt/ui/commit/c8f5ffc69430a77da34e498337f8e93a6dced4a9))
* **FileUpload:** support custom file items in `v-model` ([#6927](https://github.com/nuxt/ui/issues/6927)) ([a352073](https://github.com/nuxt/ui/commit/a352073b458614937e489e5ec4770b00f75f4376))
* **InputMenu:** add default slot ([#6969](https://github.com/nuxt/ui/issues/6969)) ([3274113](https://github.com/nuxt/ui/commit/32741135b1ceafd1ca41ba4eef6684310608162a))
* **InputNumber:** add `startingValue` and `allowInvalid` props ([#7146](https://github.com/nuxt/ui/issues/7146)) ([d856ec3](https://github.com/nuxt/ui/commit/d856ec3d5f37bef9f9eab44dbf2396286ab26e25))
* **module:** export prose components from `@nuxt/ui/components/prose` ([#7143](https://github.com/nuxt/ui/issues/7143)) ([5c302c3](https://github.com/nuxt/ui/commit/5c302c3bb83661226b74008a17741e8e001b3925))
* **NavigationMenu:** add `viewport` prop ([#7123](https://github.com/nuxt/ui/issues/7123)) ([4a3464e](https://github.com/nuxt/ui/commit/4a3464e3619321cb44c3a017db12250a906ccac4))
* **ProsePrompt:** add `prompt` prop ([#7172](https://github.com/nuxt/ui/issues/7172)) ([8c92e5f](https://github.com/nuxt/ui/commit/8c92e5f9299c6c28ced1eebfd74e1d35805ac1c6))
* **Sidebar:** add `breakpoint` prop ([#7155](https://github.com/nuxt/ui/issues/7155)) ([2113daa](https://github.com/nuxt/ui/commit/2113daa41f2dfc13ffb2c37d9d1610002229c24b))
* **Toast:** add `closeOnClick` to actions ([#7147](https://github.com/nuxt/ui/issues/7147)) ([378873a](https://github.com/nuxt/ui/commit/378873a28d5db444c52873b21a71551609f11aa0))

## :bug: Bug Fixes

* **App:** forward `nonce` prop ([#7137](https://github.com/nuxt/ui/issues/7137)) ([9271533](https://github.com/nuxt/ui/commit/927153310901c0922a593336ef5f92cbb428761f))
* **Chart:** render tooltip above center slot ([5cf6b3a](https://github.com/nuxt/ui/commit/5cf6b3a9dfba74c6280190156ae43eba2af644ce))
* **ChatMessages/ChatPromptSubmit:** add accessible names to icon buttons ([#7153](https://github.com/nuxt/ui/issues/7153)) ([3cd30e0](https://github.com/nuxt/ui/commit/3cd30e013affa172acc2048710109690d83b042c))
* **ColorModeButton:** resolve label after mount ([#7167](https://github.com/nuxt/ui/issues/7167)) ([9a12b1f](https://github.com/nuxt/ui/commit/9a12b1fbcef56286c4b824fecd0c7a50dee6e53b))
* **components:** localize hardcoded accessibility labels ([#7177](https://github.com/nuxt/ui/issues/7177)) ([fc7137c](https://github.com/nuxt/ui/commit/fc7137cd47d37d4b7af52b7d9dffa63be51d45e8))
* **components:** prevent empty trailing slot when loading ([#7027](https://github.com/nuxt/ui/issues/7027)) ([1f46ce1](https://github.com/nuxt/ui/commit/1f46ce11fa0ead45de6c4d3bf2a3761c9d7188e9))
* **components:** spin trailing loading icon with avatar ([#7168](https://github.com/nuxt/ui/issues/7168)) ([2fc9ba0](https://github.com/nuxt/ui/commit/2fc9ba0cb8edae7cbc804a7ae6477361ef20defa))
* **ContentSearch/DashboardSearch:** handle `undefined` selection when an item is toggled off ([#7170](https://github.com/nuxt/ui/issues/7170)) ([14f13af](https://github.com/nuxt/ui/commit/14f13af6b8e1e58bb239ce03eb51adbbbcef37a6))
* **ContentToc:** raise list min height ([#7113](https://github.com/nuxt/ui/issues/7113)) ([2b535b0](https://github.com/nuxt/ui/commit/2b535b0187d8755233748c5835733b13152709ac))
* **Drawer:** don't disable body pointer events with `noBodyStyles` ([#7150](https://github.com/nuxt/ui/issues/7150)) ([04f253e](https://github.com/nuxt/ui/commit/04f253edb99d24993eb74bb83ca5418a77b24997))
* **Drawer:** emit `after:leave` and `after:enter` when the animation ends ([#7107](https://github.com/nuxt/ui/issues/7107)) ([5cd317b](https://github.com/nuxt/ui/commit/5cd317bfee044346ac3d3005b1348ff5b5f0d2d9))
* **Editor:** align link styles with prose ([f943f20](https://github.com/nuxt/ui/commit/f943f2059f2eea1dcf3fc9d992f5269103d7a096))
* **FileUpload:** make the `dropzone` prop reactive ([#7055](https://github.com/nuxt/ui/issues/7055)) ([f4322e7](https://github.com/nuxt/ui/commit/f4322e7a3577939f43be0781170a4827af15122c))
* **Form:** accept empty values in `state` type ([#7165](https://github.com/nuxt/ui/issues/7165)) ([a59a3a3](https://github.com/nuxt/ui/commit/a59a3a3e00cc95f03f596d80013b05fb3abc63c1))
* **Kbd:** avoid hydration mismatch for platform-specific keys ([#7166](https://github.com/nuxt/ui/issues/7166)) ([78e72fb](https://github.com/nuxt/ui/commit/78e72fb9b7a1012146f6713bba850f8024cbd8d5))
* **Link:** promote queued prefetch on interaction ([#7124](https://github.com/nuxt/ui/issues/7124)) ([974cc0d](https://github.com/nuxt/ui/commit/974cc0d9fa22a45e450e3171c3d9024275c4ec75))
* **Listbox:** add accessible name to listbox ([#7193](https://github.com/nuxt/ui/issues/7193)) ([6bbb358](https://github.com/nuxt/ui/commit/6bbb358e1749a54d5d06df7397b7e78394756626))
* **Pagination:** localize `aria-label` of controls and pages ([#7151](https://github.com/nuxt/ui/issues/7151)) ([d2d3da0](https://github.com/nuxt/ui/commit/d2d3da0db012b8a21a003eace1b81f00e4135f32))
* **ProseA:** hide underline on focus and around inline code ([3cd61ed](https://github.com/nuxt/ui/commit/3cd61edc6d051501ee2393513b987ab44953821b))
* **SelectMenu:** keep controls outside the listbox ([#7096](https://github.com/nuxt/ui/issues/7096)) ([ded6848](https://github.com/nuxt/ui/commit/ded6848ef6bd06e724d28d425df12204b06f8328))
* **SelectMenu:** keep menu open when focus moves outside ([#7095](https://github.com/nuxt/ui/issues/7095)) ([26016e8](https://github.com/nuxt/ui/commit/26016e8d4242426c3f1085a20eb7c33f55f92360))
* **Slideover:** only cap width from `sm` breakpoint ([#7156](https://github.com/nuxt/ui/issues/7156)) ([608a3d3](https://github.com/nuxt/ui/commit/608a3d3c93feef128d82d2cfcb2a2afc60aab982))
* **Table:** measure virtualized rows with variable heights ([#7204](https://github.com/nuxt/ui/issues/7204)) ([0e487d6](https://github.com/nuxt/ui/commit/0e487d62d5cc3149e2f7ed8eb0e2520981fd6a89))
* **Table:** respect `defaultColumn` cell and header ([#7198](https://github.com/nuxt/ui/issues/7198)) ([da9125c](https://github.com/nuxt/ui/commit/da9125cabe1d7e3814cde33c4af8d8b3a8bdb8bb))
* **theme:** remove unknown and conflicting classes ([96d0a50](https://github.com/nuxt/ui/commit/96d0a50c7df17efe111fc9fc7198a31ff47a8cfc))
* **Tree:** pass `disabled` to tree item ([#7139](https://github.com/nuxt/ui/issues/7139)) ([db30f7f](https://github.com/nuxt/ui/commit/db30f7f4402e80e94b7325f0a16bca1f554a6229))
* **useToast:** skip pulse while toast is animating ([#7195](https://github.com/nuxt/ui/issues/7195)) ([e51d3a9](https://github.com/nuxt/ui/commit/e51d3a9491e7f70e8f19ecda373bdc813ea8c65a))
* **useTour:** accept any CSS selector as step target ([#7144](https://github.com/nuxt/ui/issues/7144)) ([8a7270d](https://github.com/nuxt/ui/commit/8a7270d6604b5f7fd4ab07d52a57bd47736480d0))

## :fire: Performances

* **components:** import Reka UI primitives by name instead of from `reka-ui/namespaced` ([#7176](https://github.com/nuxt/ui/issues/7176)) ([896d609](https://github.com/nuxt/ui/commit/896d60962266a62012bc89bb53a8e65e863b2921))
* **components:** pick link props without a reactive proxy ([#7208](https://github.com/nuxt/ui/issues/7208)) ([68d0467](https://github.com/nuxt/ui/commit/68d0467eff78a3bb4d4fda2dddf8d938577b28c4))
* **DashboardSearch/ContentSearch:** lazy load modal and command palette ([#7161](https://github.com/nuxt/ui/issues/7161)) ([6f50933](https://github.com/nuxt/ui/commit/6f50933451bfa1150a303378682f5282c04820d7))
* **Header/DashboardSidebar/Sidebar:** lazy load menu overlay ([#7160](https://github.com/nuxt/ui/issues/7160)) ([691899a](https://github.com/nuxt/ui/commit/691899a81fdfce05c8218f4924fcf9c32e329a1a))
* **Toaster:** lazy load toast component ([#7163](https://github.com/nuxt/ui/issues/7163)) ([1b09a26](https://github.com/nuxt/ui/commit/1b09a2678353c53107831998b9610e8898fe2ed9))
* **useComponentProps:** skip prop resolution for Vue internal flags ([#7186](https://github.com/nuxt/ui/issues/7186)) ([c029710](https://github.com/nuxt/ui/commit/c029710988bc6f472e74e1d3db92d0e5fcdfef6e))

## :green_heart: Contributors

* @benjamincanac
* @kazbekaskarov
* @danielroe
* @61021
* @cristianchiriac
* @derblub
* @devotee101
* @giaBaoJS
* @leo-2-ga-ha
* @MFA-G
* @minwookshin
* @rdjanuar
* @ttcchhmm
* @vachmara

**Full Changelog**: https://github.com/nuxt/ui/compare/v4.11.3...v4.12.0


---

## v3.4.3 (nuxt/devtools) - 2026-10-14

[Release notes](https://github.com/nuxt/devtools/releases/tag/v3.4.3)

### &nbsp;&nbsp;&nbsp;🐞 Bug Fixes

- **devtools**: Require the dev auth token for server config and storage mounts &nbsp;-&nbsp; by @antfubot in https://github.com/nuxt/devtools/issues/1124 [<samp>(0383c)</samp>](https://github.com/nuxt/devtools/commit/0383cd75)

### &nbsp;&nbsp;&nbsp;🏎 Performance

- Replace `nypm` with `package-manager-detector` &nbsp;-&nbsp; by @danielroe in https://github.com/nuxt/devtools/issues/1102 [<samp>(21904)</samp>](https://github.com/nuxt/devtools/commit/21904b9b)

##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](https://github.com/nuxt/devtools/compare/v3.4.2...v3.4.3)

---

## v4.0.0-beta.5 (nuxt/devtools) - 2026-10-13

[Release notes](https://github.com/nuxt/devtools/releases/tag/v4.0.0-beta.5)

### &nbsp;&nbsp;&nbsp;🚨 Breaking Changes

- **devtools**: Slim the install size of @nuxt/devtools &nbsp;-&nbsp; by @antfubot in https://github.com/nuxt/devtools/issues/1121 [<samp>(10f9e)</samp>](https://github.com/nuxt/devtools/commit/10f9ee88)

### &nbsp;&nbsp;&nbsp;🚀 Features

- Remove Open Graph module and integrate new assets and Open Graph plugins &nbsp;-&nbsp; by @antfu [<samp>(b4d46)</samp>](https://github.com/nuxt/devtools/commit/b4d46d3c)
- Deps on `@nuxt/devtools-assets` for now to improve the landing experience (as we have the onboard package now) &nbsp;-&nbsp; by @antfu [<samp>(93820)</samp>](https://github.com/nuxt/devtools/commit/9382024a)

### &nbsp;&nbsp;&nbsp;🐞 Bug Fixes

- **onboard**: Load DevTools v3, v4 and nightly releases &nbsp;-&nbsp; by @antfubot in https://github.com/nuxt/devtools/issues/1122 [<samp>(d0b77)</samp>](https://github.com/nuxt/devtools/commit/d0b77e80)

##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](https://github.com/nuxt/devtools/compare/v4.0.0-beta.4...v4.0.0-beta.5)

---

## v2.0.0-beta.16 (nuxt/scripts) - 2026-10-12

[Release notes](https://github.com/nuxt/scripts/releases/tag/v2.0.0-beta.16)

### &nbsp;&nbsp;&nbsp;🐞 Bug Fixes

- **ci**: Skip stale workflow results and quote headers &nbsp;-&nbsp; by @harlan-zw in https://github.com/nuxt/scripts/issues/960 [<samp>(f8ebc)</samp>](https://github.com/nuxt/scripts/commit/f8ebc7c5)
- **cloudflare**: Keep analytics collection in the browser &nbsp;-&nbsp; by @harlan-zw in https://github.com/nuxt/scripts/issues/957 [<samp>(b1319)</samp>](https://github.com/nuxt/scripts/commit/b1319301)
- **scripts**: Preserve consent when reusing script consumers &nbsp;-&nbsp; by @harlan-zw in https://github.com/nuxt/scripts/issues/961 [<samp>(e2100)</samp>](https://github.com/nuxt/scripts/commit/e2100bb4)

##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](https://github.com/nuxt/scripts/compare/v2.0.0-beta.15...v2.0.0-beta.16)

---

## v3.16.2 (nuxt/content) - 2026-10-12

[Release notes](https://github.com/nuxt/content/releases/tag/v3.16.2)

### 🐞 Bug Fixes

- Continue when package manager exits non-zero after installing - by @0xgdr in https://github.com/nuxt/content/issues/3871 [<samp>(ebfdc)</samp>](https://github.com/nuxt/content/commit/ebfdc2c9)
- **api**:
  - Don&#39;t forward body headers to internal content requests - by @devtechedge in https://github.com/nuxt/content/issues/3868 [<samp>(ffa5a)</samp>](https://github.com/nuxt/content/commit/ffa5ac39)
- **cache**:
  - Await development cache replacement - by @onmax in https://github.com/nuxt/content/issues/3846 [<samp>(75eff)</samp>](https://github.com/nuxt/content/commit/75eff79a)
- **search**:
  - Preserve word boundaries between block elements - by @maricastroc and @farnabaz in https://github.com/nuxt/content/issues/3861 [<samp>(05a30)</samp>](https://github.com/nuxt/content/commit/05a3074e)
- **security**:
  - Standard quotes and block IN operator validate - by @farnabaz in https://github.com/nuxt/content/issues/3862 [<samp>(006d1)</samp>](https://github.com/nuxt/content/commit/006d1382)
  - Accept only query-builder WHERE clauses - by @farnabaz in https://github.com/nuxt/content/issues/3877 [<samp>(9fae8)</samp>](https://github.com/nuxt/content/commit/9fae87e7)

### 🏎 Performance

- **cache**: Avoid repeated cache index copies - by @onmax in https://github.com/nuxt/content/issues/3847 [<samp>(464fb)</samp>](https://github.com/nuxt/content/commit/464fb167)
- **navigation**: Skip unused leaf sibling searches - by @onmax and @farnabaz in https://github.com/nuxt/content/issues/3845 [<samp>(6fc1e)</samp>](https://github.com/nuxt/content/commit/6fc1e262)

##### [View changes on GitHub](https://github.com/nuxt/content/compare/v3.16.1...v3.16.2)

---

## v2.0.0-beta.15 (nuxt/scripts) - 2026-10-12

[Release notes](https://github.com/nuxt/scripts/releases/tag/v2.0.0-beta.15)

### &nbsp;&nbsp;&nbsp;🐞 Bug Fixes

- **devtools**: Add repository metadata for npm publishing &nbsp;-&nbsp; by @harlan-zw in https://github.com/nuxt/scripts/issues/954 [<samp>(1f1a9)</samp>](https://github.com/nuxt/scripts/commit/1f1a9ebb)

##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](https://github.com/nuxt/scripts/compare/v2.0.0-beta.14...v2.0.0-beta.15)

---

## v1.1.5 (nuxt/hints) - 2026-10-11

[Release notes](https://github.com/nuxt/hints/releases/tag/v1.1.5)

### 🩹 Fixes

- **html-validate:** Wrap validation in a try/catch ([#377](https://github.com/nuxt/hints/pull/377))
- Support app baseURL ([#392](https://github.com/nuxt/hints/pull/392))
- **lazy-load:** Wrap imported components inside setup to support circular imports ([#393](https://github.com/nuxt/hints/pull/393))

### ❤️ Contributors

- Julien Huang ([@huang-julien](https://github.com/huang-julien))



---

## v1.0.1 (nuxt/fonts) - 2026-10-11

[Release notes](https://github.com/nuxt/fonts/releases/tag/v1.0.1)

> v1.0.1 is the next patch release.

## 👉 Changelog

[compare changes](https://github.com/nuxt/fonts/compare/v1.0.0...v1.0.1)

### 📦 Build

- prepare before prepack step ([`e2777f9`](https://github.com/nuxt/fonts/commit/e2777f9))

### ❤️ Contributors

- Daniel Roe (@danielroe)

---

## v1.0.0 (nuxt/fonts) - 2026-10-11

[Release notes](https://github.com/nuxt/fonts/releases/tag/v1.0.0)

> v1.0.0 is the first stable release of Nuxt Fonts.

Nuxt Fonts has been in production use for over a year, and the underlying stack it is built on has now stabilised: [`unifont`](https://unifont.dev), [`fontaine`](https://github.com/unjs/fontaine) and [`fontless`](https://github.com/nuxt/fontless) all reached v1 alongside this release.

- `unifont` resolves font metadata from providers
- `fontaine` uses that metadata to cut layout shift
- `fontless` does the whole thing in Vite with zero config

… and of course, `@nuxt/fonts` wraps all three and wires them into Nuxt.

Most projects should be able to upgrade simply by bumping the version, but read on for full details...!

## 🚨 Breaking (or significant) changes

### Font metadata is cached per project

Font metadata and downloaded font files are now cached in `node_modules/.cache/nuxt/fonts/meta` relative to your project root rather than to the directory you run Nuxt from. The first build after upgrading will re-resolve and re-download fonts.

You can now configure the location with the [`cache`](https://fonts.nuxt.com/get-started/configuration#cache) option, pass your own [unstorage](https://unstorage.unjs.io/) instance, or disable persistent caching with `cache: false`.

```ts
export default defineNuxtConfig({
  fonts: {
    cache: '.cache/fonts',
  },
})
```

### Font failures fail production builds

[`throwOnError`](https://fonts.nuxt.com/get-started/configuration#throwonerror) now defaults to `true` outside of dev mode. Rather than producing a build with a missing font, the build fails when a provider errors, when a font file cannot be downloaded after retries, or when you set `provider` on a family and that provider does not contain it.

A family that cannot be found by any provider still warns rather than failing, as does an unknown provider name, so fonts you declare yourself in CSS are unaffected.

```ts
export default defineNuxtConfig({
  fonts: {
    throwOnError: false,
  },
})
```

### Family-level `@font-face` descriptors now apply to provider fonts

`display` and `unicodeRange` set on a family were previously only honoured for families you declared manually with `src`, and were silently dropped for fonts resolved from a provider. They now apply in both cases. Descriptors other than `display`, `weight` and `style` (such as `stretch`, `featureSettings` and `variationSettings`) are also no longer dropped from manually declared families.

If you set any of these options on a family and relied on them being ignored, your generated CSS will change. Setting `unicodeRange` on a family marks it as subsetted, so it is no longer preloaded by default; set [`preload`](https://fonts.nuxt.com/get-started/configuration#preload) explicitly if you still want a preload link for it.

### Injected `@font-face` rules are minified with `lightningcss`

Generated `@font-face` declarations were previously minified with esbuild unless you had opted into `css.lightningcss`. They are now always minified with lightningcss, so the exact serialisation of the CSS we inject may differ (for example `local(Font Name)` rather than `local("Font Name")`). This is cosmetic, but it will show up in snapshot tests.

### The default `400 700` weight range is applied

`weights` has always been documented as defaulting to `['400 700']`, but the default was set on the wrong option and never reached the resolver, so families without an explicit `weights` resolved at weight `400` alone. The documented default now takes effect ([#619](https://github.com/nuxt/fonts/issues/619)).

A family you didn't set `weights` on will resolve a bold face as well as a regular one, so expect additional `@font-face` rules and an additional file downloaded per family. Text that silently fell back to a synthesised bold will now render in the real one.

```ts
export default defineNuxtConfig({
  fonts: {
    defaults: {
      weights: [400],
    },
  },
})
```

### Fonts are served from `/_nuxt/fonts` in Vite builds

Production builds with the Vite builder now emit font files as Vite build assets under `app.buildAssetsDir`, so they are served from `/_nuxt/fonts/<hash>.woff2` rather than `/_fonts/<hash>.woff2`. Vite owns their URLs, which means `app.cdnURL`, a relative `app.baseURL` and `experimental.renderBuiltUrl` all now apply to fonts as they do to every other built asset.

The location of a font file is an implementation detail rather than a stable URL contract. If you have hard-coded `/_fonts/` anywhere (a CDN rule, a CSP directive, a cache header, a test), point it at your build assets directory instead. Fonts are still served from `/_fonts` in development and with the webpack and rspack builders.

### `app.cdnURL` now applies to fonts

This follows from the change above. `cdnURL` was previously never applied to font URLs, so fonts were always served same-origin. They now come from your CDN.

> [!IMPORTANT]
> Browsers always fetch fonts in CORS mode, so the CDN must respond with an `Access-Control-Allow-Origin` header that covers your site. Without it, fonts that previously loaded fail silently and the browser falls back to the next family in the stack. If you set `cdnURL` and don't control the headers on it, check this before upgrading.

### `assets.prefix` is relative to `buildAssetsDir` in Vite builds

`assets.prefix` now names a directory inside `app.buildAssetsDir` in Vite production builds, and defaults to `fonts`. Setting `prefix: '/my-fonts'` serves fonts from `/_nuxt/my-fonts` rather than from `/my-fonts`. It remains a public path in development and with the webpack and rspack builders.

### `global: true` families get font fallback metrics

`global` is the escape hatch for fonts we can't detect from your CSS, but until now that meant the fonts most likely to cause layout shift were the ones we did least about: the `@font-face` went into a global stylesheet and no fallback metric overrides were generated at all.

We now generate those overrides at every usage site we can see, so `font-family: 'Anton'` in a component becomes `font-family: 'Anton', 'Anton Fallback: Arial', ...` with the matching `size-adjust` and `ascent-override` rules alongside it, exactly as it would for a family that wasn't declared globally. The `@font-face` rule itself still comes from the global stylesheet and isn't duplicated, and preload hints are unchanged. Usage we can't scan (an SVG, a family chosen at runtime) keeps working as before.

Set `fallbacks: []` on the family if you don't want the fallback rules.

### The `local` provider only scans layer `public/` directories

The [`local` provider](https://fonts.nuxt.com/get-started/providers#local) previously scanned every directory in `nitro.publicAssets`, including those that modules register for their own files. It now scans only the `public/` directory of your project and of each layer.

If you relied on fonts in another `nitro.publicAssets` directory, add it to [`local.dirs`](https://fonts.nuxt.com/get-started/providers#fonts-installed-from-npm):

```ts
export default defineNuxtConfig({
  fonts: {
    local: {
      dirs: ['../some-module/fonts'],
    },
  },
})
```

## ⚠️ Deprecations

### `experimental.processCSSVariables`

`fonts.experimental.processCSSVariables` has moved to `fonts.processCSSVariables`. The old location still works and now warns.

```ts
export default defineNuxtConfig({
  fonts: {
    processCSSVariables: true,
  },
})
```

### `fonts:public-asset-context`

Use [`fonts:resolved`](https://fonts.nuxt.com/advanced#fontsresolved) instead. It reports each family as it is resolved, with the URL every font file is served from and a `readFont()` to read its contents, so there's no need to reconstruct paths from the asset context. (The old hook still works.)

## ✨ Features

### A new DevTools panel

The Fonts panel in [Nuxt DevTools](https://devtools.nuxt.com) has been rebuilt on `fontless`. It lists every family resolved for your app, the provider that served it, the faces generated for it, where each one is used, and any warnings raised while resolving it.

https://github.com/user-attachments/assets/287f08a8-f92e-4a3d-a585-ab4ea80432db

### webpack and rspack support

Nuxt Fonts now works with the webpack and rspack builders. Previously our CSS transform ran after `css-loader` had already turned stylesheets into JavaScript modules, so no `@font-face` rule was ever injected, and a family declared with `global: true` failed the client build outright.

The transform now runs immediately before `css-loader`, which means it sees your styles after Sass and PostCSS have run, so a family named only through a preprocessor variable is detected too. There's nothing to change on your side, but a build that silently shipped no web fonts will now download them and serve them from `/_fonts`.

### Arbitrary variable axes

Variable font axes beyond `wght` now resolve from providers that publish them, so you can ask for `wdth`, `slnt`, `opsz` and more.

```ts
export default defineNuxtConfig({
  fonts: {
    families: [
      {
        name: 'Roboto Flex',
        provider: 'google',
        providerOptions: {
          google: {
            experimental: {
              variableAxis: { wdth: [['75', '100']] },
            },
          },
        },
      },
    ],
  },
})
```

### Subsetting fonts to the glyphs you use

The new `glyphs` option reduces every font file we emit to the characters needed to render the text you give it, which can dramatically cut the bytes shipped for icon fonts and single-language sites.

```ts
export default defineNuxtConfig({
  fonts: {
    defaults: {
      glyphs: 'Handgloves & 0123',
    },
  },
})
```

Where a provider can subset server-side the characters are passed through to it, so the full file is never downloaded. Every other file is subsetted after download, which needs the [`subset-font`](https://github.com/papandreou/subset-font) package; we'll offer to install it the first time you run Nuxt with `glyphs` set.

> [!IMPORTANT]
> Before enabling subsetting, make sure the font licence allows you to do so. Many do not.

### Preloading by subset

[`preload`](https://fonts.nuxt.com/get-started/configuration#preload) (on `defaults` and on individual `families`) accepts `{ subsets: [...] }` or a filter function, so you can preload just the subsets your app needs.

```ts
export default defineNuxtConfig({
  fonts: {
    defaults: {
      preload: { subsets: ['latin'] },
    },
  },
})
```

### Named font weights

`weights` accepts CSS keywords (`normal`, `bold`, `light`, ...) in config, and the `local` provider recognises them in filenames, so `MyFont-Bold.woff2` is picked up as weight `700`.

### Scanning additional local font directories

The `local` provider can scan directories beyond `public/`, and now reports which filenames it looked for when a family cannot be resolved, which makes misnamed files much easier to debug.

```ts
export default defineNuxtConfig({
  fonts: {
    local: {
      paths: ['assets/fonts'],
    },
  },
})
```

### Reuse resolved fonts from another module

Modules that need the fonts your app already uses - for example, to [render an OG image](https://github.com/nuxt-modules/og-image/) or a PDF - had to reverse-engineer internal build machinery to find them, then re-resolve and re-download the same families themselves.

The new `fonts:resolved` hook reports each family as it is resolved, with the URL every font file is served from and a `readFont()` to read its contents, so nothing has to be resolved or downloaded more than once.

```ts
const files = new Map<string, () => Promise<Buffer>>()

nuxt.hook('fonts:resolved', (font) => {
  for (const file of font.files) {
    files.set(file.url, file.readFont)
  }
})
```

Listeners run while your stylesheets are transformed, so collect what you need and call `readFont()` later. See [the hook documentation](https://fonts.nuxt.com/advanced#fontsresolved).

### Custom CSS variable prefixes

[`processCSSVariables`](https://fonts.nuxt.com/get-started/configuration#processcssvariables) accepts a custom prefix, so `processCSSVariables: 'my-app'` processes `--my-app-*` variables only.

## 🩹 Fixes

- Font asset URLs respect the app `baseURL` and a custom `cdnURL`
- Inlined `@font-face` rules are deduplicated in the rendered HTML
- Font downloads are retried before a build is failed
- Local variable fonts with weight ranges resolve correctly
- Fallback metrics are generated for fonts in the public directory
- Nitro v3 and Nuxt 5 compatibility
- Devtools UI works under a custom `baseURL` and with `@nuxt/devtools` v4
- Deprecated `experimental.processCSSVariables` now warns rather than being silently ignored
- Dev font server errors are passed to the next middleware instead of hanging the request
- Multiple `families` entries sharing a name are all applied
- The `local` provider detects camel-cased variable font markers in filenames
- Font faces injected into bundled CSS resolve their URLs correctly
- Hoisted global font faces are minified
- Fallbacks are not regenerated for already-transformed declarations
- The `local` provider no longer scans `nitro.publicAssets` directories registered by modules

## 🙏 Thank you

Thank you so much to everyone who has contributed to `@nuxt/fonts`, `unifont`, `fontaine` and `fontless` to get us here. ❤️

## 🚀 How to upgrade

After upgrading to the latest version, clear your font cache and rebuild:

```bash
rm -rf node_modules/.cache/nuxt/fonts
```

Please read the [upgrade guide](https://fonts.nuxt.com/get-started/upgrade) for the full detail, and let me know how you get on! 🙏

## 👉 Changelog

[compare changes](https://github.com/nuxt/fonts/compare/v0.14.0...v1.0.0)

### 🚀 Enhancements

- use devframe-based devtools from `fontless` (#937)
- add `fonts:resolved` hook (#921)
- ⚠️  serve fonts as vite build assets under `buildAssetsDir` (#918)
- generate fallback metrics for `global` families where used (#915)
- inject font faces under the webpack and rspack builders (#914)
- support resolving variable font axes (#909)
- **local:** accept named font weights in config and filename aliases ([`136ac36`](https://github.com/nuxt/fonts/commit/136ac36))
- **deps:** update `fontless` to `0.4.3` (#421)
- subset downloaded fonts to the glyphs a family declares (#131)
- **local:** report filenames looked for when a family can't be resolved (#895)
- **npm:** resolve installed font packages with `resolve` + `exists` hooks (#894)
- ⚠️  **deps:** update `fontless` and `unifont` (#887)
- **local:** support scanning font files from additional directories (#876)
- configurable font cache (#869)
- ⚠️  **deps:** update `unifont`, `fontaine` and `fontless` (#868)

### 🩹 Fixes

- resolve urls of font faces injected into bundled css (#939)
- minify hoisted global font faces ([`6103883`](https://github.com/nuxt/fonts/commit/6103883))
- don't regenerate fallbacks for already-transformed declarations ([`60d7904`](https://github.com/nuxt/fonts/commit/60d7904))
- **local:** only scan layer `public/` directories (#938)
- support multiple `families` entries with the same name ([`d7987a8`](https://github.com/nuxt/fonts/commit/d7987a8))
- **local:** detect camel-cased variable font markers (#931)
- use explicit file extensions in relative imports (#930)
- **local:** scan for font files during module setup (#929)
- use `fontless` preload selection (#920)
- fail before downloading fonts that need a missing `subset-font` ([`00436e1`](https://github.com/nuxt/fonts/commit/00436e1))
- respect user weights if provided ([`8b6d7f0`](https://github.com/nuxt/fonts/commit/8b6d7f0))
- apply the default `400 700` weight range (#619)
- **local:** generate fallback metrics for public directory fonts (#171)
- nitro v3 compatibility (#898)
- warn when deprecated `experimental.processCSSVariables` is set (#892)
- pass dev font server errors to the next middleware (#891)
- deduplicate inlined `@font-face` rules in rendered html (#879)
- retry font downloads and fail production builds on font errors (#877)
- support local variable fonts with weight ranges (#794)
- inline font faces from global stylesheets (#875)
- prefix font asset URLs with app `baseURL` ([`1f13e79`](https://github.com/nuxt/fonts/commit/1f13e79))
- respect `baseURL` when serving devtools UI ([`918d036`](https://github.com/nuxt/fonts/commit/918d036))
- consider global fonts for preloading as well (#856)
- **devtools:** use hook for compat with devtools v4 ([`05ae60c`](https://github.com/nuxt/fonts/commit/05ae60c))
- strip style queries when tracking fonts to preload (#872)
- pass a real H3Event in storybook mode (#807)

### 💅 Refactors

- let `fontless` fill per-category fallback defaults (#893)
- **client:** migrate away from devtools-ui-kit ([`ad5b781`](https://github.com/nuxt/fonts/commit/ad5b781))

### 📖 Documentation

- add docs for devtools panel and `fonts:resolved` ([`c9478ca`](https://github.com/nuxt/fonts/commit/c9478ca))
- document variable font usage and naming (#933)
- note that non-default subsets need configuring (#932)
- cover unicode ranges in `glyphs` and provider failure isolation ([`4b7a21b`](https://github.com/nuxt/fonts/commit/4b7a21b))
- correct some inaccuracies in the docs ([`823edb0`](https://github.com/nuxt/fonts/commit/823edb0))
- refresh the docs site for v1 (#919)
- note that lightningcss minification needs the optional peer ([`8928fb0`](https://github.com/nuxt/fonts/commit/8928fb0))
- update upgrade guide ([`5f41ed3`](https://github.com/nuxt/fonts/commit/5f41ed3))
- document `global` as the escape hatch for undetectable font usage (#917)
- drop mention of tailwindcss v3 ([`b764025`](https://github.com/nuxt/fonts/commit/b764025))

### 🏡 Chore

- fix typecheck against the module stub ([`99bb608`](https://github.com/nuxt/fonts/commit/99bb608))
- pin nuxt 5 playground ([`7a46fde`](https://github.com/nuxt/fonts/commit/7a46fde))
- **client:** don't overwrite built client when running playground ([`bb36013`](https://github.com/nuxt/fonts/commit/bb36013))
- exempt first-party packages from pnpm `minimumReleaseAge` (#862)
- replace `latest` ranges with caret ranges (#861)
- migrate to pnpm v11 (#831)
- migrate npm badges and links to npmx.dev ([`a5c61fb`](https://github.com/nuxt/fonts/commit/a5c61fb))

### ✅ Tests

- tolerate per-file font face duplication in bundled css ([`a5a4dd9`](https://github.com/nuxt/fonts/commit/a5a4dd9))
- clear the font cache of every fixture and playground ([`7995bd1`](https://github.com/nuxt/fonts/commit/7995bd1))
- cover tailwind v4 `--default-font-family` theme variables (#890)
- cover family-level font-face descriptor overrides (#888)
- cover font URLs in inlined styles with a custom `cdnURL` (#880)
- drop tailwindcss v3 ([`d7921fb`](https://github.com/nuxt/fonts/commit/d7921fb))
- use human readable font names in snapshots ([`d119be1`](https://github.com/nuxt/fonts/commit/d119be1))
- refresh snapshots + make resilient to vite 8 changes (#857)
- update test assertions for vite 8 ([`16e87f6`](https://github.com/nuxt/fonts/commit/16e87f6))
- mock adobe api responses (#819)

### 🤖 CI

- use `pnpm/setup` and `devEngines` (#907)
- adopt uppt for release workflow (#866)
- run ci for merge groups ([`8c3dd7f`](https://github.com/nuxt/fonts/commit/8c3dd7f))
- migrate agentscan-action to v2 ([`7dd7a38`](https://github.com/nuxt/fonts/commit/7dd7a38))
- add agent-scan workflow to flag bot-authored PRs ([`349b7ba`](https://github.com/nuxt/fonts/commit/349b7ba))
- rename workflow ([`8154aa6`](https://github.com/nuxt/fonts/commit/8154aa6))
- avoid checkout for reproduction comment ([`ed921dc`](https://github.com/nuxt/fonts/commit/ed921dc))

### 🎉 New Contributors

- Peter Uithoven (@peteruithoven)
- Meliceanu (@Meliceanu)
- Cynthia Rey (@cyyynthia)

### ❤️ Contributors

- Daniel Roe (@danielroe)
- Harlan Wilton (@harlan-zw)
- Peter Uithoven (@peteruithoven)
- Meliceanu (@Meliceanu)
- Cynthia Rey (@cyyynthia)

---

## v4.6.1 (nuxt/nuxt) - 2026-10-09

[Release notes](https://github.com/nuxt/nuxt/releases/tag/v4.6.1)

> v4.6.1 is the next patch release.

## 👉 Changelog

[compare changes](https://github.com/nuxt/nuxt/compare/v4.6.0...v4.6.1)

### 🔥 Performance

- **nitro:** build the portable event's web view on first access ([`cffb182d6`](https://github.com/nuxt/nuxt/commit/cffb182d6))

### 🩹 Fixes

- **vite:** match vite 8.1+ optimizer messages for deps hint (#36525)
- **nuxt:** accept any `baseURL` when fetch response type is named (#36523)
- **nitro:** resolve `nitropack/types` declarations under nodenext ([`242e1971e`](https://github.com/nuxt/nuxt/commit/242e1971e))
- **nuxt:** allow `false` in `setPageLayout` types (#36506)
- **nuxt:** align `Serialize` object types with JSON (#36503)
- **vite:** don't abort dep scan on virtual imports in installed packages (#36477)
- **nuxt:** update `publishConfig` config export extension ([`64fa191cb`](https://github.com/nuxt/nuxt/commit/64fa191cb))
- **kit:** install the package a missing subpath belongs to (#36507)
- **vite-server:** use the configured outDir as the public directory for non-ssr environment (#36501)
- **kit,nitro:** match dev handler paths on both nitro majors (#36515)
- **nuxt:** preserve onServerPrefetch for useId hydration (#36430)
- **vite-server:** include the request in dev error reports (#36489)
- **nitro:** register each dev server handler once (#36493)
- **nitro:** pass `RequestEvent` to `nuxt` dev server handlers ([`e6beceea2`](https://github.com/nuxt/nuxt/commit/e6beceea2))
- **nuxt:** type the global `$fetch` with nuxt's `TypedFetch` (#36492)
- **vite-server:** work with deploy target plugins in dev (#36491)
- **schema:** ignore `.wrangler` directory (#36487)
- **vite-server:** pass the path to the error page render (#36488)
- **nuxt,vite:** disable dev error broadcast if `BroadcastChannel` throws (#36480)
- **kit:** align semantic version regexp with nightly version format (#36479)
- **nuxt:** export types reachable from async data composables (#36478)
- **vite:** detect enclosing string delimiter in inline style urls (#36476)
- **schema:** type the `nuxt` dev server handler variant ([`452052793`](https://github.com/nuxt/nuxt/commit/452052793))
- **nitro:** inline nuxt runtime when resolved to windows paths ([`21657c6fc`](https://github.com/nuxt/nuxt/commit/21657c6fc))
- **nitro:** resolve `unhead` from nuxt in server bundle ([`dc1e2d6e6`](https://github.com/nuxt/nuxt/commit/dc1e2d6e6))

### 💅 Refactors

- **kit:** use `package-manager-detector` workspace + deno handling ([`1563a6d25`](https://github.com/nuxt/nuxt/commit/1563a6d25))

### 📖 Documentation

- document dev server handlers and `nuxt/server` scope ([`7c36a1352`](https://github.com/nuxt/nuxt/commit/7c36a1352))
- fix nightly examples (#36486)

### 🏡 Chore

- remove `CLAUDE.md` (#36462)
- relax minimum release age exclude ([`bdf98e936`](https://github.com/nuxt/nuxt/commit/bdf98e936))
- update welcome template ([`787d0d980`](https://github.com/nuxt/nuxt/commit/787d0d980))

### ✅ Tests

- resolve temporary fixture paths on macos ([`30742865c`](https://github.com/nuxt/nuxt/commit/30742865c))
- update test expectation ([`1f22a114d`](https://github.com/nuxt/nuxt/commit/1f22a114d))

### 🤖 CI

- publish 4.x releases to `latest` ([`682605dba`](https://github.com/nuxt/nuxt/commit/682605dba))
- update release workflows ([`3b8853489`](https://github.com/nuxt/nuxt/commit/3b8853489))

### 🎉 New Contributors

- okueng (@okueng)
- Kaan Gökdemir (@kaangokdemir)
- Kazbek Askarov (@kazbekaskarov)
- QvarcY (@QvarcY)
- Bruno Belloni (@brunobelloni)
- Arnaud Dematte (@adematte)

### ❤️ Contributors

- Daniel Roe (@danielroe)
- Sébastien Chopin (@atinux)
- okueng (@okueng)
- Kaan Gökdemir (@kaangokdemir)
- Kazbek Askarov (@kazbekaskarov)
- Estéban (@Barbapapazes)
- QvarcY (@QvarcY)
- Bruno Belloni (@brunobelloni)
- Amulet Kerria (@KazariEX)
- abeer0 (@iiio2)
- Arnaud Dematte (@adematte)

---

## v2.0.0-beta.14 (nuxt/scripts) - 2026-10-06

[Release notes](https://github.com/nuxt/scripts/releases/tag/v2.0.0-beta.14)

### &nbsp;&nbsp;&nbsp;🐞 Bug Fixes

- Accept Nuxt 5 nightlies and restore the Nitro 3 CI job &nbsp;-&nbsp; by @harlan-zw in https://github.com/nuxt/scripts/issues/948 [<samp>(19d6f)</samp>](https://github.com/nuxt/scripts/commit/19d6f6d8)

##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](https://github.com/nuxt/scripts/compare/v2.0.0-beta.13...v2.0.0-beta.14)

---

## v2.0.0-beta.13 (nuxt/scripts) - 2026-10-06

[Release notes](https://github.com/nuxt/scripts/releases/tag/v2.0.0-beta.13)

### &nbsp;&nbsp;&nbsp;🚨 Breaking Changes

- Require Nuxt 4.6 and use portable server APIs &nbsp;-&nbsp; by @harlan-zw and @onmax in https://github.com/nuxt/scripts/issues/946 [<samp>(00414)</samp>](https://github.com/nuxt/scripts/commit/0041431e)

##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](https://github.com/nuxt/scripts/compare/v2.0.0-beta.12...v2.0.0-beta.13)

---

## v4.0.0-beta.4 (nuxt/devtools) - 2026-10-06

[Release notes](https://github.com/nuxt/devtools/releases/tag/v4.0.0-beta.4)

### &nbsp;&nbsp;&nbsp;🚀 Features

- Add @nuxt/devtools-onboard as the opt-in entry point of Nuxt DevTools &nbsp;-&nbsp; by @antfubot and @antfu in https://github.com/nuxt/devtools/issues/1117 [<samp>(ff051)</samp>](https://github.com/nuxt/devtools/commit/ff0512e8)

### &nbsp;&nbsp;&nbsp;🐞 Bug Fixes

- Resolve typecheck errors after dependency updates &nbsp;-&nbsp; by @antfubot in https://github.com/nuxt/devtools/issues/1104 [<samp>(93ffd)</samp>](https://github.com/nuxt/devtools/commit/93ffd79a)
- Accept any nitro version in the optional peer dependency &nbsp;-&nbsp; by @mansurkhoja in https://github.com/nuxt/devtools/issues/1106 [<samp>(f96b0)</samp>](https://github.com/nuxt/devtools/commit/f96b08e4)
- **deps**:
  - Align the Nuxt nightly with nitro 3.0.260903 so the dev server boots &nbsp;-&nbsp; by @antfubot in https://github.com/nuxt/devtools/issues/1107 [<samp>(a4928)</samp>](https://github.com/nuxt/devtools/commit/a492820b)
- **devtools**:
  - Stop inlining every dependency into the Nitro v2 dev bundle &nbsp;-&nbsp; by @antfubot in https://github.com/nuxt/devtools/issues/1109 [<samp>(397f9)</samp>](https://github.com/nuxt/devtools/commit/397f9b22)
  - Contain asset RPC paths and the storage denylist to what the UI may touch &nbsp;-&nbsp; by @antfubot and **Anthony Fu** in https://github.com/nuxt/devtools/issues/1111 [<samp>(6521d)</samp>](https://github.com/nuxt/devtools/commit/6521d263)

##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](https://github.com/nuxt/devtools/compare/v4.0.0-beta.3...v4.0.0-beta.4)

---

## v4.6.0 (nuxt/nuxt) - 2026-10-05

[Release notes](https://github.com/nuxt/nuxt/releases/tag/v4.6.0)

> v4.6.0 is the next minor release.

## 📣 Some news

### 🖥️ Nuxt CLI v4

Alongside the release of Nuxt v4.6, today also brings a new major release of the Nuxt CLI: **`@nuxt/cli` v4**. It ships as a dependency of `nuxt`, so you'll get it automatically when you upgrade.

Most of what's new is in `nuxt dev`:

- **an interactive terminal UI**, showing URLs, startup progress and keyboard shortcuts, with panels to dive into error logs, routes, network requests and more
- **the dev server gives you more info**, such as why it reloaded or restarted, which `nuxt.config` keys changed, where the time went during a slow start or build, and how long each module took to set up
- **a CLI-level error channel** rendered with `my-bad` (see below), powering things like automatically reloading when a syntax error in `nuxt.config.ts` is fixed
- **a lock file** in `.nuxt/`, which lets a second `nuxt dev` (say, one started by an agent) take over or defer to the one you started, and powers new `nuxt curl` and `nuxt task` commands that talk to the running server

There's also a new `nuxt docs "<query>"` search, and `nuxt preview --takeover` can replace a running preview server. And in general `nuxt/cli` is a ***lot*** smaller and starts a ***lot*** faster:

| | v3.37 | v4.0 | |
| --- | --- | --- | --- |
| `@nuxt/cli` install size | 13.1 MB | 3.5 MB | **-73%** |
| `@nuxt/cli` dependencies | 70 | 31 | **-56%** |
| `nuxt dev`: first paint | 330 ms | 50 ms | **6.6x faster** |
| `nuxt dev`: port bound | 338 ms | 104 ms | **3.2x faster** |
| `nuxt dev`: memory at rest (Linux) | 630 MB | 440 MB | **-30%** |

<img width="903" height="638" alt="nuxt-dev" src="https://github.com/user-attachments/assets/426fe6f8-736e-410b-9129-d179f1043021" />

Although this is a major version, none of the changes should be breaking for Nuxt v4 users: we require Node.js v22.21+, v24.11+ or v26+, we drop `nuxt init` and only support `npm create nuxt@latest`, and Nuxt 2 and `@nuxt/bridge` are no longer supported.

👉 **Check out the full [Nuxt CLI v4 release notes](https://github.com/nuxt/cli/releases/tag/v4.0.0) for everything that's changed.**

### 💡 A server-agnostic Nuxt

The biggest thing about this release is our move towards making Nuxt server-agnostic.

I feel that freedom of choice is very much a fundamental value of the web, and one that unites the whole Nuxt team.

You can use `pages/` (with vue-router) or not. You can use Vite, webpack or Rspack to bundle your code. You can pick from dozens of providers to deploy to, pick any image or font provider, choose any database adapter. In every case, the framework is the same.

The server side was different. `#app` composables imported h3 types, server code imported from `h3` and `nitropack`, and every module that touched the server was tied to whichever major version of those packages Nuxt happened to depend on.

This has become particularly clear as we have been upgrading to new majors of h3 and nitro, which ship breaking changes with a cascading effect throughout the whole ecosystem.

👉 **This release changes that.**

Alongside explicitly defining our public API in `nuxt/kit` (which now does not refer to external packages), Nuxt now specifies our own types for the request event, route rules and typed `$fetch`, and we expose an import surface (`nuxt/server`) for the server utilities that will be needed by most apps.

This is the culmination of work we started almost a year ago, making it possible to use any server builder with Nuxt, not just Nitro ([#33462](https://github.com/nuxt/nuxt/pull/33462)).

Of course, under the hood, `nuxt/server` is still powered by Nitro by default - though we are also announcing a second, experimental implementation, `@nuxt/vite-server`, which allows pure-Vite server builds using the [Vite Environment API](https://vite.dev/guide/api-environment#environment-api).

> [!IMPORTANT]
> We believe that Nitro is still the right choice for almost everyone.

🌟 We see a number of key benefits for `nuxt/server`.

1. **it smooths the upgrade to Nuxt 5**, which moves to Nitro v3 and h3 v2. Server code written against `nuxt/server` on 4.6 runs unchanged there, so a module can ship one file for both.
2. **it decouples Nuxt from the Nitro release cycle**. Because we 'own' the API, we can adapt to breaking changes in Nitro or h3 without requiring a future major - and we can release Nuxt majors without having to wait for upstream releases.
3. **it makes Nuxt's code more maintainable**. It helps us preserve the separation of concerns between our API - `/app` and `/server` - and the bundler + server that you ultimately want to build your app.

... and there are a number of other benefits too, from a single type surface to being able to iterate more quickly on features.

Finally, I want to say a special thank-you to [@pi0](https://github.com/pi0), whose relentless focus on server agnosticism and work on h3, Nitro and web-standard server primitives over the last few years is what makes a portable `RequestEvent` possible at all. Thank you, Pooya. ❤️

Almost every feature in this release is already in the Nuxt 5 branch, and most of the remaining Nuxt 5 defaults can be tested today with `future.compatibilityVersion: 5` (more details below!).

> [!TIP]
> Nuxt 3 reached end-of-life on July 31, 2026, so there is no 3.x release alongside this one. If you're still on v3, the [upgrade guide](https://nuxt.com/docs/getting-started/upgrade) is waiting for you.

## 👀 Highlights

🤷 If you've read this far I'm afraid I have bad news for you: there's a lot more still to say! Nuxt 4.6 is one of our biggest minor releases, with over 420 commits since v4.5.2.

... so, you might want to grab a coffee! ☕️

### 🧩 `nuxt/server`

It has been asked for for a long time, and it now exists ([#36275](https://github.com/nuxt/nuxt/pull/36275))!

`nuxt/server` is a new import source for server code: handlers, middleware and utilities - a complement to `nuxt/app`. Where `nuxt/app` is for the part of your application that also runs in the browser, `nuxt/server` is for the part that only runs on the server.

```ts [server/api/hello.ts]
import { defineEventHandler, getQuery } from 'nuxt/server'

export default defineEventHandler((event) => {
  const { name } = getQuery<{ name?: string }>(event)
  return { message: `Hello, ${name ?? 'world'}!` }
})
```

The utilities use web standards and are typed against a portable `RequestEvent`:

```ts
event.req         // Request
event.url         // URL
event.res         // { status, statusText, headers }
event.res.headers // Headers
event.context     // per-request context
```

Under `@nuxt/nitro-server` they are backed by Nitro and h3, but you never import from either.

So the same handler runs under Nitro v2, Nitro v3 or `@nuxt/vite-server`, and a module that imports from `nuxt/server` doesn't need a peer dependency on `h3` or `nitropack`.

We think this will make a big difference in smoothing out the upgrade to Nuxt v5 and Nitro v3.

There is a typing benefit too. We no longer hoist h3 or Nitro types into your app to type `useRequestEvent`, `$fetch` or route rules, which removes a source of type conflicts when versions differ ([#36212](https://github.com/nuxt/nuxt/pull/36212), [#36214](https://github.com/nuxt/nuxt/pull/36214), [#36293](https://github.com/nuxt/nuxt/pull/36293)).

The surface is small, and covers what published modules and user code typically need: `defineEventHandler`, `createError`/`isNuxtError`, request URL, headers, query, body (plain and validated with any [Standard Schema](https://standardschema.dev) library or a function), cookies, redirects, response status, `getRouterParam(s)`, `getRequestIP`, `handleCors`, `getRouteRules`, `useRuntimeConfig`, `useAppConfig` and sessions.

```ts [server/api/users.post.ts]
import { defineEventHandler, readValidatedBody } from 'nuxt/server'
import { z } from 'zod'

export default defineEventHandler(async (event) => {
  const user = await readValidatedBody(event, z.object({ name: z.string() }))
  return { created: user.name }
})
```

We encourage you to use web APIs (`event.req.headers`, for example), or raise an issue if there's functionality you're missing from `nuxt/server` 🙏

If you do need to step outside `nuxt/server` for a particular handler, don't worry! Nothing has been taken away: import `defineEventHandler` and the helpers you need from `h3` or `nitropack/runtime` as before, and that handler works exactly as it did on Nuxt 4.5.

```ts [server/api/upload.post.ts]
import { defineEventHandler, readMultipartFormData } from 'h3'

export default defineEventHandler(async (event) => {
  const parts = await readMultipartFormData(event)
  return { received: parts?.length ?? 0 }
})
```

> [!IMPORTANT]
> On Nuxt 4, the _auto-imported_ `defineEventHandler`, `getQuery`, `readBody` and the rest are still h3's own helpers, which take a different shape of event. Import from `nuxt/server` explicitly, including `defineEventHandler` to use the new server runtime. If you mix the two, you'll see a `NUXT_E8012` error which should tell you which import to change.

A few helpers also behave differently from their h3 v1 namesakes: `sendRedirect` returns the response rather than sending it, `createError` takes `status` and `statusText`, and response headers are set through `event.res.headers`. The upgrade guide has [a table of the differences](https://nuxt.com/docs/getting-started/upgrade#moving-to-nuxtserver).

Nothing in this release _requires_ a migration. But if you have server code you'd like to make portable ahead of Nuxt 5, this is the best way.

👉 Read the [server imports guide](https://nuxt.com/docs/guide/going-further/server-imports).

### 🔐 `appSecret` and sessions

Nuxt now has a root application secret: `runtimeConfig.appSecret`, set with `NUXT_APP_SECRET` ([#35874](https://github.com/nuxt/nuxt/pull/35874), thanks to [@onmax](https://github.com/onmax)). Modules and server features derive purpose-specific secrets from it with `deriveSecret(purpose)`, so `NUXT_APP_SECRET` is the only secret you need to configure.

```bash
openssl rand -base64 32
```

In development Nuxt generates and persists one if none is configured (and warns the first time a derived secret is used). Builds never generate one.

The first thing to use it is a set of session helpers in `nuxt/server` ([#36358](https://github.com/nuxt/nuxt/pull/36358)). Sessions are sealed into a cookie with [iron](https://github.com/brc-dd/iron-webcrypto), so there's no server-side storage to configure:

```ts [server/api/visits.ts]
import { defineEventHandler, useSession } from 'nuxt/server'

export default defineEventHandler(async (event) => {
  const session = await useSession<{ visits: number }>(event)
  await session.update(data => ({ visits: (data.visits ?? 0) + 1 }))
  return { visits: session.data.visits }
})
```

> [!NOTE]
> As a reminder, runtime config keys prefixed with `app` (`runtimeConfig.app`, `runtimeConfig.appSecret`) are reserved for Nuxt.

### 🎯 Typed `$fetch`, rebuilt

`$fetch` and `useFetch` have been typed from your server routes for a long time. But the types were derived from Nitro's `InternalApi` interface, and past a few hundred routes they hit TypeScript's instantiation limit with the familiar `TS2589: Type instantiation is excessively deep and possibly infinite`.

We've rebuilt typed fetch on top of [`fetchdts`](https://github.com/danielroe/fetchdts) ([#36238](https://github.com/nuxt/nuxt/pull/36238)). Nuxt compiles your server routes into a route tree with an exact-match table for static paths and accessors specialised to your route set. Resolution cost now scales with call sites, not with route count:

| routes | before | after |
| - | - | - |
| 100 | 1,397,361 instantiations / 0.77s | 51,558 / 0.26s |
| 300 | 5,774,425 / 3.49s (`TS2589`) | 51,558 / 0.16s |
| 1000 | 12,831,467 / 7.44s (`TS2589`) | 51,558 / 0.20s |
| 3000 (200 call sites) | 71,875,148 / 53.63s (`TS2589`) | 101,678 / 0.62s |

Peak memory for the same runs dropped from 946 MB to 140 MB. 🔥

Plus, the route set also carries the `body`, `query` and `headers` a handler validates, so calls are checked more tightly than before:

```ts
// server/api/users.post.ts validates { title: string, count: number }
await $fetch('/api/users', { method: 'post', body: { title: 'a', count: 1 } })
await $fetch('/api/users', { method: 'post', body: { title: 'a', count: 'no' } })
//                                                                ^ not assignable to number
await $fetch('/api/users', { method: 'post' })
//           ^ body is required
```

On Nuxt 4 this is opt-in, because there are small changes to type inference, and hand-written `ServerRoutes` augmentations need a small rewrite. It is the default in Nuxt 5.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  experimental: {
    routeTypedFetch: true,
  },
})
```

There's also a new `experimental.strictRouteTypes` option to reject calls to paths that don't exist (otherwise these just return `unknown`), and an `'isomorphic'` mode that types your pages as `GET` routes too if you want to be able to `$fetch` from the Vue renderer with type safety.

👉 Read more in the [experimental features docs](https://nuxt.com/docs/guide/going-further/experimental-features#routetypedfetch).

### 🐛 Better errors in development with `my-bad`

Server-side errors in development used to look like this:

```
ReferenceError: foo is not defined
    at Object.<anonymous> (/_nuxt/app/pages/index.vue:1:1)
```

There was no source position or code frame, and the Youch iframe we rendered could not show you the frame in your own source either. Both are now fixed ([#36258](https://github.com/nuxt/nuxt/pull/36258), [nuxt/cli#1518](https://github.com/nuxt/cli/pull/1518)).

Dev SSR stack traces are now mapped before anything reads the error, and the Youch overlay has been replaced with [`my-bad`](https://github.com/danielroe/my-bad). It renders into your app's own error page as an overlay (or as a standalone page when the app can't render one), with the mapped stack trace and a code frame from your source, and the same report is printed in your terminal. We are still working with [@atinux](https://github.com/atinux), [@HugoRCD](https://github.com/HugoRCD) and [@antfu](https://github.com/antfu) to make these pages nicer still.

<img width="3200" height="2000" alt="my-bad-ssr-expanded-dark" src="https://github.com/user-attachments/assets/dc460902-117e-4b64-881c-1f0c80f05cbd" />
<img width="3200" height="2000" alt="my-bad-ssr-copymenu-dark" src="https://github.com/user-attachments/assets/5516ae18-09bc-4b88-a692-6f910b8b4ed6" />

With Nuxt CLI v4, there is a single live error channel at the CLI level. It survives worker restarts, so (for example) a syntax error in `nuxt.config.ts` will live-reload the page once you fix it. Each error is rendered once rather than at every layer it passes through, and the same channel streams build progress and app logs to the dev panel.

<!-- TODO: record video of fixing a syntax error in nuxt.config.ts and watch the error page live-reload -->

### 🎨 A new loading screen, 404 and error pages

[@HugoRCD](https://github.com/HugoRCD) has redrawn the loading screen you see while the dev server starts. It is now a WebGL2 particle field that traces a mountain range behind the Nuxt lockup ([#36178](https://github.com/nuxt/nuxt/pull/36178)), using a single shader and a single draw call. Without WebGL2 it falls back to the static lockup, and with `prefers-reduced-motion` the animation stops. Try hovering over it. 🏔️


<!-- VIDEO: release-assets/loading-screen-{dark,light}.mp4 (14s, cold start into app); stills: release-assets/loading-screen-{dark,light}.png -->

Hugo also gave the built-in 404 and error pages a neutral palette and lighter type ([#36255](https://github.com/nuxt/nuxt/pull/36255)), and [@MirkoJa](https://github.com/MirkoJa) added a back button to the 404 page ([#35688](https://github.com/nuxt/nuxt/pull/35688)).

<img width="3200" height="2000" alt="404-page-dark" src="https://github.com/user-attachments/assets/3070c5ac-8ade-4826-8479-ebea88fa8092" />

<!-- SCREENSHOT: release-assets/mac/404-page-{dark,light}.png and release-assets/error-page-prod-{dark,light}.png -->

### ⚡️ Vue Vapor support

Nuxt now supports Vue 3.6's [Vapor Mode](https://github.com/vuejs/core/releases/tag/v3.6.0-rc.1#about-vapor-mode) in interop mode ([#35759](https://github.com/nuxt/nuxt/pull/35759)). Your app root stays on the virtual DOM, and you can opt individual components or pages into Vapor by adding the `vapor` attribute to `<script setup>`:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  vue: {
    vapor: true,
  },
})
```

```vue [app/pages/index.vue]
<script setup vapor lang="ts">
const count = ref(0)
</script>

<template>
  <button @click="count++">
    count is {{ count }}
  </button>
</template>
```

Routing, `useAsyncData`, layouts and most built-in components keep working unchanged. Along the way we made the auto-import loader, `useAsyncData`, `definePageMeta` and slot inspection Vapor-aware, and we now have a Vapor test suite so we can track what's supported.

> [!NOTE]
> This requires Vue `^3.6.0-rc.2` or newer. See the [known limitations](https://nuxt.com/docs/guide/concepts/vuejs-development#known-limitations) and try it in a fresh project first.

### 🧩 Addons for `useFetch` and `useAsyncData`

[@cernymatej](https://github.com/cernymatej) has added an `addons` option to the `createUseFetch` and `createUseAsyncData` factories ([#35797](https://github.com/nuxt/nuxt/pull/35797)). An addon can declare custom call-site options, adjust the merged options, wrap the handler with middleware, and extend what the composable returns, and it can be reused across as many custom instances as you like.

```ts [app/composables/useApiFetch.ts]
const refreshOnFocus = defineUseFetchAddon({
  setup: (options: UseFetchAddonOptions<{ refreshOnFocus?: boolean }>) => {
    if (import.meta.server || !options.refreshOnFocus) { return }

    return (asyncData) => {
      const focused = useWindowFocus()
      watch(focused, focused => focused && asyncData.refresh())
      return { focused }
    }
  },
})

export const useApiFetch = createUseFetch({ baseURL: '/api', addons: [refreshOnFocus] })
```

```vue [app/pages/todos.vue]
<script setup lang="ts">
const { data, focused } = await useApiFetch('/todos', { refreshOnFocus: true })
</script>
```

This resolves a long list of feature requests for `useAsyncData` and `useFetch` (refresh on focus, polling, retries, auth headers and more) without making the core composables opinionated about any of them.

👉 Read about [`defineUseFetchAddon`](https://nuxt.com/docs/api/utils/define-use-fetch-addon) and [`defineUseAsyncDataAddon`](https://nuxt.com/docs/api/utils/define-use-async-data-addon).

### 🚀 Performance

There is a lot of performance work in this release.

- **`<NuxtLink>` renders 58% faster on the server** ([#36015](https://github.com/nuxt/nuxt/pull/36015)). Internal links are now rendered as a plain `<a>` with no `useLink`, no computed and no reactive state. Rendering 200 links went from 1.36ms to 0.57ms, which is 1.4x faster than a bare `<RouterLink>`.
- **Early 404s** ([#36117](https://github.com/nuxt/nuxt/pull/36117)). With `experimental.early404`, page routes are compiled into a static matcher at build time and requests that can't match any page skip creating the Vue app, running plugins and middleware entirely. On an app with 30 pages and ~23ms of boot work per render, a JSON 404 went from 37.1ms to 0.3ms.
- **Templates declare their dependencies** ([#35875](https://github.com/nuxt/nuxt/pull/35875)). The virtual file templates used in Nuxt's build used to regenerate on every file change. They now declare what invalidates them, so editing a component regenerates 0 of 49 core templates instead of all of them, and the `builder:watch` hook settles in 0.6ms instead of 36ms.
- **Cookie jars** ([#36114](https://github.com/nuxt/nuxt/pull/36114)). `useCookie` parses the cookie header once per request (or once per microtask on the client) instead of on every call. A nice side effect: a cookie set in a plugin during SSR can now be read by a later `useCookie` in a page.
- **`ssr: false` pages are tree-shaken from the server bundle** ([#35836](https://github.com/nuxt/nuxt/pull/35836), thanks to [@Austin1serb](https://github.com/Austin1serb)).
- **Serializable `definePageMeta` keys are extracted at build time** ([#35919](https://github.com/nuxt/nuxt/pull/35919)), behind `experimental.extractSerializablePageMeta`.
- **Faster dev server warm-up**: Vite's server module graph is warmed before the client ([#36154](https://github.com/nuxt/nuxt/pull/36154)), the client graph is crawled during warm-up ([#35870](https://github.com/nuxt/nuxt/pull/35870)), and warm-up yields to your first navigation so it never competes with a real request ([#36412](https://github.com/nuxt/nuxt/pull/36412)).
- **Smaller client bundle**: `unctx` is no longer shipped to the browser and `defu` is skipped for a single `app.config` ([#36371](https://github.com/nuxt/nuxt/pull/36371)).
- **Fewer dependencies**: `@nuxt/kit` no longer depends on `c12`, `untyped`, `confbox`, `pkg-types`, `ufo` or `mlly`, and `jiti` and `giget` are now optional peers loaded only when needed ([#35936](https://github.com/nuxt/nuxt/pull/35936), [#35943](https://github.com/nuxt/nuxt/pull/35943), [#35946](https://github.com/nuxt/nuxt/pull/35946), [#36071](https://github.com/nuxt/nuxt/pull/36071), [#36073](https://github.com/nuxt/nuxt/pull/36073), [#36083](https://github.com/nuxt/nuxt/pull/36083)).
- Lazy impound tracing for builds ([#36172](https://github.com/nuxt/nuxt/pull/36172)), virtual module hooks filtered by id ([#36077](https://github.com/nuxt/nuxt/pull/36077)), `isVue` checks migrated to plugin filters ([#36116](https://github.com/nuxt/nuxt/pull/36116)) and an `flru` prerender cache ([#36340](https://github.com/nuxt/nuxt/pull/36340)).

Put together, on our benchmark machine (arm64 Linux, Node 24.15, medians of 5 runs):

| | v4.5.2 | v4.6.0 | |
| --- | --- | --- | --- |
| `@nuxt/kit` install size | 6.4 MB | 2.1 MB | **-67%** |
| `@nuxt/kit` transitive dependencies | 36 | 22 | **-39%** |
| `nuxt build`, starter | 4.4 s | 3.6 s | **-18%** |
| `nuxt build`, 200 pages / 200 components / 50 routes | 11.6 s | 10.3 s | **-11%** |
| SSR throughput, page with 300 `<NuxtLink>`s | 110 req/s | 140 req/s | **+26%** |

Dev server start-up (spawn to first HTML) on the same machine is about 12% faster on a starter app, with the second request served in roughly half the time, though the CLI major changed alongside so not all of that is Nuxt.

### 📦 Lighter payloads

`useAsyncData` and `useFetch` accept a `serialize: false` option to keep data out of the `__NUXT_DATA__` payload ([#35779](https://github.com/nuxt/nuxt/pull/35779)). That's most useful inside components that never hydrate, and `experimental.stripNeverHydratedData` applies it automatically to data fetched within `hydrate-never` component trees.

Nuxt also warns in development when a page's payload exceeds 100 kB ([#35777](https://github.com/nuxt/nuxt/pull/35777)) and when a route rendered with `noScripts` relies on client-side JavaScript ([#35780](https://github.com/nuxt/nuxt/pull/35780)), and `noScripts` pages keep their non-script resource hints and attach their styles correctly ([#35803](https://github.com/nuxt/nuxt/pull/35803), [#36356](https://github.com/nuxt/nuxt/pull/36356), [#36359](https://github.com/nuxt/nuxt/pull/36359)).

`<NuxtLink>` now prefetches server-page islands ([#35808](https://github.com/nuxt/nuxt/pull/35808)), and [@atinux](https://github.com/atinux) made prefetch hints throttled and prioritised so a page full of links doesn't flood the network ([#36261](https://github.com/nuxt/nuxt/pull/36261), [#36324](https://github.com/nuxt/nuxt/pull/36324)). Building on that, route chunks, layouts, middleware, payloads, islands and resource hints all now go through one client prefetch scheduler with per-kind concurrency caps, deduplication by key, and cancellation of in-flight work when you navigate away ([#36391](https://github.com/nuxt/nuxt/pull/36391)).

### 🔮 Nuxt 5 features, today

Most of what's new in Nuxt 5 is already in 4.6, either as the default or behind a flag. `future.compatibilityVersion: 5` turns on the Nuxt 5 defaults in one go, and every one of them can be enabled (or disabled) individually.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  future: {
    compatibilityVersion: 5,
  },
})
```

Newly gated behind the flag in this release:

- **Typed pages** (`experimental.typedPages`) ([#35789](https://github.com/nuxt/nuxt/pull/35789))
- **Typed `$fetch`** (`experimental.routeTypedFetch`), described above
- **Case-sensitive routing**, matching Nitro ([#35650](https://github.com/nuxt/nuxt/pull/35650), thanks to [@Mateleo](https://github.com/Mateleo))
- **Early return from `navigateTo`** (`experimental.navigateToEarlyReturn`): `navigateTo` in `<script setup>` short-circuits the rest of the setup, so redirects and 404s don't throw on missing data ([#36115](https://github.com/nuxt/nuxt/pull/36115))
- **Serializable page meta extraction** (`experimental.extractSerializablePageMeta`)
- **Client-side payload extraction** (`experimental.payloadExtraction: 'client'`)
- **Normalized page names**, `clearNuxtState` resetting to defaults, `experimental.watcher: 'builder'`, and no auto-imported server-only head composables
- **No `baseUrl` in generated tsconfigs** ([#36040](https://github.com/nuxt/nuxt/pull/36040), thanks to [@oritwoen](https://github.com/oritwoen))
- **Inline error rendering** (`experimental.inlineErrorRendering`): when a server render fails, `error.vue` is rendered in the same request with a plain try/catch, instead of re-entering the server over an internal request to `/__nuxt_error`. Headers and cookies the failed render had already set are kept, error renders no longer pass through Nitro middleware and route rules a second time, and `render:html` fires with the original event ([#36399](https://github.com/nuxt/nuxt/pull/36399)).

The upgrade guide now lists [exactly what the flag changes on Nuxt 4](https://nuxt.com/docs/getting-started/upgrade#testing-nuxt-5).

### 🧪 Experimental: `@nuxt/vite-server`

Since v4.2 `server.builder` has been configurable. This release adds a second server builder: `@nuxt/vite-server`. It builds a Nuxt app with Vite alone ([#36218](https://github.com/nuxt/nuxt/pull/36218), [#36279](https://github.com/nuxt/nuxt/pull/36279), [#36288](https://github.com/nuxt/nuxt/pull/36288)).

This is all you need to do to configure it.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  server: {
    builder: 'vite', // 'nitro' is the default
  },
})
```

It can produce a pure client SPA, a server-rendered app with a small Node entry, a web-standard `fetch` handler for platforms that provide the server (there are e2e examples for [Cloudflare Workers](https://developers.cloudflare.com/workers/vite-plugin/), [Netlify](https://github.com/netlify/framework-adapters/tree/main/packages/vite-plugin) and [universal deploy](https://github.com/universal-deploy/universal-deploy)), as well as fully static output with `nuxt generate`.

Right now, this helps keep Nuxt's code agnostic, enforce the contract behind `nuxt/server`, and to give Vite plugins that provide a deploy target something to build on. It does not have Nitro's full feature set (there is no storage, caching, tasks or server plugins), and we expect most apps to keep using Nitro. **Nitro remains the default.**

> [!WARNING]
> This is highly experimental and the API will change. `'nitro'` and `'vite'` are new shorthands for `@nuxt/nitro-server` and `@nuxt/vite-server`.

### 🛠️ Developer experience

- **Clickable file paths** in terminal output ([#35898](https://github.com/nuxt/nuxt/pull/35898)). Warnings that mention a file now link to it in your editor, at the line responsible where we know it.
- **IDE hover docs for built-in components** ([#35701](https://github.com/nuxt/nuxt/pull/35701)). Hovering a built-in component like `<NuxtLayout>` or `<NuxtLink>` in a template now shows a short description and a link to the docs. Thanks to [@Ibochkarev](https://github.com/Ibochkarev).
- **`app/types/` and `server/types/`** are included in the right tsconfig, so ambient types and augmentations placed there are picked up ([#35783](https://github.com/nuxt/nuxt/pull/35783), thanks to [@Flo0806](https://github.com/Flo0806), who also added an augmentable `NuxtPageMeta` for typing `NuxtPage.meta` in [#34816](https://github.com/nuxt/nuxt/pull/34816)).
- **Grouping folders in `components/`**: a `(group)/` folder is excluded from the component name ([#35699](https://github.com/nuxt/nuxt/pull/35699), thanks to [@abaza738](https://github.com/abaza738)).
- **Dynamic `expires` in `useCookie`**, accepting a function ([#35628](https://github.com/nuxt/nuxt/pull/35628), thanks to [@DarlanPrado](https://github.com/DarlanPrado)).
- **A warning when a `public/` file shadows an application route** ([#35674](https://github.com/nuxt/nuxt/pull/35674), thanks to [@Norbiros](https://github.com/Norbiros)).
- **Install hints use your package manager** ([#35871](https://github.com/nuxt/nuxt/pull/35871)).
- **Prerender your error pages** as real HTML (`404.html`, or any status codes you pass) with `experimental.prerenderErrorPages` instead of an empty SPA shell ([#35193](https://github.com/nuxt/nuxt/pull/35193), thanks again to [@Flo0806](https://github.com/Flo0806)).
- `$Fetch` is exported from `nuxt/app` ([#35625](https://github.com/nuxt/nuxt/pull/35625)) and `ShallowRef` is in the Vue auto-import preset ([#36266](https://github.com/nuxt/nuxt/pull/36266)), both from [@DamianGlowala](https://github.com/DamianGlowala); `preloadComponents` and the `NuxtIsland` `name` prop are typed ([#35775](https://github.com/nuxt/nuxt/pull/35775)), and `useLayout`, `useLoadingIndicator` and `useRequestHeader` are exported from `nuxt/app` ([#36033](https://github.com/nuxt/nuxt/pull/36033)).
- **`typescript.tsConfig` is now a shared baseline** for all four generated tsconfigs, with `appTsConfig` and `serverTsConfig` for per-context overrides ([#35697](https://github.com/nuxt/nuxt/pull/35697), thanks to [@chairulakmal](https://github.com/chairulakmal)).
- **Top-level `prerender` option**, an alias for `nitro.prerender` in the same way `runtimeConfig` and `routeRules` are top-level ([#32356](https://github.com/nuxt/nuxt/pull/32356)). Nuxt now also points you towards top-level options where they exist, since those work across server builders ([#36416](https://github.com/nuxt/nuxt/pull/36416)).
- **Links to `public/` files just work.** If the router has no route for a `<NuxtLink>` target (a PDF in `public/`, say, or a link from Markdown with Nuxt Content), Nuxt falls through to a full-page load instead of rendering your 404, so `external` is no longer required ([#36169](https://github.com/nuxt/nuxt/pull/36169)).
- **Renaming a component in development refreshes its imports**, so you no longer see stale references to the old file ([#36165](https://github.com/nuxt/nuxt/pull/36165), thanks to [@oritwoen](https://github.com/oritwoen)).
- **Layers**: dependencies of layers installed from `node_modules` are pre-bundled by Vite ([#36208](https://github.com/nuxt/nuxt/pull/36208)), and symlinked layer directories resolve to their real path ([#36402](https://github.com/nuxt/nuxt/pull/36402), thanks to [@silverbackdan](https://github.com/silverbackdan)).

### 🧰 For module authors

If you maintain a module with server code, we've enabled making modules compatible with both Nuxt 4 & 5, without requiring a major bump. (And we'll be opening PRs proactively after the release of Nuxt v4.6 to assist with preparing for a Nuxt v5 release...)

- **One module for Nuxt 4 and Nuxt 5.** `addServerHandler`, `addDevServerHandler` and `addNitroPlugin` accept a map of variants per server API ([#36317](https://github.com/nuxt/nuxt/pull/36317)). Nuxt chooses the most appropriate one. A handler that imports only from `nuxt/server` needs no Nitro 2/3 variants at all (but does require Nuxt v4.6+).

  ```ts [module.ts]
  addServerHandler({
    route: '/api/my-module/status',
    handler: {
      nuxt: resolve('./runtime/server/status'),
      nitro2: resolve('./runtime/server/status.legacy'),
    },
  })
  ```

  Nuxt reads the file's imports to decide which API it uses. Where that isn't enough, you can declare `meta.compatibility.server`. `getNitroVersion` and `hasNitroVersion` are also there in case you have logic that _explicitly_ requires you to know the Nitro version installed ([#36127](https://github.com/nuxt/nuxt/pull/36127)).

  👉 Read the [server compatibility guide](https://nuxt.com/docs/guide/modules/server-compatibility) for more information.

- **Nuxt-owned, augmentable server types**: `ServerTypes`, `ServerRoutes`, `AppRouteRules` and `NuxtRequestContext`. Augment `@nuxt/schema` once; `nuxt/schema` mirrors it ([#36293](https://github.com/nuxt/nuxt/pull/36293)).
- **`useTerminal`** for host-aware prompts, status messages and tasks in progress, rendered by the CLI's dev panel when there is one ([#36162](https://github.com/nuxt/nuxt/pull/36162)).
- **`module:before` and `module:done` hooks**, which Nuxt CLI v4 uses to show per-module setup time as it happens ([#36173](https://github.com/nuxt/nuxt/pull/36173)).
- **`onConfigResolved` and `diffNuxtConfig`** to see what changed between two config loads ([#35853](https://github.com/nuxt/nuxt/pull/35853)).
- **`ensureDependencyInstalled` and `getAddDependencyCommand`** to check for and offer to install optional dependencies with the user's package manager ([#34554](https://github.com/nuxt/nuxt/pull/34554)).
- **Template `dependencies`** to say exactly what should invalidate a template ([#35875](https://github.com/nuxt/nuxt/pull/35875)).
- **`addServerImports`, `addServerImportsDir` and `addServerTemplate`** work the same across Nitro versions; a server tsconfig and versioned route config types are generated for you ([#36265](https://github.com/nuxt/nuxt/pull/36265)).
- **`@nuxt/kit` has an explicit public API** ([#36074](https://github.com/nuxt/nuxt/pull/36074)) and `@nuxt/schema` is an optional peer ([#36246](https://github.com/nuxt/nuxt/pull/36246)).
- Modules can now set `experimental.asyncContext` ([#36175](https://github.com/nuxt/nuxt/pull/36175), thanks to [@cernymatej](https://github.com/cernymatej)), Vite plugins added via kit land at the top level rather than wrapped ([#36037](https://github.com/nuxt/nuxt/pull/36037)), and more build-time warnings have moved to [diagnostic codes](https://nuxt.com/docs/errors) with docs pages ([#36138](https://github.com/nuxt/nuxt/pull/36138)).
- `@nuxt/kit` peer dependency ranges are widened to the versions actually required rather than tracking the latest of each package ([#36417](https://github.com/nuxt/nuxt/pull/36417)), and `updateRuntimeConfig` no longer warns when called before Nitro exists ([#36403](https://github.com/nuxt/nuxt/pull/36403), thanks to [@Neekoras](https://github.com/Neekoras)).

### 🔒 Security

- The internal error route is only served to an error render, and can no longer be reached from outside ([259058cf4](https://github.com/nuxt/nuxt/commit/259058cf4), [#36305](https://github.com/nuxt/nuxt/pull/36305)).
- Dev error reports are scoped for remote peers, and the dev error channel is kept out of production builds ([#36389](https://github.com/nuxt/nuxt/pull/36389), [#36407](https://github.com/nuxt/nuxt/pull/36407)).
- Unhandled error data is no longer passed to the error page ([38a40cfc0](https://github.com/nuxt/nuxt/commit/38a40cfc0)), oversized island bodies are drained before being rejected ([#36320](https://github.com/nuxt/nuxt/pull/36320)), and error-render recursion is tracked in request context rather than via a client-controllable header ([d8c729435](https://github.com/nuxt/nuxt/commit/d8c729435)).

### 🩹 Important fixes

- Awaited `useAsyncData` no longer resolves with unfetched data on hydration ([#36124](https://github.com/nuxt/nuxt/pull/36124)), awaited lazy async data resolves immediately ([#36301](https://github.com/nuxt/nuxt/pull/36301)), and `useAsyncData` types resolve for generic type params ([#36316](https://github.com/nuxt/nuxt/pull/36316)).
- `useRequestFetch` forwards request headers ([#36180](https://github.com/nuxt/nuxt/pull/36180), thanks to [@hdwebpros](https://github.com/hdwebpros)).
- `navigateTo` matches vue-router's path encoding ([#36055](https://github.com/nuxt/nuxt/pull/36055)), preserves percent-encoding in server redirects ([#36112](https://github.com/nuxt/nuxt/pull/36112)), and applies `baseURL` with `open` ([#36197](https://github.com/nuxt/nuxt/pull/36197)).
- Scoped styles apply to server component slots ([#36047](https://github.com/nuxt/nuxt/pull/36047)), island asset requests are deduped ([#36048](https://github.com/nuxt/nuxt/pull/36048)), lazy hydration no longer produces blank remounts ([#36051](https://github.com/nuxt/nuxt/pull/36051)), all from [@oritwoen](https://github.com/oritwoen), and hydrated `nuxt-client` markup is stripped from cached island HTML ([#36298](https://github.com/nuxt/nuxt/pull/36298)).
- A batch of CSS fixes across Vite, webpack and rspack: duplicate CSS links for inlined chunks ([#36056](https://github.com/nuxt/nuxt/pull/36056)), `baseURL` and `url()` rewriting in inlined styles ([#36137](https://github.com/nuxt/nuxt/pull/36137), [#36143](https://github.com/nuxt/nuxt/pull/36143)), island descendant CSS extraction ([#36260](https://github.com/nuxt/nuxt/pull/36260)) and stable style chunk names ([#36361](https://github.com/nuxt/nuxt/pull/36361)).
- View transitions handle interrupted and skipped navigations ([#35537](https://github.com/nuxt/nuxt/pull/35537) from [@Askerka00](https://github.com/Askerka00), [#36314](https://github.com/nuxt/nuxt/pull/36314)), and page transitions stay mounted for nested routes with no children ([#36304](https://github.com/nuxt/nuxt/pull/36304)).
- The streaming shell head renders after the first render pass ([#36120](https://github.com/nuxt/nuxt/pull/36120)).
- Payload URLs are parsed as origin-relative paths, so a path like `//x/_payload.json` no longer serves the wrong payload ([#36409](https://github.com/nuxt/nuxt/pull/36409), spotted by [@Kushalkhemka](https://github.com/Kushalkhemka)).
- `/index.html` is prerendered for client-only apps with islands ([#36299](https://github.com/nuxt/nuxt/pull/36299)).
- `definePageMeta` works at the top level of `setup()` ([#36245](https://github.com/nuxt/nuxt/pull/36245)), and changed auto-import sources are rescanned before their consumers ([#33671](https://github.com/nuxt/nuxt/pull/33671), thanks to [@Flo0806](https://github.com/Flo0806)).
- A template that never finishes compiling now fails the build instead of exiting 0 ([#36322](https://github.com/nuxt/nuxt/pull/36322)).
- Error causes are preserved in development ([#35632](https://github.com/nuxt/nuxt/pull/35632), thanks to [@onmax](https://github.com/onmax)).
- Layout `onBeforeLeave` reuses the pending transition promise ([#36395](https://github.com/nuxt/nuxt/pull/36395)), and `baseURL` and middleware flags are respected in apps without `pages/` ([#36034](https://github.com/nuxt/nuxt/pull/36034)).
- `stripNeverHydratedData` no longer mutates the options object ([#36035](https://github.com/nuxt/nuxt/pull/36035)), the dev error module is stubbed out of production builds ([55e61d75d](https://github.com/nuxt/nuxt/commit/55e61d75d)), and preloading a component that is not global now warns ([47de80ece](https://github.com/nuxt/nuxt/commit/47de80ece)).

### ✅ Upgrading

Our recommendation for upgrading is to run:

```sh
npx nuxt upgrade --dedupe
```

This will refresh your lockfile and pull in all the latest dependencies that Nuxt relies on, including Nuxt CLI v4.

> [!NOTE]
> This release requires Node.js `^22.22.3 || ^24.15.0 || >=26.0.0`.

If you have server code you'd like to make portable, read [Moving to `nuxt/server`](https://nuxt.com/docs/getting-started/upgrade#moving-to-nuxtserver) in the upgrade guide.


## 👉 Changelog

[compare changes](https://github.com/nuxt/nuxt/compare/v3.21.11...v4.6.0)

### 🚀 Enhancements

- **kit:** add `resolveServerVariant` + `addServerImports` variant support (#36445)
- **nuxt:** add addon support to `createUseFetch` and `createUseAsyncData` (#35797)
- **vite-server:** back `serverFetch` and route rules in `nuxt/server` ([`2386a5b6a`](https://github.com/nuxt/nuxt/commit/2386a5b6a))
- **nuxt,nitro,schema:** add `useServerHooks` to `nuxt/server` ([`e003cd46d`](https://github.com/nuxt/nuxt/commit/e003cd46d))
- **nuxt,nitro:** add `serverFetch` to `nuxt/server` ([`d14e82bc2`](https://github.com/nuxt/nuxt/commit/d14e82bc2))
- **nuxt,nitro:** add forwarded url, cookie and route rule helpers to `nuxt/server` ([`92c15e581`](https://github.com/nuxt/nuxt/commit/92c15e581))
- **nuxt,vite:** add `hook`, `bundler` and `middleware` tracing channels (#36423)
- **nuxt:** serve unmatched public asset paths on client-side navigation (#36169)
- **nuxt,schema:** add top-level `prerender` alias for `nitro.prerender` (#32356)
- **nuxt,vite-server:** render the error page in the renderer itself (#36399)
- **nuxt:** unified client prefetch scheduler (#36391)
- **nuxt:** add `useAppConfig` to `nuxt/server` ([`083b44ee4`](https://github.com/nuxt/nuxt/commit/083b44ee4))
- **nuxt:** add `handleCors` to `nuxt/server` ([`f2c93dbfc`](https://github.com/nuxt/nuxt/commit/f2c93dbfc))
- **nuxt:** add `readValidatedBody` and `getValidatedQuery` to `nuxt/server` ([`c8343d7a4`](https://github.com/nuxt/nuxt/commit/c8343d7a4))
- **nuxt:** add `getRouterParam(s)` and `getRequestIP` to `nuxt/server` ([`158901fde`](https://github.com/nuxt/nuxt/commit/158901fde))
- **nuxt,nitro,vite,vite-server:** scope dev error reports for remote peers (#36389)
- **nitro,vite:** map dev ssr stacktraces and render errors with  `my-bad` (#36258)
- **ui-templates:** use neutral palette and lighter error type (#36255)
- **ui-templates:** particle mountain loading screen (#36178)
- **nuxt:** add session utils to `nuxt/server` (#36358)
- **nuxt,schema:** add nuxt `appSecret` (#35874)
- **nuxt:** add server + client cookie jars to avoid unnecessary reads (#36114)
- **kit,nitro,schema:** register server handlers and plugins per server API (#36317)
- **nuxt,nitro,vite-server:** compile nuxt core route rules (#36307)
- **vite-server:** support `nuxt generate` prerendering (#36288)
- **kit,schema,vite-server:** render in a target's own env (+ add e2e tests) (#36279)
- **nuxt,schema:** give `nuxt/server` handlers a portable event ([`5bf478b8c`](https://github.com/nuxt/nuxt/commit/5bf478b8c))
- **nuxt,kit,schema,nitro,vite-server:** add `nuxt/server` (#36275)
- **kit:** add a server tsconfig and versioned nitro route config types (#36265)
- **nuxt:** add `ShallowRef` type to vue preset (#36266)
- **nuxt:** type `$fetch` and `useFetch` from generated server routes (#36238)
- **kit,nuxt,vite,vite-server:** add experimental pure vite server (#36218)
- **kit,schema:** add `module:before`/`module:done` hooks (#36173)
- **kit:** add `useTerminal` for host-aware prompts and tasks (#36162)
- **nuxt:** add experimental early404 for unmatched page routes (#36117)
- **nuxt:** add experimental early return after `navigateTo` (#36115)
- **kit:** nitro version utils + version-tagged server utils (#36127)
- **nuxt:** support vue vapor (#35759)
- **nitro:** allow prerendering error page (#35193)
- **nuxt:** use @nuxt/cli v4 prerelease (#35981)
- **nitro,nuxt:** improvements when rendering with `noScripts` (#35803)
- **kit,nitro,nuxt,rspack,vite,webpack:** use package manager in hints (#35871)
- **nuxt:** make file names clickable 🖱️ (#35898)
- **nitro:** warn in dev when noScripts routes rely on client JS (#35780)
- **nitro,nuxt,schema:** let templates declare dependencies (#35875)
- **nuxt:** prefetch server page islands via `<NuxtLink>` (#35808)
- **kit:** expose resolved config snapshot and diff helper (#35853)
- **nitro:** warn in dev when payload exceeds 100 kB (#35777)
- **nuxt,nitro:** auto-import types from `app/types` and `server/types` directories (#35783)
- **nuxt:** type `preloadComponents` and `NuxtIsland` name (#35775)
- **schema:** enable `typedPages` with `compatibilityVersion: 5` (#35789)
- **nuxt:** add `serialize` option to keep async data out of payload (#35779)
- **ui-templates:** add back button on 404 page (#35688)
- **kit:** easier way to define global `tsConfig` options (#35697)
- **nuxt:** log template write paths when debugging (#35686)
- **nuxt:** export `$Fetch` type (#35625)
- **nuxt:** add IDE hover docs for built-in components (#35701)
- **nuxt:** support grouping folders in component directories (#35699)
- **schema:** add augmentable `NuxtPageMeta` interface for `NuxtPage.meta` (#34816)
- **nuxt:** warn when public files override application routes (#35674)
- **nuxt:** support dynamic `expires` in `useCookie` (#35628)
- **schema:** case-sensitive routing by default in v5 (#35650)

### 🔥 Performance

- **kit:** use `package-manager-detector` to install packages (#36434)
- **vite:** stop serial-build warmup on first navigation ([`04f319837`](https://github.com/nuxt/nuxt/commit/04f319837))
- **vite:** evaluate ssr entry before the first dev render ([`2da76d248`](https://github.com/nuxt/nuxt/commit/2da76d248))
- **vite-server:** index public files only once (#36373)
- **nuxt:** drop `unctx` from client environment (+ `defu` in single-object config) (#36371)
- **nitro:** use `flru` for prerender cache (#36340)
- **nitro,nuxt:** use lazy impound tracing for builds (#36172)
- **vite:** warm the server module graph before the client (#36154)
- **nuxt,vite:** migrate `isVue` calls into plugin filters (#36116)
- **kit:** remove `confbox` and `pkg-types` from dependencies (#36083)
- **nuxt:** filter virtual module load hooks by id (#36077)
- **kit:** drop `ufo` dependency (#36073)
- **kit:** use `microdiff` and `node:crypto` (#36071)
- **nuxt:** render internal `<NuxtLink>` anchors directly on server (#36015)
- **nuxt,kit:** avoid loading `jiti` unless it is needed (#35943)
- **nuxt:** tree-shake `ssr: false` pages from server bundle (#35836)
- **nuxt:** extract serializable `definePageMeta` keys at build time (#35919)
- **vite:** crawl client module graph when warming dev server (#35870)

### 🩹 Fixes

- **nuxt:** resolve anchor hrefs through the router (#36459)
- **nuxt:** leave a newer async data entry alone when an old one is taken off (#36436)
- **nuxt:** await async layouts before navigation (#36454)
- **nuxt,vite:** show compile error overlay on client-only pages (#36444)
- **schema,vite-server:** accept `null` from prerender ignore functions ([`6c36b5e39`](https://github.com/nuxt/nuxt/commit/6c36b5e39))
- **nuxt:** keep `CookieOptions` compatible with cookie serialize options ([`62ebbd909`](https://github.com/nuxt/nuxt/commit/62ebbd909))
- **kit:** point `NUXT_B1022` at resolving templates before bundling ([`3f269cb66`](https://github.com/nuxt/nuxt/commit/3f269cb66))
- **kit:** only write missing types when building into a relocated build dir ([`dfbab4f7c`](https://github.com/nuxt/nuxt/commit/dfbab4f7c))
- **kit,nuxt:** preserve types when building into a relocated build dir (#36418)
- **nuxt,nitro:** render html page errors + json server route errors (#36455)
- **nuxt,vite-server:** keep cookies + respond to json clients on errors (#36451)
- **vite,nitro:** rewrap console if build throws ([`aec739e93`](https://github.com/nuxt/nuxt/commit/aec739e93))
- **kit,nuxt:** provide `nuxt/internal/dev-error` as a server runtime module ([`a17d9dbc6`](https://github.com/nuxt/nuxt/commit/a17d9dbc6))
- **nuxt:** allow `@nuxt/cli` runtime imports in server runtime ([`e2eb0b5e3`](https://github.com/nuxt/nuxt/commit/e2eb0b5e3))
- **nuxt:** type nitro type path helper with `NitroConfig` ([`507002bb0`](https://github.com/nuxt/nuxt/commit/507002bb0))
- **nuxt:** refresh component imports after rename (#36165)
- **nuxt:** skip browser notices without error in dev overlay (#36415)
- **kit:** widen peer dependency ranges to supported versions (#36417)
- **schema:** deprecate `nitro.*` options duplicated at the top level (#36416)
- **vite:** pre-bundle deps of layers installed in `node_modules` (#36208)
- **nuxt:** respect base URL and clear middleware flags without `pages/` (#36034)\ (#36034)
- **nuxt,nitro:** stub dev error module in production builds ([`55e61d75d`](https://github.com/nuxt/nuxt/commit/55e61d75d))
- **nitro:** do not warn for public asset dirs generated in the build dir ([`61fdd921a`](https://github.com/nuxt/nuxt/commit/61fdd921a))
- **nuxt:** resolve `@nuxt/*` type paths from nuxt's own resolution ([`3796a4105`](https://github.com/nuxt/nuxt/commit/3796a4105))
- **nuxt:** warn when preloading a component that is not global ([`47de80ece`](https://github.com/nuxt/nuxt/commit/47de80ece))
- **nitro:** resolve nitro dependency types from the copies nitro uses ([`70bf7caf7`](https://github.com/nuxt/nuxt/commit/70bf7caf7))
- **nuxt:** avoid mutating options when stripping never-hydrated data (#36035)
- **kit:** do not warn when updateRuntimeConfig runs before nitro exists (#36403)
- **kit:** resolve symlinked layer directories to their real path (#36402)
- **nuxt:** reuse pending transition promise in layout `onBeforeLeave` (#36395)
- **vite:** keep named compile report over nameless hmr payload ([`98bc0a675`](https://github.com/nuxt/nuxt/commit/98bc0a675))
- **nuxt:** reject sealed values not issued by nuxt sessions (#36413)
- **nitro,vite:** sort prerendered routes in app manifest ([`d54d0c7db`](https://github.com/nuxt/nuxt/commit/d54d0c7db))
- **nuxt:** parse payload url as origin-relative path (#36409)
- **nitro:** explain when an h3 event reaches a nuxt/server helper ([`a973b058b`](https://github.com/nuxt/nuxt/commit/a973b058b))
- **nuxt:** invalidate auto-import consumers on the hmr-less ssr dev server ([`1718612ad`](https://github.com/nuxt/nuxt/commit/1718612ad))
- **nitro:** give the portable event's response headers the full `Headers` interface ([`9c3525f6a`](https://github.com/nuxt/nuxt/commit/9c3525f6a))
- **nuxt:** accept `Endpoint`-shaped `ServerRoutes` augmentations in the `InternalApi` engine ([`9d4d1edaf`](https://github.com/nuxt/nuxt/commit/9d4d1edaf))
- **nitro:** keep dev error channel out of production builds (#36407)
- **nuxt:** share client app context across module instances ([`984832f0a`](https://github.com/nuxt/nuxt/commit/984832f0a))
- **nitro:** resolve path placeholders in nitro preview command ([`71a61556d`](https://github.com/nuxt/nuxt/commit/71a61556d))
- **nitro:** extend nitropack runtime app config with nuxt fields ([`b0e1abf52`](https://github.com/nuxt/nuxt/commit/b0e1abf52))
- **nitro:** detect an http error by brand in the dev error handler ([`134256aa4`](https://github.com/nuxt/nuxt/commit/134256aa4))
- **nuxt:** explain nitro 2 env parsing when a derived secret is unusable ([`262d62e2c`](https://github.com/nuxt/nuxt/commit/262d62e2c))
- **nuxt:** prepend the vite unctx transform so it reaches page-meta macro modules ([`3a43e1d74`](https://github.com/nuxt/nuxt/commit/3a43e1d74))
- **nitro:** renumber duplicate NUXT_E8009 diagnostic code ([`70eabb790`](https://github.com/nuxt/nuxt/commit/70eabb790))
- **vite:** await `ssrFixStacktrace` (#36372)
- **vite:** keep deduped packages out of importer-based external resolution (#36363)
- **nuxt,vite:** attach resources to pages served without scripts (#36359)
- **vite:** share a style chunk-name counter across component extractions (#36361)
- **nuxt:** keep non-script resource hints on `noScripts` routes (#36356)
- **nuxt:** strip hydrated `nuxt-client` markup from cached island html (#36298)
- **nuxt:** widen `nuxt/server` helper event types (#36335)
- **nuxt:** keep a configured appSecret and warn when it is used ([`31b47404d`](https://github.com/nuxt/nuxt/commit/31b47404d))
- **nuxt:** keep session managers in step after `clearSession` ([`4ae850572`](https://github.com/nuxt/nuxt/commit/4ae850572))
- **nuxt:** use a throttle approach for hint prefetching (#36324)
- **kit:** normalise method case when checking for duplicates ([`d7a41e6dc`](https://github.com/nuxt/nuxt/commit/d7a41e6dc))
- **kit:** respect method when checking for existing handlers (#36329)
- **kit:** register the base path of a wildcard route on nitro v2 (#36325)
- **nitro:** render streaming shell head after first render pass (#36120)
- **vite:** skip client manifest finalisation for aborted builds (#36270)
- **nitro:** apply server replacements to prerenderer (#36311)
- **kit,nuxt,schema:** let a server build declare the module backing `fetch` ([`f61a5149b`](https://github.com/nuxt/nuxt/commit/f61a5149b))
- **kit,nitro:** follow host nitro major in server build runtime fallback ([`4418fdb2d`](https://github.com/nuxt/nuxt/commit/4418fdb2d))
- **nuxt:** apply nitro type paths in `prepare:types` in dev (#36244)
- **nuxt:** forward request headers with `useRequestFetch` (#36180)
- **nitro:** serve repeated reads of a `nuxt/server` request body ([`639960e90`](https://github.com/nuxt/nuxt/commit/639960e90))
- **nitro:** write registered server plugins into the nitro config ([`e47c43d33`](https://github.com/nuxt/nuxt/commit/e47c43d33))
- **nuxt:** resolve awaited lazy async data immediately (#36301)
- **nuxt:** resolve `useAsyncData` type for generic type params (#36316)
- **nitro:** drain oversized island body before rejecting it (#36320)
- **kit,nuxt:** fail the build when a template never finishes compiling (#36322)
- **nitro:** buffer the body read through a `nuxt/server` event ([`0fca34007`](https://github.com/nuxt/nuxt/commit/0fca34007))
- **nitro:** scan a layer's server utils before the project's ([`0d23fa357`](https://github.com/nuxt/nuxt/commit/0d23fa357))
- **nitro:** pass glob patterns to devStorage fs watch ignore (#36306)
- **nuxt:** keep view transition state for interrupting navigations (#36314)
- **nuxt:** handle rejected `ready` promise of skipped view transition (#35537)
- **nitro:** serve the internal error route only to an error render ([`259058cf4`](https://github.com/nuxt/nuxt/commit/259058cf4))
- **nitro:** guard internal error render on request context ([`d8c729435`](https://github.com/nuxt/nuxt/commit/d8c729435))
- **vite:** resolve bare ssr externals from their importer (#36309)
- **nitro,vite-server:** render `error.vue` 404 when accessing `/__nuxt_error` (#36305)
- **nuxt:** skip scanning page meta if the scanner cannot parse (#36297)
- **nitro:** prerender `/index.html` for client-only apps with islands (#36299)
- **nuxt:** keep page transition mounted for nested route with no children (#36304)
- **nuxt:** respect image prefetching as preload to respect Accept hea… (#36261)
- **nuxt:** listen to `link:prefetch` hook before onNuxtReady (#36271)
- **vite:** let the app build serve a server build that is not its own pass ([`dc160687a`](https://github.com/nuxt/nuxt/commit/dc160687a))
- **vite:** let a server build that is not its own pass reach the app entry ([`bf7a83e31`](https://github.com/nuxt/nuxt/commit/bf7a83e31))
- **nitro:** load `nitropack` in any program that augments it ([`5a8519004`](https://github.com/nuxt/nuxt/commit/5a8519004))
- **kit,nitro,schema:** derive the fallback server runtime from the host nitro major ([`85f372478`](https://github.com/nuxt/nuxt/commit/85f372478))
- **nitro:** do not pass unhandled error data to error page ([`38a40cfc0`](https://github.com/nuxt/nuxt/commit/38a40cfc0))
- **kit:** declare `@nuxt/schema` as an optional peer dependency (#36246)
- **kit,nuxt,schema,vite-server:** let vite plugins own the deploy target (#36233)
- **nuxt:** avoid app config declaration conflicts (#36053)
- **nuxt:** rescan changed auto-import sources before their consumers (#33671)
- **rspack,webpack:** do not serve server bundle from dev server ([`7e07e3050`](https://github.com/nuxt/nuxt/commit/7e07e3050))
- **vite:** extract css of island descendants when inlining is off (#36260)
- **kit:** explicitly include `.vue` and other extensions tsconfigs (#36253)
- **nuxt:** resolve layout hydration guard when unmounted early (#36252)
- **nuxt:** bound island v-for on nuxt-client elements without selectiveClient ([`0b7a3c61a`](https://github.com/nuxt/nuxt/commit/0b7a3c61a))
- **nuxt:** only rewrite island uid marker in attribute position ([`40ea3de58`](https://github.com/nuxt/nuxt/commit/40ea3de58))
- **nuxt:** serialize numeric v-for island slot scopes 1-based (#36230)
- **nuxt:** support `definePageMeta` at the top level of `setup()` (#36245)
- **nuxt:** make `target` optional if calling `navigateTo` w/ open (#36196)
- **vite:** exclude stable entry chunk from preload dependencies (#36198)
- **nuxt:** apply `baseURL` when calling `navigateTo` with `open` (#36197)
- **nuxt:** expose shallow async data ref (#36075)
- **nuxt:** ignore grouping folders when collapsing repeated name segments (#36195)
- **nuxt:** register namespace binding alongside default import (#36194)
- **nuxt:** keep extracted `__proto__` page meta keys as own properties (#36193)
- **nuxt:** disable early 404 for page paths that cannot be decoded (#36191)
- **nitro:** resolve aliases and rootDir-relative asset dirs (#36209)
- **nuxt:** key dynamic meta by file path + nuxt instance (#36188)
- **schema:** keep `nuxt/schema` augmentation bridge out of bundled types (#36186)
- **kit:** forward `configFile` and `rcFile` to config loader (#36185)
- **nuxt:** validate component export name before code generation (#36181)
- **nuxt:** allow modules to set `experimental.asyncContext` (#36175)
- **schema:** type `import.meta.env` as `ImportMetaEnv` ([`fd17d697e`](https://github.com/nuxt/nuxt/commit/fd17d697e))
- **kit,nitro,schema:** ensure tsconfigs exist before build (#34646)
- **schema,nuxt:** accept partial app config input + stop merging functions (#36158)
- **ui-templates:** mark the loading page's poll as a document request ([`8d6240a99`](https://github.com/nuxt/nuxt/commit/8d6240a99))
- **ui-templates:** back off the loading page's poll (#36147)
- **vite:** rewrite every public asset `url()` in CSS (#36143)
- **vite:** apply `baseURL` to public assets in inlined styles (#36137)
- **nuxt:** resolve layout name override in layout `isCurrent` check (#36132)
- **nuxt:** bridge `AppConfigInput` augmentations into `nuxt/schema` (#36128)
- **nuxt:** don't resolve awaited `useAsyncData` with unfetched data on hydration (#36124)
- **nuxt:** preserve percent-encoding in server `navigateTo` redirects (#36112)
- **nuxt:** preserve regexp and function values when cloning import presets ([`c099af61e`](https://github.com/nuxt/nuxt/commit/c099af61e))
- **nitro:** match exact nonce attribute for streaming CSP nonce ([`22682d782`](https://github.com/nuxt/nuxt/commit/22682d782))
- **nuxt:** pass absolute paths to build cache ignore check ([`625d9f50a`](https://github.com/nuxt/nuxt/commit/625d9f50a))
- **nitro:** preserve overlapping dynamic payload rules (#34717)
- **kit:** retry CJS-global and alias load failures through jiti (#36082)
- **rspack,webpack:** respect inlineStyles predicate for global css ([`d1d245bee`](https://github.com/nuxt/nuxt/commit/d1d245bee))
- **rspack,webpack:** do not search filesystem for postcss config ([`1ff282846`](https://github.com/nuxt/nuxt/commit/1ff282846))
- **rspack,webpack:** keep url() wrapper when rewriting inlined styles ([`09fd9a117`](https://github.com/nuxt/nuxt/commit/09fd9a117))
- **nuxt:** hide internal dynamic page meta key behind a symbol (#36081)
- **nuxt:** keep page bundle restrictions out of the pages array (#36080)
- **nuxt:** avoid duplicate island asset requests (#36048)
- **kit:** reorder diagnostics by code ([`540c9e772`](https://github.com/nuxt/nuxt/commit/540c9e772))
- **kit:** retry nested load failures through jiti (#36072)
- **nuxt:** keep `<NuxtTime>` locale prop reactive after hydration (#35923)
- **nuxt:** validate `scopeId` prop passed to `<NuxtIsland>` (#36064)
- **vite,nitro:** keep css links for unrendered components (#36060)
- **nuxt:** apply scoped styles to server component slots (#36047)
- **kit,nitro:** ignore baseUrl with compatibilityVersion 5 (#36040)
- **nitro:** in dev, only add css for islands actually rendered (#36057)
- **vite:** drop duplicate CSS links for fully inlined shared chunks (#36056)
- **nuxt:** match vue-router path encoding in `navigateTo` (#36055)
- **nuxt:** avoid blank lazy hydration remounts (#36051)
- **nuxt:** don't defer hydration route for trailing-slash-only diffs (#36050)
- **kit:** add vite plugins at top level instead of wrapping them (#36037)
- **nuxt:** keep ref-initialised `useState` connected to payload state (#36038)
- **nuxt:** only compute `distURL` in development (#36032)
- **nuxt:** export `useLayout`, `useLoadingIndicator` and `useRequestHeader` (#36033)
- **vite:** recover throttled watcher changes in dev servers ([`3d1087088`](https://github.com/nuxt/nuxt/commit/3d1087088))
- **nuxt:** only map test components for webpack and rspack ([`63f8ce22e`](https://github.com/nuxt/nuxt/commit/63f8ce22e))
- **nuxt,nitro:** unwrap route rule matches when resolving rules ([`67e1b8d94`](https://github.com/nuxt/nuxt/commit/67e1b8d94))
- **nuxt:** stub client-only components + map test components in server build (#36019)
- **nuxt:** do not write readonly cookies on client (#36014)
- **nuxt:** skip cookie watcher entirely when readonly (#35997)
- **nitro,nuxt:** hoist route matcher to prevent temporal dead zone (#36012)
- **nuxt:** resolve `ufo` from nuxt dependencies (#36010)
- **nitro:** resolve paths pointing at bare module specifiers (#36011)
- **nuxt:** preserve error causes in development (#35632)
- **nuxt:** improve js type-checking ([`5a003806e`](https://github.com/nuxt/nuxt/commit/5a003806e))

### 💅 Refactors

- **nuxt,nitro:** drop `toNuxtRequestEvent` from `nuxt/server` ([`cf00e7b9e`](https://github.com/nuxt/nuxt/commit/cf00e7b9e))
- **nuxt,nitro,vite-server:** share error handling between the renderer and server builders (#36398)
- **nuxt:** drop `setResponseHeader(s)` from `nuxt/server` ([`d4b0330f9`](https://github.com/nuxt/nuxt/commit/d4b0330f9))
- **nuxt:** own more of the public api for `nuxt/app` (#36368)
- **vite-server:** return meta-refresh body for `redirect` route rules ([`0f069152c`](https://github.com/nuxt/nuxt/commit/0f069152c))
- **schema,nuxt,nitro:** move server type declarations into schema (#36293)
- **nuxt,nitro:** let a server builder name the event the app sees ([`14c7b50df`](https://github.com/nuxt/nuxt/commit/14c7b50df))
- **nuxt,nitro,schema:** collect prerender hints in nuxt context (#36277)
- **nuxt,kit,nitro,vite,vite-server:** add server runtime record + vite ssr (#36274)
- **nuxt,nitro,nuxt,schema,vite:** extract ssr renderer (#36272)
- **kit,nitro:** pass the asset dir resolution order into NUXT_B7023 ([`0e032202c`](https://github.com/nuxt/nuxt/commit/0e032202c))
- **kit,nuxt,schema,vite:** decouple core from `@nuxt/nitro-server` (#36223)
- **nuxt,schema:** own typed `$fetch` types in nuxt (#36214)
- **nitro,nuxt,schema:** decouple `#app` from h3 types and runtime (#36212)
- **kit,schema,nitro:** resolve nitro types from server builder (#36171)
- **kit,nitro,nuxt,schema:** migrate more build-time warnings -> nostics (#36138)
- **kit:** inline minimal nitro v2/v3 types and drop nitro deps (#36125)
- **kit,schema:** explicitly define kit public api (#36074)
- **nuxt:** iterate over fragment children (#36041)
- **nuxt:** remove reverse trace indexing (#36044)
- **webpack:** replace pify with node promisify (#36042)
- remove `mlly` from dependencies (#35946)
- **kit:** inline c12 and untyped, make jiti/giget optional peers (#35936)
- **vite:** share dependency-install prompt via kit (#34554)
- **nuxt:** remove `config.cjs` file in `require` export (#35805)
- **nuxt:** use native vue pausable watcher for `useCookie` (#36006)

### 📖 Documentation

- complete `nuxt/server` migration + module guides ([`27a1d9d28`](https://github.com/nuxt/nuxt/commit/27a1d9d28))
- return streams directly (#36449)
- document typing runtime config and events in modules ([`776773f1c`](https://github.com/nuxt/nuxt/commit/776773f1c))
- document declared routes in createUseFetch ([`a624e4e47`](https://github.com/nuxt/nuxt/commit/a624e4e47))
- adjust spacing (#36262)
- add a guide for moving server code to nuxt/server ([`9730d7c0a`](https://github.com/nuxt/nuxt/commit/9730d7c0a))
- document the new `nuxt/server` helpers and what stays on nitro ([`5b51b07d6`](https://github.com/nuxt/nuxt/commit/5b51b07d6))
- document `typesDir` ([`4a0780dfe`](https://github.com/nuxt/nuxt/commit/4a0780dfe))
- list remaining `compatibilityVersion: 5` defaults in the 4.x upgrade guide ([`e9d5767b8`](https://github.com/nuxt/nuxt/commit/e9d5767b8))
- use `@since 4.6.0` for surfaces shipping in 4.x ([`e6fee2f42`](https://github.com/nuxt/nuxt/commit/e6fee2f42))
- link the 5.x upgrade guide by full url ([`fc8387a1a`](https://github.com/nuxt/nuxt/commit/fc8387a1a))
- clarify Nuxt collects prerender hints and route rules ([`e5e472743`](https://github.com/nuxt/nuxt/commit/e5e472743))
- reserve app-prefixed runtime config keys for nuxt ([`5ea634670`](https://github.com/nuxt/nuxt/commit/5ea634670))
- link to the 5.x upgrade guide rather than carrying it ([`c8f2d4b26`](https://github.com/nuxt/nuxt/commit/c8f2d4b26))
- document useRequestEvent return type ([`1212aa788`](https://github.com/nuxt/nuxt/commit/1212aa788))
- document `nuxt/server` and module server compatibility ([`94e2040fa`](https://github.com/nuxt/nuxt/commit/94e2040fa))
- document $Fetch type export ([`e69ab1b89`](https://github.com/nuxt/nuxt/commit/e69ab1b89))
- document island prefetching for server-only pages ([`9c154b6da`](https://github.com/nuxt/nuxt/commit/9c154b6da))
- document kit dependency helpers ([`09c9af7a2`](https://github.com/nuxt/nuxt/commit/09c9af7a2))
- document loadNuxtConfig options and diffNuxtConfig ([`2d32d994a`](https://github.com/nuxt/nuxt/commit/2d32d994a))
- change `<NuxtTime>` prop from 'date' to 'datetime' (#36341)
- strip version prefixes ([`897977f33`](https://github.com/nuxt/nuxt/commit/897977f33))
- explain `ssrStreaming.botRegex` in more detail ([`d810367b9`](https://github.com/nuxt/nuxt/commit/d810367b9))
- update testing guide to test-utils v4.2.0 (#36234)
- move CLI command reference to nuxt/cli (#36145)
- update mcp tools and mention `X-MCP-Tools` header (#36065)
- remove `nitro/h3` import from server types example ([`86c957f79`](https://github.com/nuxt/nuxt/commit/86c957f79))
- document reverse proxy path handling (#36069)
- fix typos and grammar issues (#36061)
- mention Valibot for server-side validation (#36045)
- add `test/` in directory structure (#35991)

### 📦 Build

- **ui-templates:** don't inline the `modulepreload` polyfill (#36247)

### 🏡 Chore

- update test `engines.node` ([`20069e45b`](https://github.com/nuxt/nuxt/commit/20069e45b))
- ignore local build output in knip ([`a925055b5`](https://github.com/nuxt/nuxt/commit/a925055b5))
- prepare root types before linting ([`e093be119`](https://github.com/nuxt/nuxt/commit/e093be119))
- **ui-templates:** share generated output paths ([`83ef10ac9`](https://github.com/nuxt/nuxt/commit/83ef10ac9))
- ignore generated output in knip ([`d26c50aad`](https://github.com/nuxt/nuxt/commit/d26c50aad))
- **ui-templates:** preview templates in a grid (#36257)
- update ui templates in precommit hook (#36383)
- force lf line endings for pnpm patch files ([`5380cbe37`](https://github.com/nuxt/nuxt/commit/5380cbe37))
- **kit,nitro,vite,vite-server:** move tests out of `src` ([`337fa63c0`](https://github.com/nuxt/nuxt/commit/337fa63c0))
- allow reviews (#36215)
- update link to vue policy ([`9e3f5f6b6`](https://github.com/nuxt/nuxt/commit/9e3f5f6b6))
- update security policy (#36248)
- bump @flakiness/vitest to 1.9.2 (#36176)
- migrate release pipeline to uppt (#36167)
- send test results to Flakiness.io dashboard (#36159)
- enable `minimumReleaseAgeExcludePrune` & `catalogPrune` (#36140)
- tweak guidance ([`86c3994ec`](https://github.com/nuxt/nuxt/commit/86c3994ec))
- add guidance for agents ([`84b495a64`](https://github.com/nuxt/nuxt/commit/84b495a64))
- exempt first-party packages from pnpm minimumReleaseAge (#36001)
- don't update nitro group until approved explicitly ([`1f0f3030a`](https://github.com/nuxt/nuxt/commit/1f0f3030a))

### ✅ Tests

- allow main-only nitro diagnostic ([`6c7f9fd47`](https://github.com/nuxt/nuxt/commit/6c7f9fd47))
- allow arbitrary component names in preload type test ([`a8716b9b2`](https://github.com/nuxt/nuxt/commit/a8716b9b2))
- wait for the error page to reload itself after a compile fix ([`5828109bc`](https://github.com/nuxt/nuxt/commit/5828109bc))
- wait for ladder payloads before promoting prefetch work ([`5d9d66216`](https://github.com/nuxt/nuxt/commit/5d9d66216))
- order forwarded hint payloads before asserting recency ([`a24dfe308`](https://github.com/nuxt/nuxt/commit/a24dfe308))
- wait for restored catch-all page before asserting ([`3271893e8`](https://github.com/nuxt/nuxt/commit/3271893e8))
- cover `nuxt/server` sessions end to end ([`ddde51e2e`](https://github.com/nuxt/nuxt/commit/ddde51e2e))
- require every `main` diagnostic code to exist on 4.x ([`c66f1a5e7`](https://github.com/nuxt/nuxt/commit/c66f1a5e7))
- tolerate rewording when comparing diagnostic codes across branches ([`9d862ea97`](https://github.com/nuxt/nuxt/commit/9d862ea97))
- cover foreign `HTTPError` in dev error handler ([`f2ddcb0ba`](https://github.com/nuxt/nuxt/commit/f2ddcb0ba))
- guard diagnostic codes against drift from `4.x` ([`4150664f1`](https://github.com/nuxt/nuxt/commit/4150664f1))
- cover `import.meta.test` guard in dev error handler ([`51e8a676d`](https://github.com/nuxt/nuxt/commit/51e8a676d))
- assert the nitro 2 parsing of the `appSecret` environment override ([`0da748765`](https://github.com/nuxt/nuxt/commit/0da748765))
- fail fast with vite error overlay contents in e2e navigation ([`14ad6961d`](https://github.com/nuxt/nuxt/commit/14ad6961d))
- give builder watcher suite room for cold start ([`43e1e64a3`](https://github.com/nuxt/nuxt/commit/43e1e64a3))
- wait for async state in watcher and middleware abort tests ([`ca21185ee`](https://github.com/nuxt/nuxt/commit/ca21185ee))
- add names for runtime config tests ([`7c68ff3db`](https://github.com/nuxt/nuxt/commit/7c68ff3db))
- add regression test for inline style order (#33041)
- guard the cost of resolving a typed `$fetch` call (#36254)
- isolate dev fixtures by worker (#35937)
- add tests for `head` option of `defineNuxtComponent` (#36251)
- add property tests for pure utilities (#36190)
- drop console logs from retried navigations and report their text ([`39e55ee68`](https://github.com/nuxt/nuxt/commit/39e55ee68))
- nest the island depth-guard body in json structure, not a string ([`9b1bcb522`](https://github.com/nuxt/nuxt/commit/9b1bcb522))
- dispatch rapid suspense navigation clicks in a single task ([`fc2f6b27b`](https://github.com/nuxt/nuxt/commit/fc2f6b27b))
- dedupe test names (#36166)
- assert inlined styles keep `url()` wrappers (#36146)
- don't orphan e2e dev servers on fixture setup timeout (#36126)
- loosen unprotected import assertion for impound ([`107990d39`](https://github.com/nuxt/nuxt/commit/107990d39))
- settle page:loading:end before asserting in router options ([`7d59e9f9a`](https://github.com/nuxt/nuxt/commit/7d59e9f9a))
- assert each diagnostics catalog is sorted by code ([`21725176b`](https://github.com/nuxt/nuxt/commit/21725176b))
- report which diagnostic code and catalogs collide ([`70034f67b`](https://github.com/nuxt/nuxt/commit/70034f67b))
- disable type checking in bundle-size fixes... ([`68490ceb7`](https://github.com/nuxt/nuxt/commit/68490ceb7))
- give each payload variant its own build directory ([`421571000`](https://github.com/nuxt/nuxt/commit/421571000))
- run ui-templates tests serially ([`38faf1901`](https://github.com/nuxt/nuxt/commit/38faf1901))
- avoid island prefetch prefix collision ([`ff9a20788`](https://github.com/nuxt/nuxt/commit/ff9a20788))

### 🤖 CI

- tag 4.x nightlies with `4x` ([`9e68918cc`](https://github.com/nuxt/nuxt/commit/9e68918cc))
- use uppt for nightly releases ([`20abf8c08`](https://github.com/nuxt/nuxt/commit/20abf8c08))
- upload playwright test results for e2e failures ([`ead96f4a0`](https://github.com/nuxt/nuxt/commit/ead96f4a0))
- disable codspeed until compatible with vitest 5 ([`212287582`](https://github.com/nuxt/nuxt/commit/212287582))
- proceed on nightly publishing when one fails ([`870dfea91`](https://github.com/nuxt/nuxt/commit/870dfea91))
- add new scope ([`6989883fa`](https://github.com/nuxt/nuxt/commit/6989883fa))
- remove bridge webhook flow (#36207)
- bump uppt to v0.6.9 ([`142f427b7`](https://github.com/nuxt/nuxt/commit/142f427b7))
- bump uppt to v0.6.8 ([`a1b06cecb`](https://github.com/nuxt/nuxt/commit/a1b06cecb))
- preview release add pm option (#36141)
- drop removed triage workflows ([`5a3841acc`](https://github.com/nuxt/nuxt/commit/5a3841acc))
- use full versions in action pin comments ([`9fd234a5e`](https://github.com/nuxt/nuxt/commit/9fd234a5e))
- drop build step in ci ([`b4f401bc8`](https://github.com/nuxt/nuxt/commit/b4f401bc8))
- update agentscan (#35536)
- drop 3.x branch from workflow triggers ([`5b41eed20`](https://github.com/nuxt/nuxt/commit/5b41eed20))

### 🎉 New Contributors

- Mansurkhoja Temirkhojaev (@mansurkhoja)
- saini-25 (@saini-25)
- Nicholas (@Neekoras)
- Marc Gschwend (@mgschwend)
- Hamed (@hamedniroomand)
- Ryan Boog (@hdwebpros)
- Paulina Sędłak-Jakubowska (@iniluap)
- Khaled Waleed (@61021)
- Andrey Lushnikov (@aslushnikov)
- btea (@btea)
- syvixor (@syvixor)
- Fabian Hiller (@fabian-hiller)
- Balázs Németh (@zsilbi)
- Vincent de Vreede (@Vincentdevreede)

### ❤️ Contributors

- Daniel Roe (@danielroe)
- Mansurkhoja Temirkhojaev (@mansurkhoja)
- Alex Liu (@Mini-ghost)
- Andrei Elkin (@AndreyYolkin)
- Issayah (@VividLemon)
- Matej Černý (@cernymatej)
- Ori (@oritwoen)
- saini-25 (@saini-25)
- abeer0 (@iiio2)
- Nicholas (@Neekoras)
- Daniel West (@silverbackdan)
- Marc Gschwend (@mgschwend)
- Hugo (@HugoRCD)
- Max (@onmax)
- Sébastien Chopin (@atinux)
- Hamed (@hamedniroomand)
- Ryan Boog (@hdwebpros)
- Paulina Sędłak-Jakubowska (@iniluap)
- Aubakirov Asker (@Askerka00)
- Florian Heuberger (@Flo0806)
- Yoshihiro Yamaguchi (@yamachi4416)
- Khaled Waleed (@61021)
- Damian Głowala (@DamianGlowala)
- Andrey Lushnikov (@aslushnikov)
- btea (@btea)
- Benjamin Canac (@benjamincanac)
- Estéban (@Barbapapazes)
- Matteo Gabriele (@MatteoGabriele)
- syvixor (@syvixor)
- Fabian Hiller (@fabian-hiller)
- Balázs Németh (@zsilbi)
- Austin Serb (@Austin1serb)
- Norbiros (@Norbiros)
- Vincent de Vreede (@Vincentdevreede)
- Robin (@OrbisK)
- Mirko Jantschke (@MirkoJa)
- Chairul Akmal (@chairulakmal)
- Alexander Lichter (@TheAlexLichter)
- Bochkarev Ivan (@Ibochkarev)
- Maher (@abaza738)
- Darlan José Batista do Prado (@DarlanPrado)
- Mateleo (@Mateleo)

---

## v1.3.12 (nuxt/scripts) - 2026-10-03

[Release notes](https://github.com/nuxt/scripts/releases/tag/v1.3.12)

### &nbsp;&nbsp;&nbsp;🐞 Bug Fixes

- **proxy**: Backport GA4 client IP forwarding to 1.x &nbsp;-&nbsp; by @harlan-zw in https://github.com/nuxt/scripts/issues/941 [<samp>(ca3b0)</samp>](https://github.com/nuxt/scripts/commit/ca3b0aa5)

##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](https://github.com/nuxt/scripts/compare/v1.3.11...v1.3.12)

---

## v2.0.0-beta.12 (nuxt/scripts) - 2026-10-03

[Release notes](https://github.com/nuxt/scripts/releases/tag/v2.0.0-beta.12)

### &nbsp;&nbsp;&nbsp;🐞 Bug Fixes

- **proxy**: Forward the client IP to GA4 as `_uip` &nbsp;-&nbsp; by @felixgabler and **Claude Opus 5.5 (1M context)** in https://github.com/nuxt/scripts/issues/940 [<samp>(d7930)</samp>](https://github.com/nuxt/scripts/commit/d79307b3)

##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](https://github.com/nuxt/scripts/compare/v2.0.0-beta.11...v2.0.0-beta.12)

---

## v4.3.3 (nuxt/test-utils) - 2026-10-02

[Release notes](https://github.com/nuxt/test-utils/releases/tag/v4.3.3)

> v4.3.3 is the next patch release.

## 👉 Changelog

[compare changes](https://github.com/nuxt/test-utils/compare/v4.3.2...v4.3.3)

### 🔥 Performance

- use h3's `toWebHandler` instead of `node-mock-http` ([`abe8ad944`](https://github.com/nuxt/test-utils/commit/abe8ad944))
- resolve `h3` from the project ([`b5d802f03`](https://github.com/nuxt/test-utils/commit/b5d802f03))
- replace `estree-walker` with `oxc-walker` ([`8e8ca5e8b`](https://github.com/nuxt/test-utils/commit/8e8ca5e8b))
- replace `local-pkg` with `exsolve` ([`38938a879`](https://github.com/nuxt/test-utils/commit/38938a879))
- replace `c12` with native dotenv parsing ([`26c72afa0`](https://github.com/nuxt/test-utils/commit/26c72afa0))
- inline `destr` and `scule` usage ([`e4bfd2ebe`](https://github.com/nuxt/test-utils/commit/e4bfd2ebe))
- drop `node-fetch-native` polyfill ([`6b654de5c`](https://github.com/nuxt/test-utils/commit/6b654de5c))
- replace `nypm` with `package-manager-detector` (#1828)

### 🩹 Fixes

- **runtime-utils:** type `registerEndpoint` against the project `h3` (#1831)
- **e2e:** restore console after use nuxt kit (#1817)
- **config:** exclude aliased mock packages from optimizeDeps in browser mode (#1816)
- **runtime:** setup nuxt once per worker in no-isolate (#1821)
- **browser:** correct render helper options type (#1822)

### 🏡 Chore

- move `vue` to peer dependencies ([`e70592ffa`](https://github.com/nuxt/test-utils/commit/e70592ffa))
- declare supported `nuxt` versions as peer dependency ([`b473892c9`](https://github.com/nuxt/test-utils/commit/b473892c9))

### 🤖 CI

- run tests in merge queues ([`0ad46c892`](https://github.com/nuxt/test-utils/commit/0ad46c892))
- use `pnpm/setup` and `devEngines` (#1814)

### ❤️ Contributors

- Daniel Roe (@danielroe)
- Yoshihiro Yamaguchi (@yamachi4416)

---

## v2.0.0-beta.11 (nuxt/scripts) - 2026-10-02

[Release notes](https://github.com/nuxt/scripts/releases/tag/v2.0.0-beta.11)

### &nbsp;&nbsp;&nbsp;🐞 Bug Fixes

- Preserve visitor-specific loaders and pixel commands &nbsp;-&nbsp; by @harlan-zw in https://github.com/nuxt/scripts/issues/937 [<samp>(3c69a)</samp>](https://github.com/nuxt/scripts/commit/3c69aae7)
- **reddit-pixel**: Forward calls after pixel.js loads with the command as the first argument &nbsp;-&nbsp; by @felixgabler and **Harlan GitHub Agent** in https://github.com/nuxt/scripts/issues/936 [<samp>(b0419)</samp>](https://github.com/nuxt/scripts/commit/b0419ed6)

##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](https://github.com/nuxt/scripts/compare/v2.0.0-beta.10...v2.0.0-beta.11)

---
