Test module locally with npm pack before publishing
To test your module with external Nuxt applications before publishing, use npm pack (or your package manager equivalent) to create a tarball from your module. Then in your test project, add the module to package.json as: "my-module": "file:/path/to/tarball.tgz". This allows you to reference the module as if it were installed from a registry.
Manual testing with playground application
Having a playground Nuxt application to test your module while developing it is useful. The module starter template includes a playground application for this purpose. You can also test your module with other Nuxt applications locally using npm pack.
E2E testing workflow for Nuxt modules with Nuxt Test Utils
To perform end-to-end testing of a Nuxt module using Nuxt Test Utils, follow this workflow: (1) Create a Nuxt application to be used as a fixture inside test/fixtures/*. (2) Setup Nuxt with this fixture inside your test file. (3) Interact with the fixture using utilities from @nuxt/test-utils (e.g., fetching a page). (4) Perform checks related to this fixture (e.g., verify HTML contains specific content). (5) Repeat the process for different test scenarios.
Setup Nuxt with fixture in test files
In your test files, use the setup function from @nuxt/test-utils/e2e to initialize Nuxt with your fixture. Pass the rootDir option pointing to your fixture directory using fileURLToPath and import.meta.url to resolve the correct path.
How to list a community module
Any community modules are welcome to be listed on the official module list. To be listed, open an issue in the nuxt/modules repository using the module_request.yml template. The Nuxt team can help apply best practices before listing.
Official modules naming convention
Official modules are prefixed (scoped) with @nuxt/ (for example @nuxt/content). They are made and maintained actively by the Nuxt team. Community contributions are welcome to help improve them.
Community modules naming convention
Community modules are prefixed (scoped) with @nuxtjs/ (for example @nuxtjs/tailwindcss). They are proven modules made and maintained by community members. Contributions from anyone are welcome.
Third-party and other community modules naming convention
Third-party and other community modules are often prefixed with nuxt-. Anyone can create them using this prefix, which allows these modules to be discoverable on npm. This prefix is the best starting point to draft and try an idea.
Private or personal modules naming convention
Private or personal modules are made for a specific use case or company. They do not need to follow any specific naming rules to work with Nuxt. They are often scoped under an npm organization (for example @my-company/nuxt-auth).
Nuxt module ecosystem statistics
The Nuxt module ecosystem represents more than 35 million monthly NPM downloads and provides extended functionalities and integrations with various tools.
Transferring modules to nuxt-modules
If you have an already published and working module and want to transfer it to nuxt-modules, open an issue in the nuxt/modules repository. By joining nuxt-modules, your community module can be renamed under the @nuxtjs/ scope and provided with a subdomain (for example my-module.nuxtjs.org) for its documentation.
Benefits of joining nuxt-modules
By moving your modules to nuxt-modules, there is always someone else to help and you can join forces to make one perfect solution. The Nuxt team provides support and infrastructure for your module.
Follow starter conventions for open-source modules
The module starter includes default tools and configurations like ESLint. Sticking with these defaults ensures the module shares consistent coding style with other community modules, making it easier for others to contribute.
Module setup time warning threshold
If a Nuxt module takes more than 1 second to setup, Nuxt will emit a warning about it.
Stay version agnostic for Nuxt modules
Use 'X for Nuxt' instead of 'X for Nuxt 3' to avoid ecosystem fragmentation. Use meta.compatibility to set Nuxt version constraints instead of version-specific naming.
Defer time-consuming module logic to hooks
Nuxt waits for module setup before proceeding to the next module and starting the development server or build process. Prefer deferring time-consuming logic to Nuxt hooks instead of blocking the module setup.
Prefix module exports to avoid conflicts
Nuxt modules should provide an explicit prefix for any exposed configuration, plugin, API, composable, component, or server route to avoid conflicts with other modules, Nuxt internals, or user-defined code. Ideally, prefix them with the module's name.
Component naming convention in modules
For a module called 'nuxt-foo', components should be prefixed with the module name. Avoid names like 'Button' or 'Modal'; instead use 'FooButton' or 'FooModal'.
Composable naming convention in modules
For a module called 'nuxt-foo', composables should be prefixed with the module name. Avoid names like 'useData()' or 'useModal()'; instead use 'useFooData()' or 'useFooModal()'.
Server route naming convention in modules
For a module called 'nuxt-foo', server routes should use a unique prefix based on the module name. Use '/api/_foo/track' instead of '/api/track', or '/_foo/...' for non-API routes. This prevents conflicts with common paths like /api/auth, /api/login, or /api/user already used by applications.
Use lifecycle hooks for one-time module setup tasks
When a module needs to perform one-time setup tasks like generating configuration files, setting up databases, or installing dependencies, use lifecycle hooks (onInstall, onUpgrade) instead of running logic in the main setup function. This prevents unnecessary work on every build.
Module lifecycle hooks example
import { addServerHandler, defineNuxtModule } from 'nuxt/kit'
import { isLess } from 'verkit'
export default defineNuxtModule({
meta: {
name: 'my-database-module',
version: '1.0.0',
},
async onInstall (nuxt) {
// One-time setup: create database schema, generate config files, etc.
await generateDatabaseConfig(nuxt.options.rootDir)
},
async onUpgrade (nuxt, options, previousVersion) {
// Handle version-specific migrations
if (isLess(previousVersion, '1.0.0')) {
await migrateLegacyData()
}
},
setup (options, nuxt) {
// Regular setup logic that runs on every build
addServerHandler({ /* ... */ })
},
})
This example shows how to use lifecycle hooks for database module setup and migration handling.
Be TypeScript friendly in modules
Nuxt modules should expose types and be developed using TypeScript to provide first-class TypeScript integration. This benefits users even when they are not using TypeScript directly.
Use ESM syntax in Nuxt modules
Nuxt relies on native ESM, so modules should use ESM syntax.
Document Nuxt module usage
Module documentation in the readme file should explain why the module is useful, how to use it, and what it does. Linking to integration website and documentation is recommended.
Provide a demo for Nuxt modules
Create a minimal reproduction with the module using StackBlitz and add it to the module readme. This provides potential users a quick way to experiment with the module and helps them build minimal reproductions to send when encountering issues.
Nuxt modules definition and purpose
Nuxt modules are functions that sequentially run when starting Nuxt in development mode using `nuxt dev` or building a project for production with `nuxt build`. With modules, you can encapsulate, properly test, and share custom solutions as npm packages without adding unnecessary boilerplate to your project, or requiring changes to Nuxt itself.
Nuxt configuration and hooks enable customization
Nuxt's configuration and hooks systems make it possible to customize every aspect of Nuxt and add any integration you might need, including Vue plugins, CMS, server routes, components, logging, and other functionality.
Configure Vite plugins in nuxt.config.ts
Vite plugins can be added to a Nuxt project by importing the plugin and adding it to the vite.plugins array in nuxt.config.ts. For example, to add the @rollup/plugin-yaml plugin, import it and configure it like this:
export default defineNuxtConfig({
vite: {
plugins: [
yaml(),
],
},
})
Use addVitePlugin in Nuxt modules
When developing a Nuxt module that needs to add Vite plugins, use the addVitePlugin utility from @nuxt/kit instead of configuring directly in nuxt.config.ts. This is the recommended approach for module development.
Environment-specific Vite plugins in Nuxt 5+
In Nuxt 5+, you can apply Vite plugins to specific environments using the applyToEnvironment() method within addVitePlugin. This method receives an environment object and should return true if the plugin should apply to that environment. For example, you can check if environment.name === 'client' to apply a plugin only to the client environment.
Use Vite plugin hooks for config access in modules
When writing Vite plugins within Nuxt modules that need to access resolved Vite configuration, use the config and configResolved hooks within the Vite plugin itself. Do not use Nuxt's vite:extend, vite:extendConfig, or vite:configResolved hooks for this purpose.
addVitePlugin utility for Nuxt modules example
Example of adding a Vite plugin in a Nuxt module using addVitePlugin:
import { addVitePlugin, defineNuxtModule } from '@nuxt/kit'
import yaml from '@rollup/plugin-yaml'
export default defineNuxtModule({
setup () {
addVitePlugin(yaml())
},
})
applyToEnvironment method example for Nuxt 5+
Example of using applyToEnvironment() to apply a Vite plugin to specific environments:
import { addVitePlugin, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup () {
addVitePlugin(() => ({
name: 'my-client-plugin',
applyToEnvironment (environment) {
return environment.name === 'client'
},
// Plugin configuration
}))
},
})
Nuxt kit functions for adding routes in modules
The Nuxt kit provides extendPages (callback: pages => void) and extendRouteRules (route: string, rule: NitroRouteConfig, options: ExtendRouteRulesOptions) functions for adding routes within a Nuxt module.
nuxt-auth-utils module for sessions and authentication
The nuxt-auth-utils module provides convenient utilities for managing client-side and server-side session data in Nuxt applications. It uses secured and sealed cookies to store session data, eliminating the need for a separate database to store session data.
Install nuxt-auth-utils with nuxt CLI
Install nuxt-auth-utils using the command: npx nuxt module add auth-utils. This command installs nuxt-auth-utils as a dependency and automatically adds it to the modules section of nuxt.config.ts.
NUXT_SESSION_PASSWORD environment variable for cookie encryption
Session cookies in nuxt-auth-utils are encrypted using a secret key from the NUXT_SESSION_PASSWORD environment variable. The password must be at least 32 characters long. If not set during development, this environment variable will be automatically added to the .env file. For production, this environment variable must be manually added before deploying.
setUserSession server utility for setting user sessions
The setUserSession server utility is auto-imported by the auth-utils module and is used to set the user session in a secured cookie. It takes the event object and a session object containing user data.
useUserSession composable for authentication state
The useUserSession composable is a Vue composable exposed by nuxt-auth-utils that provides authentication state. It returns loggedIn (boolean), session (the full session object), user (user data), clear (function to clear session), and fetch (function to refresh session on client-side).
requireUserSession utility for protecting server routes
The requireUserSession utility function is provided by the auth-utils module to protect server routes. It ensures that users are logged in and have an active session. If the request does not come from a valid user session, it throws a 401 error. This function returns an object containing the user data.
Login API route implementation example
Example of a login API route in server/api/login.post.ts that accepts POST requests with email and password, validates them with zod, and uses setUserSession to set the user session if credentials are valid:
```ts
import { z } from 'zod'
const bodySchema = z.object({
email: z.email(),
password: z.string().min(8),
})
export default defineEventHandler(async (event) => {
const { email, password } = await readValidatedBody(event, bodySchema.parse)
if (email === 'admin@admin.com' && password === 'iamtheadmin') {
await setUserSession(event, {
user: {
name: 'John Doe',
},
})
return {}
}
throw createError({
status: 401,
message: 'Bad credentials',
})
})
```
Login page with form submission example
Example of a login page in app/pages/login.vue that uses useUserSession composable and submits credentials to /api/login:
```vue
<script setup lang="ts">
const { loggedIn, user, fetch: refreshSession } = useUserSession()
const credentials = reactive({
email: '',
password: '',
})
async function login () {
try {
await $fetch('/api/login', {
method: 'POST',
body: credentials,
})
await refreshSession()
await navigateTo('/')
} catch {
alert('Bad credentials')
}
}
</script>
<template>
<form @submit.prevent="login">
<input
v-model="credentials.email"
type="email"
placeholder="Email"
>
<input
v-model="credentials.password"
type="password"
placeholder="Password"
>
<button type="submit">
Login
</button>
</form>
</template>
```
Protected API route example using requireUserSession
Example of a protected API route in server/api/user/stats.get.ts that uses requireUserSession to ensure only authenticated users can access it:
```ts
export default defineEventHandler(async (event) => {
const { user } = await requireUserSession(event)
return {}
})
```
Server-side route protection is critical for data security
While client-side middleware is helpful for user experience, it is critical to implement server-side route protection for any routes with sensitive data. Without server-side protection, data can still be accessed directly. Protected routes should return a 401 error if the user is not logged in.
Extend Nuxt Interface and Build Process
To extend the Nuxt interface and hook into different stages of the build process, use Nuxt modules. Modules can interact with the Builder Core context.
Nuxt Hooks in modules using defineNuxtModule
Nuxt Hooks can be defined in Nuxt modules using the setup function of defineNuxtModule. The nuxt parameter provides access to hooks via nuxt.hook(). Example: export default defineNuxtModule({ setup (options, nuxt) { nuxt.hook('close', async () => { }) } })
@nuxt/kit installation and version requirements
The @nuxt/kit package should be explicitly installed in the dependencies section of package.json. The versions of @nuxt/kit and @nuxt/schema must be equal to or greater than the nuxt version to avoid unexpected behavior.
Nuxt Kit is ESM-only
Nuxt Kit is an ESM-only package and cannot be imported using require('@nuxt/kit'). In CommonJS contexts, use dynamic import with await import('@nuxt/kit') instead.
Nuxt Kit provides utilities for module authors
Nuxt Kit provides composable utilities for module authors to interact with Nuxt Hooks, the Nuxt Interface, and develop Nuxt modules.
Nuxt Kit utilities are only for modules
Nuxt Kit utilities are only available for modules and should not be imported in runtime code such as components, Vue composables, pages, plugins, or server routes.
Import Nuxt Kit utilities example
To use Nuxt Kit, import utilities from '@nuxt/kit': import { useNuxt } from '@nuxt/kit'
getLayerDirectories utility for multi-layer module support
The getLayerDirectories utility from Nuxt Kit allows modules to support custom multi-layer handling. It returns an array of layer directories where earlier items have higher priority and override later ones. The user's project is the first item in the array. Each layer object contains properties like root, app, server, and appPages.
Disabling modules from layers
When extending a layer, you can disable certain modules by setting the module's config key to false in your Nuxt config. For example: image: false disables @nuxt/image, pinia: false disables @pinia/nuxt, content: false disables @nuxt/content. The config key is defined by each module.
NuxtPicture setup requirement
To use NuxtPicture, you must install and enable the Nuxt Image module using the command 'npx nuxt module add image'.