Changelog

Discover the latest releases from Nuxt and the official modules.
@nuxt/scripts

v1.0.0-beta.2

   🚀 Features

   🐞 Bug Fixes

   🏎 Performance

    View changes on GitHub
@nuxt/ui

v4.5.0

✨ Highlights

🎨 New Theme component

The Theme component lets you override the theme of all child components without modifying each one individually. Pass an object to the ui prop where keys are component names and values are their slot class overrides:

<UTheme
  :ui="{
    button: {
      base: 'rounded-full'
    },
    input: {
      base: 'rounded-full'
    }
  }"
>
  <UButton label="Button" color="neutral" variant="outline" />
  <UInput placeholder="Search..." />
</UTheme>

The Theme component doesn't render any HTML element. It uses Vue's provide / inject under the hood, so overrides propagate through the entire component tree regardless of nesting depth. Theme components can be nested (innermost wins) and the ui prop on individual components always takes priority.

🌈 New neutral colors

Thanks to Tailwind CSS v4.2, four new neutral color options are now available: taupe, mauve, mist and olive. Configure them through the ui.neutral option in your app.config.ts.

🚫 Duplicate toast prevention

The Toaster now automatically prevents duplicate toasts and displays a pulse animation when a duplicate is triggered, providing a cleaner notification experience.

https://github.com/user-attachments/assets/e356affa-d170-4b7e-8a80-217132ee88e1

🚀 Features

  • DashboardSidebar/Header: add autoClose prop (#6089) (2663deb)
  • EditorDragHandle: proxy nested / nestedOptions props and emit hover event (#5960) (ed60193)
  • Form: add HTML5 validation to programmatic submit (#6002) (ed552fc)
  • module: add support for taupe / mauve / mist / olive neutral colors (#6081) (bc49d3f)
  • NavigationMenu: allow tooltip usage in horizontal orientation (#5682) (f46b504)
  • NavigationMenu: handle chip in items (#6064) (401a2c0)
  • ScrollArea: add skipMeasurement virtualize option (#5721) (548b711)
  • Select/SelectMenu: add hover effects on outline and subtle variants (94b0c31)
  • Theme: new component (#4387) (c97047d)
  • Toaster: prevent duplicate toasts and add pulse animation (3f6581a)

🐛 Bug Fixes

  • BlogPost/ChangelogVersion: use ImgHTMLAttributes type for image prop (#6007) (0185856)
  • ChatMessages: allow message props to override role defaults (#6000) (f64ec17)
  • ChatMessages: prevent flash at top before scrolling to bottom on mount (4bdcb83)
  • Checkbox/Switch: prevent data-state conflict when used inside Tooltip (2bb1a8b), closes #3599
  • CheckboxGroup: update update:modelValue emit type (#5927) (64d2e88)
  • ColorModeImage: add baseURL support for public paths (#6006) (db510f3)
  • components: add fixed prop to prevent responsive text size reduction (#6074) (8f5f44c)
  • components: nullable and optional type support (#6060) (cd3432b)
  • components: prevent iOS auto-zoom on input fields with font-size below 16px (#6040) (1262016)
  • ContentNavigation: pass nested child data to slots (#6043) (e67f77e)
  • defineShortcuts: add alt key guard (#6020) (8451f45)
  • defineShortcuts: allow shifted special character shortcuts (08facc0)
  • Drawer/Modal/Popover/Slideover: prevent unexpected close on touch when interacting with other overlays (#5695) (e2c038c)
  • Editor: handle placeholder in RTL mode (#5977) (3cc16e3)
  • EditorMentionMenu: use char prop as mention prefix instead of always @ (0b9b097), closes #6035
  • EditorToolbar: proxy size prop to dropdown menu (8f8d989)
  • InputMenu/InputNumber/SelectMenu: proxy size to buttons (1ec1698), closes #5958
  • InputMenu/Select/SelectMenu: exclude cosmetic items from model value type (#6044) (22cf1ea)
  • InputMenu/SelectMenu: sort filtered items by match relevance (058c66b), closes #4672
  • InputMenu: prevent focus on trailing button (88073b6)
  • module: update icon cssLayer option from components to base (#6076) (e8bc322)
  • NavigationMenu: allow clicking trailing slot in horizontal orientation (7f9996f), closes #5192 #6083
  • NavigationMenu: unique auto-generated item values for grouped items (7b317d9)
  • PricingPlan: truncate title (#6041) (8e86c51)
  • Select: remove useless by prop (14dceaf)
  • Table: improve perfs with shallowRef when watch deep is disabled (#6023) (bc06ce2)
  • Toast: allow update to keep toast open and reset duration (82afa0a)
  • Toast: improve animation smoothness (#6065) (ee2c0a5)
  • types: improve DotPathKeys accuracy and GetItemKeys performance (#6077) (6f7af3e)
  • useEditorMenu: rank filtered results by relevance (f53484a)

🌐 Locales

👋 New Contributors

Full Changelog: https://github.com/nuxt/ui/compare/v4.4.0...v4.5.0

@nuxt/hints

v1.0.0-alpha.8

🩹 Fixes

  • Skip hydration check if client only component (#227)
  • lazy-load: Prefer cloning component over wrapping component (#232)
  • client: Add empty unocss config object (#233)
  • lazy-load: Use NuxtComponent name for auto-imports (#235)

✅ Tests

  • Add basic sse tests (#228)

❤️ Contributors

@nuxt/hints

v1.0.0-alpha.7

compare changes

🚀 Enhancements

  • Initial component lazy load hints (#212)
  • Lazy load hints devtools integration (#220)

🩹 Fixes

  • Return correct data in endpoint (#218)
  • Use component filename if auto import for lazy-load hint (#219)
  • Move uid generation server side (#222)

💅 Refactors

  • Move to extensible hints handlers (#208)
  • Assign handler to context instead of waiting for hook result (#213)
  • Simplify handlers (#216)

🏡 Chore

  • playground: Remove relative path to use '@nuxt/hint' (#205)
  • README: Add lazy-load hints to README (#225)

🤖 CI

  • renovate: Extend nuxt configuration (#206)

❤️ Contributors

@nuxt/fonts

v0.14.0

0.14.0 is the next minor release.

🚨 Breaking changes

Default font format is now woff2 only

Font providers previously returned multiple formats (woff2, woff, truetype, etc.). The default behavior now only resolves woff2 fonts, which is supported by all modern browsers.

Your @font-face declarations will typically have fewer src entries, reducing CSS size. In most cases this is a transparent improvement.

To restore the previous behavior or add additional formats:

export default defineNuxtConfig({
  fonts: {
    defaults: {
      formats: ['woff2', 'woff', 'ttf'],
    },
  },
})

Available values: 'woff2', 'woff', 'ttf', 'otf', 'eot'.

Cache invalidation

Font metadata caches are now isolated per provider and per provider options. After upgrading, your font metadata cache (node_modules/.cache/nuxt/fonts/) will be invalidated and fonts will be re-fetched on the next build. This is a one-time occurrence.

✨ Features

Resolve fonts from node_modules

A new built-in npm provider can resolve fonts installed as npm packages. If no other provider matches a font family, @nuxt/fonts will now attempt to find it in your node_modules via CDN metadata.

export default defineNuxtConfig({
  fonts: {
    npm: {
      // options for the npm provider (optional)
    },
  },
})

Font format resolution

You can control which font formats are resolved via the new defaults.formats option:

export default defineNuxtConfig({
  fonts: {
    defaults: {
      formats: ['woff2'], // default
    },
  },
})

Provider-specific font family options

You can now pass provider-specific options when configuring individual font families:

export default defineNuxtConfig({
  fonts: {
    families: [
      {
        name: 'My Font',
        provider: 'google',
        providerOptions: {
          google: {
            // provider-specific options for this family
          },
        },
      },
    ],
  },
})

throwOnError option

Configure whether font resolution errors should throw or warn:

export default defineNuxtConfig({
  fonts: {
    throwOnError: true, // default: false
  },
})

lightningcss support

If your Nuxt project uses Vite's lightningcss mode for CSS processing (for example, if you're using rolldown-vite!), injected @font-face declarations are now minified with lightningcss instead of esbuild.

🩹 Fixes

  • Prevent font flashes in development — The dev font proxy now returns Cache-Control: public, max-age=31536000, immutable headers, preventing font flashes during HMR on SSR frameworks.
  • Broader CSS file matching — Font family injection now matches additional CSS-like file patterns (Vue SFC &lang.css query strings and inline style IDs), aligning with fontless behavior.
  • Adobe provider race condition — Fixed a race condition in the Adobe (Typekit) provider where concurrent font resolution could clear the font family map mid-flight, causing Adobe fonts to silently fail. (fix in unifont 0.7.4)
  • Prioritize sliced woff2 over full ttf — When both formats are available, woff2 subsets are now correctly prioritized over full ttf files. (fix in unifont 0.7.2)
  • Bunny provider subset filtering — The Bunny font provider now correctly filters by subsets. (fix in unifont 0.7.0)

👉 Changelog

compare changes

🚀 Enhancements

  • Upgrade to the latest versions fontless + unifont (3d634b0)
  • Support lightningcss transforms (171c9a4)
  • Add support for resolving fonts from local node_modules (#781)

🩹 Fixes

  • Prevent font flashes in development (0ec437e)
  • Include more css-ish files when injecting font-families (6e8e343)
  • deps: Bump unifont + reenable adobe tests (9d7715d)

📖 Documentation

  • Add nuxt.care health badge (8f0a978)

🏡 Chore

  • Fix changelog workflow (#776)
  • Remove changelog (in favour of github releases) (25c87c4)

✅ Tests

  • Update snapshots for adobe preloads (035091a)

🤖 CI

  • Pin github actions to full-length commit shas (18e3ff7)

❤️ Contributors

  • Daniel Roe (@danielroe)
  • Bjorn Lu (@bluwy)
@nuxt/fonts

v0.13.0

👉 Changelog

compare changes

🚀 Enhancements

  • Add fonts:public-asset-context hook (#758)

🩹 Fixes

  • Use $fetch for proxy support when downloading fonts (#732)

📖 Documentation

  • Fix Nuxt badge icon (#742)

🏡 Chore

  • Update pnpm to 10.21 and enable trust policy (7b25049)
  • Revert pnpm trust policy and restore provenance action (6d16adb)
  • Include .nuxt types + migrate to ts projects (2daad4e)

🤖 CI

  • Use new dependency review shared workflow (635bc79)
  • Use correct var (25b8fa1)
  • Try pinning to a commit hash (f40c07c)
  • Pass base-ref + head-ref to reusable workflow (e8ffe84)
  • Update name + hash (8d1165b)
  • Simplify (08b8fcb)

❤️ Contributors

  • Daniel Roe (@danielroe)
  • Harlan Wilton (@harlan-zw)
  • IO-Fire (@IO-Fire)
  • Luke Nelson (@luc122c)
nuxt

v4.3.1

4.3.1 is a regularly scheduled patch release.

👉 Changelog

compare changes

🩹 Fixes

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

💅 Refactors

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

📖 Documentation

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

🏡 Chore

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

✅ Tests

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

❤️ Contributors

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

v3.21.1

3.21.1 is a regularly schedule patch release.

👉 Changelog

compare changes

🩹 Fixes

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

💅 Refactors

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

📖 Documentation

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

🏡 Chore

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

✅ Tests

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

❤️ Contributors

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

v4.0.0

4.0.0 is the next major release.

👀 Highlights

We're releasing Nuxt Test Utils v4, with support for Vitest v4. 🚀

Better mocking support

The biggest improvement in this release is how mocking works. Nuxt initialization has been moved from setupFiles to the beforeAll hook (#1516), which means vi.mock and mockNuxtImport calls now take effect before Nuxt starts. This fixes a long-standing issue where mocks for composables used in middleware or plugins wouldn't apply reliably (#750, #836, #1496).

On top of that, mockNuxtImport now passes the original implementation to the factory function (#1552), making partial mocking much more natural:

mockNuxtImport('useRoute', original => vi.fn(original))

it('my test', async () => {
  vi.mocked(useRoute).mockImplementation(
    (...args) => ({ ...vi.mocked(useRoute).getMockImplementation()!(...args), path: '/mocked' }),
  )

  const wrapper = await mountSuspended(MyComponent)
  expect(wrapper.find('#path').text()).toBe('/mocked')
})

registerEndpoint improvements

registerEndpoint now works correctly with query parameters in URLs (#1560), and endpoints registered in setup files are no longer lost when modules reset (#1549).

🚧 Migration

@nuxt/test-utils v4 contains a few breaking changes, almost all related to requiring at least vitest v4 as a peer dependency (if you are using vitest). It replaces vite-node with Vite's native Module Runner and simplifies pool configuration.

This will mean improvements for test performance and mocking, but does require some changes to your test code.

!TIP Most of the changes below are straightforward. The biggest thing to watch out for is code that runs at the top level of a describe block — see below.

Update your dependencies

Update vitest and its companion packages together:

{
  "devDependencies": {
-   "@nuxt/test-utils": "^3.x",
-   "vitest": "^3.x",
-   "@vitest/coverage-v8": "^3.x"
+   "@nuxt/test-utils": "^4.0",
+   "vitest": "^4.0",
+   "@vitest/coverage-v8": "^4.0"
  }
}

Peer dependencies

We've tightened peer dependency ranges. You may need to update some of these:

Dependencyv3v4
vitest^3.2.0^4.0.2
happy-dom*>=20.0.11
jsdom*>=27.4.0
@jest/globals^29.5.0 || >=30.0.0>=30.0.0
@cucumber/cucumber^10.3.1 || >=11.0.0>=11.0.0
@testing-library/vue^7.0.0 || ^8.0.1^8.0.1

Later environment setup

This is the change that might require most change in your tests. Because we've moved the nuxt environment setup into beforeAll, this means composables called at the top level of a describe block will fail with [nuxt] instance unavailable.

// Before (worked in vitest v3)
describe('my test', () => {
  const router = useRouter() // ran lazily, after environment setup
  // ...
})

// After (vitest v4)
describe('my test', () => {
  let router: ReturnType<typeof useRouter>

  beforeAll(() => {
    router = useRouter() // runs after environment setup
  })
  // ...
})

This applies to useRouter(), useNuxtApp(), useRoute(), and any other Nuxt composable or auto-import.

!TIP If you only need the value within individual tests, beforeEach or directly within the test works too.

Stricter mock exports

If you use vi.mock with a factory function, accessing an export that the factory doesn't return will now throw an error instead of silently returning undefined.

// Before: accessing `bar` would silently return undefined
vi.mock('./module', () => ({ foo: 'mocked' }))

// After: accessing `bar` throws
// Fix: use importOriginal to include all exports
vi.mock('./module', async (importOriginal) => ({
  ...await importOriginal(),
  foo: 'mocked',
}))

!NOTE If you're mocking a virtual module (like #build/nuxt.config.mjs) where importOriginal can't resolve the real module, you might need to explicitly list all accessed exports in your mock factory.

Other changes

For the full list, see the vitest v4 migration guide.

👉 Changelog

compare changes

🚀 Enhancements

  • deps: ⚠️ Upgrade to vitest v4 (#1481)
  • deps: ⚠️ Drop official support for older versions of test runners + dom environments (31fdc262a)
  • runtime-utils: Pass original to mockNuxtImport factory (#1552)
  • runtime: ⚠️ Change nuxt start timing to beforeAll hook (#1516)
  • e2e: Support setup and teardown timeouts in setupBun (#1578)

🩹 Fixes

  • runtime: Handle optional chaining vueWrapper plugin installed check (#1547)
  • runtime-utils: Keep endpoints from registerEndpoint in setup file (#1549)
  • runtime-utils: Support registerEndpoint with query params (#1560)
  • runtime-utils: Avoid local variable in mockNuxtImport macro (#1564)
  • runtime-utils: Add missing nextTick import (#1563)
  • Pin h3-next to patch (1ff3bbb91)
  • playwright: Bump windows timeout (63e39b7c9)
  • config: Respect include options in non nuxt environment simple setup (#1570)

💅 Refactors

  • module: Use @nuxt/devtools-kit for devtools hooks (426e0b537)
  • runtime: Remove unnecessary querySelector (#1577)

📖 Documentation

🏡 Chore

  • Allow changelog update util to return major bump (9e86cadab)
  • Make app-vitest follow advised setup guidelines (#1542)
  • Update lockfile (6d798b5e1)
  • config: Migrate Renovate config (#1568)
  • Add test utils setup to .nuxtrc (b4021dee4)

✅ Tests

  • Avoid running root test script twice (44f6bd396)

⚠️ Breaking Changes

  • deps: ⚠️ Upgrade to vitest v4 (#1481)
  • deps: ⚠️ Drop official support for older versions of test runners + dom environments (31fdc262a)
  • runtime: ⚠️ Change nuxt start timing to beforeAll hook (#1516)

❤️ Contributors

  • Yoshihiro Yamaguchi (@yamachi4416)
  • Daniel Roe (@danielroe)
  • Adam DeHaven (@adamdehaven)