Skip to content

feat(web): version in the footer, who it is not for, and screenshots re-shot at 61% less - #336

Merged
rainmanjam merged 5 commits into
mainfrom
feat/site-review-items
Aug 14, 2026
Merged

feat(web): version in the footer, who it is not for, and screenshots re-shot at 61% less#336
rainmanjam merged 5 commits into
mainfrom
feat/site-review-items

Conversation

@rainmanjam

Copy link
Copy Markdown
Owner

The S/M-effort items from the site review, plus a re-shoot that the image work turned up as necessary.

Trust and honesty

  • Version + changelog in the footer. Two reviews flagged this independently. For software you have to install, "is this maintained" is the question that stops the download, and the site answered it nowhere. Read from git describe at 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.
  • "Is this for you?" with a not-for column. The second column is the point: the hosted-tier gap, no browser studio, no guest invites, no SLA, and one-platform streamers told outright they need none of this. Placed before the CTA so a reader who recognises themselves leaves rather than installing and blaming the software.

Correctness

  • Footer column labels <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.

before after
docs/media (17) 4013K 1587K 60%
web/public/shots (7) 1819K 707K 61%

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.png came 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.sh rather 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.

…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.
Copilot AI lite review requested due to automatic review settings August 14, 2026 04:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread scripts/capture-media.sh
f"({100 - 100 * after / before:.0f}% smaller, resolution unchanged)")
PY
else
echo " skipped: python3 with Pillow not found, shots left unquantised"
Comment thread scripts/capture-media.sh
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.
@sonarqubecloud

Copy link
Copy Markdown

@rainmanjam
rainmanjam merged commit 5febc1a into main Aug 14, 2026
28 checks passed
@rainmanjam
rainmanjam deleted the feat/site-review-items branch August 14, 2026 05:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants