Render an OpenAPI v4 'Suluk' document with the Scalar API Reference UI — natively as v4, or downgraded for vanilla Scalar.
Part of Suluk — one typed OpenAPI v4 contract projecting into every full-stack layer.
CANDIDATE tooling — not official OpenAPI. Suluk is a single-contributor candidate for OpenAPI Specification v4.0 ("Moonwalk"), unaffiliated with the OpenAPI Initiative and unable to ratify anything on the SIG's behalf.
bun add @suluk/scalar
Takes a parsed v4 document and returns a self-contained Scalar API Reference HTML page (string or Response) — no build step, no server-side React. Two tracks:
scalarV4*). Feeds the v4 doc as v4 to the suluk-forked Scalar standalone, which projects requests→operations internally, shows the 4.0.0-candidate version badge, and renders the v4-only shapes (multi-request-per-method, request-name identity via showOperationId). The fork bundle is served from @suluk/scalar-standalone on jsDelivr by default, so it works out of the box.scalar*). Projects the v4 doc down to OpenAPI 3.1 (via @suluk/openapi-compat) and feeds it to vanilla Scalar — the baseline view that runs against any pinned upstream Scalar bundle.x-suluk-cost and x-suluk-access become Scalar x-badges rendered on each operation; expanding an operation reveals the cost breakdown by source + the access rule; a "Suluk v4 contract" intro with a cost-coverage tally is prepended to the doc description.@latest. SCALAR_VERSION and SULUK_FORK_CDN are exported so the UI never drifts under you; override cdn to self-host the bytes.Reach for @suluk/scalar when you want the Scalar UI for your contract. Use scalarV4Response for the full native-v4 reference (badges, the "View as" role projector, an insights drawer); use scalarResponse for a plain, dependency-light 3.1 fallback.
Siblings for the same job:
@suluk/reference — the native v4 renderer (suluk's own UI, not Scalar's chrome).@suluk/swagger — render via Swagger UI (always through the 3.1 downgrade).@suluk/editor — an editable two-pane authoring surface (uses this package for its live preview).import { scalarV4Response } from "@suluk/scalar";
import type { OpenAPIv4Document } from "@suluk/core";
// In a Bun.serve / Hono / fetch handler:
app.get("/reference", () =>
scalarV4Response(document, {
pageTitle: "saasuluk — OpenAPI v4 reference",
brand: "saasuluk",
// optional: a per-role "View as" projector wired to an endpoint that returns the projected spec
specUrl: "/reference/spec",
views: [
{ label: "Anonymous", value: "anon" },
{ label: "Signed-in", value: "user" },
{ label: "Admin", value: "admin" },
],
// optional: an embeddable superpowers panel opened as an in-page drawer
insightsUrl: "/reference/insights",
}),
);
// Picking a role re-fetches the projected spec and re-mounts Scalar:
app.get("/reference/spec", (c) => c.json(enrichedV4(projectFor(c)).spec));
scalarV4Response defaults cdn to the published fork (SULUK_FORK_CDN). To self-host, vendor the fork bundle and pass cdn:
scalarV4Response(document, { cdn: "/vendor/scalar/standalone-suluk.js", brand: "saasuluk" });
import { scalarResponse, SCALAR_VERSION } from "@suluk/scalar";
app.get("/scalar", () =>
scalarResponse(document, {
cdn: `/vendor/scalar/standalone-${SCALAR_VERSION}.js`, // or omit for the jsDelivr default
facetBadges: false, // plain 4→3 downgrade, no suluk superpowers
}),
);
Both renderers have an HTML-string sibling (scalarV4Html, scalarHtml) returning { html, diagnostics }, where diagnostics are the lossy-conversion notes from the v4→3.1 downgrade (the native-v4 path produces none):
import { scalarHtml } from "@suluk/scalar";
const { html, diagnostics } = scalarHtml(document, { facetBadges: false });
if (diagnostics.length) console.warn("downgrade losses:", diagnostics);
When you need the facet-enriched spec object (e.g. to serve as JSON for the "View as" endpoint above), use the enriched* helpers directly:
import { enrichedV4, enrichedSpec } from "@suluk/scalar";
const { spec } = enrichedV4(document); // v4 shape, badges + detail stamped, NOT downgraded
const { spec, diagnostics } = enrichedSpec(document); // downgraded to 3.1, then facet-enriched
Neither mutates the input document. Pass { facetBadges: false } to skip the cost/access enrichment.
| Export | What it does |
|---|---|
scalarV4Response(doc, opts?) |
Native-v4 Scalar page as a text/html Response (the fork). |
scalarV4Html(doc, opts?) |
Same, as { html, diagnostics }. |
scalarResponse(doc, opts?) |
3.1-downgrade Scalar page as a Response (vanilla Scalar). |
scalarHtml(doc, opts?) |
Same, as { html, diagnostics }. |
enrichedV4(doc, opts?) |
{ spec } — v4 doc enriched with facet badges/detail/intro, no downgrade. |
enrichedSpec(doc, opts?) |
{ spec, diagnostics } — downgraded to 3.1, then facet-enriched. |
enrichFacetBadges(spec) |
Mutate a 3.1 spec: attach x-badges from x-suluk-cost/x-suluk-access. |
enrichFacetDetail(spec) |
Mutate a 3.1 spec: append the cost/access detail to each op's description. |
enrichV4Facets(doc) |
Mutate a v4 doc: stamp badges + detail on each request + the intro. |
v4Intro(spec) |
Prepend the "Suluk v4 contract" note + cost-coverage tally to info.description. |
SCALAR_VERSION |
The pinned upstream Scalar version (string). |
SULUK_FORK_CDN / SULUK_FORK_STANDALONE_VERSION |
The default fork-bundle CDN URL + its version. |
Key opts (full set in ScalarOptions / ScalarV4Options): pageTitle, cdn, facetBadges, customCss, configuration (merged into createApiReference); and for the v4 reference: brand, specUrl / specParam / views (the role projector), insightsUrl / insightsLabel (the drawer).
This package only renders — the L3 line: render/generate, never host. It takes a doc you already parsed and validated and hands back HTML; it never fetches your spec, owns your routes, or mounts a server. You inject the doc (and, for the role projector, the endpoint that returns each role's projected spec).
It also does not fork Scalar. The patched standalone — the part that teaches Scalar the native v4 shapes — lives at tooling/ts/scalar-fork/ (clone-upstream + patches/*.patch → standalone-suluk.js, see FORK.md); this package only feeds that bundle and surfaces the x-suluk-* facets as badges. To teach Scalar a new v4 shape, add a patch there, not here.
Apache-2.0