Skip to content

Deployment ​

React Starter Kit deploys as three Cloudflare Workers backed by a Neon PostgreSQL database. Infrastructure is managed with Terraform.

What Gets Deployed ​

ComponentTargetDescription
Web WorkerCloudflare WorkersEdge router – receives all traffic, routes to app/api via service bindings
App WorkerCloudflare WorkersServes the React SPA and static assets
API WorkerCloudflare WorkersHono + tRPC server, authentication, database access
DatabaseNeon PostgreSQLManaged Postgres with Hyperdrive connection pooling
InfrastructureTerraformHyperdrive configurations, optional R2 storage

See Architecture Overview for how these components connect.

Prerequisites ​

  • Cloudflare account with Workers enabled
  • Neon account for PostgreSQL hosting (sign up)
  • Terraform installed (brew install terraform or download)
  • Domain added to Cloudflare DNS (optional for initial setup)

Environments ​

EnvironmentIntended triggerURL patternPurpose
Developmentbun devlocalhost:5173Local development
StagingPush to mainstaging.example.comPre-production validation
ProductionManual dispatchexample.comLive environment

Staging and production each have their own Wrangler configuration, Hyperdrive bindings, and Terraform workspace. Development is local and provisions no cloud resources. See CI/CD for deployment triggers. Automated deploys stay off until you set the DEPLOY_ENABLED repository variable, so a fresh clone runs CI only.

Deployment Checklist ​

  1. Provision infrastructure – run Terraform to create the Hyperdrive configurations. Workers, routes and the custom domain's DNS come from Wrangler at deploy time (ADR-002)
  2. Set secrets – configure BETTER_AUTH_SECRET and RESEND_API_KEY, plus secrets for any optional integrations you enable, via Wrangler. See Cloudflare Workers for the full list
  3. Build and verify – compile every workspace, prove each worker bundles, and confirm the Cloudflare identity and production account, all before anything changes
  4. Run migrations – apply the schema to your production database. See Production Database
  5. Deploy the workers – api, then app, then web. Service bindings resolve by name at deploy time, and web holds the public route, so it flips last

Steps 3 to 5 are what an automated release does; push to main or dispatch a production run and CI/CD handles them. To do it by hand:

bash
# Preflight – nothing here changes production
bun run build

bun wrangler deploy --config apps/api/wrangler.jsonc --env="" --dry-run
bun wrangler deploy --config apps/app/wrangler.jsonc --env="" --dry-run
bun wrangler deploy --config apps/web/wrangler.jsonc --env="" --dry-run

# `--dry-run` never authenticates, so confirm the account separately
bun wrangler whoami --account <production-account-id>

Stop unless every command succeeded and whoami reports the account you meant. These are two blocks rather than one because an interactive shell does not stop on error – pasted together, a failed dry-run would scroll past and the migration would still run.

bash
# Point of no return
bun db:migrate:production

bun api:deploy --env=""
bun app:deploy --env=""
bun web:deploy --env=""

The order matters for the same reason it does in CI: migrations run against workers that are still the old ones, so a schema change has to be additive until the new workers are live.

Section Pages ​