betavoidbase is in public beta. It runs, the API is PocketBase's and is not moving, and the version is still 0.x for everything around that.Help us get it to 1.0

What git tracks

Everything that decides how the instance behaves belongs in the repository: the endpoints, the schema, the static files, the list of configuration keys, and the version of voidbase itself. One thing must never be there, and that is the values of your secrets.

In the repository

WhatWhy it matters that it is tracked
pb_hooks/Your endpoints and handlers. Reviewable, revertable, and the diff says what changed about behaviour.
pb_migrations/The schema. A deploy carries it, so production and a fresh clone end up with the same database.
pb_public/The static files, if the instance serves any.
pb_secrets/main.tsThe names of every configuration key, their types, their defaults and who may read them. The declaration, never the values.
package.json, lockfileThe version of voidbase production runs. Without it, what ships is whatever npm served that morning.

Not in the repository

Git
# a project
pb_data/                    the database and the uploaded files
pb_secrets/secrets.json     the values of your configuration
.cloud/                     the generated Cloudflare project

# a stack app
.voidbase/                  the generated instance
vb_secrets/secrets.json     the values of your configuration

voidbase init writes those ignore lines for you. If your repository did not come from it, check them before the first commit, and check them again before making the repository public.

A secret that has been committed is a secret that has leaked, even after you delete the line: it is in the history, and on any clone. Rotate it rather than trying to erase it.

So how do the values reach production?

Three different ways, depending on who is allowed to read the key.

Secrets are stored once, from your machine

A secret() value is put on the Worker by a deploy you run yourself, and lives there encrypted. The pipeline never sees it: a build has no secrets.json, and it does not need one, because the Worker already has the value.

voidbase secrets push

A deploy stores a secret the Worker does not have yet, and deliberately will not overwrite one it does. secrets push is the command that replaces, which is what you want when rotating and never what you want by accident.

Server and browser values travel with the deploy

A server() or browser() key is not a secret; it is configuration. Its value comes from the default in the declaration, which is tracked, or from the build environment, and every deploy sets it again. Most of them should simply have a default, and then there is nothing to configure anywhere.

Tokens are yours and stay yours

A local() key is never deployed at all. The deploy token is the exception that has to reach the pipeline, because a build has to be able to deploy: voidbase sync stores it as a build secret on the trigger, once, from your machine. Cloudflare keeps it and does not show it back.

Checking what production actually has

voidbase secrets

One row per declared key: its tier, whether it has a value here or a default, and whether the Worker has it. This is the command to run when something behaves differently in production, because nine times out of ten the answer is a key that was declared but never given a value.

Rotating one

# change it where the value lives, then send it
$EDITOR pb_secrets/secrets.json
voidbase secrets push

Nothing to commit, nothing to redeploy: the Worker picks up the new value on its next request. Removing a key is the reverse, and is two changes rather than one: take it out of the declaration and commit that, so the next person does not go looking for a value nothing reads.

What a build machine can see

Only what it needs: Bun's version, the deploy token as a build secret, and the declared server and browser values. Not your secrets.json, which never leaves your machine, and not the encrypted secrets on the Worker, which nothing can read back.

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.