Emailing the .ipynb, GitHub, nbviewer, Colab, Binder, a PDF, or an HTML export on a link: what each one is built for, what the reader needs, and the export trap that makes Plotly charts disappear without an error.
The analysis is done. The notebook runs top to bottom, the charts look right, and the person waiting on it (a PM, a client, your supervisor) has never installed Python. Send them the .ipynb and they open a wall of JSON.
There are half a dozen ways around that. They split on one question, and most of the confusion comes from skipping it.
Most people asking this want the first one, and most advice answers the second.
Running it means a kernel: a live Python process that executes cells. The reader changes a parameter, re-runs a cell, and sees a new result. Only a few of the options below give them that, and every one of them asks something: the notebook living in Google Drive, or a public repository and a wait.
Reading it means a snapshot: the markdown, the code if you want it shown, and the outputs exactly as they were when you last ran it. That's what a stakeholder usually needs. They want the chart and the sentence under it, not the environment that produced them. A snapshot is lighter on both ends, and there are more ways to send one.
Answer that first and you've ruled out half the list.
| Way | What the reader gets | What it's built for | Where it gets awkward |
|---|---|---|---|
| Email the .ipynb | A JSON file, unless they have Jupyter or an editor that renders notebooks | Handing the source to another notebook user | Anyone outside a data team opens raw JSON, or can't open it at all |
| GitHub | A rendered, read-only view of the notebook inside the repository | Notebooks that live in a repo next to the code | The repo is public, or the reader needs a GitHub account with access to a private one |
| nbviewer | A rendered, read-only page | Notebooks already published at a public address | It renders from a public URL, so the notebook has to be public before anyone can view it |
| Google Colab | The notebook in Colab, where they can run and edit cells | Letting someone run and tweak the analysis themselves | The notebook is stored in Google Drive and shared like a Drive file |
| Binder | A temporary live Jupyter session built from a repository | A runnable, reproducible demo | Builds from a public repository, can take a while to start, and the session doesn't last |
| A fixed document | Printing, or a formal submission that asks for a PDF | Nothing hovers or zooms, and nbconvert's PDF export needs extra tooling installed | |
| HTML export on a private link | The rendered notebook in any browser, nothing to install | Findings going to specific people | A read-only snapshot; check the file size and every chart before sending |
Checked against each project's own documentation on 1 October 2026. Tools change how they share and what they ask of the reader, so check their docs for what's current.
Two of these are really the same move. nbviewer and GitHub both show a notebook that is already public on the web. If your analysis is open work (a tutorial, a paper's companion notebook, a public dataset), that's the natural home, and there's no reason to move it.
The email row is where most people start and where it goes wrong. Even when the reader can open an .ipynb, you've sent a copy you can't correct. An email attachment vs a link for deliverables covers the size limits and the frozen-copy problem in more detail.
This is the part nobody warns you about, so we ran it. On 30 September 2026 we executed a notebook headless and exported it with nbconvert, the same way you would from a script or a scheduled job.
Matplotlib came through fine. Each figure was embedded in the HTML as an image. Nothing to configure.
Plotly vanished. With no renderer set, the executed notebook saved each figure only as Plotly's JSON data (the application/vnd.plotly.v1+json output type). The HTML exporter had nothing to draw with it. There was no warning and no error, just a gap where each chart should have been. If you don't open the export yourself, the first person to notice is your reader.
Setting a renderer brings them back. Put this near the top of the notebook, before any figure is created:
import plotly.io as pio
pio.renderers.default = "notebook"
That writes the plotting library into the notebook's output, so the export can draw every chart, offline. It also makes the file big: our export came out at 5.1 MB. The other option, notebook_connected, loads the library from Plotly's CDN instead of packing it in. The file stays small, but the reader has to be online, and on a network that lets that request through.
To hide the code, export without the input cells:
jupyter nbconvert --to html --execute --no-input analysis.ipynb
--no-input keeps the markdown and the outputs and drops the code. For a PM or a client, that's usually the version they'd actually read.
Whichever settings you use, open the exported HTML in a browser and scroll past every chart before it goes anywhere. It takes a minute, and it's the only check that catches the silent failure above.
--no-input and share that file as a private link.One thing not to do with the HTML export: upload it to Google Drive and send the Drive link. Drive shows an HTML file as its source code rather than the page, and here's why that happens.
Your outputs are content. Every route above ships what's saved in the output cells: a printed dataframe with real client rows, an environment variable you echoed while debugging, a traceback with your home directory in the path. --no-input hides the code, not the outputs. Look through the export for anything that shouldn't leave the building, and remove it at the source before you run the export again.
A snapshot doesn't update itself. The numbers in a static export are the numbers from your last run. When the data changes, you run it again and export again. What a link can do is point at the new export. It can't refresh the old one.
A static page doesn't run code. If the conversation is going to be "what happens if we change this threshold?", a snapshot will only answer the thresholds you already tried. That's the job Colab and Binder are for.
That's the job miinideck is built around: a finished analysis, going to specific people, who need to read it without installing anything.
You export the notebook to HTML and upload that one file. The reader opens the link and the whole thing renders in their browser (markdown, tables, figures, and the code if you left it in), on a laptop or a phone, with no Python, no Jupyter and no account on their side.
The link ends in 32 random characters, so nobody can guess it, and the page tells search engines not to index it. Anyone you send it to can open it, and so can anyone they forward it to. When that isn't enough, add a password. It's free on any account.
After you send it, the link is still yours:
Watch the file size, because the Plotly trap above has a second edge. A No-account upload takes files up to 3 MB, runs for 7 days, and can't be replaced. The bundled Plotly export from our test was over that line. The Free tier takes 10 MB per file, which fits it. Solo ($4.99/mo) takes 25 MB and Studio ($14.99/mo) takes 50 MB. The notebook_connected renderer is the other way to shrink it, if your reader will be online.
If the notebook is meant to be public, you want a public host instead, and the single-file hosting comparison covers those. For everything else about where a file can live and who it's for, see where to put a file online.
If your export is ready, host a Jupyter notebook as a link walks through the upload. If someone just sent you an .ipynb and you need to read it, the ipynb viewer renders it in your browser without uploading it anywhere.
A test send, your ESP's preview, a rendering-test service, a screenshot, the .html as an attachment, or a hosted page link: what each one shows the client, what a browser preview can and can't prove about an email, and the combination that gets sign-off without surprises.
Postman's published docs, SwaggerHub, a hosted docs portal, GitHub Pages, the raw OpenAPI file, or one rendered HTML page behind a private link: what each is built for, how to turn a spec into a single page with one command, and what to strip out before anyone outside sees it.
Quarto Pub, RPubs, Posit Connect Cloud, GitHub Pages or Netlify, an HTML attachment, or a private link: what each one is built for, why a rendered report loses its styling when you send the HTML on its own, and which route fits a report meant for a client or an advisor.
miinideck turns a single HTML file into an unguessable link with optional password and expiry. Default-private, never indexed.