Create a project
A backend you extend and keep: your own endpoints, handlers that run when records change, a schema in version control. It runs as one process on your machine and as one Worker on Cloudflare, from the same directory.
Start one
bun i -g @voidbase-cloud/voidbase
mkdir blog-api && cd blog-api
voidbase init
voidbase superuser upsert you@example.com your-password
voidbase serveThat is a working instance on http://127.0.0.1:8090, with the admin panel at /_/ and a sample endpoint answering GET /api/hello. init wrote this:
Inside blog-api/:
pb_hooks/: endpoints, event handlers, scheduled workpb_migrations/: the schema, as codepb_public/: static files served at/, if you want anypb_secrets/: configuration, and who may read each keypb_data/: the database and the uploaded files, git-ignored.gitignore
Only pb_hooks/ and pb_migrations/ matter on day one. Each directory has its own page:
The loop
Design the schema in the panel. Collections, fields, and the API rules that decide who may read and write what. It is the fastest way to get the shape right, and it is immediately live.
Write it down as a file in pb_migrations, so the same schema reaches production and the next person who clones this.
Add behaviour in pb_hooks: an endpoint the API does not have, a handler that fires when a record is written, a nightly job.
Run it while you work.
--devrestarts when a hook or migration changes.voidbase serve --dev
Put it on Cloudflare
One API token, which voidbase token prints the link for, declared as a local() key in pb_secrets. Then, from the project:
voidbase deployIt creates the Worker, its database, its file storage, its queue and its realtime object on the first run, stores the declared secrets on it, applies any pending migrations on the first request, and prints the address. Deploy again whenever anything changes; the data is untouched.
Or let a push do it
sync is that deploy plus the wiring, so every later push to the repository deploys by itself and every change to the instance is a commit somebody can read and revert.
voidbase syncIt needs a second token and one dashboard step the first run points at. From then on the whole loop above is: edit, commit, push. Deploy on every push is the guide, and What git tracks is the list of what belongs in the repository and what must not.
Listing and deleting instances works the same from a project as without one: voidbase instances and voidbase destroy.
Updating
voidbase updateRun it in the project. The dependency in package.json is bumped to the newest published version and installed, keeping the caret or the exact pin you already had, so a project that deliberately pins stays pinned. The change is a diff in package.json and your lockfile: review it and commit it like any other dependency bump.
voidbase update --check changes nothing. It prints the version you are on and the newest one, and exits 1 when you are behind and 2 when it could not find out, which is what a pipeline reads. --to 0.9.0 goes to a particular version rather than the newest, and --dry-run prints the command it would run without running it.
You do not have to remember to check. Any voidbase command mentions a new release once a day, from an answer cached under ~/.voidbase. It never speaks in CI or when the output is not a terminal, and VOIDBASE_NO_UPDATE_CHECK=1 silences it everywhere. Every release is written up in the release notes.
When this stops being enough
A project is a backend. When the site is yours too and you would rather write pages, typed routes and a database schema in one application than keep a frontend and a backend in step, the voidbase stack is the next page.
Fix it yourself. The link below opens this file in GitHub's editor and forks the repository for you if you need one, and your change becomes a pull request without leaving the browser.