npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@api-common/spectral-reporter

v0.2.0

Published

Turn Stoplight Spectral lint output into a rich, standalone HTML API governance report — inspired by newman-reporter-htmlextra. An API Commons tool.

Readme

Spectral Reporter

Turn Stoplight Spectral lint output into a rich, standalone HTML API governance report.

@api-common/spectral-reporter is a post-processor: you feed it Spectral's JSON output and it emits one self-contained HTML file — inline CSS and JS, no external or CDN requests — that you can open offline or attach to a CI run. It is directly inspired by Danny Dainton's newman-reporter-htmlextra, which does the same thing for Postman/Newman runs.

Live demo and landing page: reporter.apicommons.org

One of the API Commons tools, alongside API Validator, API Discovery, API Documentation, API Reusability, and MCP Install.

What's in the report

  • Pass/fail governance banner — fails if there are any errors.
  • Severity stat tiles — Errors / Warnings / Info / Hints, with reserved, always-labelled status colors (never color alone).
  • Group-by toggle — regroup findings by rule, file, or severity.
  • Search + severity filter chips — filter the whole report client-side.
  • Per-issue rows — severity chip, rule code, message, file basename, line:character; expand a row to see the JSON path and source.
  • Top-offending rules & files — mini bar-rankings so you know where to start.
  • Responsive, respects prefers-reduced-motion, visible focus states, light/dark.

Install & usage

Run it with no install:

# From a Spectral JSON results file
npx @api-common/spectral-reporter spectral-results.json -o governance-report.html

# Or pipe straight from Spectral
spectral lint -f json openapi.yaml | npx @api-common/spectral-reporter -o report.html

Or add it to a project:

npm install --save-dev @api-common/spectral-reporter

Input

Spectral's --format json / -f json output — a JSON array of findings:

[
  { "code": "operation-operationId",
    "path": ["paths", "/pets", "get", "operationId"],
    "message": "Operation must have \"operationId\".",
    "severity": 1,
    "range": { "start": { "line": 10, "character": 6 }, "end": { "line": 12, "character": 20 } },
    "source": "/abs/path/openapi.yaml" }
]

Severity integers: 0 = error, 1 = warn, 2 = info, 3 = hint. Missing source/range, empty arrays (a clean run renders a celebratory "0 issues" report), and multiple source files are all handled.

Flags

| Flag | Description | | --- | --- | | -o, --output <file> | Output path — HTML report, trend report, or SARIF (default spectral-report.html) | | --sarif <file> | Also write SARIF 2.1.0 (for GitHub code scanning) | | --format <html\|sarif> | sarif writes SARIF to -o / default instead of HTML | | --history <dir> | Render a trend report across dated JSON runs in <dir> | | --trends | Force trend mode (auto-detected when multiple inputs are given) | | --totals <file> | Positive-rule sidecar → adds a compliance scoreboard | | --title <text> | Report title (default API Governance Report) | | --dark | Force the dark theme | | --open | Best-effort open the report in your browser | | -h, --help | Show help | | --version | Print version |

SARIF output — upload findings to GitHub code scanning

The research found only 3.4% of API teams surface governance findings in GitHub code scanning. --sarif closes that gap: it converts Spectral's JSON to SARIF 2.1.0 — distinct rules become tool.driver.rules, each finding becomes a result (with ruleId, a level mapped from severity, and locations from source + range). Severity maps as error → error, warn → warning, info/hint → note; Spectral's 0-based line/character ranges are converted to SARIF's 1-based regions.

# Write SARIF only (nothing else) — ideal in a pipe
spectral lint -f json openapi.yaml | npx @api-common/spectral-reporter --sarif results.sarif

# Or write BOTH the HTML report and SARIF by also giving -o
npx @api-common/spectral-reporter spectral.json --sarif results.sarif -o report.html

In GitHub Actions, hand the file to github/codeql-action/upload-sarif so findings show up on the Security tab and inline on pull requests:

- name: Spectral → SARIF
  run: |
    npx @stoplight/spectral-cli lint -f json openapi.yaml > spectral.json || true
    npx @api-common/spectral-reporter spectral.json --sarif results.sarif
- uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: results.sarif

Trend / history reports

Feed the reporter multiple runs and it renders a trend scoreboard — total findings over time, a per-severity trend, and which rules improved or regressed — the "82% comply, up from 71% last quarter" view.

# A directory of dated JSON runs (e.g. 2026-Q1.json, 2026-Q2.json …), sorted by name
npx @api-common/spectral-reporter --history runs/ -o trend-report.html

# …or pass the run files positionally, oldest → newest (trend mode auto-detects)
npx @api-common/spectral-reporter q1.json q2.json q3.json -o trend-report.html

Each run file is ordinary Spectral -f json output; the filename (minus extension) becomes the run's label on the chart.

Positive-rule framing — report progress, not just deficits

Raw Spectral JSON only lists violations, so it can never say "82% of operations carry a unique id." Supply an optional totals sidecar with --totals and the report adds a compliance scoreboard beside the violation list. It degrades gracefully — omit the sidecar and you get the deficit-only report exactly as before.

The sidecar is per-rule { checked, passed, failed }. passed defaults to checked − failed and failed to checked − passed, so you only need two of the three:

{
  "rules": {
    "operation-operationId":        { "checked": 42, "passed": 34, "failed": 8 },
    "operation-operationId-unique":  { "checked": 42, "passed": 41 },
    "info-license":                  { "checked": 6,  "failed": 5 }
  }
}

An array form ([{ "rule": "…", "checked": …, "passed": … }, …]) is accepted too.

npx @api-common/spectral-reporter results.json --totals totals.json -o report.html

In GitHub Actions

- name: Lint & report
  run: |
    npx @stoplight/spectral-cli lint -f json openapi.yaml > spectral.json || true
    npx @api-common/spectral-reporter spectral.json -o governance-report.html
- uses: actions/upload-artifact@v4
  with:
    name: api-governance-report
    path: governance-report.html

(The || true keeps the step from failing before the report is generated; gate the build on the report's contents or Spectral's own exit code as you prefer.)

Use the renderer directly

The HTML rendering is a pure, dependency-free function shared verbatim by the CLI and the web demo:

import { renderReport } from '@api-common/spectral-reporter';

const html = renderReport(spectralResults, {
  title: 'My API Governance Report',
  dark: false,
  generatedAt: new Date().toISOString(),
  totals: { rules: { 'operation-operationId': { checked: 42, passed: 34 } } }, // optional
});

The trend renderer and the SARIF converter are the same pure, dependency-free modules the CLI and the demo use, exported as subpaths:

import { renderTrends } from '@api-common/spectral-reporter/trends';
import { toSarif }      from '@api-common/spectral-reporter/sarif';

const trendHtml = renderTrends([
  { label: '2026-Q1', results: q1 },
  { label: '2026-Q2', results: q2 },
], { generatedAt: new Date().toISOString() });

const sarifLog = toSarif(spectralResults); // a SARIF 2.1.0 log object

Develop / run locally

npm install
npm test            # node:test unit tests for the renderer
npm run cli fixtures/spectral-results.json -o /tmp/report.html   # try the CLI
npm run dev         # the landing + live demo site (Vite) at localhost:5173
npm run build       # build the static site into dist/ (what Pages deploys)

The demo and the CLI import the same src/render-report.js, so what you preview and download on the site is byte-for-byte what CI produces.

TODOs (for the human picking this up)

  • [ ] Review + npm publish v0.2.0. The repo is public and 0.1.0 is on npm; the SARIF / trends / positive-rule work is committed locally on main and left for a human to review, bump, and publish. (scope @api-common is singular — @api-commons was taken.)
  • [ ] DNS: confirm reporter.apicommons.org points at GitHub Pages.
  • [ ] Add screenshots / social card to this README and the landing page.

License

Apache-2.0 — free and open. A project of API Evangelist, maintained under API Commons. API Evangelist offers expert governance services when you want help.