Share the analysis, not a screenshot of it
The analysis is done. It renders beautifully at localhost:8888. Then
someone asks for it, and the options are all bad: a 30 MB HTML export Slack
refuses to preview, a file:// link that opens blank on their machine, a
GitHub URL that shows raw JSON, or — most commonly — a screenshot of the
chart pasted into a deck, which destroys the only thing that made the chart
worth building.
Publish the export
jupyter nbconvert --to html --embed-images analysis.ipynb
import os, requests
r = requests.post(
"https://commareports.com/api/v1/reports",
headers={"Authorization": f"Bearer {os.environ['COMMA_API_TOKEN']}"},
json={
"title": "Churn cohort analysis — September",
"html": open("analysis.html").read(),
},
)
print(r.json()["url"])
The stakeholder gets a URL. No Python, no kernel, no clone, no nbviewer, no "can you re-run it for me."
The same path works for whatever you actually use: Jupyter · Quarto · R Markdown · marimo · Observable · Colab · Databricks · Papermill · Voilà.
And for charts published on their own: Plotly · Altair · Bokeh · Vega-Lite · ECharts · HoloViews · D3 · SHAP · Folium.
Interactivity is the point
A published report runs its scripts in a sandboxed iframe (allow-scripts,
no allow-same-origin). Concretely: hover tooltips work, legend toggles
work, zoom and brush selection work, a sortable DataFrame.to_html() table
sorts, a ydata-profiling or
Sweetviz report keeps its tabs.
Two exports that famously break, and why:
- Widgets render blank — ipywidgets need embedded widget state or a live kernel. Export flag, not hosting.
- Plotly chart missing — the
export pointed at a CDN the reader's network blocked, or
include_plotlyjswas set toFalse. Embed it.
Questions land on the number
This is the part that changes how the work goes. Stakeholder feedback on analysis is almost always about one figure — a cohort that looks wrong, a denominator they expected to be different, a date range they assumed. Sent as a Slack message, that question arrives detached from the thing it's about and costs you twenty minutes of reconstruction.
Anchored comments keep it attached. They highlight the cell; the thread lives on the cell. See commenting on HTML.
When the answer is "you're right, it was deduplicated wrong," re-run and publish a revision at the same URL. The link in the ticket stays valid, and the earlier version stays visible — which is what you need when someone quotes a number from a version you have since corrected.
When the analysis should refresh itself
A weekly cohort refresh is a routine: a schedule, a re-run, a revision at the same address. Nobody asks "is this the latest?" because there is only one link. See weekly analytics digest.
Worth knowing
- Start private. Analysis usually names customers, revenue, or headcount. Publish private, widen once you've read it — see sharing & access control.
- Readers are free. Pricing is per publisher. Sharing with the whole commercial team costs nothing.
- Export folders wholesale. Quarto and nbconvert output with a
_files/sibling directory should be published as a whole folder so relative asset links resolve. - Limits. Entry HTML 5 MB; assets 25 MB per file, 250 MB and 500 files per report. Embedded base64 images are the usual reason an export is large — publishing the folder is the fix.
Try it
Comma is free — unlimited reports, unlimited commenters, unlimited revision history.