Self-hosting

Fullbleed is a single Cloudflare Worker. It needs a Cloudflare account, a D1 database, an R2 bucket (media), and — unless you stay on workers.dev — a domain that is a zone in your account. All state is in D1 and R2; the app itself is stateless.

Prerequisites

  • Node.js 20+ and pnpm
  • A Cloudflare account with Workers enabled
  • A domain zone in Cloudflare (e.g. example.com) if you want a custom domain
  • The Wrangler CLI (or pnpm exec wrangler)

Login once:

pnpm install
pnpm exec wrangler login

1. Configure

Edit wrangler.jsonc:

Key What to put
name Your worker name, e.g. fullbleed
routes[].pattern Your custom domain, e.g. cms.example.com with custom_domain: true
d1_databases[0].database_name The name you'll use for the D1 database
d1_databases[0].database_id From wrangler d1 create (step 2)
r2_buckets[0].bucket_name Your R2 bucket name
vars.APP_URL https://cms.example.com (the dashboard's public URL)
vars.MEDIA_URL https://media.example.com (public media URL, step 4)
vars.PLATFORM_ADMIN_EMAIL Email that auto-promotes to platform admin on signup

2. Create the database and bucket

pnpm exec wrangler d1 create fullbleed

Copy the returned database_id into wrangler.jsonc, then create the media bucket:

pnpm exec wrangler r2 bucket create fullbleed-media

3. Apply migrations

Local (miniflare, used by pnpm dev):

pnpm exec wrangler d1 migrations apply fullbleed --local

Production (the live D1 database):

pnpm exec wrangler d1 migrations apply fullbleed --remote

4. Custom domains (recommended)

Connect the worker domain:

pnpm exec wrangler deploy

Then connect the media bucket so MEDIA_URL actually serves files:

pnpm exec wrangler r2 bucket domain add fullbleed-media --domain media.example.com --zone-id YOUR_ZONE_ID

Get YOUR_ZONE_ID from the Cloudflare dashboard (Domain → your zone → overview).

Using workers.dev alone works for the dashboard, but the API path you hand to websites is nicer on your own domain.

5. Deploy & verify

pnpm run deploy

pnpm run deploy is a full worker deploy. Bare pnpm deploy is a pnpm built-in and will not deploy the worker.

Check health:

curl https://cms.example.com/api/health
# {"service":"fullbleed-api","status":"ok",…}

6. First signup → platform admin

Sign up at /signup using the email in PLATFORM_ADMIN_EMAIL. That account is auto-promoted to platform admin and can manage all users at /admin.

7. Local development

pnpm dev          # dev server on http://localhost:3001
pnpm build        # production build
pnpm start        # run the built worker locally (wrangler dev)

Allowed origins (API + CORS)

Browser requests to the public API (GET endpoints) carry an Origin header. Fullbleed checks it against the workspace's allowed_origins list and rejects unknown origins with 403 Origin not allowed. Server-to-server requests without an Origin header skip the check.

Add your site's origin to a workspace (replace the UUID with your workspace id, found in workspaces.id):

INSERT INTO allowed_origins (workspace_id, origin) VALUES
  ('<workspace-id>', 'https://yoursite.com');

Deployments with reporting turned on (observability.enabled) surface these queries in the Cloudflare dashboard's Logs and Metrics tabs.

Architecture

For a deep dive into request flow, auth/sessions, workspace scoping, and the public API internals, read docs/ARCHITECTURE.md in the repo (developer documentation, not user docs).