# Share a Vega-Lite Chart — Interactive, Not a PNG

Canonical: https://commareports.com/share-vega-lite-chart
Published: 2026-08-30

> A Vega-Lite chart exported to PNG loses the tooltips, the brushing and the linked selection that justified building it. Publish the HTML instead: one link, still interactive, comments on the mark.

# Share a Vega-Lite chart

Vega-Lite's whole argument is that a chart is a **specification**, not a
picture — which is why the charts it produces have tooltips, panning,
brushing, and selections that filter one view from another.

Then it comes time to show someone, and the chart becomes a PNG in a
Slack message. A picture of a tool.

## Export HTML, not an image

```python
# Altair (Python) — the usual front-end for Vega-Lite
chart.save("chart.html", inline=True)
```

The vega-lite CLI's `vl2vg | vg2svg` path is the one to avoid here — it
renders the spec down to a static SVG, which throws away exactly the
behaviour you wanted to share.

The `inline=True` matters. Without it the file references the Vega
libraries from a CDN, and the chart breaks the day the pinned version
moves or the viewer is on a locked-down network. With it, you get **one
self-contained file** — which is also the shape that publishes in a single
call.

If you're hand-writing the page, the same rule applies to your
`vega-embed` script tags: vendor them rather than linking a CDN.

## Publish it

Drag `chart.html` into [Comma](https://commareports.com/), or from a
script:

```bash
curl -fsS -X POST "https://commareports.com/api/v1/reports" \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html chart.html \
        --arg title "Retention by cohort" \
        '{title: $title, html: $html}')"
```

Scripts run inside a sandboxed iframe (`allow-scripts`, no
`allow-same-origin`), so vega-embed boots and the chart stays a chart:
tooltips on hover, brush to filter, linked selection across views, and the
"..." menu for exporting the spec. See
[interactive HTML reports](/interactive-html-reports).

## Inline your data

This is the one thing that reliably breaks. A spec whose `data` is a URL
needs that URL to be publicly reachable **and** to send permissive CORS
headers, because the sandbox has no same-origin access to your network. A
chart pointing at `http://localhost:8000/data.csv` or an internal S3 path
renders as an empty axis for everyone but you.

Inline the data into the spec for anything other people need to open.
That also makes the report a self-contained record of what the numbers
were on the day you published it, which is usually what you wanted.

## Comment on the mark

The reason to publish an interactive chart rather than an image is that
the conversation can happen on the chart. Select the outlier, leave a
thread — "this spike is the migration backfill, not real traffic" — and it
stays anchored there across revisions, so the next person who sees the
spike finds the explanation instead of asking again.

That note is worth more than the chart, and it is the thing a PNG in a
channel structurally cannot hold. See
[commenting on HTML](/comment-on-html).

## Keeping it current

If the chart is generated by a script, `PATCH` a saved report id instead
of `POST`ing a new one. Each run appends a revision at the same URL, so
the link in the doc stays live and any two revisions can be diffed. On a
schedule rather than on a push, use a
[routine](/features/routines/scheduled-html-reports).

## Limits

- **Entry HTML: 5 MB.** Inlining a large dataset is what pushes past this
  — aggregate before plotting, which usually makes the chart better too.
  Assets: 25 MB per file, 250 MB and 500 files total.
- **Scripts run, sandboxed** — no same-origin access, so no fetches into
  your private network.
- **60 requests/minute per token.**

## Try it

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

**[Publish a chart →](https://commareports.com/)**

### Related

- [Share an Altair chart](/share-altair-chart) — the Python path in detail
- [Share a Plotly HTML chart](/share-plotly-html) · [Share a Bokeh plot](/share-bokeh-plot)
- [Interactive HTML reports](/interactive-html-reports) · [Share a Folium map](/share-folium-map)
- [Share a Jupyter notebook](/share-jupyter-notebook-html) · [with Jupyter](/with/jupyter)
