Repository navigation
feat(website): add a social preview card and the full preview meta set - #884
Conversation
🦋 Changeset detectedLatest commit: 8705c7a The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
🧹 Site preview for this PR was deleted (PR closed). |
The site shipped an og:image pointing at hero-poster.webp — a 16:9 still of the film, which crops badly in a preview card and names the project only in passing. scripts/build-social-card.mjs now renders one composition at both sizes the two services want: public/media/social-card.png 1200x630 og:image public/media/github-social-preview.png 1280x640 repository social preview Committed rather than built in CI: astro build never runs `pnpm run media`, so a generated-not-committed file would not be in dist/ either, and the og:image URL would 404 in the deploy. `pnpm run social` regenerates them. Text is drawn as SVG over the woff2 files from @fontsource-variable/inter and @fontsource/jetbrains-mono — the same packages global.css imports — so a CI runner without Inter installed cannot silently swap the face. The backdrop is the page's own planet at public/media/planet.webp plus the 28px dot grid from global.css; the hero's spark stream is left out, since a still frame holds every particle at once and the density reads as noise under the copy. Base.astro emits the rest of the preview set: og:site_name, og:locale, og:image:width/height/type, og:image:alt, twitter:image, twitter:image:alt, twitter:title and twitter:description, and takes an ogImage prop that defaults to the card. The size hints are emitted only for that card, so a caller passing a different image gets no wrong crop. hero-poster.webp stays the film's poster. The 1280x640 file is uploaded by hand — Settings -> Social preview in the repository, which no workflow can set.
b70a47b to
5622a5d
Compare
The card's planet sat at left: W-470, so its disc reached x≈766 while the copy runs to x=1196 — the rim and its dust sat behind the ownership line and both licence rows. Measured on the regenerated 1200x630 card, the backdrop under the licence text drops to 6.3% non-black. The planet now sits at left: W-330, top: H-300, fully in the bottom-right corner on both sizes. The licence line reads "MIT license", Cameri's wording, instead of "MIT licensed".
|
Planet, licence wording and the hero stream, from Cameri's review of the preview card (a118073). Planet off the copy. The card's planet sat at Licence wording. "nostream" stays. The wordmark beside the mark is present at the top left, and the mark itself sits to its left. (Cameri noted the name had gone from the art in an earlier version; this branch keeps both.) Fonts. The card draws with the site's own woff2 files from Hero stream removed. The left-to-right particle stream under the homepage headline is deleted ( Site URL. Landing film. Verified: |
[Medium impact] The PR appears safe to merge, with a non-blocking mismatch between the updated hero poster and unchanged videos. Findings
|
… draw at each size Three findings from review, all reproduced. 1. The custom faces were never used. This sharp build's librsvg ignores a font-family the moment a fallback list follows it -- 'Card Sans, sans-serif' renders in the fallback, 'Card Sans' alone uses the @font-face -- and no installed family was named 'Card Sans', so text fell through to fontconfig's default, Liberation Mono. Measured as pixel mass on the headline: 22,352 for the fallback vs 18,486 for the declared face. The families are now named with no fallback ('Card', 'CardMono') and the italic face is declared rather than synthesised. 2. The planet gradient faded nothing. Both stops were fully opaque and dest-in composites by alpha, so the planet kept a hard edge. The outer stop is now stop-opacity="0". 3. social-card.png was a 1280x640 drawing resized with fit:'fill', stretching the letterforms ~4.7% vertically relative to their width. Both cards are now drawn at their own size: the text layer keeps its 1280x640 coordinates and scales uniformly into the smaller canvas, so nothing stretches. Both PNGs regenerated; headers still 1200x630 and 1280x640.
| ['A social network', FG], | ||
| ['nobody can', PINK], | ||
| ['switch off.', PINK], |
There was a problem hiding this comment.
The new copy in film.ts will not reach the deployed video. This PR updates hero-poster.webp, but leaves the tracked hero.mp4 and hero-low.mp4 unchanged. Deployment runs astro build, which does not render the film, so visitors see the updated poster followed by the old copy and layout. Regenerate and commit both videos to match the poster and film source.
Closes #876 ### What changed `website/site/public/media/hero-poster.webp` is encoded at **1440×810** instead of 1920×1080, and `scripts/build-media.mjs` resizes to 1440 so the next `pnpm run media` keeps the size instead of restoring 1920. 1440 covers the box the film actually paints in: `Hero.astro` caps it at `min(1180px, 80vw, film-h * 16/9)`, so at most 1180×664 CSS px — 1440 is **1.22×** that, enough for a 1.25× display, and no `devicePixelRatio` branch is needed. The 1359×764 in #876 was the layout before that cap landed in #899, two days after the audit; the issue's numbers describe a box the site no longer has. ### Before / after | | bytes | dimensions | |---|---|---| | before | 42,926 | 1920 × 1080 | | after | **30,878** | 1440 × 810 | **−12,048 B, −28.1%.** Both below the issue's ≤ 45 KB bound. Note the source file was already smaller than the 73,916 B the 2026-10-17 audit measured — it was re-encoded during the #858 rebrand — so the absolute saving is smaller than the audit's 36.9 KiB estimate, while the resolution waste it reported is removed. ### Visual check SSIM of the new file against the old one, both scaled with lanczos to the comparison size: | comparison size | SSIM | |---|---| | 1180 × 664 (the film's CSS cap today) | 0.9968 | | 1359 × 764 (the layout #876 measured) | 0.9964 | | 2718 × 1528 (2× device pixels) | 0.9932 | ### `og:image` was never this file The issue's second consumer no longer exists: `Base.astro` defaults `ogImage` to `/media/social-card.png`, generated at 1200×630 by `build-social-card.mjs` (#884). Nothing overrides it — `grep -rn "ogImage=" website/site/src` returns only the default and the prop declaration. So the "must stay 1920×1080" constraint does not apply, and no second 1920 file is kept. Built output confirms both: ``` dist/media/hero-poster.webp 30,878 B 1440,810 poster="/media/hero-poster.webp" property="og:image" content="https://nostream.dev/media/social-card.png" ``` ### Verification - `pnpm build` in `website/site` succeeds (prebuild's brand + hero-NIP checks included); the asset in `dist/media/` is the new one at 30,878 B. - CLS: the film keeps `aspect-ratio: 16/9` on the `<video>`, unchanged by this PR, so the poster's intrinsic size does not enter layout. ### Out of scope `admin-poster.webp` and `peering-poster.webp` are encoded by the same script at 1920 and have the same geometry mismatch. They are not measured by this issue's audit and are left alone; the fix is one `resize()` call each when someone measures them. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> <!-- coderabbit-ai-generated:v1 --> ## Summary by CodeRabbit * **Performance** * Reduced the landing page hero image width from 1920 to 1440 pixels, lowering the image’s download size while preserving visual quality. * Social preview imagery remains unchanged. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Closes #851, rel: #856.
The site's
og:imagewashero-poster.webp— a 16:9 still of the film. It crops badly in a preview card, carries no product name at card size, and says nothing a reader who has never heard of a relay can act on.What this adds
website/site/scripts/build-social-card.mjsrenders one composition at the two sizes the two services want:public/media/social-card.pngog:image(#851)public/media/github-social-preview.pngBoth are committed.
astro buildnever runspnpm run media, so a generated-but-not-committed file would not reachdist/either and theog:imageURL would 404 in the deploy.pnpm run social(also called at the end ofpnpm run media) regenerates them; a run leaves the tree clean.How the card is drawn
@fontsource-variable/interand@fontsource/jetbrains-mono— the same packagesglobal.cssimports. A CI runner has no Inter installed, and a system-font fallback would silently change the card. Copy: A social network nobody can switch off. / Own your posts, your followers and your reach, thenNostr and Marmot protocol support,MIT licensed,ema.tnsor.network.public/media/planet.webp, cropped to its disc before masking so the radial fade lands on the rim rather than in the asset's padding, plus the 28 px dot grid fromglobal.css.spark-field.tsand removed: a still frame holds every particle at once, so the density that reads as motion on the page reads as noise over the copy here. Regenerating it is not a lost capability so much as a decision —spark-field.tsremains the single source for the live effect.sharphas nopng().height()modifier and silently honoured a wrong height once.Base.astroAdds
og:site_name,og:locale,og:image:width/height/type,og:image:alt,twitter:title,twitter:description,twitter:imageandtwitter:image:alt, and anogImageprop defaulting to/media/social-card.png. The size hints are emitted only for that card, so a caller passing some other image gets no wrong crop.hero-poster.webpstays the film's poster.Verification
pnpm run buildinwebsite/site, then readdist/index.html:and parsed both PNG headers independently of sharp:
What this cannot do
The GitHub social preview has no API.
1280×640has to be uploaded by hand at Settings → Social preview; the changeset says so, and #856 stays open until it happens.