fix: track page never leaves og:image empty (#1257)
cameron's bsky post of plyr.fm/track/859 (a /record voice memo with
no artwork) rendered with a tangled.sh sheep mascot as the preview
thumbnail. root cause is entirely on our side — definitive chain
of events traced via:
curl -sL https://plyr.fm/track/859 -H "User-Agent: facebookexternalhit/1.1"
when track.image_url is null, our <svelte:head> block wraps og:image
in `{#if track.image_url && !moderation.isSensitive(...)}` and emits
nothing. bsky's card extractor (cardyb.bsky.app) then falls back to
its "first <img> in the HTML" heuristic. the ONLY <img> tag in our
ssr'd track page is the Header's "view source on tangled" social
icon, which points at tangled.sh's bsky avatar CID:
cdn.bsky.app/img/avatar/plain/did:plc:wshs7t2adsemcrrd4snkeqli/
bafkreif6z53z4ukqmdgwstspwh5asmhxheblcd2adisoccl4fflozc3kva@jpeg
that avatar is a 1000x1000 jpeg of the tangled dolly mascot. pixel-
identical to the thumb blob on cameron's post record after bsky's
client re-encoded it to a 38kb webp and uploaded it to his pds.
cardyb currently returns image: "" for the url because the extractor
cache has already expired, but at the moment cameron posted it grabbed
that tangled img tag.
this means EVERY track without artwork shared to bsky today is
rendering as the tangled sheep. it's not a one-off weirdness on
cameron's end — it's a systemic bug we've been shipping.
fix: cascade to pick the best-available preview image, always emit
og:image + twitter:image unconditionally. order:
1. track.image_url (if not sensitive) — per-track art, the primary
2. track.album.image_url (if not sensitive) — album cover if linked
3. track.artist_avatar_url (if not sensitive) — artist's bsky avatar
4. ${APP_CANONICAL_URL}/icons/icon-512.png — stable static brand
logo (served from frontend/static/icons, already referenced by
the web manifest, 200 OK + image/png + CORS *)
the og:image:width/height hint stays gated to "is real track art"
(tracks are standardized 1200x1200, but fallback dimensions vary,
and advertising wrong dimensions is worse than omitting them).
og:image:alt now emits unconditionally.
the existing cameron post has an immutable embed thumb already
committed to his pds — only he can delete and repost to refresh it.
all future shares will have proper previews once this ships.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
authored by