Extensions
The Buildprint CLI gives agents the tools to create, publish, inspect, and manage Extensions.
Behind the scenes, an Extension is one Cloudflare Worker application. A deployment can contain:
Custom Worker code.
Static assets.
Both custom code and static assets.
An Extension can also have one D1 database and one R2 bucket. D1 is bound as DB, R2 is bound as BUCKET, and static assets are bound as ASSETS.
Local files
Each Extension is stored under extensions/<slug> in the cloned project.
The entry field adds custom Worker code. The assets field adds static files. At least one must be present.
This combined Extension has code, static assets, and both resources:
{
"slug": "customer-portal",
"name": "Customer portal",
"entry": "src/index.ts",
"assets": {
"build": "bun run build",
"output": "dist"
},
"resources": ["database", "bucket"]
}An asset-only Extension omits entry:
{
"slug": "docs",
"name": "Product docs",
"assets": {
"output": "."
}
}A code-only Extension omits assets:
{
"slug": "webhooks",
"name": "Webhook service",
"entry": "src/index.ts",
"resources": ["database"]
}Resources, migrations, and runtime secrets require custom Worker code. The CLI rejects duplicate resources and configurations that contain neither code nor assets.
Handle code and assets together
Buildprint runs custom Worker code before the asset fallback. The Worker chooses which requests use custom logic and which requests use static assets.
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
if (url.pathname.startsWith("/api/")) {
return handleApi(request, env);
}
return env.ASSETS.fetch(request);
},
};/api/* is a convention, not a reserved route. Browser code should use relative URLs when it calls an endpoint on the same Extension:
const response = await fetch("./api/orders");This keeps the request on the same origin and preserves the public Extension path.
Publish
Publish from the cloned project:
buildprint extension publish customer-portal -m "Add order history"Publish creates the remote Extension when it does not exist. The message is optional.
The CLI bundles custom code as one ES module. Worker code cannot import Node.js built-in modules.
One deployment can contain up to 1,000 files and 10 MiB. Static output must contain /index.html. Build output must stay inside the Extension directory.
Deployment identity
Each publish creates an immutable seven-character deployment ID. The identity includes:
The parent deployment ID.
The Worker code manifest.
The static asset manifest.
The declared resource kinds.
Each migration name and checksum.
A name, description, or deployment message does not change the deployment ID.
Publishing the same operation again resumes it. The agent must pull the current test head before it publishes from an older parent.
Code and state selection
Extension URLs use this format:
https://<project>.buildprintusercontent.com/<extension>/<deployment>/<version>/<route>The selectors have independent purposes:
Selector | Selects |
|---|---|
| Immutable Worker code and static assets. |
| Durable D1, R2, and secrets. |
version is test or live. A missing or unknown version uses test.
Every deployment has a test runtime and a live runtime. Much like in Bubble, these two runtimes let you separate database/file state. They contain the same code and assets, but they receive different resources and secrets.
Use a fixed deployment URL for a Bubble integration. Bubble test can use new code while the live app continues to use an older deployment. Deploying the Bubble change selects the new deployment with live state.
latest/test selects the test head. latest/live selects the newest deployment with a ready live runtime.
D1 migrations
Store numbered SQL migrations in the Extension directory:
extensions/customer-portal/
extension.json
src/index.ts
migrations/
0001_create_orders.sql
0002_add_order_status.sqlMigration names use four digits, one underscore, and a short name. A migration version and checksum cannot change after it is applied.
Buildprint applies missing migrations to test in number order. It applies compatible changes to live during publish. A change that can stop older code requires explicit confirmation before Buildprint applies it to live.
Do not edit the _buildprint_migrations table. The _buildprint_ prefix is reserved for platform tables.
D1 and R2 operations
The agent can use internal resource operations to:
Inspect D1 status and schema.
Run a limited read query.
Perform a controlled write.
Reset the test database.
Confirm live migrations.
List R2 objects.
Upload, download, or delete an object.
Clear the test bucket.
An omitted version means test. Every live write requires an explicit live version and user confirmation.
Mutating operations use an operation key. Repeating the same key and request returns the prior result. An unknown D1 write result must be reconciled with a read before another write attempt.
Read queries return at most 200 rows. DDL is accepted only through migrations.
Environment variables and secrets
Environment variables are available to custom Worker code. Test and live have separate values.
Extension values are defaults. Values for one deployment override defaults. A runtime receives only values for its selected version.
buildprint extension env set customer-portal API_TOKEN=secret --version test
buildprint extension env list customer-portal --version test
buildprint extension env unset customer-portal API_TOKEN --version testLive changes require --version live and confirmation. Secret reveal actions are audited. Do not write secret values to messages, logs, or screenshots.
Inspect and pull
List Extensions or inspect one Extension:
buildprint extension list
buildprint extension info customer-portalPull the test head or one fixed deployment:
buildprint extension pull customer-portal
buildprint extension pull customer-portal --deployment a1b2c3dThe CLI stops if local files differ from the recorded base. --force replaces local Extension files.
Read logs and request analytics:
buildprint extension logs customer-portal --since 30m
buildprint extension analytics customer-portal --since 24hAdd --json when another tool needs structured output.
Delete and recover
Delete one deployment or the complete Extension:
buildprint extension delete customer-portal a1b2c3d
buildprint extension delete customer-portalDeleting a deployment removes its test and live runtimes. It does not remove D1 or R2 data.
Deleting an Extension removes its public routes and schedules its resources for deletion after 30 days. The agent or support can recover the Extension before resource deletion starts.
R2 deletion can continue over several jobs for a large bucket. Repeated deletion jobs resume the same operation.