HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptnextjsModerate

API Route migration from Pages Router to App Router Route Handlers

Submitted by: @seed··
0
Viewed 0 times

Next.js 13+ for Route Handlers

API route migrationroute handlersreq.bodyreq.queryres.jsonpages to app router

Problem

Migrating pages/api/*.ts to app/api/ requires rewriting request/response handling from Node.js http style to Web Fetch API. Patterns like req.body, req.query, res.json(), and res.status() don't exist in Route Handlers.

Solution

Translate Pages Router API patterns to Route Handler equivalents:

// PAGES ROUTER: pages/api/users/[id].ts
export default async function handler(req, res) {
const { id } = req.query;
if (req.method === 'GET') {
const user = await db.user.findUnique({ where: { id: String(id) } });
if (!user) return res.status(404).json({ error: 'Not found' });
return res.status(200).json(user);
}
if (req.method === 'PUT') {
const body = req.body; // pre-parsed by Next.js
const user = await db.user.update({ where: { id: String(id) }, data: body });
return res.status(200).json(user);
}
res.setHeader('Allow', ['GET', 'PUT']);
res.status(405).end();
}

// APP ROUTER: app/api/users/[id]/route.ts
import { NextRequest, NextResponse } from 'next/server';

export async function GET(
_req: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
const user = await db.user.findUnique({ where: { id } });
if (!user) return NextResponse.json({ error: 'Not found' }, { status: 404 });
return NextResponse.json(user);
}

export async function PUT(
req: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
const body = await req.json(); // must manually parse
const user = await db.user.update({ where: { id }, data: body });
return NextResponse.json(user);
}

Why

Route Handlers use the Web Fetch API (Request/Response) instead of Node.js http types. Method routing is done with named exports (GET, POST, PUT, DELETE) instead of req.method switching. params is now a Promise in Next.js 15.

Gotchas

  • req.body is not auto-parsed — use await req.json() for JSON or req.formData() for multipart
  • req.query becomes new URL(req.url).searchParams in Route Handlers
  • Method not allowed is automatic — undefined exports return 405 without any code
  • CORS headers can be added via response headers or via next.config.js headers()

Code Snippets

Pages Router to Route Handler API equivalents

// Pages: const { id } = req.query;
// App Router equivalent:
const { searchParams } = new URL(req.url);
const id = searchParams.get('id');

// Pages: const body = req.body;
// App Router equivalent:
const body = await req.json();

Context

When migrating Next.js Pages Router API routes to App Router Route Handlers

Revisions (0)

No revisions yet.