Skip to main content

Routes

Routes define your HTTP endpoints. Files go in config/routes/.

Example

config/routes/Users.json
{
"routes": [
{
"method": "GET",
"path": "/api/users",
"response": "User[]"
},
{
"method": "POST",
"path": "/api/users",
"body": {
"email": "string",
"name": "string"
},
"response": "User"
},
{
"method": "GET",
"path": "/api/users/:id",
"params": { "id": "uuid" },
"response": "User"
},
{
"method": "DELETE",
"path": "/api/users/:id",
"params": { "id": "uuid" }
}
]
}

Route fields

FieldTypeDescription
methodGET | POST | PUT | PATCH | DELETEHTTP method
pathstringURL path (use :param for dynamic segments)
paramsobjectURL path parameters
bodyobjectRequest body (POST/PUT/PATCH)
responsestringExpected response model name
redirectstringRedirect to another path
functionstringFunction to call
authbooleanRequire authentication
voterstringVoter to check authorization

Body validation

{
"method": "POST",
"path": "/api/users",
"body": {
"email": {
"type": "string",
"required": true,
"validation": ["notEmpty", "isEmail"]
}
}
}

Authentication

Add "auth": true to require authentication. The generated handler calls getAuthUser and returns 401 if unauthenticated:

{ "method": "GET", "path": "/api/users/:id", "auth": true, "response": "User" }

Authorization (voters)

Add "voter": "<VoterName>" to apply an authorization voter. See the Voters page.

Function routing

Add "function": "<FunctionName>" to delegate the handler to a generated function instead of a raw ORM query. See the Functions page.

Event wiring

When a route mutates a model (POST/PUT/PATCH/DELETE), any matching event is automatically invoked after the database operation. See the Events page.

Generated output

Each unique path segment generates a file:

  • /api/userssrc/app/api/users/route.ts
  • /api/users/:idsrc/app/api/users/[id]/route.ts

Example generated route

For GET /api/users/:id with "auth": true and "response": "User":

src/app/api/users/[id]/route.ts
import { NextRequest, NextResponse } from "next/server";
import { db } from "../../lib/db";
import { users } from "../../drizzle/schema";
import { eq } from "drizzle-orm";
import { getAuthUser } from "../../lib/auth";

export async function GET(_req: NextRequest, { params }: { params: { id: string } }) {
const id = params.id;
const userId = getAuthUser(_req);
if (!userId) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const data = await db
.select()
.from(users)
.where(eq(users.id, id))
.then((r) => r[0] ?? null);
if (!data) return NextResponse.json({ error: "Not found" }, { status: 404 });
return NextResponse.json(data);
}