Schema-first full-stack TypeScript framework
One schema.
Full stack.
Define your data shapes once with @cleverbrush/schema. Get type-safe servers, auto-typed clients, OpenAPI docs, dependency injection, auth, and React forms — all from that single definition. Zero duplication. Zero drift.
Contract-firstZero codegenOpenAPI 3.1Built-in auth & DIClient resilienceReact integration
Define once, use everywhere
A single contract drives your server, client, and OpenAPI docs. Types flow automatically — no duplication, no drift.
step 1contract.ts
import { defineApi, endpoint, route } from '@cleverbrush/server/contract';
import { object, string, number, array } from '@cleverbrush/schema';
const User = object({
id: string().uuid(),
name: string().minLength(2),
email: string().email(),
age: number().min(0).max(150)
});
export const api = defineApi({
users: {
list: endpoint.get('/api/users').returns(array(User)),
create: endpoint.post('/api/users')
.body(object({ name: string(), email: string(), age: number() }))
.returns(User),
get: endpoint
.get('/api/users', route({ id: string() })`/${t => t.id}`)
.returns(User)
}
});step 2server.ts
import { createServer, mapHandlers } from '@cleverbrush/server';
import { api } from './contract';
const server = createServer();
// mapHandlers gives a compile error if any endpoint is missing
mapHandlers(server, api, {
users: {
list: async () => db.users.findAll(),
create: async ({ body }) => db.users.insert(body),
get: async ({ params }) => db.users.findById(params.id)
// ^ forget one? TypeScript error: Property 'get' is missing
}
});
await server.listen(3000);step 3app.ts
import { createClient } from '@cleverbrush/client';
import { api } from './contract';
const client = createClient(api, { baseUrl: 'http://localhost:3000' });
// Fully typed — no codegen, no manual annotations
const users = await client.users.list();
// ^ User[]
const alice = await client.users.create({
body: { name: 'Alice', email: 'alice@example.com', age: 30 }
});
// ^ User — wrong shape is a compile errorHow it compares
Key differences from popular TypeScript frameworks at a glance.
| Feature | Cleverbrush | tRPC | ts-rest | Hono |
|---|---|---|---|---|
| Standard REST endpoints | Yes | No (RPC only) | Yes | Yes |
| Typed client from contract | Yes (zero codegen) | Yes | Yes | Via hc helper |
| OpenAPI 3.1 generation | Full (links, callbacks, webhooks) | Via plugin | Yes | Via Zod OpenAPI |
| Exhaustive handler mapping | mapHandlers() compile error | No | Yes (Express/Fastify) | No |
| Built-in client resilience | Retry, timeout, dedup, cache, batching | No (DIY) | No (DIY) | No client |
| Integrated auth & DI | JWT, RBAC, DI container | No | No | Auth middleware |
| WebSocket subscriptions | Typed, bidirectional | Yes | No | Basic |
| Schema-driven forms | @cleverbrush/react-form | No | No | No |
Everything you need, nothing you don't
Each library works standalone, but they compose into a seamless full-stack platform.
Schema-first serverTyped endpoints, runtime validation, content negotiation, and RFC 9457 errors — from your schema definition.Auto-typed clientZero-codegen Proxy client with built-in retry, timeout, deduplication, caching, and request batching.OpenAPI & AsyncAPIFull OpenAPI 3.1 with typed links, callbacks, webhooks, and security schemes — generated, never hand-written.Auth & RBACJWT, cookies, OAuth2, OIDC — transport-agnostic auth with typed principals and policy-based authorization.Dependency injection.NET-style DI with schemas as service keys. Singleton, scoped, and transient lifetimes. No decorators.React Query integrationTanStack Query hooks generated from your contract — typed queryKeys, mutations, Suspense, and prefetching.Schema-driven formsHeadless React forms auto-generated from schemas. Type-safe field selectors instead of string names.WebSocket subscriptionsTyped real-time channels with bidirectional messaging, tracked delivery, and automatic reconnection.Type-safe envValidate and coerce environment variables at startup. Compile-time enforcement that every leaf is bound.Schema-driven queriesType-safe Knex query builder with eager loading, column mapping, and CTE-based joins.