← All decisions

Public sites deploy to Cloudflare Pages, one project per tenant

accepted

0005 — Public sites deploy to Cloudflare Pages, one project per tenant

  • Status: accepted
  • Date: 2026-05-06
  • Deciders: Derek

Context

Each tenant has a public-facing static site rendered by Astro. Tenants need their own domain and isolated build pipeline (an Actualize build failure shouldn’t block a different tenant’s site).

Decision

One Cloudflare Pages project per tenant. The build command is the same (pnpm --filter @ark/site build with tenant-specific env vars). The domain is per-tenant. Free tier covers many tenants.

Cloudflare specifically because: actualize-v2 already proves this works, the free tier is genuinely generous, edge-deployed static hosting is what we want, and the CMS rebuild webhook flow (Cloudflare hook URL stored per-org in organizations.deploy_hook_url) is a clean integration point.

Consequences

Easier:

  • Per-tenant isolation at the deploy boundary
  • Fast static hosting; no cold starts
  • Cheap to scale to many tenants
  • The CMS-publish-triggers-rebuild flow is already a known-good pattern

Harder:

  • Provisioning a new tenant requires a Cloudflare API call (automatable via wrangler/Cloudflare API in the /new-tenant script)
  • Cross-tenant analytics needs a separate provider, not Cloudflare’s per-project analytics

Alternatives considered

  • Single Cloudflare Pages project, custom-domain routing per tenant. Loses build isolation; one tenant’s build break breaks deployment for all.
  • Vercel. Equivalent feature set; we pick Cloudflare for cost predictability and existing knowledge.
  • Self-host static via S3 + CDN. Operationally heavier; gives nothing the managed option doesn’t.