Skip to content

tzinContract-first TypeScript framework

Types that scale. Realtime built in. AI-native from day one. Declare a contract once โ€” get validation, OpenAPI, typed clients and MCP for free.

tzin

Declare once, get everything โ€‹

ts
import { t } from '@carlos-tzin/tzin'
import { contract, impl, createApp, listen } from '@carlos-tzin/tzin'

const getUser = contract({
  method: 'GET',
  path: '/users/:id',
  params: t.Object({ id: t.String() }),
  responses: {
    200: t.Object({ id: t.String(), name: t.String(), tags: t.Array(t.String()) }),
    404: t.Object({ error: t.String() }),
  },
})

export const getUserRoute = impl(getUser, async ({ params }) => {
  const user = await findUser(params.id)
  if (!user) throw new HttpError(404, 'user not found')
  return { status: 200, body: user }
})

const app = createApp([getUserRoute], { openapi: true, mcp: true })
listen(app, 3000)

From that single declaration you get:

  • Extractors, not guesses โ€” params/query/body appear only if declared, fully typed and validated.
  • Compiler-enforced responses โ€” wrong 200 shape is a type error.
  • OpenAPI 3.1 free โ€” contracts are already JSON Schema.
  • MCP free โ€” each contract becomes a tool.

Benchmarks โ€‹

N routestzin: typesHono: typestzin: instantiations
204,85172,36822,472
10015,779111,95293,128
30043,099210,912270k

Strictly linear โ€” ~130 types/endpoint.

Runtimereq/sp99
raw node:http~42k2โ€“3ms
hono~34โ€“36k3ms
tzin~30โ€“31k6ms
express~15k7ms

Quick start โ€‹

bash
npx create-tzin my-api
cd my-api
npx tzin dev    # http://localhost:3000

Want the full story? Start with Why tzin? โ†’ Getting Started.

Released under the MIT License.