Skip to content

hue web integration — @sparkles/hue npm package (SPA / SSR / SSG)

Status: planned · Date: 2026-07-23 · Scope: a JavaScript/TypeScript npm package, @sparkles/hue, that makes hue's highlighter (sparkles:syntax) a drop-in Shiki replacement for web frameworks — usable in SSG, SSR, and (later) client-side SPA rendering. Generalizes the render-side substrate (twoslash.md RS1RS3, issue #122) into a distributable, multi-framework package.

NOTE

Forward-looking — every row is not started, on the RS1 substrate (which is partial: apps/hue --html already emits cssClasses HTML). This doc owns the JS package + framework integration + backend selection; the D-side HTML contract stays in twoslash.md RS1. Status legend and IDs: see the overview.

Design & rationale

Sites highlight code with Shiki today; the goal is to let them swap Shiki for @sparkles/hue and get sparkles:syntax's precise tree-sitter highlighting instead — with the same authoring surface. One JS API, two engine backends behind it:

  • Shell-out backend (ship first) — the JS package invokes the D hue --html binary (RS1) as a subprocess and reads back the HTML fragment. Covers SSG (build-time) and, secondarily, SSR (request-time). No new engine work — it wraps the shipped --html path.
  • Wasm backend (future) — sparkles:syntax compiled to wasm (the LDC WASI fork already demonstrated — the docs cell-explorer widget) highlights client-side in the browser (SPA), and can also serve SSR in a JS/edge runtime with no native binary.

The existing RS3 (VitePress) becomes one framework integration here (FWK1); the playground (RS2) consumes the same package.

The npm package (PKG)

IDRequirementStatusTraces to
PKG1Publish @sparkles/hue — a JS/TS package exposing a Shiki-compatible highlighting API (codeToHtml / codeToHast + createHighlighter, language + theme selection) so a site swaps Shiki for @sparkles/hue with minimal change.not startedproposed npm package
PKG2Output must match the RS1 HTML contract — cssClasses (with a once-emitted stylesheet), inlineStyles, and the CSS-variable multi-theme (dark/light) mode — so existing themes and markup transfer.not startedRS1; apps/hue --html
PKG3The package must port Shiki's languageAlias map, cover the target sites' language set (the ts-grammars bundle), and fall back to plain text for unbundled grammars (the totality law).not startedRS1 alias map; sparkles:syntax grammars
PKG4The API must be backend-pluggable — the same surface dispatches to the shell-out backend (SHL) or the wasm backend (WSM); the consumer selects per environment (build vs browser vs edge).not startedSHL*/WSM*
PKG5The package may expose the twoslash overlay (twoslash.md TWM2, the .twoslash-* HTML) as an optional transform, so @sparkles/hue can also replace @shikijs/twoslash.not startedtwoslash.md TWM2

Shell-out backend (SHL) — SSG/SSR, shipped first

IDRequirementStatusTraces to
SHL1An SSG/SSR backend must invoke the D hue --html binary as a subprocess — passing code + language + theme, reading back the HTML fragment. This is the first shipped backend.not startedapps/hue --html (RS1)
SHL2It must amortize process spawns — a long-lived highlighter process / request pipe (a batch or streaming protocol), not one spawn per snippet; build-time SSG is the primary path, SSR secondary.not startedproposed batch/pipe protocol
SHL3The binary must be resolvable — prebuilt per-platform binaries shipped with (or fetched by) the package, or a configured path; a clear error if absent, never a silent failure.not startedpackage binary resolution

Wasm backend (WSM) — client-side / edge, future

IDRequirementStatusTraces to
WSM1A future backend must compile sparkles:syntax to wasm (the LDC WASI fork, already demonstrated by the docs cell-explorer widget) and highlight client-side in the browser (SPA) with no shell-out.not startedsparkles:syntax wasm (LDC WASI); memory ldc-wasm-stduni-infeasible
WSM2The wasm backend must expose the same PKG API so it drops in behind the same package; it may also serve SSR in a JS/edge runtime (no native binary).not startedPKG4
WSM3It must ship the grammar/theme data the wasm engine needs (tree-sitter grammars as wasm or data); document the payload-size trade-off vs the shell-out backend.not startedbundling concern

Framework integrations (FWK)

IDRequirementStatusTraces to
FWK1VitePress / Vue — replace Shiki via markdown.highlight (this absorbs twoslash.md RS3); light/dark theme parity.not starteddocs/.vitepress/config.mts; RS3
FWK2Next.js — a rehype / MDX integration (the rehype-pretty-code shape) over @sparkles/hue; SSG + RSC/SSR.not startedproposed rehype plugin
FWK3Solid Start — a highlighter component/primitive; SSG + SSR.not startedproposed Solid integration
FWK4A generic framework-agnostic adapter (a bare codeToHtml + a rehype plugin) so other frameworks integrate without bespoke code.not startedproposed generic adapter
FWK5Diff rendering for the web — annotated diff code blocks (the Shiki transformerNotationDiff niche) and full-file diff pages rendered through hue's HTML diff sink (DVL4/HTM9); a natural follow-on once the HTML sink renders diffs — deferred.not starteddiff-view.md DVL4

Milestones

MilestoneScopeStatusRequirements
W0The RS1 SSG code→HTML contract (the substrate)partialRS1 (twoslash.md)
W1@sparkles/hue package + shell-out SSG backend + VitePress integrationnot startedPKG*, SHL1/SHL3, FWK1
W2Next.js + Solid Start + the generic rehype adapternot startedFWK2FWK4
W3SSR via shell-out (long-lived process / pipe)not startedSHL2
W4Wasm client-side backend (LDC WASI) behind the same APInot startedWSM1/WSM2
W5Wasm SSR + the optional twoslash overlay transformnot startedWSM2, PKG5

Relationship to existing specs

PieceRole
twoslash.md RS1 (apps/hue --html)the SSG code→HTML contract the shell-out backend wraps (SHL1)
twoslash.md RS2 (playground)a consumer of this package (SSG-prerendered, then wasm)
twoslash.md RS3 (VitePress)subsumed as framework integration FWK1
twoslash.md TWM2 (.twoslash-* HTML)the optional overlay transform (PKG5)
sparkles:syntax wasm (LDC WASI)the wasm backend engine (WSM1)
proposed @sparkles/hue npm packagethe JS layer these compose into

Twoslash requirements · General requirements · Overview