API Routes

Standalone server endpoints that live alongside your pages. Export named HTTP method handlers and return Response objects directly.

File Convention

API routes live in src/api/. The file path maps to the URL:

File URL
src/api/health.ts /api/health
src/api/users.ts /api/users
src/api/users/[id].ts /api/users/:id

Method Handlers

Export named functions for each HTTP method you want to handle. Unhandled methods return 405.

src/api/users.ts
import type { LoaderArgs } from "@pracht/core";

export function GET({ request }: LoaderArgs) {
  return Response.json([
    { id: 1, name: "Alice" },
    { id: 2, name: "Bob" },
  ]);
}

export async function POST({ request }: LoaderArgs) {
  const body = await request.json();
  // Create user...
  return Response.json({ id: 3, ...body }, { status: 201 });
}

API Middleware

API routes can have their own middleware chain, separate from page middleware. Configure it in defineApp:

src/routes.ts
export const app = defineApp({
  // Page routes...
  api: {
    middleware: ["rateLimit"],
  },
});

API middleware runs before the handler, just like page middleware runs before loaders.

Full Control

API handlers receive the same LoaderArgs context (request, params, context, signal) and return standard Response objects. You have full control over status codes, headers, and body format.

export function GET() {
  return new Response("plain text", {
    status: 200,
    headers: { "content-type": "text/plain" },
  });
}