init and add
Scaffold the config, the data layer and framework glue for your project.
npx better-supabase init # before better-supabase is installed
pnpm better-supabase init # once it is a dependencyinit reads your package.json and writes:
better-supabase.config.tswithcasingwritten out (--casing camel|snake;initpickscamelby default, while a config withoutcasingmeanssnake). It lists the integrations it set up underintegrations, and carries commentedgen,envanddoctorentries for the options you would otherwise pass on every run (see Flags and the config)src/lib/supabase/index.ts, which exportsbetterSupabaseand theModelsandFunctionstypes- glue for every framework it finds, the same files
addwrites
When supabase/config.toml exists and has no [experimental.pgdelta] table,
init adds one with enabled = true, so supabase db schema declarative sync
diffs your schema files with pg-delta, the engine supabase init uses for new
projects. A table that sets enabled = false stays as it is, and init prints
the steps to switch (see BS316).
It then prints the next steps: the install command for your package manager,
supabase start, better-supabase env and better-supabase gen. Files that
already exist are never overwritten unless you pass --force or confirm the
prompt, and --dry-run shows what would be written. The names and the layout are described in Naming.
In a terminal, init asks for the casing (unless you pass --casing), the
integrations, with the detected ones checked (unless you pass --with), and
whether to overwrite files that exist. add without names asks which
integrations to add. It never asks in CI, when stdin or stdout is not a
terminal, or with --yes, which takes the flags and the defaults.
Found in package.json | Integrations |
|---|---|
next | next (and client) |
hono | hono |
@orpc/server | orpc |
vite, expo | client |
@tanstack/react-query | react (and client) |
Add more with --with edge,mcp. A project with only edge and mcp gets no
src/lib/supabase/index.ts: Edge Functions import betterSupabase from
supabase/functions/_shared/supabase.ts.
Supabase Lite
pnpm better-supabase init --lite--lite sets the project up for Supabase Lite. The
next steps install @supabase/lite as a dev dependency instead of pg, run
npx lite init and npx lite dev instead of supabase init and
supabase start, and ask you to set jwt_secret = "env(SUPABASE_JWT_SECRET)"
in supabase/config.toml with a secret of 32 or more characters in .env.
Pass backend: 'lite' to createServer (or the framework adapter) so the
server verifies Lite's HS256 tokens.
Workspaces
At the root of a pnpm, npm, yarn or bun workspace (a pnpm-workspace.yaml,
or workspaces in package.json), init writes into one package instead of
the root. In a terminal it asks which package owns the runtime, with the one
that already depends on better-supabase (or else the first with a framework)
selected. Otherwise pass it:
pnpm better-supabase init --package packages/runtimeinit then detects the frameworks and tsconfig.json of that package, writes
the config and the glue there, and prints next steps that target it:
pnpm --filter @acme/runtime add ... (or npm install -w, yarn workspace,
bun add --cwd) and better-supabase gen --cwd packages/runtime. Without
--package and without a terminal, init stops with an error that lists the
packages; --package . writes at the root as before. See
monorepos for how to split the runtime from domain
packages.
add
pnpm better-supabase add hono mcpadd without an argument sets up every integration in the config's
integrations list whose files are missing, which is how a fresh checkout
or a new package in a workspace gets its glue. When you name integrations
the config doesn't list yet, add prints the integrations entry to paste.
| Integration | Writes |
|---|---|
client | lib/supabase/client.ts with the framework's public env variables |
next | lib/supabase/server.ts (with import "server-only") and proxy.ts |
react | providers.tsx (app/providers.tsx in Next.js) and lib/hooks.ts |
hono | server.ts, which creates bs and adds the middleware and error handler |
orpc | router.ts, which creates bs and adds the auth middleware |
edge | supabase/functions/api (server.ts creates bs) plus supabase/functions/_shared/supabase.ts |
mcp | supabase/functions/mcp, an MCP server as an Edge Function (server.ts creates bs) |
Relative imports follow your tsconfig.json: they keep .ts when
allowImportingTsExtensions or rewriteRelativeImportExtensions is on.
Edge Functions always use .ts and get a deno.json import map. CI
typechecks every template against the library, so the files compile as
written. The names and the layout are described in Naming.
Last updated on