Share an Istanbul / nyc coverage report

nyc report --reporter=html produces the single most useful coverage artifact in the JavaScript ecosystem: a summary table you can sort by branch coverage, and behind every row a page with the uncovered lines highlighted in red and the uncovered branches marked with I and E.

It is also a folder of several hundred files. So it never leaves the machine that produced it, and the conversation about coverage happens over a text-summary paste that says Branches: 71.4% and nothing about which branches.

Publish the tree

npx nyc report --reporter=html --reporter=text-summary   # → coverage/

Or straight from the runner:

npx jest --coverage --coverageReporters=html
npx vitest run --coverage            # v8 or istanbul provider

Drag coverage/ (or a zip of it) into the app:

  • index.html becomes the report body — the sortable summary.
  • Every per-file page, base.css, prettify.js, sorter.js and block-navigation.js upload as assets, and their relative references are rewritten to the uploaded copies.
  • Scripts run inside a sandboxed iframe (allow-scripts, no allow-same-origin), so column sorting and the next/prev-uncovered keyboard navigation still work.

The drill-down is the whole point of the Istanbul reporter, and it survives the trip.

From CI

npx nyc report --reporter=html

curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html coverage/index.html \
        --arg title "Coverage — $GITHUB_REF_NAME" '{title: $title, html: $html}')"

PATCH the same report id every run and the URL in your README always shows current coverage, with a revision per run behind it. "Did this PR drop coverage?" becomes a diff instead of a spreadsheet of past percentages.

Run the step with if: always() — a run that failed its coverage threshold is exactly the run whose report someone needs to read.

What review adds

  • Anchored threads on the file that lost coverage, not on the percentage. See commenting on HTML.
  • Revisions, so a slow slide from 84% to 71% is visible as a trend rather than discovered during a postmortem.
  • Access per report — private, team, domain-gated, or named reviewers. See the sharing model.

Limits

  • Entry HTML: 5 MB. Assets: 25 MB per file, 250 MB and 500 files total. A very large monorepo tree can approach the 500-file cap — publish per package if it does.
  • 60 requests/minute per token.

Try it

Comma is free — unlimited reports, unlimited commenters, unlimited revision history.

Publish a coverage report →

Related