Nuxt Layers & Extends
Relevant source files
The following files were used as context for generating this wiki page:
Nuxt Layers are a powerful mechanism for sharing and extending configuration, components, composables, and other application logic across multiple projects or within a single monorepo. By using the extends property, a Nuxt application can inherit features from local directories or remote sources (such as GitHub repositories), allowing for highly modular and reusable architecture.
The system works by merging configuration objects and scanning directory structures of each layer in a specific priority order. This enables a "base" application to be defined in one layer and customized or overridden in another, facilitating standardized project starters, shared internal libraries, and complex multi-app environments.
Sources: packages/schema/src/types/schema.ts:639-647, packages/kit/src/loader/config.ts:182-192
Layer Resolution and Merging
The core of the layers system is the loadNuxtConfig utility, which identifies and resolves all layers before merging them into a final configuration object. Layers are identified through the extends and theme keys in the Nuxt configuration.
Resolution Priority
Nuxt follows a strict priority order when resolving layers to ensure predictable overrides. The priority is generally:
- Root project overrides (e.g., command line arguments).
- The root project's
nuxt.config. - Layers listed in
extends(first entry has higher priority). - Auto-scanned local layers from the
~/layers/directory.
Sources: packages/kit/src/loader/config.ts:182-205, packages/kit/test/load-nuxt-config.spec.ts:31-41
Config Loading Flow
The following diagram illustrates how Nuxt loads and merges configurations from multiple layers.
The system uses c12 for underlying config loading and defu for merging, ensuring that arrays (like modules or plugins) are concatenated while objects are deeply merged.
Sources: packages/kit/src/loader/config.ts:249-335, packages/kit/src/loader/config.ts:173-180
Application Structure Resolution
Once configuration is merged, Nuxt resolves the actual files (components, layouts, middleware) from each layer. This is handled by the resolveApp function, which iterates through all layer directories to build the virtual application structure.
Component and Layout Resolution
Nuxt scans specific directories in each layer. If a file with the same name exists in multiple layers, the one in the layer with the highest priority wins.
| Directory | Purpose | Resolution Logic |
|---|---|---|
app/ | Core app files | Looks for app.vue or App.vue across layers. |
layouts/ | Page layouts | Merges all unique layout names; higher priority layers override names. |
middleware/ | Route middleware | Collects all middleware; suffixes like .global are preserved. |
plugins/ | App plugins | Merged from layer configs and directory scanning. |
pages/ | Route definitions | Scanned to generate the route tree. |
Sources: packages/nuxt/src/core/app.ts:204-266, packages/nuxt/src/pages/module.ts:51-60
Multi-Layer Data Flow
The following sequence diagram shows how files are aggregated from layers during the app generation phase.
Layer Aliasing
Nuxt automatically provides aliases for each layer to allow developers to reference files within a specific layer without knowing the absolute path. This is especially useful for themes or shared modules.
~,~~,@,@@: These resolve to the root project or the current layer's source/root directories whenexperimental.localLayerAliasesis enabled.#layers/ <name>: A unique alias generated for each named layer, allowing direct imports from that layer's root.
Sources: packages/kit/src/loader/config.ts:354-358, packages/kit/test/load-nuxt-config.spec.ts:8-25
Page and Route Merging
The nuxt:pages module handles route generation across layers. It uses a persistent route tree in development to allow for incremental updates. When multiple layers provide pages, they are merged into a single vue-router compatible structure.
Path Overriding
If a layer provides a page at a path already defined by a higher-priority layer, the higher-priority page takes precedence. However, sub-routes and children are merged if the parent route matches.
Sources: packages/nuxt/src/pages/module.ts:114-135, packages/nuxt/src/pages/module.ts:248-268
Configuration Options
Layer behavior is controlled by several keys within the main Nuxt configuration schema.
| Option | Type | Description |
|---|---|---|
extends | string | string[] | Paths to local directories or remote git sources to use as layers. |
theme | string | Alias for a single extends entry, often used for UI frameworks. |
experimental.localLayerAliases | boolean | If true, resolves standard aliases (~, @) relative to the layer they are in. |
srcDir | string | Defined per layer; determines where Nuxt looks for pages/, components/, etc. |
Sources: packages/schema/src/types/schema.ts:639-658, packages/kit/src/loader/config.ts:400-410
Summary
Nuxt Layers provide a standardized way to build composable applications. By abstracting logic into layers, teams can maintain shared layouts, standardized API middleware, and base configurations that can be effortlessly distributed. The combination of prioritized configuration merging and automated directory scanning ensures that customization remains simple while maximizing code reuse.
Sources: packages/nuxt/src/core/app.ts:204-210, packages/kit/src/loader/config.ts:182-190