feat(website): add release OG image generator#1258
Conversation
Rsdoctor Bundle Diff AnalysisFound 12 projects in monorepo, 0 projects with changes. 📊 Quick Summary
Generated by Rsdoctor GitHub Action |
Deploying rstest with
|
| Latest commit: |
d4f6185
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://d307a904.rstest.pages.dev |
| Branch Preview URL: | https://feat-og-image-generator.rstest.pages.dev |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 84c20799b8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
8c7b7d0 to
a17b810
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a17b810aeb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Programmatic generator for per-release Open Graph images. Runs locally via
`pnpm gen:og --version <ver>` and writes a 2400x1260 (2x retina) PNG into
the design-resources repo.
Stack: satori (JSX/HTML -> SVG) + @resvg/resvg-js (SVG -> PNG) +
satori-html (template) + sharp 8-bit palette re-encoding (~500 KB ->
~140 KB with no visible loss on this design — TinyPNG-style libimagequant
quantization). Logo SVG is fetched from the assets.rspack.rs CDN at
generation time so logo updates flow through without re-committing the
template. Space Grotesk (SIL OFL) is committed under assets/fonts/.
Background is a brick pattern of pass / running / fail / skip status icons
(lucide circle-check / circle-x / loader / circle-dashed, color-matched to
@rstest/browser-ui's status palette). Grounds the og frame in the
test-runner identity rather than a generic gradient.
Layout: 7x12 grid with corner icons pinned to canvas corners (1/4 visible),
first/last row/col half-cropped at edges, odd rows offset by half a column
for brick stagger. Per-icon stroke-opacity jitter (0.06-0.26) gives a
hand-stippled feel; only the loader gets random rotation.
A radialGradient vignette is baked into the bg SVG so the v{version} hero
text reads cleanly through the wallpaper. The bg SVG is rasterized via
Resvg and embedded as <img src="data:..."> in the satori tree — satori's
`background: url(data:...)` shorthand parser doesn't accept SVG data URIs.
a17b810 to
8abdbe7
Compare
Remove `sharp` from the OG image pipeline and emit the raw resvg PNG directly. Users compress the file manually (TinyPNG / Squoosh / ImageOptim) before committing it to design-resources — the CLI now prints a tip with the TinyPNG URL on its own line so terminals make it trivially clickable. - Drop `sharp` devDep + workspace allowBuild entry - Remove libimagequant re-encoding from `render.mts` - Print compression tip + clickable URL in `cli.mts` - Update `website/AGENTS.md` to describe the manual compression step
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 86bc34ffc3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Roll back the status-icon brick-pattern background introduced in the squashed predecessor to the randomized radial-gradient version. The status-icon pattern was visually too busy; the gradient reads cleaner as a release card. Calibrate AGENTS.md size note: raw resvg output is ~300 KB for the gradient version (the previous ~500 KB / ~140 KB numbers were status-icon era). Keeps drop-sharp, cspell dictionary, and CLI TinyPNG hint changes intact.
Add a second background variant alongside the original multi-blob spread. The aurora variant builds the background from one oversize (85%-115%) saturated blob anchored to an outer quadrant, optionally paired with a smaller (45%-65%) off-hue halo in the diagonally opposite corner. Reads as "single dominant color family with a corner-anchored color leak" — the OpenAI / Stripe / Vercel hero gradient look. Why two extents on purpose: - Primary capped at 115% so the gradient retains directional structure (anything past ~120% reads as a flat color block). - Accent stays at 45%-65% so the color-leak stays localized to its corner instead of overlapping with the primary across the entire frame and muddying both into a uniform patch. randomBackground() picks aurora at 35% to keep the airy multi-blob feel the dominant look while sprinkling in stronger tonal frames. Anchor stays in QUAD_CENTERS (well off the central text column), so even on the strongest aurora the v-number and wordmark stay legible — checked against a 3x3 sample grid.
Drop the aurora background variant — it didn't add enough over the blob gradient to justify a second mode. Tighten the remaining blob gradient: - Cap blob aspect ratio at ~1.4:1. Independent w/h sampling could otherwise produce ~2.8:1 "long bar" shapes. - For elongated blobs (>1.15:1) push the short-axis center to the nearer canvas edge so one long edge clips off-canvas — otherwise both long edges sit inside the frame and the blob reads as a bar floating mid-image. Result is a soft wash spilling in from the edge. - Extract `edgeHugCenter(visibleSemi, anchor)` helper so the wide / tall mirror branches share one implementation.
Summary
Background
Each Rstest release needs an Open Graph image for its blog post
og:image/twitter:imagetags. Until now there was no template — only a single site-levelrstest-og-image.pnglived inrstack-design-resources, and per-release covers had to be hand-composed in Sketch.Implementation
website/scripts/og-image/(cli.mts + render.mts + template.mts) plus apnpm gen:og --version <ver>script.sharp/libvips.assets.rspack.rsCDN at generation time so logo updates flow through without re-committing the template.assets/fonts/(thegeistnpm package pulls innext>=13.2so its raw.ttfwas avoided).website/AGENTS.md+website/README.md: generate locally, compress externally, commit the PNG torstackjs/rstack-design-resources, CDN serves it.Out of scope
Wiring
rspress.config.tsto route each blogroutePath→ per-version PNG is a separate follow-up. The site still uses the single staticog:imageviapluginOpenGraph; only the generator + assets are added here.User Impact
None — internal tooling for release authors. Generated PNGs are committed to
rstack-design-resources, not this repo.Checklist
pnpm gen:og --version 0.5 --description …).website/AGENTS.md+website/README.mdupdated.