Handler

sevo handlers consume an InvocationContext and return a Response.

Basic Handler

import { serve } from "sevo";
import { NodeRuntimeAdapter } from "sevo/node";

serve({
  adapter: new NodeRuntimeAdapter(),
  fetch(ctx) {
    return new Response(`You requested ${ctx.request.url}`);
  },
});

The fetch function is the final application handler after middleware has run.

InvocationContext

Handlers and middleware receive InvocationContext, which contains:

ctx.request

The standard Web API Request object.

fetch(ctx) {
  return new Response(`Method: ${ctx.request.method}`);
}

ctx

Use invocation context to share per-invocation state across middleware and handlers.

import { createContextKey, serve } from "sevo";
import { NodeRuntimeAdapter } from "sevo/node";

const requestId = createContextKey<string>("unknown");

serve({
  adapter: new NodeRuntimeAdapter(),
  middleware: [
    async (ctx, next) => {
      ctx.set(requestId, crypto.randomUUID());
      return next(ctx);
    },
  ],
  fetch(ctx) {
    return Response.json({
      id: ctx.get(requestId),
    });
  },
});

ctx.capabilities

ctx.capabilities exposes runtime capabilities needed by helpers such as serveStatic(). This includes file resolution, file access, and compression transforms when supported by the current adapter.

ctx.waitUntil

Use waitUntil() to register background work that should finish before the server fully closes.

serve({
  adapter: new NodeRuntimeAdapter(),
  fetch(ctx) {
    ctx.waitUntil?.(
      fetch("https://example.com/audit", {
        method: "POST",
        body: JSON.stringify({ url: ctx.request.url }),
      }),
    );
    return new Response("ok");
  },
});

ctx.params

Route parameters extracted from the matched route pattern.

serve({
  routes: {
    "/users/:id": (ctx) => {
      return Response.json({ userId: ctx.params.id });
    },
  },
});