Next.js App Router has transformed how we build full-stack applications. In this post, we'll explore patterns for building robust, scalable APIs.
Route Handlers in App Router
App Router uses the Web Platform's Request and Response APIs, making it familiar and portable:
// app/api/users/route.ts
export async function GET(request: Request) {
const users = await prisma.user.findMany();
return Response.json(users);
}
Input Validation with Zod
Always validate incoming data. Zod provides excellent TypeScript integration:
import { z } from 'zod';
const createUserSchema = z.object({
email: z.string().email(),
name: z.string().min(2),
});
export async function POST(request: Request) {
const body = await request.json();
const result = createUserSchema.safeParse(body);
if (!result.success) {
return Response.json(
{ error: result.error.errors },
{ status: 400 }
);
}
// Proceed with validated data
}
Error Handling
Consistent error handling improves API usability:
- Use appropriate HTTP status codes
- Return structured error responses
- Don't leak internal errors to clients
Testing Your APIs
We recommend testing APIs at multiple levels:
- Unit tests for business logic
- Integration tests for database operations
- E2E tests for critical user journeys
A well-tested API is a reliable API. Invest in testing early.