Supabase
Real data in Fayz follows the BYOS — bring your own Supabase model: you create the project, point the app at it, and fayz db apply provisions the same schema shape the platform uses (the core library + each plugin's versioned modules + your incubator ones). Going from mock mode to real data is, in the end, one command. This page is the reference for the flow; the guided walkthrough is in tutorial 05.
The path has four steps: create the project → fill in .env → run fayz db apply → flip the provider. db apply reads the installed packages, builds the migration order (core → versioned plugin modules → incubator) and applies it to your project via the Management API.
Architecture in transition. These docs describe the target shape — the core library and plugin tables with the plg_ prefix — that is shipping with the industry pools wave. The package wave published today still carries the previous naming (the CLI, for instance, labels the first plan step spine, which becomes core). The command and the flow are already these; only the internal labels migrate along with the wave. Where the text shows real CLI output, it appears with the current label.
The four credentials
A Supabase project gives you four values, with different roles:
- Project URL and anon key (Project Settings → API) — these go to the browser, they're public.
- Project ref (Project Settings → General) — the project identifier.
- Personal access token / PAT (Account → Access Tokens) — a machine secret; never goes to the browser or to Git.
In .env.local (git-ignored) they're separated by prefix: VITE_ for what's public, no prefix for what's tooling.
# Runtime (these go to the browser — public values only) VITE_SUPABASE_URL=https://YOUR-REF.supabase.co VITE_SUPABASE_ANON_KEY=your-anon-key # Tooling (used by `fayz db apply` — these do NOT go to the browser) SUPABASE_PROJECT_REF=your-project-ref SUPABASE_PAT=your-personal-access-token
The CLI also accepts the aliases SUPABASE_REF and SUPABASE_ACCESS_TOKEN, and reads first from the process environment, then from <app>/.env.local, then from <app>/.env (the files never override the environment).
Plan before you apply (dry-run)
--dry-run makes no network calls and doesn't read your PAT — it's always safe to run:
npx @fayz-ai/cli db apply --dry-run
--dry-run assumes you've already run npm install: it reads the @fayz-ai/* packages from your node_modules to build the plan. Without @fayz-ai/db installed, the command errors instead of printing the plan — install your dependencies first.
It prints the ordered plan and stops. The order is always the same: core first, then each plugin's versioned migrations, and finally your incubator ones. In the current CLI output this shows up with the labels:
spine → drizzle → seed → plugins → incubator
where spine/drizzle/seed are the core steps (the label moves to core in the industry pools wave), plugins are each plugin's versioned modules, and incubator are your tables. A step only shows up if the corresponding package ships SQL files. With the current package versions the plan is still lean — as plugins start shipping migrations, new steps appear here. Don't be surprised by an "empty core" warning in the dry-run: the published @fayz-ai/db doesn't ship migrations in this generation yet, and the command itself tells you which version fixes that.
Apply for real
Once the plan looks the way you want, apply it. This command runs with your credentials and writes to the database:
npx @fayz-ai/cli db apply
It asks for confirmation before applying; use --yes to skip the prompt in CI. Without SUPABASE_PROJECT_REF and SUPABASE_PAT set, it stops with a clear error — on purpose, so it never applies against the wrong project. Useful flags for applying in pieces:
| Flag | Effect |
|---|---|
--dry-run | Only prints the ordered plan; no network calls. |
--yes, -y | Skips the confirmation (required in non-interactive shells). |
--spine-only | Applies only the core from @fayz-ai/db (the flag keeps the spine label in the current wave). |
--plugins-only | Applies only the plugin + incubator migrations. |
--only-plugins a,b | Restricts the plugins step to the named ids. |
Flip the switch
With the schema in place, switch the backend in app.manifest.json from mock to supabase and set the ref:
{
"backend": {
"provider": "supabase",
"projectRef": "your-project-ref"
}
}
And validate:
npx @fayz-ai/cli doctor
fayz db apply handles the layer ordering for you — core, then the plugin modules, then your incubator ones — in your own Supabase. You never write the core SQL by hand. To understand what's being created, see Data model.
Next: how isolation between tenants is guaranteed in RLS and multi-tenancy.