Modules
Modules are the building blocks of Nuxt. Kit provides a set of utilities to help you create and use modules. You can use these utilities to create your own modules or to reuse existing modules. For example, you can use the defineNuxtModule
function to define a module and the installModule
function to install a module programmatically.
defineNuxtModule
Define a Nuxt module, automatically merging defaults with user provided options, installing any hooks that are provided, and calling an optional setup function for full control.
Usage
import { defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
meta: {
name: 'my-module',
configKey: 'myModule'
},
defaults: {
enabled: true
},
setup (options) {
if (options.enabled) {
console.log('My Nuxt module is enabled!')
}
}
})
Type
export function defineNuxtModule<TOptions extends ModuleOptions> (
definition?: ModuleDefinition<TOptions, Partial<TOptions>, false> | NuxtModule<TOptions, Partial<TOptions>, false>,
): NuxtModule<TOptions, TOptions, false>
export function defineNuxtModule<TOptions extends ModuleOptions> (): {
with: <TOptionsDefaults extends Partial<TOptions>> (
definition: ModuleDefinition<TOptions, TOptionsDefaults, true> | NuxtModule<TOptions, TOptionsDefaults, true>
) => NuxtModule<TOptions, TOptionsDefaults, true>
}
Parameters
definition: A module definition object or a module function. The module definition object should contain the following properties:
Property | Type | Required | Description |
---|---|---|---|
meta | ModuleMeta | false | Metadata of the module. It defines the module name, version, config key and compatibility. |
defaults | T | ((nuxt: Nuxt) => T) | false | Default options for the module. If a function is provided, it will be called with the Nuxt instance as the first argument. |
schema | T | false | Schema for the module options. If provided, options will be applied to the schema. |
hooks | Partial<NuxtHooks> | false | Hooks to be installed for the module. If provided, the module will install the hooks. |
onInstall | (nuxt: Nuxt) => Awaitable<void> | false | Lifecycle hook called when the module is first installed. Requires meta.name and meta.version to be defined. |
onUpgrade | (options: T, nuxt: Nuxt, previousVersion: string) => Awaitable<void> | false | Lifecycle hook called when the module is upgraded to a newer version. Requires meta.name and meta.version to be defined. |
setup | (this: void, resolvedOptions: T, nuxt: Nuxt) => Awaitable<void | false | ModuleSetupInstallResult> | false | Setup function for the module. If provided, the module will call the setup function. |
Examples
Using configKey
to Make Your Module Configurable
When defining a Nuxt module, you can set a configKey
to specify how users should configure the module in their nuxt.config
.
import { defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
meta: {
name: 'my-module',
configKey: 'myModule'
},
defaults: {
// Module options
enabled: true
},
setup (options) {
if (options.enabled) {
console.log('My Nuxt module is enabled!')
}
}
})
Users can provide options for this module under the corresponding key in nuxt.config
.
export default defineNuxtConfig({
myModule: {
enabled: false
}
})
Defining Module Compatibility Requirements
If you're developing a Nuxt module and using APIs that are only supported in specific Nuxt versions, it's highly recommended to include compatibility.nuxt
.
export default defineNuxtModule({
meta: {
name: '@nuxt/icon',
configKey: 'icon',
compatibility: {
// Required nuxt version in semver format.
nuxt: '>=3.0.0', // or use '^3.0.0'
},
},
async setup() {
const resolver = createResolver(import.meta.url)
// Implement
},
})
If the user tries to use your module with an incompatible Nuxt version, they will receive a warning in the console.
WARN Module @nuxt/icon is disabled due to incompatibility issues:
- [nuxt] Nuxt version ^3.1.0 is required but currently using 3.0.0
Type Safety for Resolved Options with .with()
When you need type safety for your resolved/merged module options, you can use the .with()
method. This enables TypeScript to properly infer the relationship between your module's defaults and the final resolved options that your setup function receives.
import { defineNuxtModule } from '@nuxt/kit'
// Define your module options interface
interface ModuleOptions {
apiKey: string
baseURL: string
timeout?: number
retries?: number
}
export default defineNuxtModule<ModuleOptions>().with({
meta: {
name: '@nuxtjs/my-api',
configKey: 'myApi'
},
defaults: {
baseURL: 'https://api.example.com',
timeout: 5000,
retries: 3
},
setup(resolvedOptions, nuxt) {
// resolvedOptions is properly typed as:
// {
// apiKey: string // Required, no default provided
// baseURL: string // Required, has default value
// timeout: number // Optional, has default value
// retries: number // Optional, has default value
// }
console.log(resolvedOptions.baseURL) // ✅ TypeScript knows this is always defined
console.log(resolvedOptions.timeout) // ✅ TypeScript knows this is always defined
console.log(resolvedOptions.retries) // ✅ TypeScript knows this is always defined
}
})
Without using .with()
, the resolvedOptions
parameter would be typed as the raw ModuleOptions
interface, where timeout
and retries
could be undefined
even when defaults are provided. The .with()
method enables TypeScript to understand that default values make those properties non-optional in the resolved options.
Using Lifecycle Hooks for Module Installation and Upgrade
You can define lifecycle hooks that run when your module is first installed or upgraded to a new version. These hooks are useful for performing one-time setup tasks, database migrations, or cleanup operations.
meta.name
and meta.version
in your module definition. The hooks use these values to track the module's installation state in the project's .nuxtrc
file.Lifecycle hooks run before the main setup
function, and if a hook throws an error, it's logged but doesn't stop the build process.
onInstall
runs only once when the module is first added to a project.
onUpgrade
runs each time the module version increases (using semver comparison) — but only once for each version bump.
Example
import { defineNuxtModule } from '@nuxt/kit'
import semver from 'semver'
export default defineNuxtModule({
meta: {
name: 'my-awesome-module',
version: '1.2.0', // Required for lifecycle hooks
configKey: 'myAwesomeModule'
},
defaults: {
apiKey: '',
enabled: true
},
onInstall(nuxt) {
// This runs only when the module is first installed
console.log('Setting up my-awesome-module for the first time!')
// You might want to:
// - Create initial configuration files
// - Set up database schemas
// - Display welcome messages
// - Perform initial data migration
},
onUpgrade(options, nuxt, previousVersion) {
// This runs when the module is upgraded to a newer version
console.log(`Upgrading my-awesome-module from ${previousVersion} to 1.2.0`)
// You might want to:
// - Migrate configuration files
// - Update database schemas
// - Clean up deprecated files
// - Display upgrade notes
if (semver.lt(previousVersion, '1.1.0')) {
console.log('⚠️ Breaking changes in 1.1.0 - please check the migration guide')
}
},
setup(options, nuxt) {
// Regular setup logic runs on every build
if (options.enabled) {
// Configure the module
}
}
})
installModule
Install specified Nuxt module programmatically. This is helpful when your module depends on other modules. You can pass the module options as an object to inlineOptions
and they will be passed to the module's setup
function.
Usage
import { defineNuxtModule, installModule } from '@nuxt/kit'
export default defineNuxtModule({
async setup () {
// will install @nuxtjs/fontaine with Roboto font and Impact fallback
await installModule('@nuxtjs/fontaine', {
// module configuration
fonts: [
{
family: 'Roboto',
fallbacks: ['Impact'],
fallbackName: 'fallback-a',
}
]
})
}
})
Type
async function installModule (moduleToInstall: string | NuxtModule, inlineOptions?: any, nuxt?: Nuxt)
Parameters
Property | Type | Required | Description |
---|---|---|---|
moduleToInstall | string | NuxtModule | true | The module to install. Can be either a string with the module name or a module object itself. |
inlineOptions | any | false | An object with the module options to be passed to the module's setup function. |
nuxt | Nuxt | false | Nuxt instance. If not provided, it will be retrieved from the context via useNuxt() call. |
Examples
import { defineNuxtModule, installModule } from '@nuxt/kit'
export default defineNuxtModule({
async setup (options, nuxt) {
// will install @nuxtjs/fontaine with Roboto font and Impact fallback
await installModule('@nuxtjs/fontaine', {
// module configuration
fonts: [
{
family: 'Roboto',
fallbacks: ['Impact'],
fallbackName: 'fallback-a',
}
]
})
}
})