Route Handlers in Next.js let you define custom logic for HTTP requests using the native Request and Response APIs. They are only available inside the app directory and replace the need for traditional API Routes.
Create a route.ts file inside any folder in the app directory:
// app/api/route.ts
export async function GET(request: Request) {
// Handle GET request
}Note: You cannot place a route.ts file at the same level as a page.tsx file.
Route Handlers support the following methods:
Unsupported methods return a 405 Method Not Allowed response.
Next.js extends the native APIs with NextRequest and NextResponse for advanced use cases like cookies, headers, and URL parsing.
By default, Route Handlers are not cached. To cache a GET method, use the dynamic = 'force-static' config:
// app/items/route.ts
export const dynamic = 'force-static'
export async function GET() {
const res = await fetch('https://data.mongodb-api.com/...', {
headers: {
'Content-Type': 'application/json',
'API-Key': process.env.DATA_API_KEY,
},
})
const data = await res.json()
return Response.json({ data })
}Other HTTP methods are never cached, even if defined in the same file.
Route Handlers cannot coexist with page.tsx at the same path level:
| Page | Route | Result |
|---|---|---|
| app/page.js | app/route.js | Conflict ❌ |
| app/page.js | app/api/route.js | Valid ✅ |
| app/[user]/page.js | app/api/route.js | Valid ✅ |
Use RouteContext to type route parameters in TypeScript:
// app/users/[id]/route.ts
import type { NextRequest } from 'next/server'
export async function GET(_req: NextRequest, ctx: RouteContext<'/users/[id]'>) {
const { id } = await ctx.params
return Response.json({ id })
}Note: Types are generated during next dev, next build, or next typegen.
Route Handlers in Next.js offer a powerful way to manage HTTP requests directly within your app structure. With support for multiple methods, typed context, and caching control, they provide a clean and scalable alternative to traditional API routes.