Skip to content

Ask the reader to star the repo, in the nav and the footer - #87

Merged
david-sling merged 1 commit into
mainfrom
star-the-repo
Sep 21, 2026
Merged

david-sling merged 1 commit into
mainfrom
star-the-repo

Conversation

@david-sling

Copy link
Copy Markdown
Owner

The landing page linked to the repository twice and asked for nothing either time. Self-host in the nav and GitHub in the footer's Project column both led to the same URL, so each becomes the star chip rather than gaining a third link beside it.

What changed

Before After
Nav Self-host text link chip: GitHub mark + Star + count
Footer GitHub list item in Project chip: GitHub mark + Star on GitHub + count, closing the open-source block
  • lib/github.ts — repoUrl, starCount(), formatStars().
  • app/components/star-button.tsx — an async server component. No client JS.

Why a chip and not a button

DESIGN.md's ink pill rule: the only primary action on any surface is Create a channel. An open-source project asking to be starred must not compete with the thing the reader came to do, so this uses the existing .chip token — 39px against the pill's 40px, so it reads a step lighter. The nav takes the short label since the mark carries the destination; the footer has the room to spell it out.

The count

Shown whatever it is, nought included. null from starCount means GitHub did not answer — not the same as zero — and renders as no number rather than as one.

Nothing depends on the count, so every failure path returns null: a marketing number must not fail a build because GitHub was slow or had spent this IP's anonymous requests. A 2.5s abort covers the first, an hour of caching the second, which leaves /, /uses/[slug] and the 404 statically prerendered with hourly ISR. It is wrapped in React's cache rather than left to fetch's own memoisation, because the abort signal opts the request out of that and both nav and footer ask within one render.

Notes for review

  • Where GitHub's mark lives. Not icons.tsx, which declares itself an authored set on one stroke weight and one grid, and not lib/client-marks.ts, which is keyed by the agent clients that can join a channel. It sits beside its only consumer in star-button.tsx, carrying the same provenance and trademark note client-marks.ts uses (Simple Icons, CC0 1.0, drawn whole and unaltered, never larger than Wave's own mark).
  • Accessibility. The link's aria-label reads Star Wave on GitHub, 2 stars in both places; the visible label and count are aria-hidden so nothing is announced twice. This is what lets the nav get away with the one-word label.
  • formatStars rounds to tenths before branching, because (9950/1000).toFixed(1) is "9.9" in binary float.
  • The repo URL is still hardcoded in app/components/faq.tsx:6 and lib/site.ts:59. Out of scope here; worth a follow-up to point both at repoUrl.

Verification

  • 531 unit tests pass (8 new), npm run typecheck and npm run lint clean.
  • Nav at the 768px md boundary: 61px gap to the links, no overflow. Mobile: nav chip hides with the links, footer chip stays, no horizontal overflow.
  • Both chips measured against the .chip spec — pill radius, hairline at 6% ink, soft shadow, 13.5px.
  • All three surfaces carrying this chrome render both chips with no page errors.

Not run: next build, since a dev server held .next throughout. The ISR path is standard and every failure is caught, but worth a build before merge.

🤖 Generated with Claude Code

The landing page linked to the repository twice and asked for nothing
either time: `Self-host` in the nav and `GitHub` in the footer's Project
column both led to the same place. Each is now the star chip instead, so
the two places that already pointed at the repo do the asking.

A chip rather than a button, because the ink pill is the only primary
action on any surface and an open-source project asking to be starred
must not compete with the channel the reader came to create. The nav
takes the short label, since the mark carries the destination; the
footer has the room to spell it out, and closes the block that says the
project is open source.

The count is shown whatever it is, nought included. `null` from
`starCount` means GitHub did not answer, which is not the same as zero
and renders as no number rather than as one.

Nothing depends on the count, so every failure path returns null: a
marketing number must not fail a build because GitHub was slow or had
spent this IP's anonymous requests. The request carries a 2.5s abort for
the first and is cached for an hour against the second, which leaves the
pages statically prerendered with hourly ISR. It is wrapped in React's
`cache` rather than left to fetch's own memoisation, because the abort
signal opts it out of that and both the nav and the footer ask within
one render.

GitHub's mark sits beside its only consumer rather than in `icons.tsx`,
an authored set on one stroke weight and one grid, or in
`client-marks.ts`, which is keyed by the agent clients that can join a
channel. It is neither, and both files are worse for holding it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
wave Ready Ready Preview Sep 21, 2026 6:10pm UTC

@david-sling
david-sling merged commit 965d9b2 into main Sep 21, 2026
4 checks passed
@david-sling
david-sling deleted the star-the-repo branch September 21, 2026 18:12

This branch was successfully deployed

1 active deployment
Preview — 8f118825 Deployed Sep 21, 2026 by vercel[bot]
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.

1 participant