Repository navigation
refactor: www/ splits into src/pages/ and public/ - #457
Merged
Merged
Conversation
The last of the www/ split. 36 HTML documents become src/pages/; the other 804 files, which are bytes a browser fetches unchanged, become public/. The staged root renames with them: .build/www is .build/public, and wrangler.jsonc's assets.directory follows. Seventh and final slice of lifting the parked bun branch's renames onto main (#450, #451, #452, #453, #455, #456). The mapping needed no judgement: main's www/ held exactly 840 files, the branch's two destinations hold exactly those 840, and every one lands in exactly one of them. Every HTML is a page; nothing else is. EVERY SERVED ARTIFACT IS BYTE-IDENTICAL, 1497 compared with the root name normalised. The four remaining differences are path references inside cal, serendipity and the Worker: three comments and one JSON import specifier. THE BUILD COMPOSES THE SERVED TREE NOW rather than copying one directory. public/ + src/pages/ + src/content/ + src/client/ + src/styles/ all stage into .build/public, so the URL layout is untouched while the source layout says what each file IS. servedFiles() walks the three authored roots in one place, because a tripwire that walks only some of them reports a clean tree it never read. SIX THINGS THE GATES CAUGHT, and the pattern is worth stating: a blanket path sweep cannot tell a source read from a staged path, an asset from a document, or a path from a regex. * staticShellPages() read www/ for the freshness check * the Worker imported ../../www/images/hashes.json * gen-md-twins looked for page HTML under www/, then read the generated tier from the staged www/ root * the page generators in pipelines/ wrote into www/ * the .src.html twin read its AUTHORED source from the wrong root, so it fell into a catch and shipped the STAGED bytes: readable twins carrying rewritten /a/ hashes, which is the whole point of the twin lost silently. The build's own counter is what showed it, 47 from staged where main says 12. * and one false positive: `assert.match(lens, /… 401 && www/)` is a regex whose DELIMITER the sweep read as a path separator, rewriting the assertion out from under a real variable named www. Gates: 305 tests, build, lint, typecheck, routes:check, pages:check, tools:check, perf-budget, photos:check, check-wrangler, cal, wrangler dry-run.
Contributor
Wire-size diff vs merge base
Brotli q11, the quality the edge serves. Every number here is deterministic: Client assetsTotal Brotli: 0.00 KiB → 75.10 KiB (+75.10 KiB, n/a) across 21 files, 21 changed.
PagesTotal Brotli: 0.00 KiB → 502.10 KiB (+502.10 KiB, n/a) across 48 files, 48 changed.
Worker bundleNo change. 230.10 KiB gzip. Dictionary deltas (
|
oddharsh
added a commit
that referenced
this pull request
Aug 18, 2026
The bullet under the header still called public/ the live site including the _worker.js/ dispatcher, which is two moves out of date: the Worker left the served tree in #450 and the documents left it in #457. It now names what each root is for, which is the same question the table below answers per entry.
oddharsh
added a commit
that referenced
this pull request
Aug 18, 2026
* docs: the layout table describes the tree that now exists Seven slices moved almost every path in this repository (#450, #451, #452, #453, #455, #456, #457), and the automated sweeps that repointed code also walked CLAUDE.md. That left the map wrong in two different ways. STALE: the table still said public/ holds "pages, client scripts, CSS, photos, dictionaries". It holds none of the first four now. Rows added for src/pages, src/content and src/dict; scripts/ folded into the tools/ row; every row's description checked against the tree rather than against its own history. FALSE: the sweep rewrote HISTORICAL names, so the file claimed the Worker lived at `public/_worker.js/` and the photo pipeline at `public/scripts/`. Neither ever existed. A stale note is a note somebody distrusts; a false one is a note somebody follows. The naming note now records the full sequence, holding -> www -> the split, and says explicitly that the rewrites deliberately left old mentions alone, so reading `www/` in an older note is correct rather than a typo. It also drops the "duplicate path" explanation, since scripts/ no longer exists to be confused with tools/photos/. And it states the test for where a new file goes, which the table never did: if a build step transforms it, it is src/; if it ships byte-for-byte, it is public/. * docs: the intro names the split tree too The bullet under the header still called public/ the live site including the _worker.js/ dispatcher, which is two moves out of date: the Worker left the served tree in #450 and the documents left it in #457. It now names what each root is for, which is the same question the table below answers per entry. --------- Co-authored-by: Aadharsh Pannirselvam <19518661+oddharsh@users.noreply.github.com>
oddharsh
added a commit
that referenced
this pull request
Aug 19, 2026
…eated (#467) #452 moved the photo pipeline to tools/photos/ and #451/#457 moved the served tree to public/, and four ignore rules kept naming the old locations: www/scripts/zenc/target/ -> tools/photos/zenc/target/ www/scripts/.venv/ -> tools/photos/.venv/ www/ad/ -> public/ad/ www/images/meta/ -> public/images/meta/ None of the new paths existed yet, which is why nobody hit it. The first person to run photos:env or build zenc would have had a 13M venv and 218M of Rust build output appear as untracked, in the one place a git add -A would sweep them in. Verified with git check-ignore: all four new paths are ignored, and none of them is tracked today, so no committed file changes status. Co-authored-by: Aadharsh Pannirselvam <19518661+oddharsh@users.noreply.github.com>
oddharsh
added a commit
that referenced
this pull request
Aug 24, 2026
…no card `bun run og-cards` has been writing to a directory nothing serves since the 2026-08-18 split (#457) deleted www/. Both halves of the pipeline held `const HOLDING = path.join(ROOT, "www")`, which broke three things at once: the cards went to a www/og that mkdir happily created, the wallpaper read missed luna.css, and the section walk found no documents to enumerate. IT WAS SILENT FOR SIX DAYS because nobody adds a page most weeks. The tell was sitting in the tree: 18 garage cards against 22 garage pages, and no card committed since #457 itself. /garage/useragent shipped on 2026-08-21 with no card and nothing said so. This is gotcha 40's family with a hardcoded name instead of a relative expression, and the same repair applies: name the tree each use actually wants, so the next rename breaks at the constant rather than at the output. One HOLDING becomes four constants, because the served tree is three directories now and no single name is honest about it: PUBLIC public/ bytes that ship unchanged; the cards land here PAGES src/pages/ the documents the section walk enumerates STYLES src/styles/ luna.css, for the Bliss wallpaper read SERVE .build/public/ the merged URL root, which only the build assembles The local-server path now fails by name when .build/public is missing, rather than serving an empty tree, which would read as every page having lost its demo. FOUR CARDS BAKED against production: garage-typed-config, garage-hidden-flags, garage-useragent and lwe-fuse. Three first came out through the window fallback, which the HERO table's own comment records as no longer acceptable since the Explorer chrome landed in #275: a whole-window card reads as a screenshot of a browser rather than one demo panel floated on the desktop. They have hero selectors now and were re-captured. THE FAVICON STAMP TOOK TWO TRIES AND THE FIRST ONE MADE IT WORSE. Generated pages ship no `rel="icon"`, so their cards fell back to a blank blue square. Passing `/section-icons/<section>.svg` as the src looked like the fix and rendered an EMPTY WHITE BOX: the card is built with `setContent`, so the document has no base URL and a root-relative path resolves against nothing. Every page whose icon works declares it as `data:image/svg+xml,...` for exactly that reason. The fallback inlines the file the same way now, and all four cards carry their section mark. Both attempts were rendered and looked at, which is the only reason the first one did not ship. Green: build, 354 contract tests, typecheck, oxlint type-aware, tools:check.
oddharsh
added a commit
that referenced
this pull request
Aug 24, 2026
…no card (#550) * garage: two pages on wrangler config, from the work that produced them /garage/typed-config and /garage/hidden-flags, both written out of the measurements taken while converting cf-garage to wrangler's experimental TypeScript config. TYPED-CONFIG is the conversion, measured on both sides. The centrepiece is a three-pane explorer: toggle bindings and watch the config you write, the resolved config the platform receives, and the inferred Env interface move together. Every row in it is measured rather than modelled. The resolved JSON is what `wrangler build --x-cf-build-output` wrote for that binding, and each type is what tsc reported for that key, probed one key at a time. Two findings the page exists for. bindings.text("default") types the variable as the literal "default" and bindings.json({dcz: true, tier: 2}) comes back as { dcz: true; tier: number }, so a plain variable's value reaches the type, which a JSON config structurally cannot do. And the Durable Object type goes BACKWARDS: DurableObjectNamespace<undefined> under inference against a real class threaded through by `wrangler types` on the JSON config. That was measured under both entrypoint forms, the path string and the documented { type: "cf-worker" } module import, because one form failing reads as holding it wrong. So the scoreboard is split rather than a win. HIDDEN-FLAGS is the survey. All 19 flags carrying `hidden: true` in the 4.125.0 bundle, filterable, complete rather than curated, with the five that touch this site marked. The argument is that acceptance and effect are separate questions and the first is usually free, carried by four cases from this repo: the closed Browser Run schema, the zstd dictionary option three runtimes disagree about in silence, --max-versions proving a cap lives on the server through its own source comment, and --old-asset-ttl reading like a fix while being wired to the legacy Workers Sites path this site does not run. Ends on a control picker: name the shape of the doubt, get the experiment and its decision table. A BUILD INVARIANT WAS NARROWER THAN THE IDS IT SCANS FOR. Gallery link discovery matched /garage/[a-z0-9]+ while the generator has always allowed hyphens, and no page had ever carried one. The first hyphenated id generated fine, registered fine, got a hand-written shelf card, and then failed the invariant claiming the card was missing from the file it was sitting in. Widened to match the generator's own id class, with the reasoning at the line. The 38 touched static pages are one regenerated field: the garage taskbar pin goes from data-count="20" to "22". `bun run gen:shell` owns that, and the pipeline README's step list does not mention it, which is worth knowing before the next page. Verified in a real browser on a port confirmed to belong to this worktree: both demos drive, the filters and tabs re-render, the quiz renders 7 questions, and at 375px neither page overflows horizontally while the wide tables and code panes scroll inside their own containers. Green: build (52 documents, 3015 internal refs resolve, 33 quiz payloads byte-equal), pages:check, 354 contract + 353 node tests, routes:check, perf-budget, typecheck, oxlint type-aware. * fix(og): the card pipeline still pointed at www/, and four pages had no card `bun run og-cards` has been writing to a directory nothing serves since the 2026-08-18 split (#457) deleted www/. Both halves of the pipeline held `const HOLDING = path.join(ROOT, "www")`, which broke three things at once: the cards went to a www/og that mkdir happily created, the wallpaper read missed luna.css, and the section walk found no documents to enumerate. IT WAS SILENT FOR SIX DAYS because nobody adds a page most weeks. The tell was sitting in the tree: 18 garage cards against 22 garage pages, and no card committed since #457 itself. /garage/useragent shipped on 2026-08-21 with no card and nothing said so. This is gotcha 40's family with a hardcoded name instead of a relative expression, and the same repair applies: name the tree each use actually wants, so the next rename breaks at the constant rather than at the output. One HOLDING becomes four constants, because the served tree is three directories now and no single name is honest about it: PUBLIC public/ bytes that ship unchanged; the cards land here PAGES src/pages/ the documents the section walk enumerates STYLES src/styles/ luna.css, for the Bliss wallpaper read SERVE .build/public/ the merged URL root, which only the build assembles The local-server path now fails by name when .build/public is missing, rather than serving an empty tree, which would read as every page having lost its demo. FOUR CARDS BAKED against production: garage-typed-config, garage-hidden-flags, garage-useragent and lwe-fuse. Three first came out through the window fallback, which the HERO table's own comment records as no longer acceptable since the Explorer chrome landed in #275: a whole-window card reads as a screenshot of a browser rather than one demo panel floated on the desktop. They have hero selectors now and were re-captured. THE FAVICON STAMP TOOK TWO TRIES AND THE FIRST ONE MADE IT WORSE. Generated pages ship no `rel="icon"`, so their cards fell back to a blank blue square. Passing `/section-icons/<section>.svg` as the src looked like the fix and rendered an EMPTY WHITE BOX: the card is built with `setContent`, so the document has no base URL and a root-relative path resolves against nothing. Every page whose icon works declares it as `data:image/svg+xml,...` for exactly that reason. The fallback inlines the file the same way now, and all four cards carry their section mark. Both attempts were rendered and looked at, which is the only reason the first one did not ship. Green: build, 354 contract tests, typecheck, oxlint type-aware, tools:check. --------- Co-authored-by: Aadharsh Pannirselvam <19518661+oddharsh@users.noreply.github.com>
oddharsh
added a commit
that referenced
this pull request
Oct 17, 2026
8c checks that every garage/lwe page on disk is registered in site-manifest.json. The www/ split (#457, 2026-08-18) pointed its walk at public/garage and public/lwe, which still exist for av2/, enc/ and lean/ assets but hold no .html. readdir succeeded, so the check inspected 0 of the 39 pages in src/pages for 60 days and passed every build. The walk now reads src/pages, counts what it inspects, fails under 30 pages, and prints the count in the invariants summary. Invariant 10 (conflict markers) had the same shape: it read serendipity as /\.js$/ after #523 (2026-08-23) made the module TypeScript, so it scanned 0 of 3 files. It reads .ts now, and every root it walks must yield at least one file. Gotcha 75 records the class: a walk over a tree that exists but no longer holds what it checks passes on zero files. Co-authored-by: Aadharsh Pannirselvam <19518661+oddharsh@users.noreply.github.com>
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.
The last of the
www/split, and the seventh slice of lifting the parked bun branch's renames ontomain.36 HTML documents become
src/pages/. The other 804 files, which are bytes a browser fetches unchanged, becomepublic/. The staged root renames with them:.build/wwwis.build/public, andwrangler.jsonc'sassets.directoryfollows.The mapping needed no judgement.
main'swww/held exactly 840 files; the branch's two destinations hold exactly those 840; every one lands in exactly one of them. Every HTML is a page, nothing else is.Every served artifact is byte-identical
1497 compared with the root name normalised. The four remaining differences are path references inside cal, serendipity and the Worker: three comments and one JSON import specifier.
The build composes the served tree now
public/+src/pages/+src/content/+src/client/+src/styles/all stage into.build/public, so the URL layout is untouched while the source layout says what each file is. A newservedFiles()walks the three authored roots in one place, because a tripwire that walks only some of them reports a clean tree it never read.Six things the gates caught
The pattern is the point: a blanket path sweep cannot tell a source read from a staged path, an asset from a document, or a path from a regex.
staticShellPages()readwww/for the freshness check../../www/images/hashes.jsongen-md-twinslooked for page HTML underwww/, then read the generated tier from the staged rootpipelines/wrote intowww/pages:check.src.htmltwin read its authored source from the wrong rootassert.match(lens, /… 401 && www/)— a regex delimiter read as a path separatorTwo deserve more than a row. The twin bug fell into a
catchand shipped the staged bytes instead, so every readable twin carried rewritten/a/hashes — the entire purpose of a twin, lost with no error. The build's own log line is what exposed it:47 from stagedwheremainsays12. And the regex case rewrote an assertion out from under a real variable namedwww, which no amount of path-checking would have caught.Gates
305 tests, build, lint, typecheck,
routes:check,pages:check,tools:check,perf-budget,photos:check,check-wrangler, the cal suite, and awrangler deploy --dry-run.After this
www/is gone. The tree reads:public/is what a browser fetches,src/is what people author,tools/is what developers run,config/is declared state. That is the whole restructure, and the parked migration (#443) is now a toolchain swap against a settled layout rather than a 1229-file branch.