# Share an Istanbul / nyc Coverage Report — One Link for the Whole Tree

Canonical: https://commareports.com/share-istanbul-report
Published: 2026-08-31

> nyc writes a coverage/ folder with one HTML page per source file. Publish the tree to Comma for a URL that keeps the drill-down, the sorting and the per-line highlighting intact.

# 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

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

Or straight from the runner:

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

Drag `coverage/` (or a zip of it) into [the app](https://commareports.com/):

- `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

```bash
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](/docs/ci) 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](/comment-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](/docs/sharing).

## 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 →](https://commareports.com/)**

### Related

- [Share an LCOV report](/share-lcov-report) · [Share a coverage report](/share-coverage-report)
- [Share a Jest report](/share-jest-report) · [Share a Vitest report](/share-vitest-report)
- [Publish from CI](/docs/ci) · [Share a SimpleCov report](/share-simplecov-report)
