Regenerate the site figures from a headless rig - #477
Merged
Merged
Conversation
Why: the three site figures are 1x masters from 2026-08-18, so every Retina visitor gets an upscale of 1x text, and 112 src/ commits have landed since -- including the lucide icon swap, so every icon in them is retired. The manual capture path cannot fix it: it needs a human clicking the window, and its resize target disagrees with its own aspect gate by construction. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Renders the real src/ components in headless Chrome at device scale factor 2 with the Tauri surface aliased to one shim, then composites the drop shadow and traffic lights -- the only pixels macOS contributes, since the app sets titleBarStyle Overlay and draws its own titlebar. Why: the shipped figures are 1x masters from 2026-08-18, so Retina visitors get an upscale of 1x text, and the manual path needed a human clicking a window. Geometry is 2x the shipped master exactly (2924x1950 window in a 3200x2224 canvas), so screenshots.mjs and Screenshot.astro need no change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Transcribes the approved 2026-08-18 composition as typed fixtures: the same seven refs, four fictional authors, selected commit and +2 -7 diff. Parents are resolved into a real DAG so the graph draws its lanes and the diff header reads e3677fd -> 335d8fe rather than (root), and short oids expand through a seeded PRNG so the detail pane shows a plausible sha instead of zero padding. Why typed against src/lib/types.ts: a backend shape change then breaks tsc instead of quietly rendering a figure of a product that no longer exists -- which is how the hand-built AppShowcase replica died. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Screenshot.astro probed for a <name>@2x.webp through import.meta.url, which at build time points at the BUILT chunk -- so it looked in dist/public/screenshots and has2x was always false. No figure has ever shipped a srcset. The bug was invisible because it landed beside a capture path that never produced a 2x master either: there was nothing for the probe to find, so nothing looked wrong. Resolve from process.cwd() instead, which is site/ for both astro dev and astro build. Also extracts the sharp loader both site scripts had copied: each looked only for lib/index.js, and sharp 0.35 moved its entry to dist/index.mjs, so `pnpm screenshots` failed with "No sharp found" on any machine resolving 0.35. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adds the commit scene and the afterMount hook it needs: the app always launches on History and the Unified/Split toggle is local React state, so this figure clicks through the way a user does rather than being seeded into place. Driving the real UI also keeps it honest -- a scene cannot show a state the app cannot reach. get_diff answers per path: a constant meant the figure captioned NOTES.md over the engine table. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The shipped figures were 1x masters from 2026-08-18. 112 src/ commits had landed since, so every icon in them belonged to the hand-drawn set that #425 replaced with lucide, the activity bar stopped short of the window edge (#426) and a tag pill wore a branch icon (#443). Now 3200x2224 masters with @2x variants, so a Retina visitor paints them 1:1 instead of upscaling 1x text. Composition, refs and authors are the approved ones, at the same 120% app zoom the originals were shot at -- measured, the Welcome card matches the old master to within 0.5%. Retires scripts/capture.mjs: it needed a human clicking a window, and it could not have worked anyway -- it sized the WINDOW to 1600x1112pt then checked the resulting PNG, which is window plus shadow, against that same ratio. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The three site figures were 1x masters from 2026-08-18, so both halves of "blurry and old" were real — and each turned out to have a separate, invisible cause.
Blurry
Two independent breaks, either of which was enough on its own:
screenshots.mjsonly emits a@2xvariant when the master is at least 2080px wide, so it correctly refused — every Retina visitor got the 1040px file painted into 2080 device pixels.Screenshot.astro's 2x probe could never have fired. It resolved../../public/screenshots/throughimport.meta.url, which at build time points at the built chunk, so it looked indist/public/screenshots/andhas2xwas always false. No figure has ever shipped asrcset. The bug was invisible because it landed beside a capture path that never produced a 2x master either — there was nothing for the probe to find, so nothing looked wrong.Old
112
src/commits had landed since those captures. Most consequentiallya73f5ef(#425) replaced the hand-drawn icon set with lucide, so every icon in all three figures belonged to a set the app no longer ships. Also visible:babc0f7(#426) runs the activity bar to the window's bottom edge,0530187(#443) gives a tag pill a tag icon,a666295(#444) stops a narrow pane eating the subject column.Why a rig rather than a re-capture
pnpm captureneeded a human on a Retina display to size a window and click it, which is why the figures went thirty days without a refresh. It also could not have worked: it sized the window to 1600x1112pt and then checked the resulting PNG — window plus drop shadow — against that same 1.4388 ratio, which its own aspect gate would reject.So
pnpm shootrenders the realsrc/components in headless Chrome at device scale factor 2 and composites the two things macOS actually contributes. The app setstitleBarStyle: "Overlay", so it draws its entire titlebar in HTML — only the drop shadow and three traffic lights are native.lib/tauri.tsfunnel through one privateinvoke, so a scene is acmd -> fixturemap. The fake throws on an unanswered command, sopnpm shoot <scene> --reportrenders the worklist instead of leaving you to guess; a scene is done atMISSING (0).src/lib/types.ts, so a backend shape change breakstscrather than quietly rendering a product that no longer exists — which is how the hand-builtAppShowcasereplica died. It already caught a missing requiredembeddedfield while I was writing them.screenshots.mjsandScreenshot.astroneeded no change.Not run in CI. Masters and encoded WebP stay committed, so
astro buildneeds no image pipeline and the deploy installs no Chrome — the arrangementpnpm ogalready uses.Also fixed along the way
screenshots.mjsandcapture.mjshad each copied a sharp loader that looked only forlib/index.js. sharp 0.35 moved its entry todist/index.mjs, sopnpm screenshotsfailed with "No sharp found" on any machine resolving 0.35 — which reads like a missing install rather than a moved file. Extracted to onescripts/sharp.mjsthat tries both.scripts/capture.mjsis removed: leaving a broken manual path beside a working automated one invites someone to use it.Verification
pnpm test— 405 files, 4157 tests, green (re-run after the last edit)pnpm tsc --noEmitandtsc -p site/scripts/shoot/tsconfig.json --noEmit— cleanpnpm buildinsite/— green, and the built HTML now carriessrcset="/screenshots/history-dark.webp 1040w, /screenshots/history-dark@2x.webp 2080w"on all three figures, which is the end-to-end proof a Retina visitor is served the 2x assetpnpm screenshotsemits six files with no "is 1x" warningpnpm shootruns produce byte-identical mastersSpec:
docs/superpowers/specs/2026-09-17-screenshot-rig-design.mdPlan:
docs/superpowers/plans/2026-09-17-screenshot-rig.md🤖 Generated with Claude Code