Examples

A production-style full-stack Todo app that uses most of the Cleverbrush framework — server, client, auth, DI, mapper, schema-driven forms, and OpenAPI.

Todo app

The monorepo includes a complete backend + frontend demo with Docker Compose and PostgreSQL. It showcases the core workflow: define schemas once, share the contract, and get typed handlers, clients, and forms for free.

Backend packages used

PackageWhat it does in the demo
@cleverbrush/serverREST API, exhaustive handler mapping, batching, health check
@cleverbrush/schemaShared schemas for request/response bodies, queries, headers
@cleverbrush/authJWT auth, Google OAuth, role-based authorization
@cleverbrush/diDependency injection with schema-as-key tokens
@cleverbrush/envTyped env config with schema validation
@cleverbrush/knex-schemaSchema-aware Knex queries (.hasTableName(), .hasColumnName())
@cleverbrush/mapperObject mapping between DB rows and API responses
@cleverbrush/server-openapiAuto-generated OpenAPI 3.1 + AsyncAPI specs
@cleverbrush/schema-jsonDiscriminator support for OpenAPI

Frontend packages used

PackageWhat it does in the demo
@cleverbrush/clientTyped REST client with retry, timeout, dedup, cache, batching
@cleverbrush/react-formSchema-driven form fields with auto-validation
@cleverbrush/schemaShared schemas (same ones used on the server)

Key patterns from the demo

1. Shared API contract

One contract file imported by both server and client — no codegen, no type duplication:

// contract.ts — shared between frontend and backend
export const api = defineApi({
    todos: {
        list: todosResource.get()
            .query(TodoListQuerySchema)
            .responses({ 200: array(TodoResponseSchema) }),
        create: todosResource.post()
            .body(CreateTodoBodySchema)
            .responses({ 201: TodoResponseSchema }),
    }
});

2. Typed client with resilience

import { createClient } from '@cleverbrush/client/react';
import { retry, timeout, dedupe, throttlingCache, batching } from '@cleverbrush/client';

export const client = createClient(api, {
    baseUrl: BASE_URL,
    getToken: () => loadToken(),
    middlewares: [
        retry({ limit: 2 }),
        timeout({ timeout: 10_000 }),
        dedupe(),
        throttlingCache({ throttle: 2000 }),
        batching({ maxSize: 10 })
    ]
});

// Usage: fully typed, autocompleted
const todos = await client.todos.list({ query: { page: 1 } });

3. Schema-driven forms

import { useSchemaForm, Field } from '@cleverbrush/react-form';

const form = useSchemaForm(CreateTodoBodySchema);

// Validation rules come from the schema — no manual rules needed
<Field forProperty={(t) => t.title} form={form} label="Title" />
<Field forProperty={(t) => t.description} form={form} label="Description" variant="textarea" />

4. Server with auth & DI

const server = createServer()
    .use(corsMiddleware)
    .services(svc => configureDI(svc, config))
    .useAuthentication({
        defaultScheme: 'jwt',
        schemes: [jwtScheme({
            secret: config.jwt.secret,
            mapClaims: claims => ({ userId: claims.sub, role: claims.role })
        })]
    })
    .useAuthorization()
    .withHealthcheck()
    .useBatching();

mapHandlers(server, api, handlers);
server.listen(config.port);

5. Typed env config

import { env, parseEnv } from '@cleverbrush/env';

export const config = parseEnv({
    db: {
        host: env('DB_HOST', string().default('localhost')),
        port: env('DB_PORT', number().coerce().default(5432))
    },
    jwt: {
        secret: env('JWT_SECRET', string().minLength(32))
    }
});

6. DI tokens using schema

import { any } from '@cleverbrush/schema';

// Schema builders serve as DI tokens — fully typed
export const KnexToken = any().hasType<Knex>();
export const BoundQueryToken = any().hasType<BoundQuery>();

Run it yourself

Clone the repo and spin up the demo with Docker Compose:

git clone https://github.com/nicklatkovich/framework.git
cd framework/demos
docker compose up

This starts the backend, frontend, and PostgreSQL. The frontend is available at http://localhost:8080 and the API at http://localhost:3000.

Demo features

FeatureWhat it demonstrates
CRUD endpointsPagination, conflict detection (If-Match), soft delete
AuthJWT login/register, Google OAuth, RBAC (user/admin)
Export/ImportCSV file download, bulk import with 207 Multi-Status
WebhooksOpenAPI 3.1 callbacks via .callbacks()
WebSocket/SSELive todo updates, chat, AsyncAPI spec
Resilience demoSlow and flaky endpoints to test retry/timeout
Batching demoClient request batching in action
Discriminated unionsTodo events (assigned/commented/completed)
Object mappingDB rows → API responses via mapper
Schema-driven formsCreate/edit with auto-validation from schema