Skip to content

Revision · Shipping This Site to the Edge

This part was the other capstone. Where Part 11 shipped a running service down the container-and-Kubernetes path, this one shipped the book you are reading down the static-edge path — a real Bun + Turborepo monorepo of nine Astro/Starlight sites, deployed to Cloudflare Pages. The throughline was the book’s one question, sharpened: choosing a static-edge model doesn’t just automate ops work, it deletes whole categories of it, because there is no server process to run, scale, or health-check.

  • The static-edge model — “deploy” here means copy immutable files to a global CDN, not run a process. The generator runs once at build time and freezes the site into a dist/; the CDN is the runtime. That single fact deletes autoscaling, runtime secrets, process health-checks, and a class of server-side injection bugs — and the page was honest about the boundary: the moment you need per-request compute (auth, forms, live data) you’re back to running code (Workers/Pages Functions).
  • The build: one repo, nine sites — a Bun workspace (bun install resolves all apps + the shared @first-principle/ui via workspace:*) and Turborepo (bunx turbo run build) that builds in dependency order and caches by input hash, so touching one book rebuilds one book. --filter=<app> scopes a single-site build; each app emits its own dist/.
  • Cloudflare Pages & Wrangler — one Pages project per app (fp-devopsfp-devops.pages.dev); two ship paths (dashboard Git integration = pull-CD, wrangler direct upload = push-CD); the cf-deploy.sh helper for a repeatable build-and-deploy; and the key security choice — a project-scoped API token (Pages: Edit only, in gitignored .cloudflare.env) instead of a machine-wide wrangler login. It is the only secret in the system, and it’s deploy-time only.
  • Headers, CSP & caching — the _headers file Cloudflare applies to every response: the security header set (nosniff, frame-deny, HSTS-preload, Permissions-Policy), the CSP read directive by directive, the real 'wasm-unsafe-eval' one-line fix that unbroke Pagefind’s WASM search without opening up eval, and immutable year-long caching for content-hashed /_astro/* assets.
  • CI & preview deploys — GitHub Actions builds all nine sites (--frozen-lockfile, turbo run build) and cargo checks the companion crates on every push/PR; every PR gets a live preview URL (a disposable production-like environment); and merging to main is the deploy — one atomic, instantly-reversible swap, no canary needed.

Two capstones, one thread. The container path made a running process safe with a Dockerfile, a Deployment, probes, a canary, and SLO gates. The static path made a site safe by having almost none of those things — because a folder of immutable files copied to a global CDN cannot crash, cannot leak a runtime secret, and rolls back by re-pointing to a prior deploy. The engineering skill this part teaches is the judgment before any of the config: decide whether your artifact does per-request work, and the right deployment model — and everything it deletes or requires — follows. From here, the frontier part picks up exactly where the static boundary ended: when the edge stops serving only files and starts running code again.