A typed API route handler with request validation and error handling.
import { NextRequest, NextResponse } from class=class="text-emerald-400">"text-emerald-400">'next/server'
interface CreateItemBody {
name: string
description?: string
}
export async function GET(request: NextRequest) {
const { searchParams } = request.nextUrl
const page = Number(searchParams.get(class=class="text-emerald-400">"text-emerald-400">'page')) || 1
const limit = Number(searchParams.get(class=class="text-emerald-400">"text-emerald-400">'limit')) || 10
class=class="text-emerald-400">"text-gray">// Replace with your data source
const items = Array.from({ length: limit }, (_, i) => ({
id: (page - 1) * limit + i + 1,
name: class="text-emerald-400">`Item ${(page - 1) * limit + i + 1}`,
}))
return NextResponse.json({ data: items, page, limit })
}
export async function POST(request: NextRequest) {
try {
const body: CreateItemBody = await request.json()
if (!body.name) {
return NextResponse.json({ error: class=class="text-emerald-400">"text-emerald-400">'Name is required' }, { status: 400 })
}
return NextResponse.json({ data: { id: Date.now(), ...body } }, { status: 201 })
} catch {
return NextResponse.json({ error: class=class="text-emerald-400">"text-emerald-400">'Invalid JSON' }, { status: 400 })
}
}Place this file at app/api/items/route.ts. It handles GET with pagination and POST with validation. Access it at /api/items from your frontend with fetch().
Let's discuss how we can bring your idea to life. From initial concept to production-ready product — we've got you covered.