Skip to content

feat(support-matrix): public embeddable support-matrix badge service#497

Merged
Brooooooklyn merged 10 commits into
mainfrom
feat/support-matrix-badge
Jul 11, 2026
Merged

feat(support-matrix): public embeddable support-matrix badge service#497
Brooooooklyn merged 10 commits into
mainfrom
feat/support-matrix-badge

Conversation

@Brooooooklyn

Copy link
Copy Markdown
Member

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.
  • Docs at 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

param meaning
tested / nonblocking / untested per-tier triple lists; full expands to the 14-triple napi-new scaffold set
omit subtract triples or OS-group names (e.g. android, freebsd)
wasm force the Browser section
engines engines.node range → the Node.js card (floor → latest, with excluded gaps)
nodeTested majors to mark CI-tested
name package title on the card
theme dark opt-in

Resolution order: expand full → explicit triples override the seed → omit subtracts → group by OS. Most-severe tier wins on conflict (untested > nonblocking > tested).

How it's built

  • Pure, unit-tested core in lib/support-matrix/ (targets / resolve / node / query) — no edge APIs, no .wasm, fully Node-testable.
  • Rendering with satori → SVG, @resvg/resvg-wasm → PNG, reusing the existing lib/sponsors-image/{fonts,resvg} plumbing unchanged.
  • .wasm imports live only in routes/*.ts (become WebAssembly.Module at 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:

  • Fixed (6): a colocated test file was being scanned into the worker as a live crashing route (moved to lib/); engines had 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; the name param 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.
  • Refuted (1): "edge cache not enabled" — the caching is byte-identical to the sponsors service already live in prod (header-driven via the Cloudflare zone), and stale-while-revalidate works alongside s-maxage per RFC 5861.
  • Design calls (2): parser now respects upper bounds; a bare wasm=1 keeps its green/tested chip.

Tests

123 passing across the 7 support-matrix + content suites; vp check clean.

🤖 Generated with Claude Code

Brooooooklyn and others added 8 commits July 10, 2026 21:48
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>

@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: 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".

Comment thread lib/support-matrix/query.ts
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>

@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: 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".

Comment thread lib/support-matrix/targets.ts
…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>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@Brooooooklyn
Brooooooklyn merged commit 7822989 into main Jul 11, 2026
2 checks passed
@Brooooooklyn
Brooooooklyn deleted the feat/support-matrix-badge branch July 11, 2026 16:36
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.

1 participant