Skip to content

Add rich link preview cards and put counter names in shared messages - #17

Merged
spxrogers merged 1 commit into
mainfrom
claude/rich-text-counter-names-570jdp
Aug 23, 2026
Merged

Add rich link preview cards and put counter names in shared messages#17
spxrogers merged 1 commit into
mainfrom
claude/rich-text-counter-names-570jdp

Conversation

@spxrogers

Copy link
Copy Markdown
Owner

Pasted clockdown links previewed as a bare title with no image — iMessage was falling back to <title> because the pages had no Open Graph metadata at all.

What changed

OG + Twitter card metadata on all four pages (/, /timer, /stopwatch, /motivation), each pointing at its own generated 1200×630 share card. Links now unfurl as a full-width image card instead of a text-only bubble.

The counter's name now reaches the recipient. The Share button previously sent navigator.share({ title, url }), and iOS Messages ignores title. It now passes the name as text, so the message reads:

🎉 New Year's Eve — counting down on Clockdown
⟦ preview card ⟧

Clipboard "Copy Link" is unchanged — it still copies a bare URL, since that gets pasted into address bars.

tools/og/ — a dependency-free generator for the cards (headless Chromium + a small PNG cropper). Excluded from the deployed site via both workflows. Space Grotesk is fetched and cached at build time rather than vendored, so no font binaries land in the repo.

Why the name isn't in the card itself

It can't be, on static hosting. Every counter's data lives in the URL's #hash, which browsers never send to a server, and link unfurlers don't run JavaScript. There is no point in the request where a per-counter title could be rendered.

Putting it there would mean moving the data into the path or query string and serving the HTML from an edge function (Vercel/Netlify/Cloudflare) — which would also start putting counter names in server logs, where they never appear today. That tradeoff is written up in tools/og/README.md so the reasoning isn't lost.

Notes for review

Two headless Chromium quirks are worked around and documented:

  • --window-size includes window chrome, so the viewport lands ~87px short and the bottom of the card never composited. The script measures that inset, renders oversized, and crops back.
  • Chromium dithers the background gradient, and that noise dominates file size. The PNG spec's filter heuristic picks badly for it — Sub wins at 442KB vs the heuristic's 541KB. Browsers never fetch these images; only unfurlers do, once, and they cache.

Testing

  • All four pages plus hash-routed countdown/timer/stopwatch URLs load with no JS errors (headless Chromium console check).
  • Share payload verified on all three tools by stubbing navigator.share and clicking the real button: 🎉 New Year's Eve — counting down on Clockdown, 🍝 Pasta Timer — timer running on Clockdown, 💪 Plank Challenge — stopwatch running on Clockdown.
  • Generated PNGs verified 1200×630 and decoded independently to confirm the crop and re-encode round-trip.

The preview deploy on this PR won't reflect the real cards — og:image URLs are absolute to clockdown.us, so they'll resolve to production until this merges.


Generated by Claude Code

Pasted clockdown links previewed as a bare title with no image. Add Open
Graph and Twitter card metadata to all four pages, backed by generated
1200x630 share cards that mirror the live countdown's look.

The counter's own name cannot go in the preview card: every counter's data
lives in the URL's #hash, which browsers never send to a server, and link
unfurlers don't run JavaScript. On static hosting there is no point at which
a per-counter title could be rendered. Doing that would mean moving the data
into the path or query string and serving the HTML from an edge function --
which would also start putting counter names in server logs.

So the name goes where it can go: the Share button now passes it as
navigator.share({ text }), so it appears in the message body directly above
the preview card.

Also add tools/og/, a dependency-free generator for the cards (headless
Chromium plus a small PNG cropper), excluded from the deployed site.
@github-actions

Copy link
Copy Markdown
Contributor

🔗 Preview deployed: https://clockdown.us/pr/17/

github-actions Bot added a commit that referenced this pull request Aug 23, 2026
@spxrogers
spxrogers merged commit ddea1a9 into main Aug 23, 2026
2 checks passed
@spxrogers
spxrogers deleted the claude/rich-text-counter-names-570jdp branch August 23, 2026 19:01
github-actions Bot added a commit that referenced this pull request Aug 23, 2026
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