A Nuxt module is a function that runs once, in Node, while Nuxt starts or builds. It never executes in the browser and never executes inside the production server. Everything a consumer's app runs at runtime is code the module injected from its runtime/ directory. For a role that builds an internal toolkit, this is the section that separates people who have configured modules from people who can write, version and support one.
Three worlds, and every line of code lives in exactly one of them:
src/module.ts, @nuxt/kit, Node APIs, the file system, the nuxt instance. Runs once per nuxt dev / nuxt build / nuxt generate, sequentially with the other modules, in the order of nuxt.options.modules.src/runtime/server/** plus the SSR side of plugins and composables. Runs inside Nitro, per request, in a long-lived process.src/runtime/app/** in the browser, once per tab session.Most module bugs are boundary bugs: a value that exists in the build world (an option, nuxt.options, a path on disk) is assumed to exist at runtime, where it does not unless the module deliberately carried it across through runtime config, appConfig or a generated template.
Everything a module can do reduces to three operations on the build-world nuxt instance:
nuxt.options: add a CSS entry, set an alias, merge defaults into runtimeConfig, push a Vite plugin. Later modules see the mutation immediately; earlier ones have already run.nuxt.hook('pages:extend', ...), nuxt.hook('nitro:config', ...), nuxt.hook('modules:done', ...). Hooks are how a module reacts to things that have not happened yet and how modules cooperate without importing each other..nuxt. Kit helpers such as addPlugin, addImports, addServerHandler and addTemplate are ergonomic wrappers over those three primitives; each one either pushes into nuxt.options or registers a hook that does.If you can name which primitive a helper uses underneath, you can predict its ordering behaviour, what happens when two modules call it, and where to look when it does not do what you expect.
A layer is declarative: it ships app code and config that Nuxt merges. It cannot execute anything at build time. The moment a toolkit needs to do something (generate a route registry, inject a plugin in the right position, validate options, react to the consumer's config) that logic has to be a module. In practice a company toolkit is a layer that lists its module in modules, so consumers get conventions, app code and build behaviour from a single extends entry (see Layers).
Two mechanics make that combination safe. Layer configs are merged with defu, so modules arrays concatenate; Nuxt then deduplicates modules by their meta.name, so the layer and the project can both list the same module and it runs once. And because module options are resolved as defu(inlineOptions, nuxt.config[configKey], defaults), the project's config beats the layer's, which beats the module's defaults, mirroring how file overrides work between layers.
The pages in this section follow the life of a module from the inside out: what defineNuxtModule does with your definition, the kit helpers and what they do underneath, how an option travels from the build world to the browser, the rules of the runtime directory, hooks, templates and types, composing with other modules, testing, and finally building and publishing without breaking consumers.
"A module is build-time code: a function Nuxt calls once, in Node, while it starts or builds, in the order of the modules array. It can do three things: mutate nuxt.options, register hooks, and generate or register files. Everything the user's app executes at runtime comes from my runtime/ directory, which I inject with kit helpers like addPlugin or addImports. That boundary is the source of most module bugs: build-world values do not exist at runtime unless I deliberately carry them across through runtime config, appConfig or a template. A layer cannot run code, so a toolkit that needs build-time logic is a layer plus a module, and Nuxt deduplicates the module by name if both list it."
Designing a team layer
The senior-craft page for layers - defining a small public surface, theming through app.config, override recipes, performance and security costs per app, governance, and rolling out breaking changes.
The mental model
What defineNuxtModule does with your definition, the three worlds a line of module code can live in, how Nuxt orders and deduplicates modules, and when onInstall and onUpgrade fire.