Routing

Nitro support filesystem routing as well as defining route rules for maximum flexibility and performance.

Filesystem Routing

Nitro supports file-based routing for your API routes.

Handler files inside api/ and routes/ directory will be automatically mapped to unjs/h3 routes.

api/
  test.ts      <-- /api/test
routes/
  hello.ts     <-- /hello
nitro.config.ts
Some providers like Vercel use a top-level api/ directory as a feature, therefore routes placed in /api wont work. You will have to use routes/api/.
If you are using Nuxt, move the api/ and routes/ inside the server/ directory.

Simple route

// api/hello.ts
export default eventHandler(() => {
  return { hello: 'world' }
})

You can now universally call this API using await $fetch('/api/hello').

Route with params

// routes/hello/[name].ts
export default eventHandler(event => `Hello ${event.context.params.name}!`)
/hello/nitro
Hello nitro!

To include the /, use [...name].ts:

// routes/hello/[...name].ts
export default eventHandler(event => `Hello ${event.context.params.name}!`)
/hello/nitro/is/hot
Hello nitro/is/hot!

Specific request method

API route with a specific HTTP request method (get, post, put, delete, options and so on).

GET
// routes/users/[id].get.ts
export default eventHandler(async (event) => {
  const { id } = event.context.params
  // TODO: fetch user by id
  return `User profile!`
})
POST
// routes/users.post.ts
export default eventHandler(async event => {
  const body = await readBody(event)
  // TODO: Handle body and add user
  return { updated: true }
})

Check out h3 JSDocs for all available utilities like readBody.

Catch all route

// routes/[...].ts
export default eventHandler(event => `Default page`)

Route Rules

Nitro allows you to add logic at the top-level of your configuration, useful for redirecting, proxying, caching and adding headers to routes.

It is a map from route pattern (following unjs/radix3) to route options.

When cache option is set, handlers matching pattern will be automatically wrapped with defineCachedEventHandler.

See the Cache API for all available cache options.

swr: true|number is shortcut for cache: { swr: true, maxAge: number }

Example:

nitro.config.ts
import { defineNitroConfig } from 'nitropack/config'

export default defineNitroConfig({
  routeRules: {
    '/blog/**': { swr: true },
    '/blog/**': { swr: 600 },
    '/blog/**': { static: true },
    '/blog/**': { cache: { /* cache options*/ } },
    '/assets/**': { headers: { 'cache-control': 's-maxage=0' } },
    '/api/v1/**': { cors: true, headers: { 'access-control-allow-methods': 'GET' } },
    '/old-page': { redirect: '/new-page' },
    '/proxy/example': { proxy: 'https://example.com' },
    '/proxy/**': { proxy: '/api/**' },
  }
})
nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/blog/**': { swr: true },
    '/blog/**': { swr: 600 },
    '/blog/**': { static: true },
    '/blog/**': { cache: { /* cache options*/ } },
    '/assets/**': { headers: { 'cache-control': 's-maxage=0' } },
    '/api/v1/**': { cors: true, headers: { 'access-control-allow-methods': 'GET' } },
    '/old-page': { redirect: '/new-page' },
    '/proxy/example': { proxy: 'https://example.com' },
    '/proxy/**': { proxy: '/api/**' },
  }
})