This pass audited the site as an existing production application rather than a draft. Nothing about the visual identity, the routes, the canonical origin or the published claims changed. Four things that were broken without failing anything are fixed, and every one of them now has a check that would catch it again.
The local Worker preview never ran the Worker
The Worker is bound to akasammythepuppy.me as a custom domain. With that route active and no local override, wrangler dev never invoked the Worker at all: every worker-first path answered 308 Permanent Redirect with a Location identical to the request URL. That disabled npm run preview and, with it, every browser-level check in the repository — test:browser, test:interactions, test:lighthouse and test:revalidation all ran against an endless self-redirect instead of the site.
The preview command now passes local route overrides, dev:worker exists as README already documented, and a test keeps both in place. With the preview working again, the browser suite reports zero failures across all 31 canonical routes.
test-browser.mjs also used to fetch the schema.org vocabulary mid-test. That is now a pinned snapshot in the repository, refreshed deliberately by tools/update-schema-vocabulary.mjs, so structured-data validation is deterministic and does not depend on a third-party fetch. test-lighthouse.mjs used to exit successfully when the sitemap returned no routes, reporting a pass over zero measured pages; it now fails instead.
The site could not be printed
Five at-rules in the main stylesheet were written @mediaprint instead of @media print. Browsers ignore an unknown at-rule, so every print rule on the site — hiding the fixed header, flattening the hero, hiding the Discord and calendar embeds — had never applied.
With them corrected, measurement showed two further problems. Browsers drop background colours when printing, but the text colours stayed as authored, so inner pages printed near-white text on white paper. And the gradient headings use background-clip: text with a transparent colour, so every h1 printed as nothing at all. Both are fixed. Printed text colour is now measured on ten routes, one per stylesheet combination — including /press/ and /media-kit/, the two pages most likely to be saved as a PDF.
The stylesheets had no source
Four minified stylesheets, 162 KB in total, had no unminified source anywhere in the repository. They could only be changed by editing minified text, which is how several superseded redesign layers survived unnoticed. The sources now live in src/styles/, the minified bundles are generated during the build like the JavaScript ones, and a test fails if a bundle stops matching its source.
With the stylesheets readable, 17% of the CSS turned out to be rules no page can reach — layout classes from the pre-Astro release and three redesigns since. They are removed, and the count is held at zero by a check that reads authored sources as well as built output, so degraded-state styling such as the social-feed fallback is not mistaken for dead code.
One header and footer instead of twelve
The header and footer existed in twelve copies. They had already drifted: the footer on blog and changelog entries was missing its Media kit link, and only /press/ marked its own footer link with aria-current. Both are fixed, the navigation is defined once, and a test checks every route’s header and footer against one declared specification.
Accessibility and search
The browser suite only ever ran accessibility checks at desktop width in a page’s initial state. It now also runs at 390 and 768 pixels wide, with the mobile navigation open, and checks that Enter opens it, Escape closes it, every entry is visible, and no page scrolls sideways. Result across all 31 routes at both widths, open and closed: zero violations.
The eight authored routes carried hand-maintained sitemap lastmod dates that all read the same day regardless of what had changed. Those dates are now derived from the content that renders each route, and deliberately do not move when only a cached feed refreshes.
Tooltips are not accessible names
Post-build HTML used to add a title attribute to every anchor and every captioned image. 1,365 anchor titles and 127 image titles, 42 KB of attributes across the build — and 1,316 of the anchor titles repeated their own visible link text exactly. A title is a tooltip no keyboard or touch user can reach, the HTML specification discourages relying on it, and a screen reader set to announce titles reads the same words twice.
The injection is gone. What replaces it is the thing the titles were standing in for: every link now has a real accessible name, from its text, an aria-label, or the alt text of an image inside it, and a test checks that on every link in every built page. Removing the titles is what made it possible to check — title counted as a name, so an unnamed link looked named. Authored titles are untouched, and the release audit no longer demands a title it does not need.
Delivered HTML dropped from 42 KB of title attributes to 2 KB. Accessibility stayed at 100 with zero violations, which is the point: nothing was lost but the duplication.
One stylesheet request per page
The per-page CSS purge wrote one stylesheet per original link, so 27 pages requested two purged
stylesheets and /work/ requested three. Every one of them blocks rendering, and Lighthouse put
the cost of the two extra on /work/ at about 150 ms.
They are now concatenated in their original link order into a single request. The delivered CSS is
byte-identical on all 40 built documents — the same rules in the same cascade order, in one file
instead of three. On /work/ the render-blocking estimate went from 150 ms to 0 and largest
contentful paint from 2.37 s to 2.28 s; /, /community/, /press/ and /media-kit/ now score
100 for performance. A stylesheet carrying a media attribute would change what it applies to, so
it stays its own request rather than joining the bundle.
The checks now run where they can fail
Adding checks is only half of it. The Cloudflare validation workflow ran the delivery tests
before the build and no browser checks at all, so three of the new tests would have failed on a
fresh checkout — they read dist/, which does not exist yet at that point — and the accessibility
and print coverage would never have run in CI regardless of what it found locally.
The suites are now split by what they need: test:delivery for checks that read only source, and
test:built for checks that inspect built output. The workflow runs the first before the build and
the second after it, then starts the Worker preview, proves it serves pages rather than redirecting
to itself, and runs the browser and accessibility suites against it. The regression reports are
kept as build artifacts.
The weekly health report could not fail
The scheduled Lighthouse report ran against production every Monday and always succeeded,
whatever it found. Two reasons. It read a missing category as Number(undefined || 0), so a page
Lighthouse could not load appeared in the table as a row of zeros — which reads like a
catastrophic site problem while hiding the real one, a failed page load. And it enforced no
threshold at all, so a genuine drop to 42 produced a tidy table and a green run.
It now distinguishes “not measured” from zero, surfaces the runtime error when Lighthouse could not load a page, and fails when any category falls below 90 — the same bar the pre-deploy check uses, so the two cannot disagree. The verdict goes at the top of the report rather than being left for someone to work out from the numbers.
The workflow was also fetching lighthouse@12.8.2 through npx while the repository pins 13.4.1,
so the weekly production numbers came from a different major version than the pre-deploy numbers
and the two were never comparable. It now installs the locked dependencies and uses the pinned
version.
A ledger that has to be true
REGRESSION-LOG.md records what happened. It cannot stop anything happening again — a written
“we added a check” is worth nothing if the check was deleted, was never wired into a suite, or never
existed.
REGRESSION-LEDGER.md is now generated from tools/regression-ledger.json, one row per behaviour
that must not break again: what must hold, what went wrong, the check that holds it, and the suite
that runs it. A test makes every row falsifiable — the named check has to exist, has to appear in the
script the row claims, and a check that reads built output must not sit in the suite that runs before
the build. A guard with no row fails, and so does a stale ledger document. Twenty invariants, and all
four failure paths were verified by hand rather than assumed.
Nothing moved for search
This work touched stylesheets, build tooling and tests. That is the kind of change that is supposed to be invisible to Google, Bing, Yandex and the AI crawlers, but nothing was checking, so it was an assertion rather than a measurement.
tools/indexing-surface.mjs now captures everything a crawler keys on: robots.txt by hash, the
sitemap inventory, and per route the canonical, robots directives, hreflang, Open Graph identity,
H1 count and every JSON-LD type, plus the Worker’s HTTP robots header, the redirect rules and the
discovery files. Measured against the state before this audit began, the entire crawler-facing
surface shows four differences: the one new changelog page and its sitemap entry, and two meta
descriptions deliberately shortened because they were truncating in results. Not one canonical,
robots directive, hreflang, Open Graph value, schema type or redirect rule changed.
That surface is now a committed snapshot, and a test compares every build against it. Changing how the site is indexed is still possible — it just has to be deliberate.
The typeface the site asked for was never delivered
Every stylesheet led its font stack with Inter. Nothing loaded it — no @font-face, no font link,
no font file in the repository — so Inter applied only to visitors who happened to have it
installed locally, and everyone else quietly got the next family in the list.
That is not cosmetic. Serving a real Inter build against the fallback the site actually delivers, Inter sets about 6.8% narrower: the home page ran 239 pixels shorter, About 896 pixels shorter. Visitors were seeing measurably different layouts depending on what fonts they happened to own.
Self-hosting was the other option and was rejected on the numbers. The full variable file is 344 KB, and even a Latin subset adds a request and a swap to a site whose stylesheets are already purged per page and whose cumulative layout shift is 0.000 on every route. So the stack now declares only what is actually delivered, the design is identical for every visitor, and nothing new is downloaded. A check fails if a family is named without being shipped.
Validation evidence
The static Astro build, the release audit across 32 canonical pages, 49 Worker and feature tests, 271 delivery tests, 7 feed-delivery tests, the browser suite across 32 routes with zero failures, and 74 responsive, keyboard and print checks with zero failures. Lighthouse on six representative routes: performance 98 to 100, accessibility 100, best practices 100, SEO 100.
Every document produced by the build was compared against the previous build. The only differences are the two navigation corrections above and the regenerated stylesheets; no route, canonical URL, robots directive, sitemap entry or published claim changed. test:interactions was not run here because it requires the public Google Calendar embed to load, which the audit environment could not reach.
