Share a Chart.js chart
Chart.js is what you reach for when the question is "can you plot this by Friday". A canvas, a script tag, a data array — twenty lines and you have something worth showing people.
Showing people is where it stops being twenty lines.
The file works on your machine. Emailed, it arrives as an attachment that downloads rather than opens. Committed to a repo, GitHub shows the source. Pasted into Slack, it becomes a filename. So it gets screenshotted, and a screenshot of an interactive chart is a chart with the hover values, the legend toggles and the zoom removed.
Publish it
Drag the HTML into the app, or POST it:
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 t "Weekly active users — Q3" '{title: $t, html: $html}')"
Report HTML renders with scripts enabled inside a sandboxed iframe
(allow-scripts, no allow-same-origin), so Chart.js initialises, draws to
its canvas, and keeps its interactions: hover tooltips, click-to-toggle series
in the legend, and the zoom plugin if you are using it.
Make the page self-contained
The one thing that reliably breaks a shared Chart.js page is the CDN reference:
<!-- fragile: depends on a third party, and on the protocol matching -->
<script src="http://cdn.example.com/chart.js"></script>
Two failure modes. An http:// script inside an https:// page is blocked as
mixed content with no visible error —
just a blank canvas. And a CDN that stops serving that version, or a reader
behind a proxy that blocks it, produces the same blank canvas years later.
For a chart that has to keep working, inline the library:
curl -sL https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.js > chart.umd.js
python3 - <<'EOF'
html = open("chart.html").read()
lib = open("chart.umd.js").read()
open("chart.html","w").write(
html.replace('<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.js"></script>',
f"<script>{lib}</script>"))
EOF
Now the report is one file that renders identically in five years.
Publish the data with the chart
A chart is a claim. Upload the CSV or JSON behind it as an asset on the same report and it becomes a claim somebody can check — which is the difference between a chart people believe and a chart people act on.
Keep one URL as the numbers change
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 chart.html \
--arg t "Weekly active users — week $(date +%V)" '{title: $t, html: $html}')"
Regenerate the chart on a schedule and PATCH the same report id: the link in the channel keeps showing current numbers, and the revision list is the history. See scheduled HTML reports.
What review adds
- Anchored threads on the anomaly, so the explanation travels with the chart — see commenting on HTML.
- Revisions, so "was it already trending down in August?" is answerable.
- Access per report — private, team, domain-gated or named reviewers. See the sharing model.
Limits
- Entry HTML: 5 MB. Inlining Chart.js costs roughly 200 KB; a large embedded dataset is the part that grows — upload it as an asset and fetch it instead.
- 60 requests/minute per token.
Try it
Comma is free — unlimited reports, unlimited commenters, unlimited revision history.