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
| Binding | Type | Resource (prod) | Resource (staging) |
|---|---|---|---|
DB | D1 | alokai-cms-db | alokai-cms-db-staging |
ASSETS | R2 | alokai-cms-assets | alokai-cms-assets-staging |
CACHE | KV | CACHE (prod namespace) | CACHE (staging namespace) |
AI | Workers AI | account-wide | account-wide |
BROWSER | Browser Rendering | account-wide | account-wide |
MCP | Service binding | alokai-cms-mcp | alokai-cms-mcp-staging |
STITCH_JOBS | Durable Object | StitchJobsDO (sqlite) | same |
PAGE_CAPTURE_JOBS | Durable Object | PageCaptureJobsDO (sqlite) | same |
STATIC_ASSETS | Worker assets | apps/cms/dist/ | same |
Create the production resources
-
D1 database
Terminal window npx wrangler d1 create alokai-cms-dbCopy the
database_idinto the productiond1_databases[0]block inapps/cms/wrangler.jsonc. -
R2 bucket
Terminal window npx wrangler r2 bucket create alokai-cms-assets -
KV namespace
Terminal window npx wrangler kv namespace create CACHECopy the
idinto the productionkv_namespaces[0]block. -
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.
-
Apply migrations to the remote D1
On a brand new database:
Terminal window yarn workspace cms db:migrate:prodThe deploy workflows (CI and deploy-prod) include an auto-backfill step that detects when a DB has the schema applied but the
d1_migrationstracker 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:prodyarn workspace cms db:migrate:prod # should report "No migrations to apply." -
Set production secrets
Terminal window cd apps/cmsnpx wrangler secret put AUTH_JWT_SECRET# paste at least 32 random charactersopenssl rand -hex 32 | npx wrangler secret put TOKEN_ENCRYPTION_KEYSee Secrets for the full list (OIDC, etc.) and rotation guidance.
-
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:prodyarn workspace cms deploy:prodcms.alokai-apps.comis the production custom domain (declared inwrangler.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.
-
Provision the staging D1, R2, and KV
Terminal window npx wrangler d1 create alokai-cms-db-stagingnpx wrangler r2 bucket create alokai-cms-assets-stagingnpx wrangler kv namespace create CACHE --env staging -
Apply migrations
Terminal window yarn workspace cms db:migrate:stagingThe CI workflow auto-backfills the
d1_migrationstracker if it’s missing on a pre-existing DB — see Migrations. -
Set staging secrets
Terminal window cd apps/cmsnpx wrangler secret put AUTH_JWT_SECRET --env stagingopenssl rand -hex 32 | npx wrangler secret put TOKEN_ENCRYPTION_KEY --env staging -
Deploy MCP staging, then CMS staging
Terminal window yarn workspace @alokai/cms-mcp deploy:stagingyarn workspace cms deploy:stagingStaging 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.