Skip to main content

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

AreaHighlights
Core APICRUD, filtering (30+ operators), cursor pagination, aggregations, relations, batch ops, soft delete, computed/masked fields, optimistic locking, nested writes
Real-timeSSE subscriptions, live aggregations, changelog, mutation tracking
Auth & securityOIDC provider, federated login, JWT, sessions, MFA/TOTP, magic links, API keys, RSQL scopes, field masking, security headers
Platform servicesFile storage, email, billing, background tasks, KV store, health checks
Client libraryTyped client, React hooks, live queries, offline, auth, file uploads, type generation, React Native
Runs everywhereNode, Cloudflare Workers, SQLite & PostgreSQL, Durable Object KV
ToolingCLI scaffolder, OpenAPI, Admin UI, middleware, error handling

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 >=18 is an optional peer dependency, only needed for the React client hooks.

Where to go next