One declarative product truth.
Every platform projected from it.
Describe your Supabase backend once, in a single supabase.yaml contract.
supabase_client_gen projects it into typed Dart clients, living documentation,
and validation that proves everything stays in sync — deterministic, drift-proof, agent-operable.
How it works
Contract in, consistency out.
The contract is the canonical description of your backend. Everything else — clients, docs, checks — is a projection of that one truth.
Write the contract
Tables, enums, access rules, RPCs, edge functions, realtime, storage — one readable
YAML file. Already have a database? init --from-db drafts it for you.
Generate every projection
One command emits the complete typed Dart client — models, repositories, RPC and edge function wrappers, storage clients — plus a Markdown data dictionary.
Prove consistency
validate reconciles database, contract, generated code, and TS types;
doctor lints against best practices. CI gates on both.
# supabase.yaml — the single source of truth data_model: public: things: ownership: workspace primary_key: id fields: id: uuid workspace_id: uuid name: text category: thing_category notes: text nullable_fields: [notes] enum_values: thing_category: [device, document, other] client_access: select: member_of_workspace insert: member_of_workspace rpc_functions: add_thing_note: args: { p_thing_id: uuid, p_note: text } returns: uuid
// GENERATED by supabase_client_gen — do not edit final repo = ThingRepository(supabase.client); // Typed, workspace-scoped, null-safe: final things = await repo.select(workspaceId: wsId); final created = await repo.insert( {'workspace_id': wsId, 'name': 'Drill'}); // Realtime stream from the publication: repo.stream(workspaceId: wsId) .listen((things) => render(things)); // RPC as a typed top-level function: final noteId = await addThingNote( pThingId: thing.id, pNote: 'inspected'); // thing.category is a real Dart enum: if (thing.category == ThingCategory.device) { ... }
# Gate it all in CI — drift never ships: $ dart run supabase_client_gen:generate --contract supabase.yaml --check $ dart run supabase_client_gen:validate --contract supabase.yaml --mode=all --with-db $ dart run supabase_client_gen:doctor --contract supabase.yaml --json --strict ✓ DB ↔ contract aligned ✓ generated client up to date ✓ TS types match ✓ 0 doctor errors
Features
Everything the contract knows, every surface gets.
Built for Flutter + Supabase teams who treat generated code as a public API: versioned, reviewed, and gated in CI.
{} Typed models & repositories
Equatable models with fromJson/toJson/copyWith, repositories with typed select / insert / update / delete / stream — workspace scoping derived from the contract.
ƒ RPC functions, end to end
Each rpc_functions entry becomes a typed Dart function over client.rpc — optional args honour Postgres DEFAULTs, returns: row:<table> decodes into your models.
⌗ Composite keys & views
primary_key: [session_id, user_id] yields update/delete with one parameter per key part. kind: view generates strictly read-only repositories.
λ Edge function clients
Client-invoked edge functions become typed top-level wrappers over functions.invoke — required and optional request fields straight from the contract.
M↓ CONTRACT.md docs emitter
Every generate run writes a deterministic Markdown data dictionary of the whole backend — the fastest way to hand its shape to a colleague or an AI.
⇄ Brownfield import
init --from-db introspects an existing database into a draft contract — the prisma db pull of this tool. Offline variant: init --from-gen-types.
✚ Doctor: best-practice linter
DR-coded findings with path and concrete fix: missing primary keys, undocumented access, public buckets, RLS disabled, SECURITY DEFINER drift — JSON output for CI.
◫ Contract Cockpit
A zero-server, statically built visualization: interactive schema graph, security matrix, function cards, realtime & storage surface.
● Drift traffic light
Doctor findings render as a red/amber/green strip in the cockpit, with status dots on affected tables in the schema graph. Drift is visible before it ships.
≡ Deterministic, golden-tested
The same contract produces byte-identical output on any machine — no database required. Every emitter ships with golden snapshots and a compile check.
Contract Cockpit
See the whole backend at a glance.
The cockpit renders any contract as a static, zero-server site: an interactive schema graph, a security matrix of who-may-do-what, function cards, the realtime & storage surface — and a drift traffic light fed by real doctor findings.
Built in the open
Real product, real contract, real findings.
MIT, no strings
Everything — generator, validators, doctor, cockpit — is MIT-licensed and developed in public. Use it, fork it, ship it.
Battle-tested daily
MercyNight, an interactive party-music app, is the reference user — and the live demo shows its actual backend contract, doctor findings included.
Giving back
This tool exists because the Flutter + Supabase gap was worth closing for everyone, not just for one codebase. Issues and PRs welcome on GitHub.