The Supabase developer experience, running locally.
Fakebase mimics the developer-facing shape of Supabase, backed by an in-process kernel. Build prototypes at zero-setup speed anywhere @supabase/supabase-js runs, then export real Supabase SQL migrations and database.types.tswhen you're ready to ship.
import { createClient, createMemoryKernel } from "@byronwade/fakebase";
import schema from "./fakebase/schema";
const kernel = createMemoryKernel(schema);
export const supabase = createClient("local", "dev-key", { kernel });
// Same call shape as @supabase/supabase-js:
const { data, error } = await supabase
.from("posts")
.select("*")
.eq("published", true)
.order("created_at", { ascending: false });Zero setup
No Docker, no local Postgres. createMemoryKernel() or a .fakebase/ JSON folder and you're writing data.
Same API surface
from().select().eq(), auth, storage, realtime, rpc — the exact @supabase/supabase-js call shape.
First-class export
Generate supabase/migrations/*.sql, seed.sql, and database.types.ts that drop into a real project.
Honest capabilities
Unsupported features throw a structured CapabilityError instead of silently faking behavior.
Fast today, honest about tomorrow
Fakebase is designed to be thrown away. The point is to get you to a working prototype, then out of the way — on the exact contract you'll ship against.
Code against the contract
Write your app against the @supabase/supabase-js client shape — any framework, today, with no backend.
Pick your fidelity
Swap the kernel adapter — memory, JSON, SQLite, or real Postgres-in-WASM (pglite) — without touching app code.
Export & ship
Emit Supabase-compatible SQL, seeds, and types, verify against real Postgres, then swap createClient.
I kept hitting the same wall while prototyping — especially with AI in the loop. I wanted to move fast on a design and have the schema and migrations come along for the ride, instead of stopping to re-provision a database and hand-sync migrations every time the shape of an idea changed.
So Fakebase is the tool I wanted: spin up a Supabase-shaped backend in-process, iterate on a near‑launch‑ready prototype as fast as you (or your AI) can change your mind, and when it settles, export real migrations and types instead of rewriting them. Quick and easy for prototyping, honest about the path to production.
Byron Wade
Creator of Fakebase
Honest capability labels
Every Supabase-shaped API is labeled by how faithfully Fakebase reproduces it. No silent gaps.
| Area | Fidelity | Notes |
|---|---|---|
| Database CRUD + filters | Exact | from().select().eq()… order / range / single |
| Generated types | Exact | database.types.ts from schema IR |
| Migrations + SQL export | Exact | Supabase-compatible SQL + seed.sql |
| RPC (rpc / functions.invoke) | Close | Local function registry |
| Auth (password / OTP / sessions) | Close | Local GoTrue-shaped flows |
| Storage (buckets / objects / URLs) | Close | Local filesystem + signed tokens |
| Realtime (broadcast / changes) | Close | In-process pub/sub |
| RLS policies | Partial | Dev approximation — verify on real Postgres |
| OAuth / SSO / MFA / passkeys | Unsupported | Capability-gated errors |
Full method-by-method matrix lives in the docs.
The path to real Supabase is short
Five steps from local prototype to production-ready Supabase project.
- 1
fakebase migrate export --supabaseWrite supabase/migrations/*.sql from your schema IR.
- 2
fakebase seed exportGenerate supabase/seed.sql from local data.
- 3
fakebase types genEmit database.types.ts — identical shape to Supabase's generator.
- 4
fakebase verify supabaseRun the compatibility suite against a real Supabase stack.
- 5
swap createClientReplace fakebase's createClient with @supabase/supabase-js. Done.