Into a voidbase stack

Your instance becomes part of an application rather than a service beside it. The site, the typed routes and the collections live in one repository and deploy as one Worker.

Whether you want this

Pick it if the frontend does not exist yet, or exists and you are willing to move it. The site and the backend ship together after this, which means one deploy, one address and no CORS, and it also means a voidbase upgrade and your own application go live in the same artifact.

If your frontend is already built and deployed somewhere you are happy with, a voidbase project is the smaller change and keeps the two apart.

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.

Start the application

A stack is a Void app with the voidbase adapter added. Start a stack app covers the layout; this is the short version.

bun add void
bunx void init                       # asks which framework and starter
bun add @voidbase-cloud/voidbase
// vite.config.ts
import { defineConfig } from "vite";
import { voidPlugin } from "void";
import { voidbaseAdapter } from "@voidbase-cloud/voidbase/adapter/plugin";

export default defineConfig({ plugins: [voidPlugin(), voidbaseAdapter()] });

Bring the collections across

Export from the instance you have, then import into the one the dev server is running, voidbase dev on 5180.

bunx @voidbase-cloud/voidbase export ./snapshot --url https://blog-api.example.workers.dev --admin you@example.com:your-password
bunx @voidbase-cloud/voidbase import ./snapshot/collections.json --url http://127.0.0.1:5180 --admin you@example.com:your-password

The import changed the dev instance's database and nothing else. Write the list down in vb_migrations, which the build copies into the generated instance's pb_migrations, so a fresh checkout builds the same collections rather than needing the import again.

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

Build and connect

bunx @voidbase-cloud/voidbase sync --repo you/my-app    # builds, deploys from .voidbase/, connects the repository

Sync runs the build, which turns the Void app into an instance under .voidbase/, deploys from there and wires the repository to Cloudflare Workers Builds. The stack pipeline covers what shipping both halves at once changes about CI.

Two things that move

Hooks become TypeScript. A project's hooks run in the server's JavaScript runtime; a stack's are vb_hooks, one per file, typed and bundled by the build, and routes/, middleware/, crons/ and queues/ are the rest of them.

Configuration is declared once. vb_secrets serves the server, the build and the browser from one declaration, and says which of the three each key is allowed to reach.

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.