Nitro
Nitro is an open source TypeScript framework to build ultra-fast web servers. Nuxt uses Nitro as its server engine. You can use useNitro to access the Nitro instance (or tryUseNitro if your module should also work without Nitro), addServerHandler to add a server handler, addDevServerHandler to add a server handler to be used only in development mode, addNitroPlugin to add a plugin to extend Nitro's runtime behavior, and addPrerenderRoutes to add routes to be prerendered by Nitro.
addServerHandler
Adds a Nitro server handler. Use this if you want to create server middleware or a custom route.
Usage
import { addServerHandler, createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup (options) {
const { resolve } = createResolver(import.meta.url)
addServerHandler({
route: '/robots.txt',
handler: resolve('./runtime/robots.get'),
})
},
})
Type
function addServerHandler (handler: ServerHandlerInput): void
Parameters
handler: A handler object with the following properties:
| Property | Type | Required | Description |
|---|---|---|---|
handler | string | { nuxt?: string, nitro2?: string, nitro3?: string } | true | Path to the event handler, or one path per server API. Nuxt registers the implementation the application's server can run. |
route | string | false | The route to match, exactly. End it in /** to match the paths below it as well. If an empty string is used, the handler is registered as middleware. |
middleware | boolean | false | Specifies this is a middleware handler. Middleware are called on every route and should normally return nothing to pass to the next handlers. |
lazy | boolean | false | Use lazy loading to import the handler. This is useful when you only want to load the handler on demand. |
method | string | false | Router method matcher. If handler name contains method name, it will be used as a default value. |
A route ending in /** matches its base path too, so route: '/_fonts/**' serves /_fonts and everything below it. On a Nitro 2 host, whose router matches only the paths below the base, Nuxt registers the base path as a second route so that one registration behaves the same on both.
Example
Basic Usage
You can use addServerHandler to add a server handler from your module.
import { addServerHandler, createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup (options) {
const { resolve } = createResolver(import.meta.url)
addServerHandler({
route: '/robots.txt',
handler: resolve('./runtime/robots.get'),
})
},
})
import { defineEventHandler } from 'nitro/h3'
export default defineEventHandler(() => {
return {
body: `User-agent: *\nDisallow: /`,
}
})
When you access /robots.txt, it will return the following response:
User-agent: *
Disallow: /
addDevServerHandler
Adds a Nitro server handler to be used only in development mode. This handler will be excluded from production build.
Usage
import { defineEventHandler } from 'nitro/h3'
import { addDevServerHandler, createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup () {
addDevServerHandler({
handler: defineEventHandler(() => {
return {
body: `Response generated at ${new Date().toISOString()}`,
}
}),
route: '/_handler',
})
},
})
Type
function addDevServerHandler (handler: DevServerHandlerInput): void
Parameters
handler: A handler object with the following properties:
| Property | Type | Required | Description |
|---|---|---|---|
handler | EventHandler | true | Event handler. |
route | string | false | Path prefix or route. If an empty string used, will be used as a middleware. |
Example
Basic Usage
In some cases, you may want to create a server handler specifically for development purposes, such as a Tailwind config viewer.
import { joinURL } from 'ufo'
import { addDevServerHandler, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
async setup (options, nuxt) {
const route = joinURL(nuxt.options.app?.baseURL, '/_tailwind')
// @ts-expect-error - tailwind-config-viewer does not have correct types
const createServer = await import('tailwind-config-viewer/server/index.js').then(r => r.default || r) as any
const viewerDevMiddleware = createServer({ tailwindConfigProvider: () => options, routerPrefix: route }).asMiddleware()
addDevServerHandler({ route, handler: viewerDevMiddleware })
},
})
useNitro
Returns the Nitro instance.
useNitro() only after ready hook.Usage
import { defineNuxtModule, useNitro } from '@nuxt/kit'
export default defineNuxtModule({
setup (options, nuxt) {
const resolver = createResolver(import.meta.url)
nuxt.hook('ready', () => {
const nitro = useNitro()
// Do something with Nitro instance
})
},
})
Type
function useNitro (): Nitro
tryUseNitro
Returns the Nitro instance, or undefined when there is none.
There is no Nitro instance before the ready hook has run, and none at all when the
configured server.builder does not use Nitro, such as a
builder that outputs a client-only SPA. Use this rather than useNitro() for anything that
should keep working without a server: server routes, route rules and prerendering are all
absent in that case.
Usage
import { defineNuxtModule, tryUseNitro } from '@nuxt/kit'
export default defineNuxtModule({
setup (options, nuxt) {
nuxt.hook('ready', () => {
const nitro = tryUseNitro()
if (!nitro) {
// no server: skip anything that would only run there
return
}
})
},
})
Type
function tryUseNitro (): Nitro | undefined
addNitroPlugin
Add plugin to extend Nitro's runtime behavior.
addServerPlugin before Nuxt v4.6.definePlugin from nitro within your plugin file. The same requirement applies to utilities such as useRuntimeConfig.Usage
import { addNitroPlugin, createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup () {
const { resolve } = createResolver(import.meta.url)
addNitroPlugin(resolve('./runtime/plugin.ts'))
},
})
Type
function addNitroPlugin (plugin: string | { nitro2?: string, nitro3?: string }): void
Parameters
| Property | Type | Required | Description |
|---|---|---|---|
plugin | string | { nitro2?: string, nitro3?: string } | true | Path to the plugin, or one path per nitro major for a module shipping an implementation for each. The plugin must export a default function that accepts the Nitro instance as an argument. |
Example
import { addNitroPlugin, createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup () {
const { resolve } = createResolver(import.meta.url)
addNitroPlugin(resolve('./runtime/plugin.ts'))
},
})
import { definePlugin } from 'nitro'
export default definePlugin((nitroApp) => {
nitroApp.hooks.hook('request', (event) => {
console.log('on request', event.req.url)
})
nitroApp.hooks.hook('response', async (res) => {
console.log('on response', await res.text())
})
})
addPrerenderRoutes
Add routes to be prerendered to Nitro.
Usage
import { addPrerenderRoutes, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
meta: {
name: 'nuxt-sitemap',
configKey: 'sitemap',
},
defaults: {
sitemapUrl: '/sitemap.xml',
prerender: true,
},
setup (options) {
if (options.prerender) {
addPrerenderRoutes(options.sitemapUrl)
}
},
})
Type
function addPrerenderRoutes (routes: string | string[]): void
Parameters
| Property | Type | Required | Description |
|---|---|---|---|
routes | string | string[] | true | A route or an array of routes to prerender. |
addServerImports
Add imports to the server. It makes your imports available in Nitro without the need to import them manually.
shared/ directory, the function must be imported from the same source file for both addImports and addServerImports and should have identical signature. That source file should not import anything context-specific (i.e., Nitro context, Nuxt app context) or else it might cause errors during type-checking.Usage
import { addServerImports, createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup (options) {
const names = [
'useStoryblok',
'useStoryblokApi',
'useStoryblokBridge',
'renderRichText',
'RichTextSchema',
]
names.forEach(name =>
addServerImports({ name, as: name, from: '@storyblok/vue' }),
)
},
})
Type
function addServerImports (dirs: NuxtImport | NuxtImport[]): void
Parameters
imports: An object or an array of objects with the following properties:
| Property | Type | Required | Description |
|---|---|---|---|
name | string | true | Import name to be detected. |
from | string | true | Module specifier to import from. |
priority | number | false | Priority of the import; if multiple imports have the same name, the one with the highest priority will be used. |
disabled | boolean | false | If this import is disabled. |
meta | Record<string, any> | false | Metadata of the import. |
type | boolean | false | If this import is a pure type import. |
typeFrom | string | false | Use this as the from value when generating type declarations. |
as | string | false | Import as this name. |
addServerImportsDir
Add a directory to be scanned for auto-imports by Nitro.
Usage
import { addServerImportsDir, createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
meta: {
name: 'my-module',
configKey: 'myModule',
},
setup (options) {
const { resolve } = createResolver(import.meta.url)
addServerImportsDir(resolve('./runtime/server/composables'))
},
})
Type
function addServerImportsDir (dirs: string | string[], opts: { prepend?: boolean }): void
Parameters
| Property | Type | Required | Description |
|---|---|---|---|
dirs | string | string[] | true | A directory or an array of directories to register to be scanned by Nitro. |
opts | { prepend?: boolean } | false | Options for the import directory. If prepend is true, the directory is added to the beginning of the scan list. |
Example
You can use addServerImportsDir to add a directory to be scanned by Nitro. This is useful when you want Nitro to auto-import functions from a custom server directory.
import { addServerImportsDir, createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
meta: {
name: 'my-module',
configKey: 'myModule',
},
setup (options) {
const { resolve } = createResolver(import.meta.url)
addServerImportsDir(resolve('./runtime/server/composables'))
},
})
export function useApiSecret () {
const { apiSecret } = useRuntimeConfig()
return apiSecret
}
You can then use the useApiSecret function in your server code:
import { defineEventHandler } from 'nitro/h3'
const useApiSecret = (): string => ''
// ---cut---
export default defineEventHandler(() => {
const apiSecret = useApiSecret()
// Do something with the apiSecret
})
addServerScanDir
Add directories to be scanned by Nitro. It will check for subdirectories, which will be registered
just like the ~~/server folder is.
~~/server/api, ~~/server/routes, ~~/server/middleware, and ~~/server/utils are scanned.Usage
import { addServerScanDir, createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
meta: {
name: 'my-module',
configKey: 'myModule',
},
setup (options) {
const { resolve } = createResolver(import.meta.url)
addServerScanDir(resolve('./runtime/server'))
},
})
Type
function addServerScanDir (dirs: string | string[], opts: { prepend?: boolean }): void
Parameters
| Property | Type | Required | Description |
|---|---|---|---|
dirs | string | string[] | true | A directory or an array of directories to register to be scanned for by Nitro as server dirs. |
opts | { prepend?: boolean } | false | Options for the import directory. If prepend is true, the directory is added to the beginning of the scan list. |
Example
You can use addServerScanDir to add a directory to be scanned by Nitro. This is useful when you want to add a custom server directory.
import { addServerScanDir, createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
meta: {
name: 'my-module',
configKey: 'myModule',
},
setup (options) {
const { resolve } = createResolver(import.meta.url)
addServerScanDir(resolve('./runtime/server'))
},
})
export function hello () {
return 'Hello from server utils!'
}
You can then use the hello function in your server code.
import { defineEventHandler } from 'nitro/h3'
function hello () {
return 'Hello from server utils!'
}
// ---cut---
export default defineEventHandler(() => {
return hello() // Hello from server utils!
})