Baseplate

A Postgres backend you run yourself: an HTTP API over your tables with per-user row access, auth, file storage, encrypted backups, and a local studio. Open source, MIT.

The studio's row security panel for a cards table: reads and writes are the owner's, with the CREATE POLICY statement the database runs.

The problem

One developer with a handful of small apps needs a database, an API, login, files and backups before anything else. A managed platform gives you that in an afternoon, along with a bill and a data owner that are not you. Rolling it yourself takes days.

  1. Small app
  2. Needs a backend
  3. Platform bill, or days of setup

What I built

  1. 01Postgres and PostgREST behind Caddy, with row-level security on every table before it takes its first row.
  2. 02Auth, storage and backup services in TypeScript on Docker Compose. Two commands from an empty folder to a running API.
  3. 03A local studio, a CLI and an MCP server, all calling the same ten use cases.
  4. 04Terraform that creates a Hetzner server, firewall, DNS record and TLS certificate from the operator's own account tokens. Those tokens never leave the operator's machine.
  5. 05A typed client that answers { data, error } and never throws, so a failure is a value the app renders.

Features

  • The cards table in the studio, browsed as one signed-in caller: seven rows, all with that caller's owner_id.

1 of 2

The hard part

The database decides

There is no anon key and no filter in the app. A table nobody declared is locked rather than left open, and every policy is re-applied on every start, so a restore or a restart can never leave a table exposed. The proof is two callers against one endpoint: the second one gets an empty array because Postgres said so, not because the app remembered to filter. CI packs the package, installs it into an empty project, and runs that proof against the installed copy, not the checkout.

Stack

Links