Blog

Turning a Jupyter Notebook Into Something You Can Actually Send Someone

January 1, 1970

jupyterpythonnotebookspresentation

There's a specific, familiar moment in every analytics project: the notebook runs top to bottom, the charts look right, the conclusion is clear — and now someone asks for the results, and the honest answer is that the results live in a .ipynb file that only makes sense to someone with a Python environment and the patience to run every cell in order.

This is a solved problem in the sense that everyone has a workaround. It's not a solved problem in the sense that none of the workarounds are good.

The usual paths, and why each one loses something

Screenshot the output cells. Fast, but static, and it strips out everything except the exact chart you happened to screenshot. If someone asks "what about last quarter," you're back in the notebook.

Export to HTML via nbconvert. Preserves more, but ships the entire notebook — code cells, stray debugging output, that one cell you forgot to delete — to someone who wanted the conclusion, not the process.

jupyter nbconvert --to html analysis.ipynb

Rebuild it as slides. Accurate and clean, but now you're maintaining two versions of the same analysis — the notebook where the real work happens, and the slide deck that's perpetually one revision behind it.

Turn it into a PDF report. Reasonable for a one-time deliverable, but frozen at export time. Any update means redoing the export and re-sending the file.

What's actually being asked for

Almost nobody wants the notebook. They want the three charts that mattered, the sentence of context around each one, and ideally something they can open without installing anything. The notebook is where you found the answer — it was never meant to be the way you deliver it, and using it as both is where the friction comes from.

The cleaner mental model: analysis and delivery are two different documents that happen to share a data source. The notebook can stay exactly as messy as it needs to be, because it's a workspace, not a deliverable.

Doing this without maintaining two documents

The core issue with "just rebuild it elsewhere" is the duplication — every update to the analysis means manually re-syncing the presentable version. That only stops being a chore if both versions are reading from the same underlying query rather than a copy-pasted dataframe.

# the notebook: exploratory, messy, iterating fast
df = pd.read_sql(query, conn)
df.groupby("region").revenue.sum().plot(kind="bar")  # just checking something
df[df.revenue < 0]  # huh, why are there negative values
# ...twenty more cells like this
# the same query, referenced directly in a Pyodide node —
# no dataframe copy-pasted, no re-running the whole notebook
df = infig.query("quarterly_revenue_by_region")

Because Infigured's Python nodes run on Pyodide against workspace-level queries rather than local files, the "clean version" isn't a rebuild of the notebook — it's a small number of nodes referencing the same query object the notebook used, arranged with markdown commentary around them. The notebook stays your scratch space. The document is what you send.

The actual win

It's not that this replaces notebooks — notebooks remain the right tool for exploration. It's that the deliverable no longer has to be a compromise between "the notebook" and "a from-scratch rebuild." It's a small, direct extraction of the two or three things that mattered, live against the same data.


Related: Streamlit vs. a Shareable Dashboard: When You Don't Need an App

Continue the workflow

Explore related guides

Next step

Move from insight to a stakeholder-ready story.

Infigure helps teams replace the export-to-slides loop with one connected reporting workflow for analysis, narrative, and delivery.