2026 landscape

The v5 readiness plan

A concrete checklist for making a module and a layer Nuxt 5 ready, and turning the findings into an interview story.

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?".

Module readiness

  • Grep the whole package for 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.
  • Review every 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.
  • Replace deep nitropack runtime imports and any direct nitro.storage access in server code; prefer Nuxt's auto-imports so the Nitro v3 move is invisible.
  • Never chain .then() on callHook; await it, because it may return void.
  • Check anything keyed on page component names, and anything depending on case-insensitive routes.
  • Make sure clearNuxtState semantics (reset to default rather than undefined) do not break a composable that treated undefined as "cleared".
  • Check CSS or selectors that targeted the <ClientOnly> placeholder element, which becomes an HTML comment.
  • Confirm the package type-checks with stricter settings, and that engines allows the Node version v5 requires.
  • Run the fixtures with future: { compatibilityVersion: 5 }, then against nuxt-nightly in CI.

Layer readiness

Everything above applies to the layer's own runtime code, plus:

  • Layer config: paths still resolved from import.meta.url; no reliance on TypeScript baseUrl for alias resolution, which v5 stops using.
  • Layer plugins: process.* replaced; the object syntax (name, parallel, dependsOn) preferred so ordering is explicit rather than name-based.
  • Layer server code: imports audited for the Nitro v3 move; shipped handlers use Nuxt's auto-imports rather than deep package paths.
  • Layer pages and links: case-sensitive routing means /About no longer matches pages/about.vue; grep your links, redirects and tests.
  • Layer components: anything written with the Options API, since it is compiled out of the client bundle in v5 mode.
  • Fixtures: the fixture that lives outside the layer folder gets the v5 flag too, because that is where alias and resolution changes surface.
  • Compatibility range: decide and publish which Nuxt versions the next layer major supports, and put the lowest one in CI alongside latest and nightly.

How it works

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:

test/fixtures/v5/nuxt.config.ts
export default defineNuxtConfig({
  extends: ['../../..'],
  future: { compatibilityVersion: 5 },
})
test/v5.test.ts
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"')
  })
})
Gotcha· A green nightly job that nobody reads

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.

Exercise

Exercise
  • Work through the module list against nuxt-team-toolkit and the layer list against your base layer. Write every finding and its fix into your notes.
  • Add the v5 fixture and the nightly CI job. Let the nightly fail once and read the error.
  • Turn the findings into a three-sentence story: what you audited, what broke, what you changed. That is your answer to the readiness question.

Be able to say

Be able to say· What would you do in your first month to prepare our tooling for Nuxt 5?

"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."