
# Routing

> Options for defining routes, handlers, and route-level behavior.

::note
All examples on this page assume the following import in `nitro.config.ts`:

```ts
import { defineConfig } from "nitro";
```
::

### `baseURL`

- Default: `"/"`{lang=ts} (or `NITRO_APP_BASE_URL` environment variable if provided)

Server's main base URL.

```ts
export default defineConfig({
  baseURL: "/app/", // serve app under /app/ prefix
});
```

### `apiBaseURL`

- Default: `"/api"`{lang=ts}

Changes the default API base URL prefix.

```ts
export default defineConfig({
  apiBaseURL: "/server/api", // api routes under /server/api/
});
```

### `serverEntry`

- Type: `false`{lang=ts} | `string`{lang=ts} | `{ handler: string, format?: EventHandlerFormat }`{lang=ts}

Custom server entry point configuration. Set to `false` to disable the default server entry.

```ts
export default defineConfig({
  serverEntry: "./server.ts",
});
```

:read-more{to="/docs/server-entry"}

### `handlers`

Server handlers and routes.

If `routes/`, `api/` or `middleware/` directories exist inside the server directory, they will be automatically added to the handlers array.

```ts
export default defineConfig({
  handlers: [
    { route: "/health", handler: "./handlers/health.ts" },
    { route: "/admin/**", handler: "./handlers/admin.ts", method: "get" },
  ],
});
```

:read-more{to="/docs/routing"}

### `devHandlers`

Handlers provided as programmatic instances instead of file paths. Unlike regular [`handlers`](#handlers), which are imported and transformed by the bundler, `devHandlers` accept a handler function directly.

**Note:** They are **only available in development mode** and **not in the production build**.

```ts
export default defineConfig({
  devHandlers: [
    { route: "/__dev", handler: defineHandler(() => "dev-only route") },
  ],
});
```

### `routes`

- Default: `{}`{lang=ts}

Inline route definitions. A map from route pattern to handler path or handler options.

```ts
export default defineConfig({
  routes: {
    "/hello": "./routes/hello.ts",
    "/greet": { handler: "./routes/greet.ts", method: "post" },
  },
});
```

### `errorHandler`

- Type: `string`{lang=ts} | `string[]`{lang=ts}

Path(s) to custom runtime error handler(s). Replaces nitro's built-in error page.

```ts [nitro.config.ts]
import { defineConfig } from "nitro";

export default defineConfig({
  errorHandler: "~/error",
});
```

```ts [error.ts]
import { defineErrorHandler } from "nitro";

export default defineErrorHandler((error, event) => {
  return new Response('[custom error handler] ' + error.stack, {
    headers: { 'Content-Type': 'text/plain' }
  });
});
```

### `routeRules`

**🧪 Experimental!**

Route options. It is a map from route pattern (following [rou3](https://github.com/h3js/rou3)) to route options.

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

See the [Cache API](/docs/cache) for all available cache options.

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

```js
routeRules: {
  '/blog/**': { swr: true },
  '/feed/**': { swr: 600 },
  '/docs/**': { static: true },
  '/dashboard/**': { 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' }, // uses status code 307 (Temporary Redirect)
  '/old-page2': { redirect: { to:'/new-page2', statusCode: 301 } },
  '/old-page/**': { redirect: '/new-page/**' },
  '/proxy/example': { proxy: 'https://example.com' },
  '/proxy/**': { proxy: '/api/**' },
}
```

:read-more{to="/docs/routing#route-rules"}

### `prerender`

Prerendering options. Any route specified will be fetched during the build and copied to the `.output/public` directory as a static asset.

Default:

```ts
{
  autoSubfolderIndex: true,
  concurrency: 1,
  interval: 0,
  failOnError: false,
  crawlLinks: false,
  ignore: [],
  routes: []
}
```

Any route that starts with a prefix listed in `ignore`, or matches a route pattern (a string containing `*` or `:`, such as `/blog/**` or `/users/:id`), a regular expression or a function, will be ignored. See [Prerendering](/docs/prerendering#ignoring-routes) for details.

If the `crawlLinks` option is set to `true`, nitro starts with `/` by default (or all routes in the `routes` array), extracts `<a>` tags from HTML pages, and prerenders them as well.

You can set the `failOnError` option to `true` to stop the CI when Nitro could not prerender a route. List status codes in `ignoreStatusCodes` (for example `[404]`) to keep routes failing with them from stopping the build, unless every prerendered route failed and nothing was written.

The `interval` and `concurrency` options let you control the speed of prerendering, which can be useful to avoid rate limits when calling external APIs.

The `autoSubfolderIndex` option controls how files are generated in the `.output/public` directory:

```bash
# autoSubfolderIndex: true (default)
/about -> .output/public/about/index.html
# autoSubfolderIndex: false
/about -> .output/public/about.html
```

This option is useful when your hosting provider does not give you an option regarding the trailing slash.

Set `ignoreUnprefixedPublicAssets` to `true` to skip prerendering public assets that do not have a base URL prefix.
