Week one in public: shipping a static site on Cloudflare Workers
Published · Updated
Cloudflare Workers · deployment diagram
From source to the reader
Conceptual deployment path. The build, upload, domain binding and reader-facing check are separate steps; a successful upload alone is not a live-site receipt.
- SOURCE Astro pages + articles Content and layout live in the source repository.
- BUILD npm run build → dist/ Astro produces static HTML and assets.
- SERVE Worker static assets The uploaded directory is served at the Worker origin and attached domain.
- VERIFY Fetch the real page Check HTTP response, expected text and assets as a reader.
This is a dated build log, corrected October 15, 2026. Operational measurements are scoped to their cited audit dates; see the evidence note below for the private-source limit.
This is the first build-in-public entry for Workman AI Labs: how this exact site went from nothing to live, what it cost so far, and what’s still broken. It’s deliberately small. Most launch stories skip the boring middle; the boring middle is the part worth writing down.
Evidence note — October 15, 2026: the operational counts and incident history below come from retained private receipts, not public downloads or a new live audit. Private receipt paths have been removed from the reader copy; the editorial record retains their mapping. Diagrams explain the design and do not prove runtime state.
The shape of the thing
The site is an Astro static site served by a Cloudflare Worker that does nothing but serve static assets. No server code, no database, no framework running at the edge. The initial configuration was a small static-assets wrapper (the current configuration also has a custom-domain binding):
{
"name": "workmanailabs-site",
"compatibility_date": "2026-10-07",
"workers_dev": true,
"assets": { "directory": "./dist" }
}
The Worker exists because Cloudflare’s static-assets Workers let you ship a plain directory of files with a Worker wrapper for free, and because it keeps the door open: if a page ever needs server logic (a form endpoint, a redirect table), the Worker is already there.
The build, in order
- Scaffold Astro, write the first post. One commit: layout, content collection with a
draft/publishedstatus field, about + disclosure pages, and the first case-study post written with its receipts cited. - Build and deploy.
npm run buildproducesdist/;npx wrangler deploypushes it. No CI, no pipeline — one command, run from the repo, using wrangler’s local OAuth. - Verify like a reader, not a deployer.
curlthe live origin, confirm HTTP 200 and the page title. On 2026-10-12:https://workmanailabs-site.glen-bbc.workers.dev/returned 200 with title “Workman AI Labs”. That’s the receipt — not the deploy command’s exit code.
What it costs
Correction — October 15, 2026: the initial configuration shows a static-assets site without database or queue bindings. That does not prove zero total infrastructure cost. No billing receipt here establishes hosting charges, domain cost, subscriptions, equipment or energy, so the former zero-cost headline has been removed. A monetary total needs actual billing evidence.
What’s still broken (the honest section)
The custom domain doesn’t work yet. The plan is workmanailabs.com served from the same Worker. The zone is set up on Cloudflare, but as of publishing morning, the domain’s nameservers still pointed at the registrar’s defaults:
NS: dns1.registrar-servers.com. dns2.registrar-servers.com.
— meaning the nameserver change at the registrar was attempted but hasn’t taken effect. At that original check, the custom domain did not serve the site and the Worker origin did.
Correction — October 15, 2026: the domain now serves the site. Earlier versions of this article contained conflicting October 13 and October 14 cutover notes. Those notes do not establish the exact first moment of the flip; the retained October 14 HTTP/DNS observation supports the domain working by that check. The contradictory first-cutover dates are withdrawn rather than selecting one without a dated cutover receipt. The initial failure above remains part of the launch history.
That’s the part launch stories usually edit out: the site was done before the domain was.
What I’d do the same, and what I’d change
Same: static-only, one-command deploy, and writing the receipts as I go instead of reconstructing them later. The receipts are why this post exists — every one of these steps was logged at the time it happened.
Change: I’d have checked the registrar’s nameserver save button harder before building anything DNS-dependent. The original launch was delayed by the DNS cutover. As the dated correction above records, that domain issue is no longer outstanding; no timing comparison is established here.
Next in the series
A post on the content system itself — the flag rules that decide what gets published here and what stays a draft until it can prove itself. The next post distinguishes the editorial review policy from the field types actually enforced by the schema.
[Source receipts: site repo git history (9e4ce7d, fab2600), wrangler.jsonc, live HTTP and DNS checks run 2026-10-12.]
Public references
Cloudflare Workers static assets documents the serving mechanism. It does not establish our deployment time or total bill.