App data storage options
Compare basebuddy-data, a separate Supabase/Postgres database, and the same database as your content before choosing where BaseBuddy stores setup state.
BaseBuddy app data is the setup state for BaseBuddy itself. It is separate from your content database tables.
App data includes local BaseBuddy users, password hashes, session token hashes, projects, members, permissions, invitations, saved mappings, sidebar layout, and audit events.
App data does not include database URLs, auth signing secrets, Supabase keys, S3 keys, or content rows. Those stay in environment variables or in your existing content database.
Quick choice
| Choice | Best for | Extra setup | Main tradeoff |
|---|---|---|---|
basebuddy-data/ folder on same server | One server, simple self-hosting, easiest local setup | None | The server must keep basebuddy-data/ on persistent writable storage |
| A new Supabase/Postgres database | Production installs, restarts, multiple app instances, cleaner separation | Run BaseBuddy app-data table setup | One more database URL to manage |
| Same database as your content | One database to manage, simple Supabase projects, smaller deployments | Run BaseBuddy app-data table setup | The content database role must also read/write BaseBuddy app-data tables |
If you are unsure and running one VPS or one Docker container with a volume, choose basebuddy-data/.
If your host replaces local files on deploy, restarts often, or may run more than one BaseBuddy server, choose a Supabase/Postgres app-data backend. For production with the cleanest separation, choose a new Supabase/Postgres database.
`basebuddy-data/` folder on same server
This is the default. Leave BASEBUDDY_APP_STATE_BACKEND blank, or set:
shBASEBUDDY_APP_STATE_BACKEND=basebuddy-dataBaseBuddy creates:
textprocess.cwd()/basebuddy-data/basebuddy.config.json
process.cwd()/basebuddy-data/basebuddy.audit.jsonlThe app and CLI create this folder automatically. Users do not need to create it by hand.
basebuddy.config.json stores users, sessions, projects, members, permissions, invitations, mappings, and sidebar layout. basebuddy.audit.jsonl stores login, logout, and local user change events.
The running app needs read/write access to basebuddy-data/. In production, that folder must survive deploys, restarts, and container replacement. Use a persistent volume or host-level persistent storage.
Use this when BaseBuddy runs on one server, you control the filesystem, you can mount or preserve basebuddy-data/, and you want the shortest setup.
Avoid this option when the host is immutable or serverless, deploys replace the app filesystem, you run multiple BaseBuddy instances at the same time, or you cannot back up the folder reliably.
No table setup is needed:
shpnpm basebuddy setup \
--owner-email owner@example.com \
--owner-name "Owner" \
--owner-password "replace-with-a-strong-password"
pnpm basebuddy doctorA new Supabase/Postgres database
Use:
shBASEBUDDY_APP_STATE_BACKEND=supabase-split-project
BASEBUDDY_APP_STATE_DATABASE_URL=postgresql://...The content database still comes from:
shBASEBUDDY_CONTENT_DATABASE_URL=postgresql://...BaseBuddy stores app data in the separate database, inside:
textbasebuddy.app_state
basebuddy.audit_eventsThis stores the same app data as the default folder backend: users, session hashes, projects, members, permissions, invitations, mappings, sidebar layout, and audit events.
The app-data database role must be able to read and write the BaseBuddy-owned basebuddy schema.
To prepare the tables:
shpnpm basebuddy app-data:migrate
pnpm basebuddy app-data:checkIf the runtime role cannot create schemas or tables, print SQL and run it with an admin role:
shpnpm basebuddy app-data:sqlThen run pnpm basebuddy app-data:check.
Use this when BaseBuddy runs in production, deploys may replace local files, the app may restart often, you may run more than one BaseBuddy instance, you want BaseBuddy app data separate from content data, or you prefer database backups over filesystem backups.
The tradeoff is one more database URL to manage. Keep BASEBUDDY_APP_STATE_DATABASE_URL in env, never in docs, screenshots, mapping JSON, or app data.
Same database as your content
Use:
shBASEBUDDY_APP_STATE_BACKEND=supabase-same-project
BASEBUDDY_CONTENT_DATABASE_URL=postgresql://...There is no separate BASEBUDDY_APP_STATE_DATABASE_URL for this mode. BaseBuddy uses the content database connection for both content access and app-data access.
BaseBuddy app data lives in:
textbasebuddy.app_state
basebuddy.audit_eventsYour content tables remain in their existing schemas. BaseBuddy does not rename, reshape, or migrate those tables during setup.
The database role in BASEBUDDY_CONTENT_DATABASE_URL needs both the content-table permissions editors need and read/write access to basebuddy.app_state and basebuddy.audit_events.
Prepare the app-data tables with:
shpnpm basebuddy app-data:migrate
pnpm basebuddy app-data:checkIf the role cannot create tables:
shpnpm basebuddy app-data:sqlRun the SQL in your database SQL editor, then run app-data:check.
Use this when you want one database to manage, the content database is already durable and backed up, your deployment host cannot keep basebuddy-data/, and you are comfortable storing BaseBuddy app data beside your content database.
This is simpler than a separate database, but it mixes BaseBuddy app data with your content database. Keep permissions tight: the role should have only the content table access editors need, plus the BaseBuddy-owned basebuddy schema access.
Auth behavior in all three options
BaseBuddy does not use Supabase Auth for editor login.
In every app-data option:
- users are local BaseBuddy users;
- passwords are hashed before storage;
- sessions are signed with
BASEBUDDY_AUTH_SECRET; - session records live in the selected app-data backend;
- invites and member roles live in the selected app-data backend.
Changing app-data storage changes where these BaseBuddy records live. It does not change the login model.
Backup differences
| Choice | Back up this | Do not commit |
|---|---|---|
basebuddy-data/ | basebuddy-data/basebuddy.config.json and basebuddy-data/basebuddy.audit.jsonl | basebuddy-data/ |
| New Supabase/Postgres database | basebuddy schema tables in the app-data database | database URLs and dumps with secrets |
| Same database as content | basebuddy schema tables plus normal content DB backups | database URLs and dumps with secrets |
Keep backups private. App data contains local user records, password hashes, session hashes, mappings, permissions, invitations, and project setup.
Hosting differences
| Host shape | Recommended choice |
|---|---|
| Single VPS with persistent disk | basebuddy-data/ |
| Docker on one server with a mounted volume | basebuddy-data/ |
| Dokploy with persistent volume | basebuddy-data/ or split database |
| Multiple app instances | New Supabase/Postgres database |
| Immutable/serverless host without durable writable storage | New Supabase/Postgres database |
| Small Supabase-first setup that wants one database | Same database as content |
The default basebuddy-data/ backend is not a good fit for Vercel, Netlify, or similar immutable deploys unless you provide durable writable storage.
CLI flow by option
For basebuddy-data/:
shpnpm basebuddy setup \
--owner-email owner@example.com \
--owner-name "Owner" \
--owner-password "replace-with-a-strong-password"
pnpm basebuddy doctorFor a new Supabase/Postgres database:
shBASEBUDDY_APP_STATE_BACKEND=supabase-split-project
BASEBUDDY_APP_STATE_DATABASE_URL=postgresql://...
pnpm basebuddy app-data:migrate
pnpm basebuddy app-data:check
pnpm basebuddy setup \
--owner-email owner@example.com \
--owner-name "Owner" \
--owner-password "replace-with-a-strong-password"
pnpm basebuddy doctorFor the same database as content:
shBASEBUDDY_APP_STATE_BACKEND=supabase-same-project
BASEBUDDY_CONTENT_DATABASE_URL=postgresql://...
pnpm basebuddy app-data:migrate
pnpm basebuddy app-data:check
pnpm basebuddy setup \
--owner-email owner@example.com \
--owner-name "Owner" \
--owner-password "replace-with-a-strong-password"
pnpm basebuddy doctorHow to decide
Choose basebuddy-data/ if you want the simplest setup and can keep one private folder persistent.
Choose a new Supabase/Postgres database if you want the cleanest production setup, app restarts without filesystem concerns, and app data separated from content.
Choose the same database as content if you want one database to manage and can grant the same connection role both BaseBuddy app-data access and restricted content-table access.