DocumentationComponentsTheme Creator
Theme CreatorGitHubIntroduction
InstallationUsageThemingMotion
Components
AI agentsContributing

Rendered reality

What to do when a screenshot shows a break the gates missed — the reproduction procedure, the serving traps that fake hydration errors, and the mount and anatomy detectors.

Someone shows you a screenshot of a page that is plainly broken. You open the same URL and it is fine. Every gate is green. This file is the procedure for that moment — written from a live incident (2026-09-23, the combobox playground) where the procedure worked, including the parts where the investigator's first readings were wrong.

The premise: the corpus makes builders write correct responsive code. It cannot police rendered reality. Three failure classes live entirely outside the rules, and each has a different detector:

ClassDetector
Arrangement that passes every gateanatomy assertions (qa:mounted seeds) + a person
A state that exists on one machine onlythis procedure
Client-only mount windows / chunk failuresqa:mounted + the preview pipeline's own error handling

1. Believe the screenshot, then classify

The screenshot is data. It shows a state that existed. Your job is to find which kind of state: a settled layout you can reproduce, or a transient / machine-local one you cannot. Do not argue with the reporter about what they saw; find out when what they saw can exist.

2. The settled-state sweep

Measure the real page, by geometry, across the axes a user's machine can vary. Every probe is getBoundingClientRect + computed style — never eyeballing.

  • Widths: 320 · 430 · 766 · 881 · 1024 · 1400 · 1512 (or bisect around the reporter's). Remember the pane scales: assert clientWidth equals the width you asked for before trusting any number from it — a "23px overflow at 768" in the incident was an artifact of measuring at 753.
  • Root font size: 16 / 20 / 24px via document.documentElement.style.fontSize — simulates the browser's default font setting, the axis our px breakpoints ignore (01). A rem-built component should scale its boxes; the incident component grew 288 → 360 → 432 cleanly, which cleared this hypothesis.
  • Font stack: swap fontFamily to system-ui, Arial, Segoe UI, and measure clipping — a webfont that failed on the reporter's machine renders wider and clips where yours fits.

Two self-traps from the incident, so they are not rediscovered:

  • A "same row" check with a ±26px tolerance called a 20px-stacked label "beside" its control. Pick tolerances from the measured healthy layout, not from air.
  • input.scrollWidth === clientWidth looked like "fits with zero slack — fragile!". It was nothing of the kind: the input is flex-grow: 1, so the two are equal by construction at any font. Know what the equality means before reading it as a signal.

3. The client-only window

curl the URL and grep the raw HTML for the content in the screenshot.

If it is absent from the server payload, the element mounts client-side and everything between first paint and settled hydration is a state a screenshot can catch — and, with an error, a state that can persist. In the incident, "Select a fruit" appeared nowhere in 538KB of SSR HTML.

Then check the error path in the pipeline that mounts it:

  • Is there a .catch on the dynamic import? An error boundary above it? A rejected React.lazy stays rejected in any module-level cache — the page is then broken until a hard reload, which is exactly the signature "it looked broken for a while / reload fixed it".
  • Deploy skew: chunk hashes rotate every deploy. A tab opened before a deploy 404s its old chunk names. Check the deploy log for that day.

The one-question discriminator to send the reporter: does a hard reload fix it? Heals → stale-chunk / mid-mount class, mechanism above. Survives → it is a settled state; go back to §2 and bisect harder.

4. Serving traps that fake the whole investigation

The export writes both route.html and a route/ directory of RSC payloads. A generic static server that resolves the directory first — or a probe that appends a trailing slash — hydrates the wrong payload and throws React #418 on every route. In the incident this manufactured 110 phantom hydration failures until the canonical scripts/serve-export.ts was used. Measure the export only through it.

And read suite results from a JSON reporter file, never from piped stdout: the incident's first run printed "49 passed" through the shell filter while the true count was 74 failing of 118 (reference_rtk_output_filtering).

5. The detectors we now own

qa:mounted (docs repo) loads every route of the export and asserts, per page: zero page errors, zero failed chunk requests, and every [data-preview-frame] contains at least one element with a real layout box — the geometric mount gate the QA harness got in docs#454 and the site itself never had. It waits for the geometry it asserts, not a proxy: its own first draft waited on scrollWidth stability and failed 73 routes, because an empty frame is perfectly stable. The suite carries a MUTATE= hook and is only trusted because each detector was forced red: empty → 110, pageerror → 118, anatomy → exactly the seeded 1, clean → 0.

Anatomy seeds (in the same suite) are the first positional assertions we own — qa:styles records w/h but no x/y (08). Each seed names two slots on one route and asserts left-edge alignment, vertical gap range, and a width floor. An entry is added by measuring the healthy layout first — the combobox seed's numbers (left delta ≤ 24, gap 0–16, width ≥ 200) are its measured healthy values with margin, not invented thresholds. One seed per incident: every layout that reaches this file's §1 earns its assertion on the way out.

What none of this covers, so nobody over-reads a green run: a preview stuck on its Suspense fallback occupies a box and passes; deploy-skew itself is testable only in the pipeline's own retry tests; and arrangement on the ~100 unseeded routes is still guarded by exactly one thing — a person looking. That detector fired first in the incident too.

6. If you cannot reproduce it

Say so, with the matrix of what you ruled out — that is a result, not a failure. Ask for two facts only: browser + zoom, and the hard-reload test. Do not name a mechanism you have not measured; the incident's investigator wrongly proposed two before landing on the one the evidence supported, and both wrong turns are recorded above so they cost nothing next time.

Responsive QA checklistComponents

On this page

1. Believe the screenshot, then classify2. The settled-state sweep3. The client-only window4. Serving traps that fake the whole investigation5. The detectors we now own6. If you cannot reproduce it