Share an Altair chart

The reason to use Altair rather than matplotlib is the interaction — the tooltip, the brush selection, the linked view that filters the other panel. Every one of those is destroyed by the way charts usually get shared, which is a PNG pasted into a channel.

import altair as alt

chart = alt.Chart(df).mark_circle().encode(
    x="week:O", y="latency_p95:Q", color="service:N",
    tooltip=["service", "week", "latency_p95"],
).interactive()

chart.save("chart.html")

Publish the file

curl -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 \
        '{title: "p95 latency by service", html: $html}')"

Or drag chart.html into the app.

The chart keeps working at the link. Report HTML renders with scripts enabled inside a sandboxed iframe (allow-scripts, no allow-same-origin), so the Vega runtime initialises and the zoom, tooltips and selections behave exactly as they do in your notebook — see interactive HTML reports.

Online vs. self-contained

chart.save() writes a page that loads Vega, Vega-Lite and vega-embed from jsDelivr, which is allow-listed — the chart renders at the link without further work.

Use chart.save("chart.html", inline=True) (with vl-convert-python installed) when the audience might be offline or on a locked-down network. The file gets larger; it stops depending on anything.

Chart plus narrative

A chart on its own answers a question nobody asked. Build the page in Python and publish that instead:

html = f"""
<h1>p95 latency, weeks 20–40</h1>
<p>Two services regressed after the connection-pool change in week 32.</p>
{chart.to_html()}
"""

Then POST html. The same trick works for a composed view — (chart1 | chart2) keeps the selections linked across both panels.

Keeping it current

PATCH the same report id when the data refreshes, or run the script on a routine so the URL you pasted into the wiki three months ago still shows this week's numbers. Each refresh appends a revision, so the change is inspectable rather than silent.

Limits

  • Entry HTML: 5 MB. Altair inlines the data by default, so a chart over a large frame can pass that — aggregate before plotting, or reference the data as an asset URL.
  • 60 requests/minute per token.

Try it

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

Publish an interactive chart →

Related