Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/dvlkit/nuxe/llms.txt

Use this file to discover all available pages before exploring further.

Nuxe bundles a Nitro-powered server alongside your Vue application. Any file you place inside server/api/ becomes an HTTP endpoint served under the /api prefix. There is no router configuration to write — the file name determines both the URL path and the accepted HTTP method.

File naming conventions

Encode the HTTP method as a suffix before the file extension. When no suffix is present the handler responds to all methods.
FileMethodURL
server/api/ping.get.tsGET/api/ping
server/api/users.post.tsPOST/api/users
server/api/users/[id].delete.tsDELETE/api/users/:id
server/api/health.tsAll methods/api/health
Supported method suffixes are .get, .post, .put, .patch, .delete, .head, and .options.
The default API prefix is /api. You can change it by setting server.apiPrefix in nuxe.config.ts.

Writing a route handler

Every handler exports a default function wrapped in defineEventHandler. The function receives an H3Event and returns any JSON-serialisable value (or a Response for full control). The playground’s ping.get.ts shows a complete, realistic example — reading query parameters, simulating delay, and returning different status codes based on the request:
// server/api/ping.get.ts
import { defineEventHandler, getQuery, setResponseStatus } from '@dvlkit/nuxe/server'

export default defineEventHandler(async (event) => {
  const query = getQuery(event)

  if (query.delay) {
    await new Promise((resolve) => setTimeout(resolve, Number(query.delay)))
  }

  const status = query.status ? Number(query.status) : 200
  if (status >= 400) {
    setResponseStatus(event, status)
    return { message: `Error ${status}`, timestamp: Date.now() }
  }

  return {
    message: 'pong',
    timestamp: Date.now(),
    query: typeof query.q === 'string' ? query.q : null,
  }
})
The whoami.get.ts handler demonstrates returning a structured object — Nuxe serialises it to JSON automatically:
// server/api/whoami.get.ts
import { defineEventHandler } from '@dvlkit/nuxe/server'

export default defineEventHandler((event) => {
  return {
    id: '0fc98cdf-53b1-4ed6-b0bb-907c37a4cc10',
    code: '26093',
    slug: 'calza-deportiva-26093',
    name: 'Calza deportiva',
    brand: 'Bsoul',
    price: 10000,
    conditions: ['nuevo'],
    images: [{ url: '/img.png' }],
  }
})

Available h3 utilities

Import everything you need from @dvlkit/nuxe/server. These are all thin re-exports of the upstream h3 library.

Request reading

getQuery · getRouterParam · readBody · getHeader · getRequestURL · getMethod

Response writing

setResponseStatus · setHeader · sendRedirect

Cookies

getCookie · setCookie · deleteCookie · parseCookies

Error handling

createError — creates an h3 error with status code and message

Request utilities

getQuery(event)
function
Returns the parsed query string as a plain object. All values are string | string[].
getRouterParam(event, name)
function
Returns a single dynamic path parameter. For a route file named [id].get.ts, call getRouterParam(event, 'id').
readBody(event)
function
Reads and JSON-parses the request body. Returns a Promise that resolves to the parsed value.
getHeader(event, name)
function
Returns the value of a request header, or undefined if absent.
getRequestURL(event)
function
Returns a URL object for the full request URL, including protocol and host.
getMethod(event)
function
Returns the HTTP method string in uppercase, e.g. 'GET' or 'POST'.

Response utilities

setResponseStatus(event, code, message?)
function
Sets the HTTP status code for the response. Call before returning the response body.
setHeader(event, name, value)
function
Sets a single response header.
sendRedirect(event, location, code?)
function
Sends an HTTP redirect response. code defaults to 302.
createError({ statusCode, statusMessage })
function
Creates an h3 error. Throw this to abort the handler and return an error response with the given status code.
export default defineEventHandler((event) => {
  const token = getHeader(event, 'authorization')
  if (!token) {
    throw createError({ statusCode: 401, statusMessage: 'Unauthorized' })
  }
  return { ok: true }
})
Returns the value of a single cookie from the request.
Sets a Set-Cookie header on the response.
Clears a cookie by setting its expiry to the past.
parseCookies(event)
function
Returns all request cookies as a Record<string, string>.

TypeScript types

@dvlkit/nuxe/server also exports the following h3 TypeScript types for annotating your handlers:
TypeDescription
H3EventThe event object passed to every defineEventHandler callback
H3EventContextThe event.context record for attaching request-scoped data
EventHandlerThe function signature returned by defineEventHandler
// server/api/example.get.ts
import { defineEventHandler, type H3Event } from '@dvlkit/nuxe/server'

function extractToken(event: H3Event): string | undefined {
  return getHeader(event, 'authorization')?.replace('Bearer ', '')
}

export default defineEventHandler((event) => {
  const token = extractToken(event)
  return { token }
})

Runtime config in server routes

useRuntimeConfig() works inside server API handlers the same way it does in Vue components. Values under the public key are safe to return to clients; private keys (defined at the top level of runtimeConfig) are server-only:
// server/api/config-check.get.ts
import { defineEventHandler } from '@dvlkit/nuxe/server'

export default defineEventHandler(() => {
  const config = useRuntimeConfig()
  // config.secretKey is only available here (server-only)
  // config.public.apiBase is safe to return
  return { apiBase: config.public.apiBase }
})

Custom request logging

Place a nuxe-request-logger.ts file at the project root to intercept every request before it reaches your route handlers. The file receives the Nitro app instance and wraps its fetch method:
// nuxe-request-logger.ts (project root)
import { logRequest } from '@dvlkit/nuxe/utils/logger'

export default function (nitroApp) {
  const originalFetch = nitroApp.fetch
  nitroApp.fetch = async (request) => {
    const start = Date.now()
    const response = await originalFetch(request)
    try {
      const url = new URL(request.url, 'http://localhost')
      const method = request.method || 'GET'
      const status = response.status
      // Skip internal Vite/dev-server requests
      if (
        url.pathname.startsWith('/@') ||
        url.pathname.startsWith('/node_modules/') ||
        url.pathname.startsWith('/__vite_ping') ||
        url.pathname.startsWith('/__open-in-editor')
      ) {
        return response
      }
      logRequest(method, url.pathname + url.search, status, Date.now() - start)
    } catch {}
    return response
  }
}
The request logger file is loaded at server startup, before any route handler runs. It is the right place for cross-cutting concerns like structured logging, rate limiting counters, or request tracing headers.

Build docs developers (and LLMs) love