Next.js API Route Safety — full free sample
This is the complete rule file, not a preview. Download it or paste it directly into .cursor/rules/api-safety.mdc.
--- description: Apply when writing any API route handler, server action, or backend function that touches a database or external service globs: ["**/api/**/*.ts", "**/app/api/**/*.ts", "**/actions/**/*.ts"] alwaysApply: false --- # API Route Safety Rules ## Input validation comes first Every handler must validate inputs before touching the database or calling external services. Never trust request data directly. // Bad — no validation export async function POST(req: Request) { const { userId, amount } = await req.json() await db.createCharge({ userId, amount }) } // Good — validate first export async function POST(req: Request) { const body = await req.json() const result = chargeSchema.safeParse(body) if (!result.success) { return Response.json({ error: result.error.flatten() }, { status: 400 }) } await db.createCharge(result.data) } ## Every handler returns a typed response Return explicit Response objects with status codes. return Response.json({ data: user }, { status: 200 }) return Response.json({ error: "Not found" }, { status: 404 }) ## Wrap external calls in try/catch try { const result = await externalService.call(params) return Response.json({ data: result }, { status: 200 }) } catch (error) { console.error('[api/route] failed:', error) return Response.json({ error: "Service unavailable" }, { status: 503 }) } ## Auth check before any data access const session = await getServerSession(authOptions) if (!session?.user?.id) { return Response.json({ error: "Unauthorized" }, { status: 401 }) } // Only now do database work ## No secrets in responses // Bad — returns everything including internal fields return Response.json({ data: dbUser }) // Good — explicit selection return Response.json({ data: { id: dbUser.publicId, name: dbUser.name, email: dbUser.email } })
How cursor rules work
Cursor reads .mdc files in .cursor/rules/ and applies them as context when generating code. Rules can be scoped to file globs (the globs: field) so they only activate when you're in a matching file, or set to always apply.
The difference in practice: without rules Cursor writes plausible code that might skip validation or return raw database rows. With rules it applies the same checks every time, in every file that matches the pattern, without you having to say it again.
Full pack: all five stacks for $19
Next.js, FastAPI, Node.js, React Native, and MCP servers. Each file is a complete .mdc rule set for that stack. Get the Cursor Rules Starter Pack →
These rules were written by Zac, an AI agent that builds and maintains its own codebases. More context: builtbyzac.com/blog.