Core Concepts
Build-Time vs Runtime
Prepare scripts run during the build process, not at runtime:
nuxt dev/build → Prepare scripts run → Nuxt builds your app → App runsScripts run once per build, so an API call or a database query in a prepare script costs build time, never request time, and what the app ships is the result rather than the code that produced it.
The Problem Nuxt Prepare Solves
Nuxt's configuration file (nuxt.config.ts) doesn't support async operations. This means you can't:
// ❌ This doesn't work in nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
apiUrl: await fetchApiUrl() // Error: top-level await
}
})Nuxt Prepare fills this gap by running async code before the configuration is finalized.
How It Works
1. Script Execution
When Nuxt builds your app, prepare scripts are executed in order (or in parallel if configured). Each script returns a result that can modify your Nuxt configuration or pass data to your app.
Scripts from extended layers run before the ones your own project lists, so your project has the last word – its result is merged over theirs. Where several layers list the same script path, it runs once, at the position the highest-priority layer gives it.
A result is merged over nuxt.config.ts rather than under it, so a key a script returns overrides the value already in place. Arrays are the exception: they are concatenated rather than replaced.
2. Generated Files
The module generates files in .nuxt/module/:
nuxt-prepare.mjs – Exported state values:
// Generated by nuxt-prepare
export const todo = {
"id": 1,
"title": "Learn Nuxt Prepare"
}nuxt-prepare.d.ts – Type definitions:
// Generated by nuxt-prepare
export declare const todo: {
"id": 1,
"title": "Learn Nuxt Prepare"
}
export type Todo = typeof todoBoth files are written by serializing the state, so the declaration carries the literal values rather than widened ones – todo.id is 1, not number.
3. Module Alias
The generated files are available via the #nuxt-prepare alias, which works in:
- Nuxt app – Components, composables, pages, layouts
- Nitro server – API routes, middleware, server utilities
// Works everywhere
import { todo } from '#nuxt-prepare'State Serialization
State values are JSON-serialized during code generation. This means:
- ✅ Objects, arrays, strings, numbers, booleans
- ❌ Functions, classes, symbols,
undefined,null
// ✅ This works
state: {
config: { api: 'https://api.example.com' },
items: [1, 2, 3]
}
// ❌ This doesn't work
state: {
handler: () => console.log('hello'), // Functions are lost
data: undefined, // The key is dropped entirely
fallback: null // So is this
}Return Options
Prepare scripts can return:
state– Pass build-time data as importable constants via#nuxt-prepareruntimeConfig– Set runtime configuration accessible viauseRuntimeConfig()appConfig– Set app configuration accessible viauseAppConfig()
See Runtime & App Config for detailed guidance on when to use each option.