voidbase cloud
Instances from a page, in your own Cloudflare account. Sign in with Cloudflare, name one, and your browser creates it: a Worker with the admin panel, a D1 database, an R2 bucket and a queue, owned by you and billed to you. voidbase.cloud never holds it.
Try it from the cloud page. The backend of that page is itself such an instance, and so is the demo.
What the site keeps, and what your browser does
The site keeps four things: your sign-in, your Cloudflare and GitHub tokens sealed at rest, the rows about your instances and repositories, and two pass-throughs that forward a call to Cloudflare's or GitHub's API with your token, because Cloudflare's API sends no CORS headers and neither token ever reaches the browser. Everything else is the page's own work, with voidbase's own code: an instance is created, upgraded and deleted in your account; a repository is created from a template or linked and wired to the instance; an instance's plugins are changed through the instance's own installer, with a session you mint on it from the page. Nothing is built for your instance by anyone but its own pipeline.
Creating one
Cloudflare shows which accounts and permissions the site asks for, and nothing is created until you click create. The form takes a name, which of your accounts it goes in, and what to start from: nothing, for a bare instance, or one of the site's templates, which makes a repository in your GitHub in the same click, sets its variables to the instance and wires the instance to deploy from it. The instance is provisioned from the release the site holds, and the superuser password is shown once and kept nowhere, so write it down.
Starting from a template needs GitHub connected, which the page asks for once. The repository reads the instance's address from its PB_VB_URL variable, and one step stays in Cloudflare's dashboard the first time: connecting the repository under Builds so a push deploys it. The page prints the link.
The instance's card
What you do to a backend after making one, each a call the page makes itself. Most of them sign in to the instance with its superuser first, and the session is shared by the panels.
| Panel | What it does |
|---|---|
| Plugins | What the instance runs and where each plugin came from, what our marketplace and any other one by URL serve, and install, update and remove through the instance's own installer. On an instance deployed from a repository a change is a commit there, and its build deploys it. An install names only a marketplace the project's voidbase.lock already trusts. |
| Logs | The last entries, newest first, with a level and a window, and an "errors only" toggle that asks for the 5xx answers and anything the instance recorded an error for. On an instance without the observability plugin: the last entries with a filter in PocketBase's syntax. |
| Metrics | The window's requests and errors, the error rate, p50, p95 and p99, the status split and the five slowest routes, over an hour or a day. On an instance without the observability plugin: requests and errors over the last 24 hours, one bar per hour, from the instance's own logs. |
| Observability | Not a panel of its own: the observability plugin is what Logs and Metrics read, and the plugin answers from one of two sources. The Analytics Engine dataset, when the instance was deployed with --analytics and carries a token to query it, holds one sampled data point per request, so those numbers are about all the traffic. The instance's own request log is always there and needs nothing, but it keeps entries at or above the log level, which is warnings and errors by default, so those numbers are about what went wrong rather than everything that happened. Each answer says which one it used, and the panel repeats it in a line. The card itself carries the last hour as three numbers, asked for once when you sign in to the instance. |
| Backups | The archives in the instance's storage, each verified after it is written and again on demand. Take a full one or a data one, download, verify, restore, delete. |
| Superusers | Who can open its panel. Add one, remove one; the last one stays. |
| Payments | Which provider answers, the webhook URL to register, and the customers, subscriptions and payments the webhooks wrote; or, with no provider key set, the secrets that would set one. |
| Translations | What the translations plugin has and has not, one row per declared collection and one column per locale, each cell the strings written of the strings there are. Pick a collection and a locale and the records missing a field in it are listed, a page at a time, each field with a box that writes it; the record goes once nothing of it is missing. It is for finishing a few strings, not for translating a site: no import, no export, no machine translation. With neither knob set, the two that would start the plugin; on an instance without it, a line saying so. |
| Domains | The hostnames the domains plugin reports from the instance and which is canonical, and setting them, which is the plugin's knob written where that instance's deploy reads it. Below them, what your account has attached to the Worker, so a hostname on one side and not the other shows. |
| Secrets | The Worker's secrets by name. A value is written and never read back; the managed ones are listed only. |
| Members | Who is on the instance, what each of them may do, and which invitations nobody has accepted yet. An owner invites by email, changes a role and takes somebody off; everybody else sees the list. |
Beside those: upgrade the instance to the site's current release in place, its database, files, domains and superuser kept; roll that upgrade back, for a week; wire another repository to it, from a template or one you have; delete it, which takes the Worker and everything it owns after you type the name back.
Teams
An instance belongs to a team, not to whoever clicked first. Whoever creates one is its first owner, and from the card's Members panel an owner adds anybody else by email address. Each person has one of three roles, and the role is on the card so you can see at a glance what an instance is to you.
| Role | What it reaches |
|---|---|
| Owner | Everything, including deleting the instance and changing who is on it. An instance always has at least one: the last owner cannot be removed or demoted, so there is never one with nobody who may hand it on. |
| Admin | Everything to the instance: upgrade, roll back, domains, secrets, plugins, backups, and wiring a repository to it. Not deleting it, and not who is on it. |
| Viewer | Reads what the instance reports: logs, metrics, plugins, the backups list, the team. Changes nothing, and the card offers them no button that would. |
An invitation is an email with a link. Open it signed in with the address it was sent to and you are on the instance; open it as somebody else and it says which address it was for. A link works once: accepting it clears it, and an invitation nobody has accepted shows on the panel as pending until they do or the owner takes it back. If the site it was sent from has no mail set up, the invitation still exists and the panel hands the inviter the link to send however they like.
What a role does not do is hand over a Cloudflare account. The instance stays where it was made, and everybody on it works in that account with their own Cloudflare sign-in: this site holds each person's token for them and never lends one to another. So somebody you make an admin needs their own access to the account the instance lives in before an upgrade or a secret goes through; Cloudflare answers that question, and the roles here answer what we let them ask.
Setting a domain
A deployed instance carries the domains plugin, and the plugin is what attaches a hostname: at deploy time it reads VOIDBASE_DOMAINS (comma separated, the first canonical), turns the workers.dev address off, attaches each hostname through Cloudflare, waits for the certificate and sends the other hostnames to the canonical one with a 301. The panel sets that knob rather than doing the work itself, and it reads the plugin's own report back as the truth.
On an instance deployed from a repository, setting a domain is one commit to it, the way a plugin install is one commit: VOIDBASE_DOMAINS goes into the project's vb_secrets/main.ts, where the deploy reads its knobs, and the change lands on the next deploy, which the push starts. On an instance with no repository there is no deploy a browser can run, so the panel sets the plugin's two vars on the Worker and attaches the hostnames itself; the panel says so in a line, and the instance reports them as it would after a deploy. What that case does not get is the redirects, which the plugin sets around a deploy as zone rules, so a second hostname there answers on its own name. Under both, the Workers Custom Domains your account has attached to that Worker are listed as what the account has attached, so a hostname the plugin does not report, or one it reports that the account does not have, is visible rather than hidden.
Every button is a command
Nothing is dashboard-only. The cloud page shows a CLI token for the signed-in user, which is the same session the page uses and expires when it does. The commands are plain HTTP against the site, so they work from the standalone executable as well as the npm package, and the session is kept in ~/.config/voidbase/cloud.json, mode 600.
voidbase cloud login --token <token> # the "CLI token" the cloud page shows; --url for another site
voidbase cloud whoami # the user, the Cloudflare connection and its accounts, GitHubvoidbase cloud instances # yours, with status, release and url
voidbase cloud instances create shop # provisioned in your own account from the site's release
# --account picks one of several, --email the superuser
voidbase cloud instances upgrade shop # to the site's current release, in place
voidbase cloud instances delete shop --yes # the Worker, its D1, R2, queue and domains; asks first without --yesvoidbase cloud repos # the repositories linked to your instances
voidbase cloud repos create shop --template voidbase-site --name my-site --private
voidbase cloud repos link shop owner/name # one you already have; unlink owner/name forgets it (GitHub keeps it)voidbase cloud plugins shop --email you@example.com --password ... # what it runs
voidbase cloud plugins shop install echo --email ... --password ... # install name[@version] [--marketplace url the project trusts]
voidbase cloud plugins shop update --email ... --password ... # update [name]
voidbase cloud plugins shop remove echo --email ... --password ...An instance is named by its name (shop finds vb-shop) or its id, every verb takes --json for the raw result, and a verb that fails exits non-zero with the site's, Cloudflare's or the instance's own message.
Updating
New instances are created on the release the site holds, which we publish into it when one is out. An instance that already exists stays on its release until you upgrade it, from its card or with voidbase cloud instances upgrade: the same Worker, its data, secrets and domains kept, the migrations of the new release run on the next boot. An instance deployed from a repository is the other case: there the release is the repository's dependency, and a push is what changes it.
An upgrade is reversible for a week. The row keeps the release the instance was on and when it moved, and the card offers "Roll back to" that release for seven days: the same provisioning, on the recorded release instead of the current one, its database, files, secrets and domains kept. After seven days the button is gone and the card says the release it is on. This one is the page's for now: voidbase cloud instances upgrade takes no release yet.
What a rollback does not undo is migrations. The ones the newer release ran have run, and nothing reverses them, so a rollback can leave the database ahead of the code reading it. Rolling back also clears the recorded release, so a rollback is not itself rollable; the way forward from there is the upgrade again, or a backup taken before the upgrade.
When you would rather hold the commands yourself
The instance is yours either way, and the npm CLI reaches the same account with voidbase deploy, voidbase instances and voidbase destroy. The difference is who runs the toolchain: your browser, or your machine. Moving between them is voidbase migrate, like anywhere else.
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.