This page is a to-do list rather than an explanation, and doing it is worth more than reading it. A candidate who says "I ran our layer against the v5 flag and here are the three things that broke" has the single best answer available to the question "how would you make our modules Nuxt 5 ready?".
process.server|process.client|process.browser|process.dev|process.test and replace with import.meta.*. The nuxt/prefer-import-meta ESLint rule finds the leftovers.addVitePlugin and extendViteConfig call: the client/server options are deprecated for the Environment API, and extendViteConfig itself is deprecated. Move to a plugin with applyToEnvironment, and re-check any prepend/enforce assumption after the Rolldown switch.nitropack runtime imports and any direct nitro.storage access in server code; prefer Nuxt's auto-imports so the Nitro v3 move is invisible..then() on callHook; await it, because it may return void.clearNuxtState semantics (reset to default rather than undefined) do not break a composable that treated undefined as "cleared".<ClientOnly> placeholder element, which becomes an HTML comment.engines allows the Node version v5 requires.future: { compatibilityVersion: 5 }, then against nuxt-nightly in CI.Everything above applies to the layer's own runtime code, plus:
import.meta.url; no reliance on TypeScript baseUrl for alias resolution, which v5 stops using.process.* replaced; the object syntax (name, parallel, dependsOn) preferred so ordering is explicit rather than name-based./About no longer matches pages/about.vue; grep your links, redirects and tests.Two commands that do most of the audit:
# 1. Every process.* leftover in shipped code
rg -n 'process\.(server|client|browser|dev|test)\b' src layers app server
# 2. Run the whole test suite the way Nuxt 5 will behave
NUXT_COMPATIBILITY_VERSION=5 pnpm test # or set future.compatibilityVersion in the fixture configs
A fixture dedicated to the flag, so the normal suite stays green while you work through the list:
export default defineNuxtConfig({
extends: ['../../..'],
future: { compatibilityVersion: 5 },
})
import { fileURLToPath } from 'node:url'
import { describe, expect, it } from 'vitest'
import { $fetch, setup } from '@nuxt/test-utils/e2e'
describe('nuxt 5 compatibility', async () => {
await setup({ rootDir: fileURLToPath(new URL('./fixtures/v5', import.meta.url)) })
it('renders what the layer ships under v5 semantics', async () => {
const html = await $fetch('/')
expect(html).toContain('data-source="layer"')
})
})
continue-on-error: true keeps the nightly from blocking pull requests, and also makes it invisible. Route its failures somewhere a human sees them — a scheduled run that opens an issue, or a notification — or it becomes a checkbox rather than an early-warning system.
nuxt-team-toolkit and the layer list against your base layer. Write every finding and its fix into your notes.v5 fixture and the nightly CI job. Let the nightly fail once and read the error."Make the breakage visible, then work the list. Visible means a fixture with future.compatibilityVersion: 5 and a nightly CI job against nuxt-nightly whose failures reach a human. The list is the upgrade guide turned into greps and audits: process.* to import.meta.*, Vite plugins off the deprecated client/server options and onto applyToEnvironment, no deep nitropack imports because of Nitro v3, no .then() on callHook, and checks on case-sensitive routing, page component names and the <ClientOnly> placeholder. Each finding gets fixed in the current major, so when v5 actually lands the upgrade is a version bump rather than a project."