Nuxt layers are a powerful feature that you can use to share and reuse partial Nuxt applications within a monorepo, or from a git repository or npm package. The layers structure is almost identical to a standard Nuxt application, which makes them easy to author and maintain.
A minimal Nuxt layer directory should contain a nuxt.config.ts file to indicate it is a layer.
export default defineNuxtConfig({})
Additionally, certain other files in the layer directory will be auto-scanned and used by Nuxt for the project extending this layer.
app/components/* - Extend the default componentsapp/composables/* - Extend the default composablesapp/layouts/* - Extend the default layoutsapp/middleware/* - Extend the default middlewareapp/pages/* - Extend the default pagesapp/plugins/* - Extend the default pluginsapp/utils/* - Extend the default utilsapp/app.config.ts - Extend the default app configserver/* - Extend the default server endpoints & middlewarenuxt.config.ts- Extend the default nuxt configexport default defineNuxtConfig({
extends: [
'./base',
],
})
When extending from multiple layers, it's important to understand the override order. Layers with higher priority override layers with lower priority when they define the same files or components.
The priority order from highest to lowest is:
~~/layers directory - sorted alphabetically (Z has higher priority than A)extends config - first entry has higher priority than secondextends - Use for external dependencies (npm packages, remote repositories) or layers outside your project directory~~/layers directory - Use for local layers that are part of your project~/layers/1.z-layer, ~/layers/2.a-layer. This way 2.a-layer will have higher priority than 1.z-layer.export default defineNuxtConfig({
extends: [
// Local layer outside the project
'../base',
// NPM package
'@my-themes/awesome',
// Remote repository
'github:my-themes/awesome#v1',
],
})
If you also have ~~/layers/custom, the priority order is:
~~/layers/custom../base@my-themes/awesomegithub:my-themes/awesome#v1 (lowest)This means your project files will override any layer, and ~~/layers/custom will override anything in extends.
To get started you can initialize a layer with the nuxt/starter/layer template. This will create a basic structure you can build upon. Execute this command within the terminal to get started:
npm create nuxt -- --template layer nuxt-layer
Follow up on the README instructions for the next steps.
You can publish and share layers by either using a remote source or an npm package.
You can use a git repository to share your Nuxt layer. Some examples:
export default defineNuxtConfig({
extends: [
// GitHub Remote Source
'github:username/repoName',
// GitHub Remote Source within /base directory
'github:username/repoName/base',
// GitHub Remote Source from dev branch
'github:username/repoName#dev',
// GitHub Remote Source from v1.0.0 tag
'github:username/repoName#v1.0.0',
// GitLab Remote Source example
'gitlab:username/repoName',
// Bitbucket Remote Source example
'bitbucket:username/repoName',
],
})
GIGET_AUTH=<token> to provide a token.GIGET_GITHUB_URL=<url> or GIGET_GITLAB_URL=<url> environment variable - or directly configure it with the auth option in your nuxt.config.node_modules/.c12/layer_name/node_modules/) that is not accessible to your package manager.install: true in your layer options.export default defineNuxtConfig({
extends: [
['github:username/repoName', { install: true }],
],
})
You can publish Nuxt layers as an npm package that contains the files and dependencies you want to extend. This allows you to share your config with others, use it in multiple projects or use it privately.
To extend from an npm package, you need to make sure that the module is published to npm and installed in the user's project as a devDependency. Then you can use the module name to extend the current nuxt config:
export default defineNuxtConfig({
extends: [
// Node Module with scope
'@scope/moduleName',
// or just the module name
'moduleName',
],
})
To publish a layer directory as an npm package, you want to make sure that the package.json has the correct properties filled out. This will make sure that the files are included when the package is published.
{
"name": "my-theme",
"version": "1.0.0",
"type": "module",
"main": "./nuxt.config.ts",
"dependencies": {},
"devDependencies": {
"nuxt": "^3.0.0"
}
}
dependencies. The nuxt dependency, and anything only used for testing the layer before publishing, should remain in the devDependencies field.Now you can proceed to publish the module to npm, either publicly or privately.
Auto-scanned layers (from your ~~/layers directory) automatically create aliases. For example, you can access your ~~/layers/test layer via #layers/test.
If you want to create named layer aliases for other layers, you can specify a name in the configuration of the layer.
export default defineNuxtConfig({
$meta: {
name: 'example',
},
})
This will produce an alias of #layers/example which points to your layer.
When importing using global aliases (such as ~/ and @/) in a layer components and composables, note that these aliases are resolved relative to the user's project paths. As a workaround, you can use relative paths to import them, or use named layer aliases.
Also when using relative paths in nuxt.config file of a layer, (with exception of nested extends) they are resolved relative to user's project instead of the layer. As a workaround, use full resolved paths in nuxt.config:
import { fileURLToPath } from 'node:url'
import { dirname, join } from 'node:path'
const currentDir = dirname(fileURLToPath(import.meta.url))
export default defineNuxtConfig({
css: [
join(currentDir, './app/assets/main.css'),
],
})
You can use the getLayerDirectories utility from Nuxt Kit to support custom multi-layer handling for your modules.
import { defineNuxtModule, getLayerDirectories } from 'nuxt/kit'
export default defineNuxtModule({
setup (_options, nuxt) {
const layerDirs = getLayerDirectories()
for (const [index, layer] of layerDirs.entries()) {
console.log(`Layer ${index}:`)
console.log(` Root: ${layer.root}`)
console.log(` App: ${layer.app}`)
console.log(` Server: ${layer.server}`)
console.log(` Pages: ${layer.appPages}`)
// ... other directories
}
},
})
Notes:
Configuration loading and extends support is handled by unjs/c12, merged using unjs/defu and remote git sources are supported using unjs/giget. Check the docs and source code to learn more.