Traditional Python development separates three things:
.py files)NBDev believes all three should live in one place — your notebook!
"Write once, get everything automatically."
From a single notebook in nbs/, NBDev automatically generates:
| Output | Command |
|---|---|
.py package files |
nbdev_export |
| Documentation website | nbdev_docs |
| PyPI package | nbdev_pypi |
| README.md | nbdev_readme |
your-project/
├── nbs/ # Your source notebooks (edit here!)
│ ├── 00_core.ipynb # Your main module
│ ├── index.ipynb # Documentation homepage + README
│ ├── _quarto.yml # Quarto styling config
│ └── styles.css # Custom CSS for docs
├── your_library/ # Auto-generated .py files (don't edit!)
│ └── core.py
├── _proc/ # Auto-generated docs (don't edit!)
├── .github/workflows/ # CI/CD automation
│ ├── test.yml # Runs tests on every push
│ └── deploy.yml # Deploys docs on every push
├── pyproject.toml # Package configuration
├── README.md # Auto-generated from index.ipynb
├── LICENSE # Your project license
└── MANIFEST.in # Extra files to include in package
This is your project's settings file. The most important section is dependencies:
[project]
name = "your-library"
version = "0.1.0"
description = "Your library description"
dependencies = ["fasthtml", "numpy"]
dependencies!
#| DirectivesThese are NBDev's instructions inside code cells:
| Directive | Purpose |
|---|---|
#| default_exp core |
Export this notebook to core.py |
#| export |
Include this cell in the .py file |
#| hide |
Hide this cell from documentation |
| Cell Type | Exported? | In Docs? | In Tests? |
|---|---|---|---|
Code + #| export |
✅ Yes | ✅ Yes | ✅ Yes |
Code without #| export |
❌ No | ✅ Yes | ✅ Yes |
Code + #| hide |
❌ No | ❌ No | ✅ Yes |
| Note/Markdown | ❌ No | ✅ Yes | ❌ No |
Just add assert in any non-exported code cell:
assert add(2, 3) == 5 # passes ✅
assert add(2, 3) == 6 # fails ❌
Use show_doc() to display nicely formatted function docs:
from nbdev.showdoc import *
show_doc(your_function)
# Install NBDev
pip install nbdev
# Install Quarto (for docs)
wget https://quarto.org/download/latest/quarto-linux-amd64.deb
sudo dpkg -i quarto-linux-amd64.deb
# Create new NBDev project
gh repo create # create GitHub repo
git clone <repo-url> # clone it
cd <repo>
nbdev_new # initialize NBDev
# Install your library in editable mode (do once)
pip install -e .
# After making changes to notebooks
nbdev_clean # clean notebook metadata
nbdev_export # export to .py files
nbdev_test # run all tests
# Push to GitHub
git add .
git commit -m "your message"
git push
# Build docs locally
nbdev_docs
# Generate README from index.ipynb
nbdev_readme
# Upload to PyPI (do once: register at pypi.org)
nbdev_pypi
Edit notebook in nbs/
↓
nbdev_clean → removes messy metadata
↓
nbdev_export → generates .py files
↓
nbdev_test → runs all tests
↓
git push → triggers GitHub Actions
↓
GitHub Actions → runs CI tests automatically
↓
nbdev_docs → builds documentation
↓
GitHub Pages → hosts documentation website
NBDev sets up two GitHub Actions automatically:
test.yml — runs on every push:
.pydeploy.yml — runs after tests pass:
gh-pages branch
(Do this once per repo)
.py files directly — always edit the notebook and run nbdev_exportnbdev_clean before pushing — keeps git history clean00_, 01_) for notebook order.py moduleindex.ipynb = your homepage + README
Happy building!