A directory the binary serves
The hooks and the schema in git, served by the one file you downloaded. Nothing is installed and nothing is built, which is the whole point of this shape and also its limit: it does not reach Cloudflare.
Whether this is the one you want
Take it if you run your own server and want the backend reviewable. A colleague clones the repository, downloads the executable for their platform, and has the same collections and the same endpoints.
Take a voidbase project instead if you want it on Cloudflare. It is the same directories with a package.json beside them, because deploying runs Void and wrangler out of node_modules and the executable has neither. voidbase init is part of that toolchain too, which is why the directories below are made by hand.
Start it
Download the executable first if you have not. Then make the two directories the executable reads, beside it.
mkdir blog-api && cd blog-api
cp ~/Downloads/voidbase .
mkdir pb_hooks pb_migrations
printf 'pb_data/\nvoidbase\n' > .gitignore # the data, and the executable itself
./voidbase superuser upsert you@example.com your-passwordInside blog-api/:
pb_hooks/: endpoints, event handlers and scheduled work, in JavaScriptpb_migrations/: the collections, as code, applied once and in orderpb_data/: the database and the uploads, git-ignoredvoidbase: the executable, git-ignored; everyone downloads the build for their platform.gitignore
The loop
./voidbase serveThe API is on 8090 and the panel is at /_/. Hooks and migrations are read when the server starts, so a change to either is a restart.
/// <reference path="../pb_data/types.d.ts" />
routerAdd("GET", "/api/hello", (e) => e.json(200, { hello: "world" }));Save that as pb_hooks/hello.pb.js, start the server, and the endpoint is live. What else hooks can do is in the pb_hooks reference, and the schema is in pb_migrations. Both apply here unchanged: the directories are the same ones, and only the toolchain around them is missing. Configuration on this shape is the process environment, which $os.getenv reads.
Getting it onto a server
Copy the directory, put the executable beside it, and run it under a service manager. The standalone page has a systemd unit that does this, and the pipeline for this shape turns the copy into something a push does.
The data does not travel with the repository. A first deploy starts with an empty database and applies your migrations. To move existing records as well, migrate takes a backup on the instance you have and restores it on the one you just started, over HTTP, in either direction:
./voidbase migrate http://127.0.0.1:8090 https://api.example.com \
--from-email you@example.com --from-password ... --to-email you@example.com --to-password ..../voidbase export <dir> and ./voidbase import collections.json are the smaller tools beside it: a copy of everything on disk, and a schema applied to a running instance.
Updating
./voidbase update --backupIt replaces the executable in place and keeps pb_data/ untouched. The tracked directories are yours and are never rewritten, so an upgrade is one file changing and nothing in the repository moving.
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 1.0.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
The moment you want Cloudflare, a declared configuration in pb_secrets, a package from npm inside a hook, or the site and the backend in one deploy. The first three are a voidbase project and the fourth is a stack. Both keep the directories you already have.
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.