# How to Share a Folder of HTML Files (index.html + assets) in 2026

Canonical: https://commareports.com/share-html-folder
Published: 2026-09-06

> Multi-file HTML output — index.html plus assets, images and sub-pages — breaks when you send one file. How to share a whole HTML folder so every relative link still works.

# How to share a folder of HTML files

Plenty of tools do not produce *an* HTML file. They produce a directory:

```
coverage/
├── index.html
├── assets/
│   ├── style.css
│   └── app.js
├── img/
│   └── chart.png
└── src/
    └── parser.py.html
```

Jest and pytest coverage, Allure, Sphinx, MkDocs, Storybook, JaCoCo,
Lighthouse, profiling output — nearly all of them. Every one of those files
matters, and every relative link between them assumes they stay neighbours.

Send `index.html` on its own and the reader gets grey text on white.

## Why one file is not enough

The browser resolves `./assets/style.css` relative to wherever `index.html`
currently is. Move the file alone into an email attachment, a chat upload,
or a cloud-storage preview, and those neighbours no longer exist. The page
loads — it just loads without its styling, its charts and its sub-pages.
The longer diagnosis is in
[why a shared HTML report has no CSS](/html-report-broken-css).

Sub-pages make it worse: a coverage report's per-file drilldown is dozens
of linked pages. There is no "just send the important one."

## Option 1 — collapse it into a single file

If the generator can inline its own resources, take that. One file travels
anywhere:

| Tool          | Flag                                            |
| ------------- | ----------------------------------------------- |
| nbconvert     | `--to html --embed-images`                      |
| Quarto        | `-M embed-resources:true`                       |
| R Markdown    | `self_contained: true` (the default)            |
| pandoc        | `--embed-resources --standalone`                |
| Plotly        | `write_html(..., include_plotlyjs="inline")`    |

Not every tool offers it. Coverage reports and docs sites are genuinely
multi-page and cannot be flattened.

## Option 2 — share the bundle

Zip the directory **contents** — `index.html` at the archive root — and
publish the zip. Comma serves bundles from one origin, so relative paths,
sub-pages and assets behave exactly as they did locally.

```bash
cd coverage && zip -qr ../coverage.zip . && cd ..

curl -X POST https://commareports.com/api/v1/reports \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -F "title=Coverage — main @ $(git rev-parse --short HEAD)" \
  -F "visibility=team" \
  -F "bundle=@coverage.zip"
```

Or drag the zip into [/new](/login) if you would rather not use a terminal.

**Getting the zip right.** `cd` into the directory before zipping. Zipping
from the parent (`zip -r coverage.zip coverage/`) nests everything one
level deeper, so there is no `index.html` at the root and the entry point
404s. If your archive has a wrapper folder, that is the bug.

## What the bundle gets you

- **Every link works.** Drilldowns, per-file pages, search indexes and
  fonts resolve against one origin.
- **Access per report.** Private, team, your email domain, any signed-in
  user, or an unlisted link — decided per bundle, not per bucket. See
  [sharing and access control](/docs/sharing).
- **Comments on the rendered page.** A reviewer selects the uncovered
  branch or the failing test row and leaves a thread anchored to it. See
  [commenting on HTML](/comment-on-html).
- **Revisions at one URL.** `PATCH` the same id from the next CI run; the
  link in your README never changes and any two runs are diffable. See
  [publishing from CI](/docs/ci).
- **Sandboxed execution.** Bundles render with `allow-scripts` and no
  `allow-same-origin`, so interactive output runs without reaching anyone's
  session.

## What not to do

- **Emailing the zip.** The recipient must download, unzip and find
  `index.html` on a machine that may refuse to open it — and mail gateways
  strip archives containing `.js` more often than you would expect.
- **Cloud storage previews.** Drive, Dropbox, Box and SharePoint all store
  the folder and none of them render it. See
  [Dropbox HTML preview](/dropbox-html-preview) and
  [Box HTML preview](/box-html-preview).
- **Screenshotting the summary.** It loses the drilldown, which is the only
  part anyone needed. See
  [stop screenshotting reports](/stop-screenshotting-reports).

## Related

- [Host an HTML file](/host-html-file) ·
  [Upload an HTML file, get a link](/upload-html-file-get-link)
- [Share a coverage report](/share-coverage-report) ·
  [Share an Allure report](/share-allure-report) ·
  [Share a Storybook static build](/share-storybook-static)
- [Serve an HTML file locally](/serve-html-file-locally) ·
  [Share an HTML report](/share-html-report)
