Queue-North-Website/scripts
null 28b07abc28 fix(build): the prerender preloaded the logo, hoisted any tag, and hid its errors
Four faults in the one build step that decides what a crawler receives.
Closes #233 and #232.

1. Every page preloaded /logo.png. The hero hint was keyed on the first
   `loading="eager"` image, and that is the header logo, on every page. So the
   image each page actually paints first was never preloaded, and React's own
   preload for it was being discarded as a duplicate. It now keys on the image
   React marked with a high fetch priority, matched case-insensitively, because
   React writes the attribute camelCase in HTML and a case-sensitive match would
   have quietly removed every preload instead.

2. The hoist moved ANY title, meta or link out of the body into <head>. An
   inline <svg><title> is a picture's label, and microdata rides in
   <meta itemprop>: both would have become page-level head tags the moment the
   long-form copy carried an icon with a title. SVG blocks are now parked before
   the hoist, and itemprop tags stay where they are.

3. `page.replace('</head>', body)` interprets `$&`, `$'` and `$$` INSIDE the
   replacement, and the replacement is page copy. React escapes & into &amp;, so
   any `$` immediately before an escaped character injected markup. Copy carries
   no `$` today; the next page with a price would have. Replacement is now a
   split and join, and each marker must appear exactly once.

4. A render error named no route, and a Suspense fallback shipped silently as
   an empty page. Both now fail the build and say which route.

Also refuses to run over its own output: dist/index.html is both the template
and the home page, so a second run without a rebuild gave every page two
canonicals.

Proven by mutation, each restored afterwards: a probe <svg><title> in the footer
stays in the body on all 19 pages and no page gains a second title; a Suspense
boundary fails the build naming the route; a second prerender run refuses; copy
reading "Save $10 & more" reaches the page literally with one root div; and
every page now preloads its own hero, with none preloading the logo.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 04:32:33 -05:00
..
verify.d security: the scanner never ran its private-key pattern, and verify never saw dist 2026-09-10 04:23:39 -05:00
backup.sh chore: adopt template scripts and git hooks, retire phase-versioning 2026-08-18 01:18:20 -05:00
check-env.sh security: the scanner never ran its private-key pattern, and verify never saw dist 2026-09-10 04:23:39 -05:00
deploy.sh fix(deploy): stop two ways this tooling would have broken production 2026-08-18 03:33:20 -05:00
doc-triggers.py chore: adopt template scripts and git hooks, retire phase-versioning 2026-08-18 01:18:20 -05:00
docker-test.sh chore: add docker-push.sh, docker-test.sh, npm scripts, bump v0.5.0 2026-05-14 01:18:44 -05:00
forgejo-issue.py chore: adopt template scripts and git hooks, retire phase-versioning 2026-08-18 01:18:20 -05:00
healthcheck.sh fix(infra): queuenorth.com is the production origin, and it is this deployment 2026-08-18 02:08:12 -05:00
preflight.sh fix(infra): queuenorth.com is the production origin, and it is this deployment 2026-08-18 02:08:12 -05:00
prerender.js fix(build): the prerender preloaded the logo, hoisted any tag, and hid its errors 2026-09-10 04:32:33 -05:00
qa-browser.mjs fix(ui): header CTA clipped at iPad portrait, and reCAPTCHA cut off at 320px 2026-08-18 04:05:37 -05:00
release.sh fix(deploy): stop two ways this tooling would have broken production 2026-08-18 03:33:20 -05:00
restore-check.sh chore: adopt template scripts and git hooks, retire phase-versioning 2026-08-18 01:18:20 -05:00
secrets.sh security: the scanner never ran its private-key pattern, and verify never saw dist 2026-09-10 04:23:39 -05:00
status.sh chore: adopt template scripts and git hooks, retire phase-versioning 2026-08-18 01:18:20 -05:00
verify.sh chore: adopt template scripts and git hooks, retire phase-versioning 2026-08-18 01:18:20 -05:00