Skip to content

feat(website): add release OG image generator#1258

Open
fi3ework wants to merge 7 commits into
mainfrom
feat/og-image-generator
Open

feat(website): add release OG image generator#1258
fi3ework wants to merge 7 commits into
mainfrom
feat/og-image-generator

Conversation

@fi3ework

@fi3ework fi3ework commented May 14, 2026

Copy link
Copy Markdown
Member

Summary

image

Background

Each Rstest release needs an Open Graph image for its blog post og:image / twitter:image tags. Until now there was no template — only a single site-level rstest-og-image.png lived in rstack-design-resources, and per-release covers had to be hand-composed in Sketch.

Implementation

  • Add website/scripts/og-image/ (cli.mts + render.mts + template.mts) plus a pnpm gen:og --version <ver> script.
  • Pipeline: satori (HTML → SVG via satori-html) → @resvg/resvg-js (SVG → PNG) rendered at 2x zoom for retina (final 2400×1260). Raw resvg PNG is emitted as-is; the CLI prints a tip with the TinyPNG URL on its own indented line so the URL stays clickable, and the author compresses externally (TinyPNG / Squoosh / ImageOptim) before committing to design-resources. This keeps the toolchain free of native deps like sharp/libvips.
  • Logo SVG is fetched from the assets.rspack.rs CDN at generation time so logo updates flow through without re-committing the template.
  • Background uses randomized radial gradients: weighted color schemes (tonal/duo/tri), quadrant-anchored blob placement to keep gradient mass off the central text column, single-blob visibility floor. Blob aspect ratio is capped at ~1.4:1 and elongated blobs hug a canvas edge so one long edge clips off-canvas — together these prevent "long bar" shapes floating mid-frame.
  • Space Grotesk (SIL OFL) is committed under assets/fonts/ (the geist npm package pulls in next>=13.2 so its raw .ttf was avoided).
  • Documents the manual workflow in website/AGENTS.md + website/README.md: generate locally, compress externally, commit the PNG to rstackjs/rstack-design-resources, CDN serves it.

Out of scope

Wiring rspress.config.ts to route each blog routePath → per-version PNG is a separate follow-up. The site still uses the single static og:image via pluginOpenGraph; 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

  • Tests updated (or not required). Manual CLI script; verified by running it (pnpm gen:og --version 0.5 --description …).
  • Documentation updated (or not required). website/AGENTS.md + website/README.md updated.

Validation: ran pnpm format, pnpm run lint, pnpm run typecheck, and pnpm --filter rstest-website build. Skipped pnpm test / e2e because the change is a standalone website CLI script with no runtime impact on @rstest/* packages.

@fi3ework fi3ework changed the title feat(website): add release OG image generator docs(website): add release OG image generator May 14, 2026
@github-actions

github-actions Bot commented May 14, 2026

Copy link
Copy Markdown

Rsdoctor Bundle Diff Analysis

Found 12 projects in monorepo, 0 projects with changes.

📊 Quick Summary
Project Total Size Change
adapter-rsbuild 3.7 KB 0
adapter-rslib 24.7 KB 0
adapter-rspack 7.8 KB 0
browser 2.0 MB 0
browser-react 3.7 KB 0
browser-ui 803.5 KB 0
coverage-istanbul 9.6 KB 0
core/browser 970.0 KB 0
core/loaders 869.0 B 0
core/main 1.7 MB 0
vscode/extension 26.9 MB 0
vscode/worker 14.4 KB 0

Generated by Rsdoctor GitHub Action

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 14, 2026

Copy link
Copy Markdown

Deploying rstest with  Cloudflare Pages  Cloudflare Pages

Latest commit: d4f6185
Status: ✅  Deploy successful!
Preview URL: https://d307a904.rstest.pages.dev
Branch Preview URL: https://feat-og-image-generator.rstest.pages.dev

View logs

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread website/README.md Outdated
@fi3ework fi3ework force-pushed the feat/og-image-generator branch from 8c7b7d0 to a17b810 Compare May 15, 2026 03:29
@fi3ework fi3ework changed the title docs(website): add release OG image generator feat(website): add release OG image generator May 15, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread website/AGENTS.md Outdated
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.
@fi3ework fi3ework force-pushed the feat/og-image-generator branch from a17b810 to 8abdbe7 Compare May 15, 2026 03:35
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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread website/scripts/og-image/assets/fonts/LICENSE.txt
@fi3ework fi3ework requested a review from 9aoy May 15, 2026 05:16
fi3ework added 3 commits May 15, 2026 14:41
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.
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