Appearance
To share an executable notebook, put it in a public Git repository with an environment file that pins your dependencies, then expose it through a service like Binder, which builds a container from that repository and launches a live, in-browser session anyone can run. The reader clicks a badge, waits for the build, and executes your analysis end to end — no install, no "works on my machine". The two things that make or break this are an honest environment file and keeping data out of the repository.
Step 1: Make the repository self-describing
Binder and similar tools build only from what your repository declares. Add one environment file at the root. The most portable choice is requirements.txt, but environment.yml (conda) or a pinned uv.lock also work.
text
# requirements.txt
pandas==2.2.2
matplotlib==3.9.0
jupyterlab==4.2.0Pin versions. An unpinned file builds today and breaks in six months when an upstream release changes behaviour. If you need system libraries (for example tesseract for OCR), add an apt.txt listing them.
Step 2: Add a Binder badge and test the build
Push to GitHub, then go to mybinder.org, paste the repository URL, and launch. Copy the generated badge into your README so readers can click straight in:
markdown
[](https://mybinder.org/v2/gh/USER/REPO/HEAD)The first build can take several minutes while Binder assembles the image; subsequent launches are cached and faster. Always test the badge from a private browser window — that is the experience your reader gets.
Why won't my notebook run on Binder when it works locally?
Three causes account for nearly every failure:
- Undeclared packages — you
import seabornbut never listed it. Binder has only what your environment file names. - Hard-coded absolute paths —
/home/elara/data/...does not exist in the container. Use relative paths. - Missing data — the notebook reads
corpus.csvthat lives only on your laptop.
Fix the third by fetching data at runtime instead of committing it:
python
import pathlib, urllib.request
p = pathlib.Path("data/corpus.csv")
if not p.exists():
p.parent.mkdir(exist_ok=True)
urllib.request.urlretrieve(
"https://zenodo.org/record/XXXX/files/corpus.csv", p)Which sharing route should I choose?
| Tool | Runs code? | Login | Your exact env? | Persistence |
|---|---|---|---|---|
| nbviewer / HTML export | No | No | n/a | High (static) |
| Google Colab | Yes | Google account | No (Colab stack) | Session-based |
| Binder | Yes | No | Yes (declared) | Ephemeral |
| JupyterLite | Yes (in-browser) | No | Limited (pure-Python) | Static hosting |
For a quick, login-free "click and run" of your environment, Binder wins. For zero-build, server-less hosting of pure-Python notebooks, JupyterLite is increasingly viable. For long-term preservation, neither is enough on its own.
How do I make a shared notebook survive for years?
Binder is a convenience layer, not an archive — images and free services change. For durability, pin everything, then deposit a snapshot of the repository and a sample dataset to Zenodo, which mints a DOI and keeps an immutable copy. Cite that DOI, and link the Binder badge as the live, runnable mirror. That combination gives readers both "run it now" and "still here in 2035".
Key Takeaways
- An executable notebook ships with its environment so readers can run it, not just view outputs.
- Binder builds a live container from a public repo's pinned environment file — no login required.
- Declare every package and avoid absolute paths; the container has only what you commit.
- Keep data out of the repo: fetch a sample at runtime or pull from a DOI in the first cell.
- Choose by need: nbviewer to view, Colab for Google's stack, Binder for your exact environment.
- Pair Binder with a Zenodo deposit for long-term, citable preservation.
Frequently Asked Questions
What does it mean to share an executable notebook?
It means giving readers a notebook they can actually run in a browser, with the environment provided, rather than a static PDF or a screenshot of outputs. Tools like Binder build a live container from your repository so anyone can click and execute.
What is Binder and how does it work?
Binder (mybinder.org) reads your Git repository, builds a Docker image from your environment files, and launches a temporary JupyterLab session in the browser. It is free and needs no login, but sessions are ephemeral and time-limited.
Why won't my notebook run on Binder when it works locally?
Usually a missing or under-pinned environment file, or hard-coded local paths and large data files that aren't in the repo. Binder only has what your repository declares, so undeclared packages and absent data both break it.
What is the difference between Binder, Colab and a static export?
A static export (nbviewer, HTML) shows outputs but can't run. Colab runs notebooks on Google infrastructure with a login and its own preinstalled stack. Binder runs your exact declared environment with no login, but is slower to build and ephemeral.
How do I make sure my shared notebook keeps working in years to come?
Pin your dependencies, archive a snapshot of the repository and data to Zenodo for a DOI, and don't rely on Binder alone — it is a convenience layer, not long-term preservation.
How big can the data be for a Binder-shared notebook?
Keep the repository light — ideally under a few hundred megabytes. For larger corpora, fetch a sample at launch or download from a DOI in the first cell rather than committing the data.