Repository navigation
feat(ledger, around): build both pages at deploy, fetch their live rows as islands - #928
Merged
Merged
Conversation
…ws as islands /ledger and /around rendered per request, so each shipped at the edge's q4 brotli with no dcz delta and no ETag, although most of each page is fixed prose and CSS. build.ts step 5b now bakes both shells, in the lib/island.ts shape /whoareyou and /garage/dyno took. /ledger's line items, total and cost line arrive from /ledger/lines.html, and /around's crawl rows from /around/snapshot.html. Both islands are the same for every visitor, so each sits behind cachedRender at the page's old 5-minute edge TTL. Measured against production and the built Worker: - /ledger: 5,539 B today; shell 4,502 B at q11 plus a ~710 B fragment. First visit -6%, a return visit pays only the fragment. - /around: 5,967 B today; shell 4,022 B plus a ~1,747 B fragment. First visit -3%, return visit likewise the fragment alone. Each placeholder is its renderer's own frame with the live row count: one unnamed row per crawler the ledger can name (production shows all 16), and one per neighbour (always 20). Contract tests pin both counts against independently sized reads, and each goes red when its placeholder loses a row. The owner's /around?bust=SECRET still works: it re-crawls and overwrites the colo's cached snapshot before the shell goes out. Also: - /around said "Refreshed: every 30 min by cron"; the crawl has been daily at 05:41 UTC since 2026-08-14. It says once a day now. - Accept: text/markdown on /around now gets the hand twin. - "/around*" folds three exact run_worker_first rows, and dev gets the "/ledger/*" glob production already had, which clears the build's standing allowlist-mismatch warning.
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
aadhar-sh | 05bcffc | Sep 25 2026, 07:05 PM |
Contributor
Wire-size diff vs merge base
Brotli q11, the quality the edge serves. Every number here is deterministic: Client assetsNo change. 27 files, 91.60 KiB Brotli total. PagesTotal Brotli: 613.89 KiB → 622.22 KiB (+8.33 KiB, +1.4%) across 63 files, 2 changed.
Worker bundle258.02 KiB → 258.75 KiB gzip (+0.73 KiB, +0.3%) Largest module deltas (raw bytes in bundle):
Dictionary transportFamily dictionary acquisition: no change, 14.41 KiB q11.
|
cachedRender stores the fragment inside waitUntil after hashing a weak ETag. The test waited one setTimeout(0) and then counted puts, which passed under bun and lost the race on CI's node, symlink leg. It now collects the waitUntil promises and awaits them.
oddharsh
enabled auto-merge (squash)
September 25, 2026 18:56
…islands # Conflicts: # CLAUDE.md # tools/build.ts
This was referenced Sep 25, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes
/ledgerand/aroundstop rendering per request. build.ts step 5b bakes both shells, in thelib/island.tsshape/whoareyou(#924) and/garage/dyno(#926) took:/ledger: the invoice paper, the terms and the CSS are baked. The line items, the total and the cost line arrive from/ledger/lines.html./around: the lede and the footer are baked. The crawl's meta line and its 20 rows arrive from/around/snapshot.html.Both islands are the same for every visitor, so each sits behind
cachedRenderat the 5-minute edge TTL the page used to take, rather thanislandResponse'sno-storedefault.What it buys
Measured against production and a local build of the Worker. Fragment sizes are the edge's q4 brotli, which is what a Worker response ships at.
/ledger/aroundA return visit revalidates the shell to a 304, or takes a dcz delta after a deploy (2,631 B and 2,129 B), and pays for the fragment only. These come out ahead on a first visit where dyno came out even, because their live halves are small. Dyno's chart was about half of its page.
The placeholders
Each placeholder is its renderer's own frame with the live row count, and it names nothing:
/ledger: one unread line per crawler the table can name. That's 16, which is what production's trailing window shows today./around: one unnamed row per neighbour. The crawl always reports all 20.Contract tests compare each placeholder against a live render sized independently: from
CRAWLERSand fromNEIGHBORS. Both tests go red when their placeholder loses a row. My first ledger test sized its "live" read from the mount itself, so it could only agree with itself; its control passed when it should have failed, and that is what caught it.bun run clsreads both pages clean on desktop and phone, with the control seen./aroundwas measured against production's real snapshot seeded into local KV.One known gap: when the ledger has fewer crawlers than 16 in its window, or no read token, the island is shorter than the placeholder. A local Worker has no token, so there it collapses to a one-line note. The shift happens inside the replaced island, and the lab read it clean anyway.
Also
/around?bust=SECRETstill works. A built page can't take a query, so the bust moved intorefreshAroundSnapshot. It re-crawls, then overwrites the colo's cached snapshot, awaited, before the shell goes out. The island the shell then fetches is the new crawl, and not whatever KV'scacheTtlstill holds. A wrong or missing secret does nothing./aroundsaid "Refreshed: every 30 min by cron". The crawl has run daily at 05:41 UTC since 2026-08-14. It now says "once a day", and the route-oracle comment that said*/30agrees.Accept: text/markdownon/aroundnow serves the hand twin. Same exact-route gap as dyno's."/around*"folds three exactrun_worker_firstrows and covers the fragment. Dev gets the"/ledger/*"glob production already had, which clears the build's standing warning about the two allowlists disagreeing.Verification
bun run build,bun run lint,bun run typecheck: clean, including after merging feat(garage): /garage/dictionary, the dictionary the runtime dropped #927.bun run test: 923 pass.bun run test:node: 913 pass, 10 skipped (the HTMLRewriter-only tests), 0 fail.bun run routes:check: 183 routes, 0 failures. New rows cover each island mount and fragment, plus/around's Markdown negotiation.link, so the preload was used), no console errors, and each failure note shows only underdata-state="failed".Not in this PR
/serendipity, which is now the one large page still on the loose script policy, since #925 covered everything that goes throughlunaPage.