Skip to content

Cloudflare Setup

Alokai CMS runs on Cloudflare Workers and binds to D1, R2, KV, Workers AI, the Browser Rendering API, and a service-bound MCP worker. This page walks through provisioning everything for both production and staging so the deploy workflows in .github/workflows/ci.yml (staging) and .github/workflows/deploy-prod.yml (production) have something to deploy to.

The repo’s apps/cms/wrangler.jsonc is already wired up for the canonical Alokai-Inc. account. If you’re standing up a fresh tenant, replace the IDs as you go.

Bindings overview

BindingTypeResource (prod)Resource (staging)
DBD1alokai-cms-dbalokai-cms-db-staging
ASSETSR2alokai-cms-assetsalokai-cms-assets-staging
CACHEKVCACHE (prod namespace)CACHE (staging namespace)
AIWorkers AIaccount-wideaccount-wide
BROWSERBrowser Renderingaccount-wideaccount-wide
MCPService bindingalokai-cms-mcpalokai-cms-mcp-staging
STITCH_JOBSDurable ObjectStitchJobsDO (sqlite)same
PAGE_CAPTURE_JOBSDurable ObjectPageCaptureJobsDO (sqlite)same
STATIC_ASSETSWorker assetsapps/cms/dist/same

Create the production resources

  1. D1 database

    Terminal window
    npx wrangler d1 create alokai-cms-db

    Copy the database_id into the production d1_databases[0] block in apps/cms/wrangler.jsonc.

  2. R2 bucket

    Terminal window
    npx wrangler r2 bucket create alokai-cms-assets
  3. KV namespace

    Terminal window
    npx wrangler kv namespace create CACHE

    Copy the id into the production kv_namespaces[0] block.

  4. No setup needed for AI / Browser Rendering

    Both are bindings — already declared in the canonical config. Workers AI requires the account to be on a Workers Paid plan; Browser Rendering must be enabled for the account.

  5. Apply migrations to the remote D1

    On a brand new database:

    Terminal window
    yarn workspace cms db:migrate:prod

    The deploy workflows (CI and deploy-prod) include an auto-backfill step that detects when a DB has the schema applied but the d1_migrations tracker is empty (legacy runtime-migrated DBs) and runs the backfill before applying. See Migrations for the mechanic.

    If you’re standing up an environment by hand and want to skip the workflow’s auto-detection, run the backfill yourself:

    Terminal window
    yarn workspace cms db:migrate:backfill:prod
    yarn workspace cms db:migrate:prod # should report "No migrations to apply."
  6. Set production secrets

    Terminal window
    cd apps/cms
    npx wrangler secret put AUTH_JWT_SECRET
    # paste at least 32 random characters
    openssl rand -hex 32 | npx wrangler secret put TOKEN_ENCRYPTION_KEY

    See Secrets for the full list (OIDC, etc.) and rotation guidance.

  7. Deploy MCP, then CMS

    The CMS worker has a service binding to MCP, so MCP must exist first for the deploy to attach successfully.

    Terminal window
    yarn workspace @alokai/cms-mcp deploy:prod
    yarn workspace cms deploy:prod

    cms.alokai-apps.com is the production custom domain (declared in wrangler.jsonc#routes).

Create the staging resources

Same flow with --env staging and the -staging suffixed names. The env.staging block in apps/cms/wrangler.jsonc already references all of them.

  1. Provision the staging D1, R2, and KV

    Terminal window
    npx wrangler d1 create alokai-cms-db-staging
    npx wrangler r2 bucket create alokai-cms-assets-staging
    npx wrangler kv namespace create CACHE --env staging
  2. Apply migrations

    Terminal window
    yarn workspace cms db:migrate:staging

    The CI workflow auto-backfills the d1_migrations tracker if it’s missing on a pre-existing DB — see Migrations.

  3. Set staging secrets

    Terminal window
    cd apps/cms
    npx wrangler secret put AUTH_JWT_SECRET --env staging
    openssl rand -hex 32 | npx wrangler secret put TOKEN_ENCRYPTION_KEY --env staging
  4. Deploy MCP staging, then CMS staging

    Terminal window
    yarn workspace @alokai/cms-mcp deploy:staging
    yarn workspace cms deploy:staging

    Staging custom domain: cms-staging.alokai-apps.com.

Durable Objects

StitchJobsDO and PageCaptureJobsDO are SQLite-backed Durable Objects. The migrations[] block in wrangler.jsonc declares them as new_sqlite_classes. No remote provisioning is needed beyond deploying — the first deploy creates the namespaces. If you ever rename a class, add a new migrations[] tag (v3, v4, …) rather than editing an existing one.

MCP service binding

apps/cms/wrangler.jsonc#services binds the CMS worker to the MCP worker by name (alokai-cms-mcp in prod, alokai-cms-mcp-staging in staging). The MCP worker’s wrangler.toml reciprocally binds back to cms / cms-staging, so both sides dispatch via env.MCP.fetch(...) and env.CMS.fetch(...) over the zero-latency intra-account path.

Custom domain

In the Cloudflare dashboard: Workers & Pages → cms (or cms-staging) → Settings → Triggers → Custom Domains. The domain is already declared in wrangler.jsonc#routes as custom_domain: true, so subsequent deploys are idempotent.

CORS

If the storefront lives on a different origin than the Worker, configure CORS in apps/cms/src/server/index.ts. The default config allows the production storefronts and localhost for dev.