fix(server): preview snapshots preserve blurred backdrops#24618
Preview snapshots capture at full scale and resize the finished PNG, so blurred backdrops show the page as rendered. Fixes #20899.
Other visible effects: at 125% zoom the PNG is now capped at 1280×711 instead of 1600×889, and the old black padding disappears. Wide plain pages preserve their content and layout with text/edge resampling differences. Narrow controls are byte-identical.
Takeover
Rebuilt from @watashiwaaniket’s #20924, which identified Chromium’s scaled-capture defect and the full-capture/canvas-resize approach. The resize runs in the tab’s isolated world instead of opening a scratch page and threading a callback through snapshot inputs. HTML-namespaced canvas creation preserves XML-page snapshots. Replaced the wiring tests with real Chromium tests for blurred, plain, and XML documents. No new dependency or wire change.
Evidence
Supplemental N1 and RM: extended matrix, capture index, and complete reproduction bundle. Supplemental before is merge-base 8bcef34f; after remains b7fddd87.
Linux Xvfb, Electron 44.9.3 / Chromium 152.0.7977.167, genuine Electron webview attached through DesktopBrowserChannel; actual server preview_snapshot outputs. N1 uses 1440×800, scroll 600, zoom 1/DPR 2 and zoom 1.25/DPR 2.5. RM uses real CDP reduced-motion emulation with a running-animation positive control, then stable reduced-motion snapshots. All returned PNGs are 1280×711 and byte-identical to repeats 500 ms later. Independent headed references, two diffs per pair, debugger/attachment/media provenance, ffmpeg X11 recordings and scripts are in the index. Reference resampling leaves edge/text differences; viewer timing is approximate.
| Supplemental row | Before | After | Comparison and two diffs per pair |
|---|---|---|---|
| N1 · native attachment · 100% | Before N1 at 100% | After N1 at 100% | Reference and diffs |
| N1 · native attachment · 125% | Before N1 at 125% | After N1 at 125% | Reference and diffs |
| RM · reduced-motion animation fixture | Before RM | After RM | Reference and diffs |
Independent supplemental proof audit: SUFFICIENT for N1 and RM. All 18 diff images independently recomputed; public fixtures rebuilt byte-for-byte; a fresh actual-server N1 reproduction at 125% passed. Reproduction evidence. Supplemental capture and both proof audits: GPT-6.1 Sol through Codex/T3 delegation.
Fixture matrix, full evidence index, and reproduction bundle contain the headed references, raw images, metrics, fixture/driver scripts, hashes, and nonsecret service traces. All scripts remain external to the PR.
Actual before: c4fa4629. Actual after: b7fddd87, including main by merge commit. Preview source is identical between the captured baseline and current main 8bcef34f.
Chromium 156.0.8078.70: actual headless server snapshot service at DPR 2 versus a matching headed Chromium reference under Xvfb. Height 800 CSS px, root font 16 px; actual dimensions and zoom metrics are in the index. Every static capture matched a second capture 500 ms later. Threshold-0 RGB differences are amplified ×4; threshold-10 masks mark channel differences >10. A7 comparisons normalize the baseline’s 1600×889 image to 1280×711; raw images remain linked in the index.
Identical interaction script: start recording, scroll to 600, snapshot, zoom to 125%, snapshot, reset zoom, scroll to 0, snapshot, reload/reconnect, stop. Before timestamps; after timestamps. Both revisions show an enlarged page after Reset zoom and a blank reload interval before viewer recovery; these are existing observations, not claimed fixes.
| Recording | Before | After |
|---|---|---|
| Immediate start/stop: usable first frame | before-C3.mp4 | after-C3.mp4 |
| Scroll/zoom/snapshot during recording | before-A7-C4.mp4 | after-A7-C4.mp4 |
| Real Browser viewer and reconnect | before-C4-viewer.mp4 | after-C4-viewer.mp4 |
12/12 required rows captured, 13 scenarios including the 640/641 boundary. XML X1 extends the original matrix and succeeds before and after.
Verification log
- Tests:
ServerBrowserPage.test.ts16→19;ServerBrowser.test.ts27 unchanged. Final merged head: 46/46 pass. Blur regression fails on baseline; XML regression failed on the intermediate implementation and passes after the namespace fix. - Scoped lint/format and server typecheck passed. No repository-wide checks run.
- Review round 1: A found missing evidence; B found the XML canvas regression. Fixed with namespaced canvas and one regression test. Round 2: both GPT-6.1 Sol and Claude Opus 5.5 returned MERGE; no remaining concrete findings..
- Independent proof audit: SUFFICIENT: independently rebuilt A1 through a fresh app server and thread-bound MCP; 0/910,080 pixels differ. All 78 diff images independently recomputed..
- CI: Initial publication read: 11 successful, 16 pending, 0 failing; dispatcher owns monitoring and landing.. No merge performed.
- Unverified rows: none of N1/RM remain. Evidence covers Linux Xvfb native attachment and reduced-motion media set through the attached guest’s existing CDP debugger; no public reduced-motion configuration API or separate headless-server reduced-motion run is claimed. Physical-monitor and other platform behavior were not tested. All changed files remain server paths.
- Complexity: base64 conversion O(encoded bytes); raster decode/draw O(pixels). A 3,000-token malformed input rejected in 1.1–2.7 ms; invalid PNG bytes rejected in 3.5–5.1 ms (Chromium 148). Resize measured 85–130 ms at 1280×800/DPR2 and 380–520 ms at 3840×2160/DPR2..
- Takeover friction log; baseline and scoped-test verification.
- Models/harnesses: GPT-6.1 Sol via Codex and Claude Opus 5.5 through T3 delegation. Integrated evidence transport used a fresh GPT-6 Astra/Codex provider turn; original author credited above.
Checks
Added 5 commits
- chore(server): remove outdated scaled capture comment097dc0d
- Merge remote-tracking branch 'origin/main' into takeover/pr-20924b7fddd8
- test(server): takeover tests for #20924 backdrop-filter snapshotscc41db2
- fix(server): snapshots of XML documents shrink their screenshot againf8587a5
- fix(server): snapshots of backdrop-filter pages show the page as renderedfbed625
Approvability
Verdict: Approved at b7fddd8
Macroscope's review found this PR approvable — This is a focused server preview fix that captures full-resolution PNGs and downsamples them in-page to avoid Chromium's backdrop-filter mirroring, with regression coverage for blurred, plain, and XML pages. Recording and live still JPEG paths retain full-scale behavior, with no schema, dependency, or configuration changes.
You can add or adjust custom eligibility rules. Learn more.
Thread transfer impact
✅ Thread transfer remains within every enforced ceiling.
| Provider | Metric | Main baseline | This PR | Impact | PR ceiling | |
|---|---|---|---|---|---|---|
| Codex | Total thread wire | 5.0 KiB | 5.0 KiB | −7 B (−0.1%) | 6.8 KiB | ✅ |
| Codex | Thread snapshot wire | 3.8 KiB | 3.8 KiB | 0 B (0.0%) | 4.9 KiB | ✅ |
| Codex | Live turn WebSocket wire | 1.2 KiB | 1.2 KiB | −7 B (−0.6%) | 2.0 KiB | ✅ |
| Codex | Live turn WebSocket decoded | 20.9 KiB | 20.9 KiB | 0 B (0.0%) | 29.3 KiB | ✅ |
| Codex | Live turn messages | 2 | 2 | 0 (0.0%) | 8 | ✅ |
| Claude | Total thread wire | 5.0 KiB | 5.0 KiB | +7 B (+0.1%) | 6.8 KiB | ✅ |
| Claude | Thread snapshot wire | 3.8 KiB | 3.8 KiB | 0 B (0.0%) | 4.9 KiB | ✅ |
| Claude | Live turn WebSocket wire | 1.2 KiB | 1.2 KiB | +7 B (+0.6%) | 2.0 KiB | ✅ |
| Claude | Live turn WebSocket decoded | 21.2 KiB | 21.2 KiB | 0 B (0.0%) | 29.3 KiB | ✅ |
| Claude | Live turn messages | 2 | 2 | 0 (0.0%) | 8 | ✅ |
Baseline: 97548db · PR result: b7fddd8 · Source CI: success
Scenario and decoded snapshot size
10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
- Codex decoded thread snapshot: 108.5 KiB
- Claude decoded thread snapshot: 108.8 KiB
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.
No actionable comments were generated in the recent review.
External image Recent review info
External image Run configuration
- Source mode: Auto
- Repository: pingdotgg/t3code
- Branch: takeover/pr-20924
- File: .coderabbit.config.ts
- Commit: b7fddd8
- Layers: Repository TS config
- Review profile: CHILL
- Plan: Team
- Run ID:
2498d8c6-d26f-4f97-ab43-118e38a9cadb
External image Commits
Reviewing files that changed from the base of the PR and between 97548db62dd68a1859dd15fabb957e3ae746f65f and b7fddd87a69bb9f868bfd54928aaf4ae881c9432.
External image Files selected for processing: 4
apps/server/src/preview/ServerBrowser.test.tsapps/server/src/preview/ServerBrowser.tsapps/server/src/preview/ServerBrowserPage.test.tsapps/server/src/preview/ServerBrowserPage.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 1 remain after this review.
Walkthrough
Viewport screenshots now capture the full viewport before resizing the PNG when needed. Recording and viewer still-frame capture use the simplified capture API. New tests cover blurred backdrops, plain pages, and XML documents.
Changes: Screenshot capture
Layer / File(s) Summary Full-viewport capture and PNG resizing
apps/server/src/preview/ServerBrowserPage.ts,apps/server/src/preview/ServerBrowserPage.test.tsCapture no longer uses scaled clips or page offsets. When the calculated scale is below one, the captured PNG is resized in an isolated world. Tests check image dimensions and sampled colors. Recording and viewer capture callers
apps/server/src/preview/ServerBrowser.ts,apps/server/src/preview/ServerBrowser.test.tsRecording initialization and viewer still-frame capture use the simplified capture API. The test session mock handles the Runtime.callFunctionOnresponse.Priority: External image Normal
Estimated code review effort: 3 (Moderate) | ~20 minutes
Change: Bug fix · Severity of issue fixed: Medium
Possibly related PRs
- pingdotgg/t3code#24523: Adds locking and deadlines to preview capture paths that call
ServerBrowserPage.captureViewport.
Suggested labels:
bugfix,size:MSuggested reviewers:
scottn-pv- pingdotgg/t3code#24523: Adds locking and deadlines to preview capture paths that call
Merge Risk: External image Minimal · up to b7fdd
No actionable merge-blocking issue is established for the snapshot change; merge after normal checks.
Pre-merge checks: Passed 3 · Failed 1
Failed Failed checks: 1 warning
Check name Status Explanation Resolution Description check Warning The description provides detailed problem context, implementation changes, evidence, verification results, limitations, and agent attribution. However, it omits the required Problem, Change, Scope and… Restructure the description using all required template headings. Under Scope and approval, link the triaged issue or approved discussion and include the specific maintainer approval comment, or explain why this focused fix qualifies for an… Passed Passed checks: 3 passed
Check name Status Explanation Title check Passed The title clearly and concisely identifies the main change: preserving blurred backdrops in server preview snapshots. Linked Issues check Passed Issue #20899requires correctpreview_snapshotrendering for blurred backdrops at desktop width inapps/server. The reviewed change captures the full viewport without a scaled clip, then resizes o…Out of Scope Changes check Passed The changed files remain in the server preview capture path and its tests. The ServerBrowsercall-site updates adapt recording and viewer capture to the new capture API. These changes support the ca…Full details: Linked Issues check
Explanation
Issue
#20899requires correctpreview_snapshotrendering for blurred backdrops at desktop width inapps/server. The reviewed change captures the full viewport without a scaled clip, then resizes oversized PNG output in the tab isolated world. The added Chromium test covers a 1280×800backdrop-filterpage and verifies blue-left/red-right pixels instead of mirrored content. The added plain-page and XML tests cover the related resize paths. The PR evidence reports the required desktop fixture matrix and passing final tests.
Full details: Out of Scope Changes check
Explanation
The changed files remain in the server preview capture path and its tests. The
ServerBrowsercall-site updates adapt recording and viewer capture to the new capture API. These changes support the capture implementation and do not establish unrelated behavior changes, dependencies, or wire changes.
Full details: Description check
Explanation
The description provides detailed problem context, implementation changes, evidence, verification results, limitations, and agent attribution. However, it omits the required Problem, Change, Scope and approval, and Verification headings. It also does not include explicit maintainer approval for the direction and scope; model review results do not satisfy that requirement.
Resolution
Restructure the description using all required template headings. Under Scope and approval, link the triaged issue or approved discussion and include the specific maintainer approval comment, or explain why this focused fix qualifies for an exemption. Keep the existing verification details under Verification and state any checks that were not run.
Finishing Touches
📝 Generate docstrings
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
- Commit to this branch
- Create a new PR
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Comment @coderabbitai help to get the list of available commands.
Thanks @juliusmarminge for carrying this over the line, and good catch on the XML canvas. If the squash commit can include this, it matches your other takeovers:
Co-authored-by: Aniket Dhakane 55570910+watashiwaaniket@users.noreply.github.com