feat(support-matrix): public embeddable support-matrix badge service#497
Conversation
Design for a public, parameterized support-matrix image on napi.rs that ecosystem packages embed in their READMEs instead of hand-maintaining SVGs. Self-contained query-encoded URL (tested/nonblocking/untested tiers + full/omit shortcuts + engines-derived Node card), combined SVG+PNG rendered at the edge via the sponsors satori/resvg mechanics, plus a docs page and an interactive URL-builder. lzma is the reference case. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5 tasks (data/resolve/node lib, renderer, routes, builder page, docs) executing the support-matrix badge spec. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Task 1 of the support-matrix image service: the fully-unit-tested core under lib/support-matrix/ (no satori, no edge APIs, no wasm). - targets.ts: TARGETS (23 triples), FULL scaffold set, OS_GROUPS, ALIASES, normalizeTriple() — canonical Rust-triple vocabulary; labels derived from arch+abi; prototype-key-safe normalization that never throws. - node.ts: deriveNode() + NODE_LATEST — a tiny in-repo semver-range reader (^maj.min / >=maj / bare maj / || unions) yielding headline, excluded-gap prose, and per-major pills; never throws on garbage. - resolve.ts: resolveMatrix() + MatrixModel/OsSection/BrowserModel/Tier — full→seed, explicit-override (most-severe wins), omit, group-by-OS, browser section for wasm; never throws on bad input. 39 tests green (targets 13, node 11, resolve 15), incl. the lzma fixture (11 tested / 2 nonblocking / 4 untested + browser). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Render a MatrixModel into the three-card support-matrix badge (Node.js,
Platforms grouped by OS, Browser) as a self-contained SVG, and orchestrate
SVG/PNG output. Reuses the sponsors satori/resvg/font plumbing unchanged.
- theme.ts: light/dark Palette + three tier colors (green/amber/gray)
- card.ts: React-less satori node tree; ensureYoga memo; data-URI icons
- render.ts: renderMatrix -> {body, contentType}; PNG via reused resvg at 2x
- card.test.ts: structural invariants + normalized string snapshots
(lzma / full / minimal, light + dark)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wire Tasks 1 & 2 into the two public endpoints:
- lib/support-matrix/query.ts: parseSupportMatrixQuery — the shared, unit-
tested parser mapping raw URL params to the resolver's MatrixQuery + theme
(comma-split lists, nodeTested→ints, engines/name/wasm passthrough).
- routes/support-matrix.{svg,png}.ts: parse → resolveMatrix → loadFonts →
renderMatrix → Response. Pure function of the query (no KV/R2/cron), cached
hard (s-maxage=86400 + a week SWR). yoga/resvg wasm imported in the routes;
yoga/resvg init happen inside renderMatrix. No CORP/COEP.
- routes/support-matrix.test.ts: parser units + lzma query round-trip, plus a
real handler integration (vi.mock substitutes the edge .wasm modules) that
drives satori+resvg — svg→image/svg+xml/<svg>, png→image/png, malformed→200.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add buildSupportMatrixQuery — the pure, unit-tested inverse of
parseSupportMatrixQuery — and an interactive island page at /support-matrix
that turns napi.targets + tier/engine/name inputs into the self-contained
badge URL, with a live <img> preview and copy-paste <picture>/PNG snippets.
- lib/support-matrix/query.ts: buildSupportMatrixQuery + SupportMatrixQueryInput
- lib/support-matrix/query.test.ts: 9 tests, incl. the lzma round-trip
- components/support-matrix-builder/index.tsx: the builder (pure helpers only,
no renderer/satori/resvg/wasm; SSR-safe, clipboard guarded)
- pages/support-matrix.{island.tsx,server.ts}: prerender=true page mounting the
builder as a relative-import 'load' island
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add content/docs/more/support-matrix-badge.{en,cn,pt-BR}.mdx documenting the
public /support-matrix.{svg,png} badge endpoints: the query-param reference,
the full/omit resolution rules, copy-paste <picture>/PNG embed snippets, and
the worked @napi-rs/lzma example. Link to the /support-matrix builder
(locale-prefixed in cn/pt-BR per the i18n link rule).
Regenerate the served pages/ mirrors, lib/nav/index.ts, and the route map
(the latter also registers the Task-4 /support-matrix builder page, whose
route-map entry had not been regenerated).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…hten node parser, render name, fix docs links+encoding Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 43e0b6d22d
ℹ️ 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".
The /support-matrix builder page is self-documenting; remove the separate docs/more/support-matrix-badge page across all locales along with its generated pages mirrors, _meta entries, nav items, and route-map entry. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2a105af232
ℹ️ 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".
…oongarch64 + windows-gnu targets Addresses two PR review findings: - nodeTested: the route parser (query.ts) and the builder's live-preview parser used bare parseInt, so a mistyped `nodeTested=22garbage` became 22 and painted Node 22 CI-tested — the resolver's strict guard sits downstream and never saw the raw token. Require whole-digit tokens in both parsers. - Target vocabulary: add loongarch64-unknown-linux-gnu (loong64) and x86_64-pc-windows-gnu (x64 gnu) — both are napi CLI AVAILABLE_TARGETS that normalizeTriple previously rejected, so the builder flagged them unknown and the badge silently omitted them. (universal-apple-darwin stays excluded as a fat/meta target, not a platform chip.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
What
A public, self-contained support-matrix badge service so any ecosystem package can show its compatibility table as an embeddable image — the napi.rs analog of a shields.io badge, but for the platform/Node/browser matrix.
GET /support-matrix.svg?<query>— for GitHub READMEs (pair two in a<picture>for light/dark).GET /support-matrix.png?<query>— for npm / crates.io, whose READMEs strip<picture>and inline SVG./support-matrix— an interactive URL-builder page with a live preview and copy-paste<picture>/ PNG snippets.content/docs/more/support-matrix-badge.{en,cn,pt-BR}.mdx.Everything is query-encoded and self-contained — the image is a pure function of its URL, so it needs no per-package state and edge-caches like the existing sponsors image service.
Query model
tested/nonblocking/untestedfullexpands to the 14-triple napi-new scaffold setomitandroid,freebsd)wasmenginesengines.noderange → the Node.js card (floor → latest, with excluded gaps)nodeTestednamethemedarkopt-inResolution order: expand
full→ explicit triples override the seed →omitsubtracts → group by OS. Most-severe tier wins on conflict (untested > nonblocking > tested).How it's built
lib/support-matrix/(targets/resolve/node/query) — no edge APIs, no.wasm, fully Node-testable.satori→ SVG,@resvg/resvg-wasm→ PNG, reusing the existinglib/sponsors-image/{fonts,resvg}plumbing unchanged..wasmimports live only inroutes/*.ts(becomeWebAssembly.Moduleat the edge); the lib stays pure.Review
Executed via subagent-driven development, then a whole-branch adversarial review. The review raised 8 findings; each was independently re-verified against the real control flow before acting:
lib/);engineshad no length cap (renderable OOM on a 128 MB isolate) — now capped; the Node range parser accepted junk (junk22junk→ v22) and ignored upper bounds — now anchored and respects<X/<=X/ hyphen ranges; thenameparam was parsed and documented but never rendered — now drawn as a card title; localized docs linked to non-existent/cn/…//pt-BR/…builder URLs — repointed to the single root page; doc badge snippets had raw spaces that broke markdown image parsing — now percent-encoded.stale-while-revalidateworks alongsides-maxageper RFC 5861.wasm=1keeps its green/tested chip.Tests
123passing across the 7 support-matrix + content suites;vp checkclean.🤖 Generated with Claude Code