feat(web): version in the footer, who it is not for, and screenshots re-shot at 61% less - #336
Merged
Conversation
…at 57% less
Four items from the site review, and one measurement that contradicts the review
it came from.
VERSION AND CHANGELOG IN THE FOOTER. Two reviews flagged this independently from
different briefs -- one as a trust signal, one as project-continuity risk. For
software a visitor has to install and run, "is this maintained" is the question
that stops the download, and the site answered it nowhere while v0.6.0 sat in
the releases.
Read from `git describe` at build time rather than typed. A hand-written version
is a claim that goes stale silently, and a stale one is worse than none: it says
"last touched at 0.4" about a project on 0.6. If the tag cannot be resolved --
shallow clone, tarball, no tags -- the line is omitted rather than guessed, and
the build still succeeds.
"IS THIS FOR YOU?" WITH A NOT-FOR COLUMN. The second column is the point. The
site never stated its own limits, and a product that cannot say who it is wrong
for reads as marketing. It names the hosted-tier gap, the missing browser studio
and guest invites, the absence of an SLA, and says outright that a
one-platform-one-mix streamer needs none of this. Placed before the call to
action, so a reader who recognises themselves leaves rather than installing and
concluding the software is bad at something it never claimed.
FOOTER COLUMN LABELS ARE NO LONGER <h2>. "Product", "Docs", "Project" are
four-word labels, and as headings they landed in every page's outline between
the real content headings.
og:image:width/height/alt and twitter:image:alt. A scraper that has not fetched
the image yet uses the dimensions to reserve space. The numbers state what the
file IS -- 2560x1280, which is 2:1 against the documented 1.91:1 -- rather than
what we wish it were; reshooting it is a separate change.
SCREENSHOTS: 1957K -> 856K, 56.6%, AND THE RESOLUTION IS UNCHANGED.
The performance review recommended 256 colours at 1440px wide, measured at
73.5%. Two things made that wrong here, both measured rather than assumed:
- The lightbox landed after that review. Inline the shots render at 635 CSS px,
so 1440 is ample; expanded they reach 1152 CSS px, which at dpr 2 wants 2304.
Downscaling to 1440 would have blurred the view the lightbox exists to give.
- Resizing makes the compression WORSE. 256 colours at native 2880 saves 57.1%;
at 2304 only 42.6%, and 02-routing.png grew 19%. Interpolated colours from
the resample defeat both the palette and PNG's filters, where a native
screenshot's flat regions quantise almost perfectly.
So: quantise, do not resize. Quality checked rather than assumed -- RMSE 0.19% to
0.52% of range, and a 700x150 crop of the smallest text in the densest shot is
indistinguishable between the two.
…antise in the capture script The shipped screenshots were taken on 2026-08-06. Eighteen UI commits have landed since, four of which -- AppLayout.tsx, index.css, StatusDot.tsx, UpdateBanner.tsx -- appear in EVERY captured view. All seven site shots differ from their re-captures, so the site was showing a week-old product. What the routing shot gains is the clearest case: it now carries the platform-defaults row, Kick among them, and the music-rights control. Neither existed when the old one was taken, and both are things a visitor evaluating this against a hosted service would look for. QUANTISATION MOVED INTO capture-media.sh. It was going to be a hand-run step after each capture, which is a step that gets skipped once and then every later capture is silently twice the size it needs to be. The script writes the committed artefacts, so the script is where the compression belongs. docs/media 4013K -> 1587K (60%, 17 shots) web/public 1819K -> 707K (61%, the 7 on the site) Resolution is untouched at 2880x1800 and RMSE lands between 0.06% and 0.15% of range -- lower than the 0.19%-0.52% the previous shots quantised to, because a fresh capture has cleaner flat regions than one that has been through a generation of processing. Deliberately NOT resized, which is the counterintuitive half. Downscaling makes PNG compression WORSE on this material: resampling invents intermediate colours along every edge, defeating both the palette and the row filters. At 2304px the same quantisation saved only 42.6%, and 02-routing.png came out 19% LARGER than its full-resolution self. The site's lightbox expands these to 1152 CSS px, so at dpr 2 it wants 2304 regardless -- there is no width to give back even if it did help. Pillow's absence skips the step with a note rather than failing the run. This executes on laptops, and a missing optional dependency should cost bytes, not the whole capture.
There was a problem hiding this comment.
Pull request overview
Updates the marketing site and media-capture workflow to improve trust signals (maintenance/version), user expectation-setting, social sharing metadata correctness, and screenshot artifact size.
Changes:
- Adds an “Is this for you?” section with explicit “Not built for” guidance before the CTA.
- Improves social preview metadata by adding OG image dimensions + alt text and Twitter image alt text.
- Adds build-time version/changelog links in the footer and integrates PNG quantization into
capture-media.sh.
Reviewed changes
Copilot reviewed 4 out of 30 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| web/src/pages/index.astro | Adds “Built for / Not built for” section before the CTA to set expectations. |
| web/src/layouts/Base.astro | Adds OG image width/height/alt and Twitter image alt metadata. |
| web/src/components/Footer.astro | Adds build-time git-tag version + changelog links; changes footer column labels from headings to paragraphs. |
| scripts/capture-media.sh | Adds optional Pillow-based PNG quantization step to reduce screenshot sizes. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| f"({100 - 100 * after / before:.0f}% smaller, resolution unchanged)") | ||
| PY | ||
| else | ||
| echo " skipped: python3 with Pillow not found, shots left unquantised" |
Comment on lines
+253
to
+256
| was = os.path.getsize(path) | ||
| im = Image.open(path).convert("RGB") | ||
| im.quantize(colors=256, method=Image.MEDIANCUT, | ||
| dither=Image.FLOYDSTEINBERG).save(path, optimize=True) |
…ison label scrolled away from its answers Two layout defects found by measuring the live site at a 375px viewport, both confirmed before being fixed and both invisible on a desktop. THE DOCUMENT WAS WIDER THAN THE SCREEN. /download scrolled to 630px and /comparison to 570px against a 375px viewport -- the whole page moving sideways, not an element scrolling inside its own box. The cause is the grid `min-width: auto` default. A grid child will not shrink below the intrinsic minimum width of its contents, and several cards hold a <pre> with a long unbreakable command line, so that minimum is far wider than a phone. The card could not shrink, so it pushed the document out with it. The <pre> elements already carried `overflow-x: auto` and it was doing nothing, because the overflow it existed to absorb was being handed upward to the page instead. `min-width: 0` on .card lets the card shrink so the scroll container that was always there is the one that takes it. After: 375px on both, with the <code> still reaching 588px INSIDE its own scroller, which is the intent. THE COMPARISON TABLES LOST THEIR ROW LABELS. These tables are 46rem wide by necessity -- four columns of prose -- so on a phone they scroll horizontally. That part is fine. What was not fine is that swiping far enough to read the restream.io column took the Capability cell off the left edge with it, leaving a grid of bare Yes and No against nothing. The answer becomes unreadable exactly when the reader has scrolled far enough to care about it. The first column is now pinned. Its opaque background is load-bearing rather than decorative: without one the scrolling cells slide visibly underneath the label. AND THE FIRST ATTEMPT AT THAT WAS WRONG IN A WAY WORTH RECORDING. It used `var(--color-bg)`, which this theme does not define -- the page paints --color-ink. The declaration resolved to transparent, and the measurement said `position: sticky` and `stayedPinned: true` while the background read `rgba(0, 0, 0, 0)`. Every property that describes the mechanism was correct and the thing it exists to do was broken. Caught by checking the computed background rather than only the pinning. GUARDED IN check-build.mjs, with an honest scope. A static check cannot prove no page overflows -- that needs a browser and a real layout. It proves the three declarations that made the overflow go away are still present, which is how this regresses, because all three read as inert. The third specifically catches --color-bg reappearing. Each guard was mutation-tested: min-width removed, sticky changed to static, and --color-ink changed back to --color-bg. Each fired its own named check and no other.
… move to Workers The nav already had the machinery -- aria-current on the active link, text-fg against text-muted -- and it had been dead since the site moved to Cloudflare Workers. That build emits FLAT FILES, so Astro.url.pathname is "/features.html" while the link href is "/features". The comparison was false everywhere, on every page, so nothing was ever marked: no aria-current for a screen reader, and the link for the page you were already standing on painted the same muted grey as the four you were not. WHY IT SURVIVED A REVIEW OF THE LIVE SITE. A nav where nothing is highlighted does not look broken. It looks like a design decision. The review that found it reported the symptom correctly -- "active links render in identical rgb(155, 169, 186)" -- and prescribed adding aria-current, which was already there. The mechanism was present and the input to it was wrong. Normalising the path fixes both navs. Both suffixes are stripped so this holds whichever way the output format is configured later, and "" collapses back to "/" for the home page, which correctly marks nothing -- the home link is the logo and is not among the four. THE MOBILE MENU WAS A SEPARATE HALF. It never called the active() helper at all, so the first fix left the desktop nav correct and the phone menu still blank -- and the phone menu is the ONLY navigation a phone has, which makes it the half that mattered more. Caught by counting the marked anchors per page rather than by looking at the desktop rendering and calling it done. Guarded in check-build.mjs by asserting each nav page marks its own link TWICE. Two rather than one is the point: one would have passed the half-fix. Mutation-tested both ways. Un-normalising the path reproduces the Workers regression exactly and reports 0 of 2; removing only the mobile aria-current reports 1 of 2. Each fired its own named check.
…ces measuring contradicted them
Four reviewers with deliberately different briefs -- information architecture,
copy, layout, and a comparable-product pattern survey -- then every finding
re-measured directly before being written down.
The re-measuring is the reason this document is worth keeping. Three findings
did not survive it, and those three are the most useful entries:
- "Active nav links render identical to inactive" was a real symptom with the
wrong cause. aria-current and text-fg were already present; the flat-file
build made the path comparison false, so the prescribed fix would have
changed nothing.
- "Downscale the screenshots to 1440px for a 73.5% saving" is backwards on
this material. Resizing makes PNG compression WORSE -- 42.6% at 2304px, with
one shot coming out 19% larger than full resolution.
- My own first sticky-column fix used a token this theme does not define. It
resolved to transparent while every property describing the mechanism read
as correct.
Also records what is already RIGHT, measured rather than assumed: one 1280px
grid at x=80 on every page, one type scale, screenshots at a consistent 688x430
and 1.60:1, and a docs split that folds cleanly to one column. A future redesign
should have to argue with numbers to change any of it.
The gaps are stated rather than papered over: one reviewer did not return in
time and one was refused for quota.
|
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 S/M-effort items from the site review, plus a re-shoot that the image work turned up as necessary.
Trust and honesty
git describeat build time — a hand-typed version goes stale silently, and a stale one is worse than none. Omitted entirely if the tag can't be resolved.Correctness
<h2>→<p>— four-word labels were landing in every page's heading outline.og:image:width/height/alt+twitter:image:alt. The numbers state what the file is (2560×1280, 2:1 against the documented 1.91:1) rather than what we wish it were.Screenshots: re-shot, then 61% smaller at unchanged resolution
The shipped shots were from 2026-08-06, with 18 UI commits since — four of them in files that appear in every view. All seven differed. The routing shot now carries the platform-defaults row (Kick included) and music rights, neither of which existed a week ago.
docs/media(17)web/public/shots(7)Resolution untouched at 2880×1800; RMSE 0.06–0.15% of range.
Not resized, which is the counterintuitive half. Downscaling makes PNG compression worse here — resampling invents intermediate colours along every edge, defeating both the palette and the row filters. At 2304px the same quantisation saved only 42.6%, and
02-routing.pngcame out 19% larger than its full-resolution self. The lightbox expands these to 1152 CSS px, so at dpr 2 it wants 2304 anyway.Quantisation now lives in
capture-media.shrather than as a hand-run step — the script writes the committed artefacts, so a step done by hand gets skipped once and every later capture is silently double-sized.