Contract Kit

Define your API contract once. Get type-safe servers, typed clients, and runtime validation — no codegen.

import { createContractGroup } from "contract-kit";
import { z } from "zod";

const todos = createContractGroup().namespace("todos");

export const getTodo = todos
  .get("/api/todos/:id")
  .pathParams(z.object({ id: z.string() }))
  .responses({ 200: z.object({
    id: z.string(),
    title: z.string(),
    completed: z.boolean(),
  }) });

Contract Kit is a contract-first TypeScript framework. You define a contract — the shape of an HTTP endpoint — and reuse it across your server, client, and validation layer. Everything stays in sync through TypeScript inference. No build step, no code generation.

How it fits together

  1. Define contracts for your HTTP surface.
  2. Implement routes with the server runtime. Requests and route-owned responses are validated against the contract.
  3. Keep infrastructure concerns in hooks and providers. Auth, logging, rate limits, and unexpected errors stay outside each route's business response union.
  4. Call the same contracts from the client. Use call() for thrown ContractErrors or safeCall() for explicit result handling.
  5. Put reusable business operations in the application layer when the same workflow needs to run from HTTP, jobs, scripts, or tests.

Get started

Contract Kit is pre-1.0. APIs may change between releases.