Type-safe RPC for TypeScript

The RPC Framework for the Web

Katman is a type-safe RPC framework with compiled pipelines powering the next generation of TypeScript APIs.

import { katman } from 'katman'
import { z } from 'zod'

const k = katman({
  context: (req) => ({ db: getDB() }),
})

// Guard — flat, no callbacks
const auth = k.guard(async (ctx) => {
  const user = await verify(ctx.headers.auth)
  if (!user) throw new KatmanError('UNAUTHORIZED')
  return { user }
})

// Procedure — typed end-to-end
const users = k.query(
  z.object({ limit: z.number().optional() }),
  ({ input, ctx }) => ctx.db.users.find(input)
)

k.serve(k.router({ users }), {
  port: 3000, scalar: true, ws: true
})
Architecture

Build your API in composable layers

Guards enrich context

Return { user }, { permissions } from a flat function. No onion callbacks. Types accumulate automatically.

Compiled at startup

Guards are unrolled, wraps are pre-linked. The pipeline is a direct function chain — zero closures per request.

Types flow end-to-end

Input, output, context, errors — fully typed from server to client. Inferred from your code, never generated.

Standard Schema

Zod, Valibot, ArkType — bring your own validator. Works through the Standard Schema specification.

Developer experience

From zero to production

Single package

Server, client, plugins, codecs. One npm install. No monorepo of scoped packages.

Typed errors

Define error maps per procedure. fail() is typed — the compiler catches wrong codes.

Lifecycle hooks

request, response, error, serve:start — powered by hookable. Sync fast-path when unused.

Response cache

ohash-keyed TTL cache with prefix invalidation. Skip pipeline + stringify on cache hit.

Lazy loading

lazy(() => import('./routes/users')) for code splitting. Cached after first load.

Contract-first

Define the API shape, share with frontend, implement on backend. Types enforced.

Wire formats

Three protocols, automatic negotiation

JSON
default

Universal. Fastest encode/decode. Works everywhere. Zero config.

MessagePack
binary

30% smaller payloads. Native Date. One flag: binary: true

devalue
rich types

Date, Map, Set, BigInt, RegExp, circular refs. Automatic round-trip.

Integrations

Works with your stack

React Actions

createAction() returns [error, data] tuples. FormData with bracket notation.

TanStack Query

queryOptions, mutationOptions, queryKey. React, Vue, Solid, Svelte.

AI SDK

routerToTools() — LLMs call your procedures through function calling.

Fastify

Register as a plugin alongside existing REST routes.

Server

One line to deploy

serve()

One-line Node.js server. Auto port finding, HTTP/2 with TLS, WebSocket on same port.

k.serve(router, {

  port: 3000,

  scalar: true,

  ws: true,

  http2: { cert, key }

})

handler()

Fetch API handler — works everywhere. Content negotiation is automatic.

Node.js
Bun
Deno
Cloudflare
Plugins

Extend without ceremony

CORS

corsHeaders() — string, array, or dynamic origin matching.

OpenTelemetry

otelWrap(tracer) — each procedure call becomes a span.

Pino

loggingHooks() — structured request/response/error logging.

Rate Limiting

Sliding window guard. In-memory or custom backend.

Start building with Katman

Prepare for a development environment that can finally keep pace with the speed of your mind.

Get Started