GioJSdocs
Building Your App

Route Handlers

API endpoints, Server-Sent Events, and WebSockets with route.ts files.

A route.ts (or route.js) file turns its folder into a server endpoint. Export a function per HTTP method - GET, POST, PUT, PATCH, DELETE:

ts
// app/api/notes/[id]/route.ts
import type { GioRequest } from '@gio.js/core';

export async function POST(req: GioRequest) {
  const { text } = req.json<{ text: string }>();
  const user = req.cookies['session'];       // parsed Cookie header
  const id = req.params['id'];               // from the [id] segment
  return { saved: text, id };                // → application/json, 200
}

The request object

Handlers receive a GioRequest: method, path, params, query, lowercased headers, parsed cookies, the raw body (bodyBase64 is true for binary bodies), and a json() helper.

What you can return

  • Any JSON-serializable value - sent as application/json with status 200.
  • A web-standard Response - its status, headers, and body pass through.
  • null / undefined - 204 No Content.
  • A GioEventStream (GET only) - switches the connection to SSE.
ts
export function DELETE() {
  return new Response('gone', { status: 202, headers: { 'X-Reason': 'cleanup' } });
}

Server-Sent Events

ts
// app/ticker/route.ts
import { GioEventStream } from '@gio.js/core';

export function GET() {
  return new GioEventStream((stream) => {
    const t = setInterval(() => stream.send({ time: Date.now() }), 1000);
    return () => clearInterval(t);           // runs when the client disconnects
  });
}

Rules

  • Handler responses are never cached or coalesced - every request runs your code.
  • Requests for methods you didn't export get 405 with an Allow header.
  • A GET without a GET handler falls through to a sibling page.tsx if one exists.
  • Pages only answer GET/HEAD - mutations belong in route handlers.
  • A thrown error is logged server-side and answered with a JSON 500 (no internals leaked).
  • Export wsHandler from the same file for WebSockets - see the WebSockets page.