Server Imports

Source
`nuxt/server` is the import surface for server code that isn't tied to a particular server runtime.

It's possible to use different server builders with Nuxt, either Nitro 3 (nitro, with Nuxt 5+), Nitro 2 (nitropack, with Nuxt 3/4), or Vite directly.

nuxt/server exists to provide agnostic utilities for server code that aren't tied to a particular server runtime. It is the second runtime surface of Nuxt, alongside nuxt/app (also reachable as #app), which is for the part of your application that also runs in the browser.

server/api/hello.ts
import { defineEventHandler, getQuery } from 'nuxt/server'

export default defineEventHandler((event) => {
  const { name } = getQuery<{ name?: string }>(event)
  return { message: `Hello, ${name ?? 'world'}!` }
})

This code can run under @nuxt/nitro-server and under @nuxt/vite-server, and will also keep running across an h3 or Nitro major, because Nuxt absorbs those changes centrally.

nuxt/server ships from Nuxt 4.6, so one file can serve Nuxt 4.6 running nitropack v2, Nuxt 5 running Nitro v3, and anything a future builder brings.

nuxt is installed in every Nuxt application, so nuxt/server resolves with no alias and no added dependency. A module importing from it needs no peer dependency on h3 or Nitro.

Types and Utilities

ImportPurpose
defineEventHandlerDefine a request handler.
createError, isNuxtErrorConstruct and recognise an HTTP error.
getRequestURLThe URL of the request.
getRequestHeader, getRequestHeadersRead request headers.
getQueryRead the query string.
readBodyRead and parse the request body.
getCookie, setCookie, deleteCookieRead and write cookies.
setResponseStatusSet the response status and reason phrase.
setResponseHeader, setResponseHeadersSet response headers.
sendRedirectRedirect the request.
getRouteRulesThe route rules matched for the request.
useRuntimeConfigThe server's runtime configuration.
toNuxtRequestEventThe event in the shape the server runtime provides.

Types are exported alongside the utilities: RequestEvent, RequestEventContext, NuxtRequestEvent, EventHandler, AppRouteRules, ServerRoutes, NuxtError, NuxtErrorDetails, NuxtErrorJSON and NuxtErrorLike.

These names are auto-imported in server code, so the import statement above is optional. Writing it keeps the file working in a project with server auto-imports off, and is what a module should do.

defineEventHandler preserves your handler's return type, which is what types $fetch and useFetch calls to the route. Annotate the value you return rather than the handler.

The Event

RequestEvent is the event that nuxt/server utilities operate from, including the request, its URL, the response to be sent, and the request context.

interface RequestEvent {
  readonly req: Request
  url: URL
  readonly res: { status?: number, statusText?: string, readonly headers: Headers }
  readonly context: RequestEventContext
}

Nitro adds more on top, such as event.node, event.runtime and event.waitUntil(), but these four core properties work in all runtimes, and need no helpers:

server/api/echo.post.ts
export default defineEventHandler(async (event) => {
  const { id } = await event.req.json()
  return { id, page: event.url.searchParams.get('page') }
})

NuxtRequestEvent is the same request in the shape the configured builder provides, which is h3's H3Event under @nuxt/nitro-server. You can get a type-safe version of the event for the server builder you're using by calling toNuxtRequestEvent(event).

Reaching Past the Surface

nuxt/server isn't a re-export of h3, so if you need something else that h3 and Nitro offer, such as the server lifecycle (definePlugin, defineErrorHandler and the Nitro app hooks), you would import it directly.

Most of those helpers take the event as it is:

server/api/upload.post.ts
import { defineEventHandler } from 'nuxt/server'
import { readValidatedBody } from 'nitro/h3'

export default defineEventHandler(async (event) => {
  const body = await readValidatedBody(event, schema)
  return { received: body }
})

That works for any h3 helper that only reads the request: readValidatedBody, getValidatedQuery, getRouterParam, getRouterParams, getRequestIP, assertMethod, and the session helpers (useSession, getSession, updateSession, clearSession).

A helper that needs the runtime's own event gets it from toNuxtRequestEvent:

server/api/cors.ts
import { defineEventHandler, toNuxtRequestEvent } from 'nuxt/server'
import { handleCors } from 'nitro/h3'

export default defineEventHandler((event) => {
  handleCors(toNuxtRequestEvent(event), { origin: '*' })
  return { ok: true }
})

Helpers that need you to call toNuxtRequestEvent are the CORS helpers (such as handleCors), proxy, proxyRequest, fetchWithEvent, writeEarlyHints, and reading event.node, event.waitUntil() or event.runtime. The helper works on every builder, and a cast to NuxtRequestEvent is safe even if the runtime's event is web-shaped, as it is under @nuxt/nitro-server.

Nitro's own APIs mostly take no event at all: getRouteRules(method, pathname), serverFetch(), defineCachedHandler(), useStorage(), useDatabase() and tasks.

If you find you are writing Nitro-specific code, you may simply prefer to import defineEventHandler from nitro/h3 instead:
server/api/cors.ts
import { defineEventHandler, handleCors } from 'nitro/h3'

export default defineEventHandler((event) => {
  handleCors(event, { origin: '*' })
  return { ok: true }
})

What Isn't Portable

Three key areas you may need will mean you need to reach outside nuxt/server, because Nuxt can't provide them for every builder:

  • Storage. useStorage() comes from nitro/storage, and so does the driver configuration behind it.
  • Sessions. The sealed-session helpers come from nitro/h3. They accept the portable event, but importing them pins the file to Nitro.
  • Caching. defineCachedHandler() and defineCachedFunction() come from nitro/cache.

Server Code Only

Importing nuxt/server from a Vue component, a plugin or the shared/ directory fails the build, and the error points you at #app, #imports, $fetch and useFetch instead. Its types still resolve in those contexts, which is what lets $fetch know what your server routes return.

Modules

A module whose runtime code imports only from nuxt/server runs under any server builder from v4.6 onwards, with no version check and no dependency on h3 or Nitro:

runtime/server/api/status.ts
import { defineEventHandler, useRuntimeConfig } from 'nuxt/server'

export default defineEventHandler(() => ({
  version: useRuntimeConfig().myModule.version,
}))
Leave nuxt/server external when you bundle; it will be resolved in the Nuxt build to the right server builder utilities.

Supporting Nuxt versions <4.6 takes one more step, because those projects have no nuxt/server to resolve. You can instead register the portable file and the one you ship today side by side, and Nuxt will pick whichever the application can run.

See how to register one handler per server API, and what the Nitro v2 compatibility layer does for a module that hasn't migrated.
Learn how a server builder supplies the implementations behind nuxt/server.