Skip to content

feat(whoareyou): build the page at deploy, fetch its values as an island - #924

Merged
oddharsh merged 1 commit into
mainfrom
claude/whoareyou-island
Sep 25, 2026
Merged

oddharsh merged 1 commit into
mainfrom
claude/whoareyou-island

Conversation

@oddharsh

Copy link
Copy Markdown
Owner

What changes

/whoareyou stops rendering per request. build.ts step 5b bakes it once, like /security. The per-request rows arrive after load from /whoareyou/values.html, a no-store HTML fragment the Worker renders for that request alone.

before after
document on the wire 8,293 B (edge q4 brotli) 6,288 B (q11 twin)
return visit with the family dictionary same 8,293 B 4,492 B (dcz delta)
script-src 'self' 'unsafe-inline' three sha256 hashes
ETag, 304 no yes

The fragment adds one request of its own, preloaded from <head>, so it starts while the document is still parsing. In a real browser against the built tree, performance recorded exactly one fetch of it, with initiator link, so the preload was consumed rather than duplicated.

lib/island.ts: the convention, written down once

This is the homepage's shape (/photos/grid.html, /rn/tracks.html) turned into four exports, so the next page imports it instead of copying a hydrator out of index.html:

  • islandPreload(url): the <head> preload, with crossorigin, which is required even same-origin or the fragment is fetched twice.
  • islandMount(id, url, placeholder, noscript): the mount carries its own URL in data-island.
  • islandScript(): takes no arguments. It finds every mount by attribute, so the script text is identical on every page that uses it (one CSP hash site-wide), and nothing caller-supplied is ever interpolated into it. It requires an x-island: 1 marker before injecting, because an edge 5xx is also text/html. On failure it leaves the placeholder and sets data-state="failed".
  • islandResponse(body): no-store, noindex, and the marker.

The placeholder is drawn by the same renderer as the live fragment, fed a placeholder model. bun run cls reads /whoareyou clean on desktop and phone, with its control passing, and a contract test pins the placeholder and a typical browser visitor's live fragment to the same row count.

What moved, stated on the page

The values now describe the fragment request. That is normally the same connection, IP and TLS session as the page, with a later clock and its own ray id. The referrer is the one field that would be wrong, since the fragment's Referer is the page, so that row is filled in the browser from document.referrer. The callout and the Markdown twin both say so.

Also

  • Bug fix: on HTTP/2 the page showed "QUIC round-trip 0 ms" beside the real TCP row. Measured over curl today: cf.clientQuicRtt is 0 rather than absent on TCP, which is the mirror of the TCP fix from 2026-09-21. The transport now decides both rows.
  • run_worker_first: /whoareyou and /whoareyou.json fold into /whoareyou*. This covers the fragment and frees a row.
  • link-integrity now treats /cdn-cgi/* as Cloudflare's namespace. /whoareyou became the first built page to link /cdn-cgi/trace, and the build caught it.

Verification

  • bun run build, bun run lint, bun run typecheck: clean.
  • bun run routes:check: 178 routes, 0 failures. New rows cover the island mount (fullPage), the fragment (fragment), and Markdown negotiation.
  • New contract-whoareyou-is-a-built-document: passes under bun and node.
  • Full bun run test: 907/910. The one twin failure was a stale .build (fixed by a rebuild). The two remaining failures are in contract-photo-pipeline-failures, and they also flake on a clean origin/main checkout on this machine: a different test failed on each of four runs, and one run passed 24/24.
  • Browser, against the built Worker: the island goes live, the failure note shows only in data-state="failed", there are no CSP violations, and /cdn-cgi/trace 404s locally as expected (it is edge-only).

Not in this PR

This is the first of a series moving the site's per-request pages onto one pattern. Next: /ledger, the bare terminal frames (fixed bytes, so no island needed), /coffee (cal cannot import from the site tree, gotcha 16), and a /garage page measuring the before and after.

/whoareyou rendered per request, so it went out at the edge's q4 brotli
(8,293 B against 6,836 B at q11), with no dcz delta, no ETag, and the
loose 'unsafe-inline' script policy. About half the body is fixed prose.

The page is now baked by build.ts step 5b like /security, and the
per-request rows arrive from /whoareyou/values.html after load. Built
shell: 6,288 B at q11, 4,492 B as a family dcz delta, hashed CSP.

lib/island.ts writes the convention down once: a preload with
crossorigin, a placeholder drawn by the same renderer as the fragment,
an x-island marker the loader requires, and one constant loader script
shared by every page that uses it. The layout-shift lab reads the page
clean on desktop and phone.

The fragment's own Referer is the page, so the referrer row is filled
from document.referrer instead, and the callout says what moved.

Also fixes "QUIC round-trip 0 ms" showing beside the real TCP row on
HTTP/2: cf.clientQuicRtt is 0 rather than absent on TCP, the mirror of
the TCP fix from 2026-09-21.
@github-actions github-actions Bot added area: content Authored documents and prose area: docs Runbooks and repository prose area: infra Declared Cloudflare state, wrangler config, pins area: tools Developer tooling and the contract suite area: worker The site Worker: routing, rendering, bindings release-path Touches what decides which commit reaches production type: feat New capability or surface labels Sep 25, 2026
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
aadhar-sh 01af2c0 Sep 25 2026, 05:43 PM

@github-actions

Copy link
Copy Markdown
Contributor

Wire-size diff vs merge base

34fd4043ad05f1c21b341c06798a4592d63d1067 → 66a191f71995856a04527e673f682a1c9a5d6522

Brotli q11, the quality the edge serves. Every number here is deterministic:
an unchanged file produces no row. Advisory — this check fails on nothing.

Client assets

No change. 27 files, 91.44 KiB Brotli total.

Pages

Total Brotli: 589.76 KiB → 595.90 KiB (+6.14 KiB, +1.0%) across 58 files, 1 changed.

file base head Δ
whoareyou.html — 6.14 KiB new

Worker bundle

254.08 KiB → 255.37 KiB gzip (+1.29 KiB, +0.5%)

Largest module deltas (raw bytes in bundle):

file base head Δ
.build/src/worker/whoareyou.ts 22.17 KiB 24.41 KiB +2.24 KiB (+10.1%)
.build/src/worker/lib/island.ts — 0.92 KiB new
.build/src/worker/index.ts 12.24 KiB 12.60 KiB +0.36 KiB (+3.0%)
.build/src/worker/lib/csp-hashes.ts 6.48 KiB 6.63 KiB +0.15 KiB (+2.4%)

Dictionary transport

Family dictionary acquisition: no change, 14.41 KiB q11.

pd/: 168 → 169 deltas, 520.38 KiB → 524.77 KiB (+4.39 KiB).

@oddharsh
oddharsh merged commit 1e7dae2 into main Sep 25, 2026
15 checks passed
@oddharsh
oddharsh deleted the claude/whoareyou-island branch September 25, 2026 18:02
oddharsh added a commit that referenced this pull request Sep 25, 2026
)

/garage/dyno rendered per request, and a cold KV miss held the whole
document behind a fetch to raw.githubusercontent.com with a 3 s budget.
It also shipped at the edge's q4 brotli with no dcz delta, no ETag, and
the loose 'unsafe-inline' script policy, for a series that moves once a
night.

build.ts step 5b now bakes the shell, like /whoareyou (#924). The chart,
callout and recent-pulls table arrive from /garage/dyno/pulls.html
through lib/island.ts. The placeholder is the same renderer fed a
14-row model with no dates or numbers, so the swap adds no rows, and
the layout-shift lab reads the page clean on desktop and phone. Unlike
/whoareyou's values, the fragment is the same for every visitor, so it
takes the JSON endpoint's 5-minute cache instead of no-store.

Measured against the built Worker: shell 4,288 B at q11, 2,342 B as a
family dcz delta. First visit is even with today (8,158 B across two
requests against 8,060 B in one). A return visit revalidates the shell
to a 304 and pays only the fragment, about 3.9 KB.

Also:
- Accept: text/markdown on /garage/dyno returned HTML, because the
  exact route never negotiated. It serves the hand twin now, and the
  route oracle has a row for it.
- explorerDetails were passed as strings rather than {term, value}, so
  "N pulls recorded" never rendered. Dropped: a baked shell cannot know
  the count. dyno.ts goes from 3 type errors to 1.
- link-integrity's route scan had matched `new Map([...])` since the
  table became ROUTE_TABLE on 2026-08-19, so its routeKeys set was
  empty. It uses invariant #1's pattern and a 60-key floor now. It
  surfaced because /garage/dyno.json sits under the governed /garage
  prefix and this is the first built page to link it.

Co-authored-by: Aadharsh Pannirselvam <19518661+oddharsh@users.noreply.github.com>
oddharsh added a commit that referenced this pull request Sep 25, 2026
…he baked-shell route

/whoareyou and /garage/dyno moved to a shell baked at build time while this
page was being written, so production's 15 brotli pages become 13 once that
release finishes ramping. Totals, the chart and the card now describe the 13
(81,228 to 63,449 bytes, 21.9% at level 6), and a new section sets the
baked-shell route against the runtime fix.
oddharsh added a commit that referenced this pull request Sep 25, 2026
…927)

* feat(garage): /garage/dictionary, the dictionary the runtime dropped

15 of the 66 registered pages answer returning Chromium visitors with plain
brotli instead of a dcz delta, because the Worker renders them per request and
workerd's node:zlib zstd dropped its dictionary option. The page measures what
cloudflare/workerd#7106 would be worth once it ships: 97,711 to 76,557 bytes
(21.6%) at zstd level 6, a near constant 1,178 to 1,694 bytes per page because
the delta removes the shared shell, for a median 0.207 ms of CPU under Node.
It also says what the fix cannot reach (fetch() fragments), and runs a live
demo that fetches the page a second time to show the dictionary's effect.

tools/runtime-dcz-probe.ts produces every number on the page and writes
nothing. The garage README now lists gen:shell, which the checklist skipped
and the build requires.

* fix(garage): count the 13 pages left after #924 and #926, and weigh the baked-shell route

/whoareyou and /garage/dyno moved to a shell baked at build time while this
page was being written, so production's 15 brotli pages become 13 once that
release finishes ramping. Totals, the chart and the card now describe the 13
(81,228 to 63,449 bytes, 21.9% at level 6), and a new section sets the
baked-shell route against the runtime fix.

---------

Co-authored-by: Aadharsh Pannirselvam <19518661+oddharsh@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: content Authored documents and prose area: docs Runbooks and repository prose area: infra Declared Cloudflare state, wrangler config, pins area: tools Developer tooling and the contract suite area: worker The site Worker: routing, rendering, bindings release-path Touches what decides which commit reaches production type: feat New capability or surface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant