BaseBuddy is a self-hosted editor for existing Supabase and Postgres databases. It works with the tables you already have, then turns saved mappings into a clean editor for your team.
Website · Demo · Install · Docs · Support · License · Security · Changelog · GitHub
BaseBuddy is for teams that already have content in Postgres or Supabase and want a real editor without rebuilding their database around a CMS.
You install BaseBuddy, connect it to your database, map your existing tables and fields, and start editing. The saved mapping is the source of truth. Your database stays yours.
BaseBuddy is especially useful when you want:
- a clean editor for existing posts, pages, docs, guides, or content tables;
- a minimal TipTap editor that can work with Markdown and HTML storage formats;
- media and file management through Supabase Storage or S3-compatible buckets;
- SEO fields, redirects, slugs, authors, categories, tags, and publishing workflows;
- role-based and user-specific permissions;
- an admin UI that respects the shape of your current schema.
BaseBuddy is careful around your production database.
- It does not rename your tables.
- It does not reshape your schema during normal editing.
- It does not store per-project database credentials in project rows.
- It does not silently publish, unpublish, or archive content when you click Save.
- It does not rewrite unchanged fields just because a post was opened.
- It does not coerce Markdown into HTML, HTML into Markdown, arrays into strings, or one storage shape into another on normal save.
Save writes dirty fields only. Publish, Unpublish, and Archive are explicit actions.
flowchart LR
Database["Your Supabase/Postgres database"] --> Mapping["Saved BaseBuddy mapping"]
Mapping --> Runtime["Storage-first runtime"]
Runtime --> Editor["BaseBuddy editor"]
Editor --> Dirty["Dirty-field save"]
Dirty --> Database
BaseBuddy separates three ideas:
- Storage contract: where a value lives, what shape it has, whether it is editable, and how it should be patched.
- Semantic role: optional meaning like title, content, slug, status, author, category, tags, or featured image.
- UI: the editor control selected from the storage contract, then refined by semantic role.
It also keeps the control plane and content plane separate in the runtime model. The control plane stores BaseBuddy projects, members, roles, invitations, mappings, and sessions. The content plane is your existing database schema and storage buckets.
That is why BaseBuddy can support flexible schemas without pretending every database looks like the same CMS template.
You need:
- Node.js 22 recommended;
pnpm@10.32.1;- a Supabase/Postgres project for BaseBuddy setup data;
- a Supabase/Postgres database or schema with content you want to edit.
Clone and install:
git clone git@github.com:basebuddy-cms/basebuddy.git
cd basebuddy
pnpm install
pnpm devThe dev server runs on:
http://localhost:8080
Open onboarding:
http://localhost:8080/onboarding
The onboarding page is designed to work before .env exists. It helps you choose an install shape, copy the right env values, apply the BaseBuddy migration, configure Supabase Auth, and verify that the install is ready.
BaseBuddy supports two common setups.
flowchart TB
subgraph Same["Same-project install"]
One["One Supabase/Postgres project"]
One --> ControlA["BaseBuddy tables"]
One --> ContentA["Your content tables"]
end
subgraph Split["Split-project install"]
ControlB["Control project"] --> BaseBuddyTables["BaseBuddy tables"]
ContentB["Content project"] --> ExistingTables["Your content tables"]
end
Use a same-project install when you want the simplest setup.
Use a split-project install when you want BaseBuddy's control tables separate from the database that stores your content.
The generated env values come from /onboarding, but the examples are here:
After editing .env, restart the app so Next.js picks up the new values.
BaseBuddy needs its own control-plane tables for projects, members, roles, invitations, mappings, and edit sessions.
Apply the baseline migration to the BaseBuddy control database:
psql "$BASEBUDDY_DATABASE_URL" -v ON_ERROR_STOP=1 -f supabase/migrations/20260420130000_basebuddy_self_host_baseline.sqlFor split-project installs, apply it to BASEBUDDY_CONTROL_DATABASE_URL instead.
You can also paste the SQL into the Supabase SQL editor.
Once setup is ready:
- Sign in.
- Open
/projects. - Create a project.
- Open the project editor.
- Map Posts first.
- Map authors, categories, tags, media, files, SEO fields, redirects, and workflow fields as needed.
- Save the mapping.
- Start editing content.
Auto-detection can help, but manual mapping is always available. If BaseBuddy cannot safely infer a field, it keeps the field read-only or unsupported instead of guessing.
Build and start:
pnpm build
pnpm startpnpm start serves the app on port 8080.
Before exposing BaseBuddy publicly:
- configure Supabase Auth redirect URLs;
- run the setup checker;
- put the app behind HTTPS;
- set request body limits that match your upload policy;
- use a shared upstream rate limiter if you run multiple app instances.
Useful checks:
pnpm setup:check
pnpm build
pnpm testFor browser tests, copy .env.playwright.example to .env.playwright, fill in test credentials, then run:
pnpm test:e2eStart with:
- Install guide
- Configuration
- Onboarding
- Projects and mapping
- Permissions
- Storage and media
- Storage UI matrix
- Caps and rate limits
- Deployment
- Troubleshooting
Contributions are welcome. Please read Contributing before opening a pull request.
If you are changing mapping behavior, runtime storage semantics, permissions, setup env assumptions, or route ownership, update the relevant docs and tests in the same change.
BaseBuddy is licensed under AGPL-3.0-or-later. See LICENSE.md.
If you modify BaseBuddy and let users interact with it over a network, the AGPL requires that those users can receive the corresponding source code for your modified version.

