Hydration likely fails on every prerendered page #226

Closed
opened 2026-09-10 04:13:34 -05:00 by null · 0 comments
Owner

Seen at a25077d (v0.9.5). Source-verified; the runtime effect is unconfirmed, which is the first step below.

What is true now. scripts/prerender.js:59-66 moves the JSON-LD scripts from <main> into <head>, but the client render still expects them inside <main>. Separately, src/main.jsx renders sonner's <Toaster>, which outputs a <section> the server HTML does not have. React most likely discards the prerendered DOM and re-renders every page on the client, leaving duplicate head tags in the live DOM.

What it costs. Every page pays a full client re-render. Worse, any new difference between server and client output is invisible: browsers see the client render and crawlers the server one. README.md:102 ("the SPA hydrates on top") is probably false.

What to do, in order.

  1. Measure hydration errors on every page with qa-browser's console capture (see the qa-browser issue).
  2. If confirmed: leave the JSON-LD in the body, where it is valid, and mount the Toaster after hydration.
  3. Re-measure to zero.

Why it might be deferred. The fix can expose other mismatches. If it cascades, it is deferred only by Null's explicit decision; it predates this work, and the release is not made worse without it.

Verify: opening each of the 18 pages of a local build in a browser shows no hydration error in the console (qa-browser reports zero), and the Elements panel shows exactly one title and one canonical after load.

Seen at a25077d (v0.9.5). Source-verified; the runtime effect is unconfirmed, which is the first step below. **What is true now.** `scripts/prerender.js:59-66` moves the JSON-LD scripts from `<main>` into `<head>`, but the client render still expects them inside `<main>`. Separately, `src/main.jsx` renders sonner's `<Toaster>`, which outputs a `<section>` the server HTML does not have. React most likely discards the prerendered DOM and re-renders every page on the client, leaving duplicate head tags in the live DOM. **What it costs.** Every page pays a full client re-render. Worse, any new difference between server and client output is invisible: browsers see the client render and crawlers the server one. `README.md:102` ("the SPA hydrates on top") is probably false. **What to do, in order.** 1. Measure hydration errors on every page with qa-browser's console capture (see the qa-browser issue). 2. If confirmed: leave the JSON-LD in the body, where it is valid, and mount the Toaster after hydration. 3. Re-measure to zero. **Why it might be deferred.** The fix can expose other mismatches. If it cascades, it is deferred only by Null's explicit decision; it predates this work, and the release is not made worse without it. Verify: opening each of the 18 pages of a local build in a browser shows no hydration error in the console (qa-browser reports zero), and the Elements panel shows exactly one title and one canonical after load.
null added this to the Batch 18: Guards and landmines found building Batch 17 milestone 2026-09-10 04:13:34 -05:00
null added the
P2
bug
frontend
labels 2026-09-10 04:13:34 -05:00
null closed this issue 2026-09-10 04:37:38 -05:00
Sign in to join this conversation.
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: null/Queue-North-Website#226
No description provided.