Local development
Run the platform from a local checkout so you can change and test it.
On this pageSet up the repository · Run the API and dashboard locally · Test your changes
Setting up the repository
These steps clone your fork and install dependencies with Vite+. Run them in the same terminal. Step 2 runs inside the void directory from step 1.
git clone https://github.com/your-org/void.git
cd voidExample output: The repository cloned into void/.
vp install
vpr install:void-devExample output: Workspace dependencies installed, then the void-dev command.
void-dev --helpExample output: The void-dev help text.
Use the Node.js version recorded in .node-version.
install:void-dev builds the CLI, shared packages, and platform runtime, then makes this checkout's built CLI globally available as void-dev. Public packages export their built files, so run vp run build:core after later source changes to refresh the alias. The installer refuses to replace an unrelated global command. Remove only this checkout's alias with vpr uninstall:void-dev. The commands on these development pages run from the repository root.
Finding the implementation
| Directory | Purpose |
|---|---|
packages/void | Framework, application runtime, and CLI |
packages/platform | Installer contracts, packaged Workers, and platform migrations |
packages/deploy-core, packages/deploy-cloudflare | Shared deployment contracts and Cloudflare upload code |
platform/packages/api | Users, projects, deployments, provisioning, and administrator API/UI |
platform/packages/dispatch | Application routing and static assets |
platform/packages/proxy | AI, remote bindings, and revalidation |
platform/packages/email-gateway | Inbound mail routing and tenant delivery |
platform/packages/tail | Runtime log ingestion |
platform/packages/dashboard | Dashboard source and local UI components in ui/ |
The @voidcloud/* names identify workspace implementation packages. Their private: true flags prevent publishing those packages to npm. Deployable core Workers are bundled into the public @void/platform package.
The core installer creates the API, dispatch, proxy, tail, and email gateway Workers. The dashboard and managed GitHub build services are available in the source tree but are not included in that installation. Adding an optional service requires its infrastructure, bindings, authentication, and capability configuration together.
Running the API locally
Start a local PostgreSQL server with psql and pg_isready on your path. This step creates the dev database, applies migrations, seeds an administrator and starts the API.
vp run --filter @voidcloud/api setup --admin-email dev@example.com
vp run --filter @voidcloud/api dev:adminExample output: Local setup with the admin user, then the API dev server.
The command disables the optional build containers, so basic API and admin work does not require Docker. To develop managed builds, install Docker and run the API with containers enabled.
Open http://localhost:8787/admin/. Setup writes the API's local database connection and development authentication bypass to platform/packages/api/.dev.vars. It configures platform/packages/dashboard/.env for the separate dashboard. Both files are ignored by Git. Production installations get separate credentials through the installer.
The API's development bypass lets you work on the browser admin UI without setting up OAuth. Operator CLI sessions still require administrator authentication; they do not use the browser bypass.
dev:admin watches source files and automatically reloads the browser after edits. Keep it running while working on the admin dashboard's React components and styles; no platform deployment is needed. The setup includes sample users, projects, and deployments for trying each view locally.
Running the dashboard locally
The dashboard is a separate app. This step starts it in another terminal after API setup.
vp run --filter @voidcloud/dashboard devExample output: The dashboard dev server URL.
Setup points the dashboard's local .env at the API you started:
API_URL=http://localhost:8787
SITE_DOMAIN=apps.example.comOpen the Vite URL and choose Dev login (local API). That button appears for a localhost API and uses the local development sign-in endpoint.
You can also point the dashboard at an API that you operate. If Cloudflare Access protects that API, install cloudflared and opt into the dashboard's local token helper with matching origins:
API_URL=https://platform.example.com
CF_ACCESS_APP_URL=https://platform.example.com
SITE_DOMAIN=apps.example.comThe helper refreshes an Access session before the dev server starts. Human dashboard requests require the user's Access session as well as their SDK login; a service token does not represent that user. Service-token pairs are for scoped machine operations. This is dashboard development configuration; Access credentials are separate from platform login credentials.
For a deployed dashboard, bind its API service to your platform API, configure DASHBOARD_URL on both the dashboard and API, and include that exact dashboard origin in the platform's Access protection application. The dashboard passes the browser's company identity to the API using that service binding. Its login page shows The platform's currently enabled methods, and Account supports adding an additional login identity.
Testing changes
This step runs the tests for the area you changed.
vp test run platform/packages/api/test/integration/operator-auth.test.ts
vp run checkExample output: The test results, then the check results.
These steps build the packages and run the full checks before a release.
vp run build:all
vp run checkExample output: All packages built, then checks passed.
vp lint
vp run lint:platformExample output: Lint results for the repo and the platform.
vp fmt --check
vp test runExample output: Formatting checked, then the test results.
vp run build:docsExample output: The docs built without errors.
Platform integration tests use their local test database by default. To test against PostgreSQL, set VOID_TEST_DATABASE_URL to a disposable database: these tests clear tables between cases.
To exercise a deployed application, deploy a disposable copy of playground/kitchen-sink and pass its URL as SMOKE_URL to the smoke test described in platform/scripts/kitchen-sink-smoke-test.md. That test creates and removes application data.