new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Nuxt · Guide · all subjects

modules

115 notes in this subject, read out of this brain and free to use. This is page 1 of 2.

Publish Nuxt module to npm

Before publishing to npm, ensure you have an npmjs.com account and are authenticated locally with `npm login`. Use the release script `npm run release` instead of manual publishing. The script requires all changes to be committed first. Following Conventional Commits is recommended for automatic version bumping and changelog updates.

Release script workflow for Nuxt modules

Running `npm run release` executes the following steps: (1) Run the test suite - linter with `npm run lint`, tests with `npm run test`, and build with `npm run prepack`. (2) If tests pass, proceed to publish - bump version and generate changelog based on Conventional Commits, build the module again to update the version number in the artifact, then publish to npm and push a git tag to origin.

Create first Nuxt module with starter template

To create a Nuxt module using the official starter template, run one of the following commands depending on your package manager: `npm create nuxt -- -t module my-module` (npm), `yarn create nuxt -t module my-module` (yarn), `pnpm create nuxt -t module my-module` (pnpm), or `bun create nuxt --template=module my-module` (bun). This creates a project called `my-module` with all necessary boilerplate for module development and publication.

First steps after creating a Nuxt module

After creating a module project: (1) Open the module folder in your IDE, (2) Install dependencies using your package manager, (3) Run `npm run dev:prepare` to prepare local files for development.

Develop Nuxt module with playground

To develop a Nuxt module, launch the playground development server with `npm run dev`. The playground will reload automatically when you make changes to your module in the `src` directory. Build the playground with `npm run dev:build`. Any nuxt command can be run against the playground directory using the syntax `nuxt <COMMAND> playground`.

Test Nuxt module starter suite

The module starter includes a linter powered by ESLint (run with `npm run lint`) and a test runner powered by Vitest (run with `npm run test` or `npm run test:watch`).

Build Nuxt module with @nuxt/module-builder

Nuxt modules use `@nuxt/module-builder` as their builder. It requires no configuration, supports TypeScript, and properly bundles assets for distribution. Build your module by running `npm run prepack`. The builder is automatically used by the playground during development and by the release script when publishing.

defineNuxtModule object syntax properties

The object passed to defineNuxtModule can have these properties: meta (with name, configKey, and compatibility constraints), defaults (default module configuration options, can be a function), hooks (shorthand to register Nuxt hooks), moduleDependencies (configuration for other modules), and setup (the function holding module logic, can be asynchronous).

defineNuxtModule meta property fields

The meta property in defineNuxtModule contains: name (usually the npm package name), configKey (the key in nuxt.config that holds module options), and compatibility (with a nuxt field for semver version constraints of supported Nuxt versions).

defineNuxtModule moduleDependencies configuration

The moduleDependencies property allows configuration for other modules. For each dependency, you can specify: version (a version constraint, throws error on startup if user has different version), optional (boolean, defaults to false; if false, the module is added to the list of modules to be installed), overrides (configuration to override nuxt.options), and defaults (configuration to set that will override module defaults but not nuxt.options).

defineNuxtModule wrapper function behavior

defineNuxtModule returns a wrapper function with the low-level (inlineOptions, nuxt) module signature. This wrapper automatically: supports defaults and meta.configKey for merging module options, provides type hints and type inference, ensures the module installs only once using a key from meta.name or meta.configKey, registers Nuxt hooks automatically, checks for compatibility issues, exposes getOptions and getMeta, ensures backward and upward compatibility, and integrates with module builder tooling.

Module runtime directory purpose

The runtime directory in a module allows modules to provide or inject runtime code to applications they're installed on. Modules themselves are not included in the application runtime, but the runtime directory enables injection of application code.

Runtime directory assets for Nitro server engine

Inside a module's runtime directory, you can provide assets for the Nitro server engine: API routes, middlewares, and Nitro plugins. These can be injected into users' applications.

Runtime directory assets for Nuxt applications

Inside a module's runtime directory, you can provide assets for Nuxt applications: Vue components, composables, and Nuxt plugins. These can be injected into users' Nuxt applications.

Runtime directory other assets

A module's runtime directory can provide any other kind of asset you want to inject in users' Nuxt applications, such as stylesheets, 3D models, images, or other files.

Published modules and auto-imports limitation

Published modules cannot leverage auto-imports for assets within their runtime directory. Instead, they must import assets explicitly from '#imports' or similar sources. Auto-imports are not enabled for files within node_modules (where published modules live) for performance reasons.

Two types of Nuxt modules

Nuxt modules are either published modules distributed on npm, or local modules that exist within a Nuxt project. Local modules can be inlined in Nuxt config or placed within the modules directory. In either case, they work in the same way.

Module definition entry point

The module definition is the entry point of a module and is what gets loaded by Nuxt when the module is referenced within a Nuxt configuration. At a low level, a module definition is a simple, potentially asynchronous function accepting inline user options and a nuxt object to interact with Nuxt.

Basic module definition function signature

A basic module definition function accepts two parameters: inlineOptions (the user options passed to the module) and nuxt (an object for interacting with Nuxt). The function can be asynchronous.

defineNuxtModule helper recommended approach

The recommended way to define a module is using the object-syntax with defineNuxtModule from @nuxt/kit, including a meta property to identify the module. This is especially recommended when publishing to npm. This helper makes writing modules more straightforward by implementing common patterns, guaranteeing future compatibility, and improving the experience for both module authors and users.

moduleDependencies basic structure

The moduleDependencies object uses module identifiers as keys (npm package names, local paths, or Nuxt aliases) and configuration objects as values. Each entry can specify version constraints, configuration overrides, defaults, and whether the dependency is optional.

moduleDependencies options reference

Each entry in moduleDependencies accepts four fields: (1) version - a semver range that Nuxt validates against the resolved module's version; applies only when dependency resolves to a package.json, so no-op for project-local modules. (2) overrides - configuration applied on top of nuxt.options, taking precedence over user configuration. (3) defaults - configuration applied below nuxt.options, where user configuration takes precedence. (4) optional - if true, the module is not installed automatically when missing, though overrides and defaults are still applied if the module is installed elsewhere.

moduleDependencies example with Tailwind CSS

Example showing a module depending on @nuxtjs/tailwindcss with version constraint >=6, overrides setting exposeConfig to true, and defaults specifying tailwind configuration including darkMode and content paths. The setup function then injects a CSS file containing Tailwind directives.

moduleDependencies option overview

The moduleDependencies option is used to declare dependencies on other modules in a Nuxt module. Nuxt ensures those modules are installed in the correct order, validates version constraints, and merges configuration. This option replaces the deprecated installModule function.

Local module paths in moduleDependencies

When declaring dependencies on local modules in the modules/ directory, use file paths relative to the project root. For example, a module at modules/foo.ts referencing modules/bar.ts must use './modules/bar', not './bar'. Nuxt aliases such as ~/modules/bar avoid this ambiguity.

Register keyed composables for state consistency

Use the keyedComposables option in nuxt.options.optimization.keyedComposables to register functions that need state consistency between server and client. Nuxt's compiler will automatically inject a unique stable key as an additional argument when the function is called with fewer than the specified argumentLength.

Modify Nuxt configuration in modules

Modules can read and alter Nuxt configuration via the nuxt.options object. When modifying complex configurations, consider using the defu utility to safely merge values. Example: nuxt.options.experimental ||= {} to create an object if it doesn't exist before setting properties.

Expose module options to runtime using runtimeConfig

Module options are not available at runtime by default. To expose module options to runtime code, use Nuxt's runtimeConfig configuration. Store module options in nuxt.options.runtimeConfig.public.myModule using defu to extend rather than overwrite user-provided config. Access exposed options at runtime using useRuntimeConfig().public.myModule.

Don't expose sensitive data in public runtime config

Be careful not to expose sensitive module configuration like private API keys in the public runtime config, as they will end up in the public bundle and be visible to users.

Add plugins from modules using addPlugin

Modules can register plugins using the addPlugin utility from @nuxt/kit. Use createResolver(import.meta.url) to resolve relative paths within the module. Call addPlugin with the resolved path to the plugin file.

Add Vue components from modules using addComponent

Use the addComponent utility to register Vue components as auto-imports in Nuxt. Provide the component name (used in templates), optionally the export name if it's a named export, and the filePath. Components can come from the module's runtime directory or from an external library.

Add multiple components directory from module using addComponentsDir

Use addComponentsDir to add an entire directory of components at once instead of registering each component individually. Provide the path to the components directory.

Module components and composables must be in runtime/app folder

All components, pages, composables and other files that would normally be placed in the app/ folder must be placed in runtime/app/ within a module. This ensures they can be type-checked properly.

Add composables from modules using addImports

Use the addImports utility to register composables as auto-imports. Provide the composable name, an optional alias (as), and the path to the composable. Multiple composables can be added by passing an array of objects.

Add composables directory from module using addImportsDir

Use addImportsDir to add an entire directory of composables at once instead of registering each individually. Provide the path to the composables directory.

Prefix module exports to avoid conflicts

It is highly recommended to prefix your module's exported components, composables, and server routes to avoid conflicts with user code or other modules.

keyedComposables configuration properties

The keyedComposables configuration accepts an array of objects with these properties: | Property | Type | Description | |----------|------|-------------| | name | string | The function name. Use 'default' for default exports (the callable name will be derived from the filename in camelCase). | | source | string | Resolved path to the file where the function is defined. Supports Nuxt aliases (~, @, etc.). | | argumentLength | number | Maximum number of arguments the function accepts. When called with fewer arguments, a unique key is injected. |

Key injection requires direct imports, not barrel exports

Key injection for keyed composables only works with direct imports from the exact source file specified in the source property. It does not follow barrel exports (like index.ts files that re-export). The function must be imported directly from the configured source file for the key injection to work.

Key injection requires statically analyzable function calls

Key injection for keyed composables only works when the compiler can statically analyze the function call. Dynamic property access, variable reassignment, callbacks, and destructured renaming in nested scopes will not trigger key injection.

Add route middleware from modules using addRouteMiddleware

Use the addRouteMiddleware utility to register route middleware from your module. Provide the global flag (true for global middleware), a name, and the path to the middleware file.

Add server routes from modules using addServerHandler

Use the addServerHandler utility to register server routes from your module. Provide the route path and the handler file path. Routes can include dynamic parameters like :name or catch-all patterns like **:path.

Prefix module server routes to avoid conflicts

It is highly recommended to prefix your module's server routes to avoid conflicts with user-defined routes. Common paths like /api/auth, /api/login, or /api/user may already be used by the application.

Add stylesheets from modules

Modules can inject stylesheets by pushing the resolved stylesheet path to nuxt.options.css array using the createResolver helper.

Add public assets from modules using Nitro publicAssets

Modules can expose public assets through Nitro's publicAssets option. Hook into the 'nitro:config' event, initialize nitroConfig.publicAssets as an array if needed, then push objects with dir (resolved path) and maxAge (cache duration in seconds) properties.

Declare module dependencies using moduleDependencies

If your module depends on other modules, specify them using the moduleDependencies option in the module definition. This ensures dependent modules are loaded before your module.

nitro:prepare:types hook for server type references

Use the `nitro:prepare:types` hook to extend TypeScript references for server context. The hook provides a `references` array where paths can be added: `nuxt.hook('nitro:prepare:types', ({ references }) => { references.push({ path: resolve('./augments.d.ts') }) })`.

Module directory structure for type contexts

Nuxt automatically includes module directories in appropriate type contexts based on their location: `my-module/runtime/` is in app type context, `my-module/runtime/server/` is in server type context, and `my-module/` (excluding runtime directories) is in node type context. Type declaration files placed in these directories are automatically augmented.

Modules can hook to lifecycle hooks through hooks map or programmatically

Modules can hook to Nuxt lifecycle hooks in two ways: through the `hooks` map in the module definition for declarative hooks, or programmatically using `nuxt.hook()` in the setup function. Example: `hooks: { 'app:error': (err) => {...} }` or `nuxt.hook('pages:extend', (pages) => {...})`.

Module cleanup with close hook

Modules that open resources, handle resources, or start watchers should clean them up when the Nuxt lifecycle is done using the `close` hook. This hook is called at the end of the Nuxt lifecycle to allow modules to perform cleanup operations.

Custom module hooks should be called in modules:done

Modules that define custom hooks and expect other modules to subscribe to them should call these hooks in the `modules:done` hook. This ensures all other modules have been set up and can register their listeners to the hook during their own setup function.

addTemplate utility for virtual files

Use the `addTemplate` utility to add a virtual file that can be imported into the user's app. The file is added to Nuxt's internal virtual file system and can be imported from '#build/<filename>'. It takes parameters including `filename` and `getContents()` which returns the file contents as a string.

addServerTemplate utility for server virtual files

Use the `addServerTemplate` utility to add a virtual file for the server. The file is added to Nitro's virtual file system and can be imported in server code directly by filename without the '#build/' prefix. It takes the same parameters as `addTemplate`: `filename` and `getContents()`.

updateTemplates utility for reloading templates

Use the `updateTemplates` utility to reload templates/virtual files. It can filter which templates to reload using a filter function. Example: `updateTemplates({ filter: t => t.filename === 'my-module-feature.mjs' })` reloads a specific template.

addTypeTemplate utility for type declarations

Use the `addTypeTemplate` utility to add a type declaration file to the user's project and automatically add a reference to it in the generated `nuxt.d.ts` file. It takes parameters including `filename` and `getContents()`. This is useful for augmenting Nuxt interfaces or providing global types.

prepare:types hook for granular type control

Use the `prepare:types` hook to register a callback that injects types with granular control. The hook provides `references`, `sharedReferences`, and `nodeReferences` arrays. Each can be used to add paths: `references.push({ path: resolve('./augments.d.ts') })`.

Extend TypeScript configuration from modules

Modules can extend TypeScript configuration by modifying `nuxt.options.typescript.tsConfig`, `nuxt.options.typescript.sharedTsConfig`, `nuxt.options.typescript.nodeTsConfig`, or `nuxt.options.typescript.serverTsConfig`. Push paths to the `include` array to add type files: `nuxt.options.typescript.tsConfig.include ??= []; nuxt.options.typescript.tsConfig.include.push(resolve('./augments.d.ts'))`.

Create a fixture Nuxt application for module testing

When testing a Nuxt module with Nuxt Test Utils, create a test fixture by placing a Nuxt application inside test/fixtures/* directory. This fixture should be a standard Nuxt configuration file (nuxt.config.ts) that imports and registers your module in the modules array.

Example: E2E test setup with Nuxt Test Utils

import { describe, expect, it } from 'vitest' import { fileURLToPath } from 'node:url' import { $fetch, setup } from '@nuxt/test-utils/e2e' describe('ssr', async () => { await setup({ rootDir: fileURLToPath(new URL('./fixtures/ssr', import.meta.url)), }) it('renders the index page', async () => { const html = await $fetch('/') expect(html).toContain('<div>ssr</div>') }) }) describe('csr', async () => { /* ... */ })

Nuxt Test Utils is the recommended library for module E2E testing

Nuxt Test Utils is the go-to library for end-to-end testing of Nuxt modules. It provides utilities like $fetch for interacting with test fixtures and setup for configuring the test environment.

Example: Fixture nuxt.config.ts for module testing

import MyModule from '../../../src/module' export default defineNuxtConfig({ ssr: true, modules: [ MyModule, ], })

Give your agent this brain