KB / infrastructure / deploy-workflow
Deploy Workflow
Apps deploy to Cloudflare Pages via cf-deploy-prod.sh; blog CI builds WASM first; run deploys in background to avoid blocking.
Deploy Workflow
Every app in the monorepo deploys to Cloudflare Pages. The deploy script is scripts/cf-deploy-prod.sh, invoked per-app as bun run cf:deploy:prod.
Manual deploy pattern
After committing and pushing:
cd apps/<app> && bun run cf:deploy:prod
Always run deploys with run_in_background: true (in agent sessions) so the next task isn't blocked on Cloudflare's ~30–60 s upload time. Do NOT run two background deploys in parallel — cf-deploy-prod.sh renames .env.local to .env.local.deploy-bak during the run; parallel invocations collide on that rename and lose CLOUDFLARE_API_TOKEN.
CI pipeline (cf-deploy.yml)
The GitHub Actions workflow deploys on push to master using a matrix over all apps. The blog matrix entry has additional steps:
dtolnay/rust-toolchain@stablejetli/wasm-pack-actionbun run wasm:build:releasebun build+ deploy
All other apps skip the Rust/WASM steps.
CI validation commands
# Check recent master CI runs
gh run list --branch master --event push --limit 10 \
--json databaseId,headSha,status,conclusion,name,updatedAt
# Inspect a failed job
gh run view <run-id> --job <job-id> --log-failed
Output directories
All TanStack Start apps build to dist/client/. The wrangler.toml for each app sets:
pages_build_output_dir = "dist/client"
Verification
After a deploy notification, confirm the production URL returns 200 and the expected content. A blog deploy is healthy if dist/client/ contains 700+ index.html files. If every post URL serves the homepage, WASM was likely missing during the build — see the WASM prerender CI article.