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 })
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.
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.
Three protocols, automatic negotiation
JSON
defaultUniversal. Fastest encode/decode. Works everywhere. Zero config.
MessagePack
binary30% smaller payloads. Native Date. One flag: binary: true
devalue
rich typesDate, Map, Set, BigInt, RegExp, circular refs. Automatic round-trip.
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.
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.
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.
Backed by the community
Start building with Katman
Prepare for a development environment that can finally keep pace with the speed of your mind.
Get Started