nextjs-api-routes

CoderMariusz's avatarfrom CoderMariusz

Apply when building API endpoints in Next.js App Router using Route Handlers.

⭐1stars🔀0forks📁View on GitHub🕐Updated Jan 4, 2026

When & Why to Use This Skill

This Claude skill provides comprehensive patterns and best practices for building robust API endpoints using Next.js App Router Route Handlers. It streamlines backend development by offering standardized templates for dynamic routing, request validation, and error handling, ensuring your Next.js APIs are scalable, secure, and follow modern web standards.

Use Cases

  • Developing RESTful API endpoints for CRUD operations within a Next.js App Router project.
  • Implementing dynamic route parameters to fetch, update, or delete specific database resources.
  • Handling complex request data including URL query parameters, custom headers, and JSON body parsing.
  • Setting up standardized error handling and CORS configurations to ensure secure and reliable cross-origin communication.
  • Applying best practices to separate business logic from route handlers and implementing strict input validation using tools like Zod.
namenextjs-api-routes
descriptionApply when building API endpoints in Next.js App Router using Route Handlers.
version1.0.0
tokens~650
confidencehigh
- https//nextjs.org/docs/app/api-reference/functions/next-request
last_validated2025-01-10
next_review2025-01-24
tags[nextjs, api, routes, backend]

When to Use

Apply when building API endpoints in Next.js App Router using Route Handlers.

Patterns

Pattern 1: Basic Route Handler

// Source: https://nextjs.org/docs/app/building-your-application/routing/route-handlers
// app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server';

export async function GET(request: NextRequest) {
  const users = await db.users.findMany();
  return NextResponse.json(users);
}

export async function POST(request: NextRequest) {
  const body = await request.json();
  const user = await db.users.create({ data: body });
  return NextResponse.json(user, { status: 201 });
}

Pattern 2: Dynamic Route Parameters

// Source: https://nextjs.org/docs/app/building-your-application/routing/route-handlers
// app/api/users/[id]/route.ts
interface RouteParams {
  params: Promise<{ id: string }>;
}

export async function GET(request: NextRequest, { params }: RouteParams) {
  const { id } = await params;
  const user = await db.users.findUnique({ where: { id } });

  if (!user) {
    return NextResponse.json({ error: 'Not found' }, { status: 404 });
  }
  return NextResponse.json(user);
}

export async function DELETE(request: NextRequest, { params }: RouteParams) {
  const { id } = await params;
  await db.users.delete({ where: { id } });
  return new NextResponse(null, { status: 204 });
}

Pattern 3: Query Parameters & Headers

// Source: https://nextjs.org/docs/app/api-reference/functions/next-request
export async function GET(request: NextRequest) {
  // Query params
  const searchParams = request.nextUrl.searchParams;
  const page = parseInt(searchParams.get('page') || '1');
  const limit = parseInt(searchParams.get('limit') || '10');

  // Headers
  const authHeader = request.headers.get('authorization');
  if (!authHeader) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  const data = await db.items.findMany({
    skip: (page - 1) * limit,
    take: limit,
  });

  return NextResponse.json({ data, page, limit });
}

Pattern 4: Error Handling Pattern

// Source: https://nextjs.org/docs/app/building-your-application/routing/route-handlers
export async function POST(request: NextRequest) {
  try {
    const body = await request.json();

    // Validation
    const result = schema.safeParse(body);
    if (!result.success) {
      return NextResponse.json(
        { error: 'Validation failed', details: result.error.flatten() },
        { status: 400 }
      );
    }

    const item = await db.items.create({ data: result.data });
    return NextResponse.json(item, { status: 201 });

  } catch (error) {
    console.error('API Error:', error);
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500 }
    );
  }
}

Pattern 5: CORS Headers

// Source: https://nextjs.org/docs/app/building-your-application/routing/route-handlers
export async function OPTIONS() {
  return new NextResponse(null, {
    status: 204,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type, Authorization',
    },
  });
}

Anti-Patterns

  • Business logic in route handlers - Extract to service layer
  • No error handling - Always wrap in try/catch
  • Returning errors as 200 - Use appropriate status codes
  • No input validation - Always validate with Zod

Verification Checklist

  • All routes have error handling
  • Input validated before processing
  • Correct HTTP status codes used
  • Auth checked where required
  • CORS configured if needed