From harness-claude
Creates HTTP endpoints in Next.js App Router using route.ts with typed method exports. Useful for REST APIs, webhooks, file downloads, and streaming responses.
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:next-route-handlersThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Create HTTP endpoints in the App Router using route.ts with typed method exports
Create HTTP endpoints in the App Router using route.ts with typed method exports
app/api/[resource]/route.ts and export named async functions GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS.(request: NextRequest) as the first parameter — use request.json(), request.text(), or request.formData() to parse the body.Response or NextResponse — use NextResponse.json(data, { status }) for JSON responses.({ params }: { params: { id: string } }).request.text() to read the raw body (needed for HMAC verification), then parse JSON manually.runtime export to 'edge' for global low-latency endpoints; omit it (defaults to Node.js) when you need Node.js APIs.export const dynamic = 'force-dynamic' if a GET handler should never be cached (e.g., it reads cookies or returns live data).// app/api/posts/[id]/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { z } from 'zod';
const updateSchema = z.object({ title: z.string().min(1) });
export async function GET(_request: NextRequest, { params }: { params: { id: string } }) {
const post = await db.post.findUnique({ where: { id: params.id } });
if (!post) return NextResponse.json({ error: 'Not found' }, { status: 404 });
return NextResponse.json(post);
}
export async function PATCH(request: NextRequest, { params }: { params: { id: string } }) {
const body = await request.json();
const parsed = updateSchema.safeParse(body);
if (!parsed.success) {
return NextResponse.json({ errors: parsed.error.flatten() }, { status: 422 });
}
const post = await db.post.update({ where: { id: params.id }, data: parsed.data });
return NextResponse.json(post);
}
Route Handlers replace pages/api/ routes in the App Router. They live at app/api/**/route.ts (or any nested location in app/ that does not conflict with a page.tsx). A route.ts file and a page.tsx file cannot coexist in the same directory.
Caching behavior: GET Route Handlers are statically cached by default when they do not read dynamic data (cookies(), headers(), request body). Use export const dynamic = 'force-dynamic' or read from request to opt out of caching.
Webhook pattern: Stripe and GitHub require reading the raw request body for HMAC signature verification. Read with await request.text(), verify the signature, then JSON.parse() the body manually. Using request.json() first consumes the stream and makes raw body unavailable.
Streaming responses: Return a ReadableStream in the Response body for streaming endpoints. This pattern is common for AI streaming responses (OpenAI, Anthropic SDK).
CORS: Route Handlers need explicit CORS headers for cross-origin requests. Handle OPTIONS requests and set Access-Control-Allow-* headers in both the OPTIONS handler and the main method handlers.
tRPC integration: tRPC's Next.js adapter mounts a single Route Handler at app/api/trpc/[trpc]/route.ts and delegates all procedure calls through it.
https://nextjs.org/docs/app/building-your-application/routing/route-handlers
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeBuilds Next.js App Router API routes with Route Handlers for HTTP methods, request bodies (JSON/form/text), dynamic params, queries, headers, and JSON responses.
Designs RESTful API routes with Next.js App Router, Zod validation, auth guards, and typed responses. Activates when discussing API endpoints, route structure, or request/response schemas.
Creates REST API endpoints inside a Nuxt project using Nitro's event-handler model and H3 utilities. Handles file-based routing, request body parsing, query parameters, route params, error serialization, and custom response headers.