Covara
Your Drizzle schema is already a backend.
Covara turns a Drizzle ORM schema into a complete, production-ready API — REST endpoints, real-time subscriptions, auth, file uploads, billing, email, and background jobs — with a type-safe, offline-first TypeScript client on the other end. It is built on Hono and runs standalone on Node or at the edge on Cloudflare Workers.
The problem Covara solves
Every product backend is the same 80%: CRUD endpoints, filtering, pagination, auth, sessions, password reset, file uploads, webhooks for payments, transactional email, a job queue, and a client that talks to all of it. You rewrite this plumbing for every project, and the pieces never quite fit together — your realtime layer doesn't know about your auth scopes, your client types drift from your API, your offline cache fights your subscriptions.
Covara makes that 80% one coherent system derived from a single source of truth: your Drizzle schema.
- Define a table → get a full REST API with filtering, pagination, aggregations, batch ops, and OpenAPI docs.
- Add an auth scope → it is enforced everywhere: queries, mutations, subscriptions, search.
- Mutate data anywhere — a generated endpoint, a custom route, or an RPC — and every subscribed client updates in real time.
- Use the client → full TypeScript inference, optimistic updates, an offline queue, and automatic reconnect, in React, React Native, or plain TypeScript.
The remaining 20% — your business logic — lives in lifecycle hooks, RPC procedures, and ordinary Hono routes, with the framework's mutation tracking and typing intact.
In one screen
// server: a table becomes an API
import { createCovara, rsql } from "covara";
import { startServer } from "covara/node";
const app = createCovara({ cors: true }).resource("/todos", todosTable, {
id: todosTable.id,
db,
auth: { update: async (user) => rsql`userId==${user.id}` },
});
await startServer(app, { port: 3000 });
// client: the API becomes live UI
import { useLiveList } from "covara/client/react";
function TodoList() {
const { items, mutate } = useLiveList<Todo>("/api/todos", { orderBy: "position" });
return items.map((todo) => (
<Todo key={todo.id} {...todo} onDelete={() => mutate.delete(todo.id)} />
));
// creates/updates/deletes apply optimistically, sync offline,
// and stream to every other connected client over SSE
}
How the pieces fit together
A mutation through any path — a generated endpoint, a custom Hono route wrapped with mutation tracking, or an RPC procedure — writes to the changelog. Subscriptions read the changelog and push deltas to connected clients with sequence numbers for reliable, resumable delivery.
Feature map
Requirements
- Node.js 18+ or Cloudflare Workers (
nodejs_compat) - TypeScript 5+
- Drizzle ORM (peer dependency
>=0.30.0) - Hono 4+
- Zod (peer dependency
>=3.0.0) - React
>=18is an optional peer dependency, only needed for the React client hooks.
Where to go next
- Quick Start — scaffold a project or add Covara to an existing app in a few minutes.
- Tutorial: a real-time todo app — build a complete app end to end, server and client.
- Resources & the app factory — the central abstraction every endpoint is built on.
- Contracts — the formal guarantees (and non-guarantees) the framework commits to.