Cloudflare is DNS-only (grey-cloud) for upbeatbytes.com — no proxy/CDN/edge — so
the warm() step (curl every chunk + key routes through the public domain) wasn't
priming any edge; it just GET every asset from the already-fast static origin,
generating thousands of internal-origin requests per deploy (the "traffic spike"
in the logs). Removed it. Kept the valuable part: chunks-before-shell ordering,
14-day chunk grace, service-worker last. No change for visitors.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Post-deploy slow-load fix (telemetry-confirmed): boot-slow beacons showed the
shell arriving fast (33-79ms) but freshly-deployed chunks taking 3-5s, every
event within ~6-8min of a deploy, the same chunks fast HITs later. Cause: the
new shell went live pointing at chunk hashes not yet warm at the edge, so the
first visitor fetched them cold from the residential origin (modulepreload
fires them together → one unlucky "chunk warmer").
Reorder sync-static.sh: warm the immutable chunks at the edge BEFORE swapping in
the new shell, so a published shell never references cold chunks. Shell + routes
still warmed after publish. Pure deploy-script change — no runtime/SW changes.
Warms the origin's nearest POP (covers local users + our own post-deploy
testing); a distant POP still cold-fills once (inherent to a residential origin).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* client_error details, not just a count: new client_errors table + POST
/api/client-error (reason/path/user-agent/time) + GET /api/admin/client-errors.
The boot-seatbelt beacon now sends the reason + path (once per page); the admin
Overview lists the recent errors so we can tell chunk vs SW vs API vs JS — the
truth meter for the next day as the new SW propagates.
* Deploy warming now also hits the shell, routes (/play /account /admin), SW,
version.json, word lists, and icons/logo/font — not just immutable chunks.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The post-deploy blank/slow load: new hashed chunks weren't in Cloudflare yet, so
the first visitor pulled them cold from the residential origin — AND the service
worker simultaneously precached ~30 of those cold assets (a request storm),
pushing past the 7s boot timeout.
* sync-static.sh now warms the CF edge cache (fetches every immutable asset
through the public domain) so the first visitor gets HITs, not cold-origin.
* Service worker no longer bulk-precaches on install (the browser already caches
immutable assets for a year); it caches the shell + assets lazily as used. No
more storm.
* Boot-recovery timeout 7s → 10s so a merely-slow load doesn't flash the card.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per Codex. Shared deploy/sync-static.sh used by both publish scripts: sync new
hashed chunks first WITHOUT pruning old ones (grace window so in-flight/old
clients keep chunks they still need), then other assets, then index.html, then
service-worker.js last — so a new shell never appears before its chunks exist.
Old immutable chunks pruned after 14 days to bound disk growth.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>