Into a directory the binary serves

Put what defines your instance into git and keep running it with the executable you already have. Nothing is installed, and nothing here reaches Cloudflare, which is the trade this page makes.

Where the instance you have is

Every step below reaches it the same way, over the API with a superuser. What differs is the address.

Downloaded the executable

It is serving a directory on this machine, so the address is the one it printed: http://127.0.0.1:8090 unless you changed it. Leave it running while you work.

Made it with the CLI

The CLI knows it by name and can tell you its port.

voidbase local ls                    # the name and port of each one
voidbase local start blog            # if it is not already running

On Cloudflare, or on voidbase cloud

The address is the Worker's, and the superuser is the one you were given when it was created. Nothing has to be running locally for this: export reads it over the network like any other client.

Make the directory

init writes the three directories the server reads. The executable has the command, so this needs no toolchain.

mkdir blog-api && cd blog-api
cp ~/Downloads/voidbase .          # the executable you already downloaded
./voidbase init

Take the collections out, and put them back

Export against the instance you already have. Then start the one this directory defines and import into it; import works over the API, so the new instance has to be running and needs its address and a superuser.

./voidbase export ./snapshot --url http://127.0.0.1:8090 --admin you@example.com:your-password
./voidbase serve --dev --http 127.0.0.1:8091    # a second port, while the old instance is still on 8090
./voidbase import ./snapshot/collections.json --url http://127.0.0.1:8091 --admin you@example.com:your-password

The snapshot also holds the rows, as data.db, and the uploaded files under storage/. Those are data and stay out of the repository; what git tracks is the rule, and it is the same rule here.

The import changed this instance's database and nothing else. What the repository defines is in pb_migrations/, so write the export down as a migration that applies the same list; a fresh clone then builds the collections without the import.

// pb_migrations/1757500000_collections.js
migrate((app) => {
  app.importCollections([
    // the contents of snapshot/collections.json
  ], false);
});

Ignore the three things that must not be committed

Git
pb_data/
pb_secrets/secrets.json
voidbase

The database and the uploads are in pb_data/, the values of your configuration are in pb_secrets/secrets.json, and the executable is a build artifact that a colleague downloads for their own platform rather than takes from yours. init writes the first two lines; add the third.

Run it from the directory

--dev restarts when a hook or a migration changes, so editing a tracked file is the loop. Once the old instance is gone, drop --http and it is back on 8090.

What you give up, and what you can do about it

Deploying to Cloudflare needs the npm package, because it runs Void and wrangler out of node_modules. This directory cannot do it, so the deploy is yours: the same directory on a server, and the executable started by a unit file. The standalone page has the unit, and the pipeline for this shape is a job that checks the directory, then moves it and restarts the service.

If Cloudflare is what you wanted, this directory is already most of a voidbase project: add a package.json with the dependency and the same three directories keep working.

Found something wrong on this 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.