Jupyter Book
GitHub Overview
jupyter-book/jupyter-book
Create beautiful, publication-quality books and documents from computational content.
Topics
Star History
Documentation Tool
Jupyter Book
Overview
Jupyter Book is an open-source tool for creating beautiful, publication-quality books and documents from Jupyter notebooks and Markdown files. It has become the de facto standard for researchers and educators to publish computational narratives.
Details
Jupyter Book was developed in 2019 as part of the Executable Books project and has revolutionized the sharing of computational science content. It combines the power of the Sphinx documentation engine with the interactivity of Jupyter notebooks to create high-quality research and educational publications. It supports MyST Markdown (Markedly Structured Text), allowing you to use all Sphinx features in Markdown. It handles Jupyter notebooks and Markdown files uniformly, generating academic-quality documents that include executable code, mathematical equations, figures, and references. As of 2025, it powers over 14,000 open online textbooks, knowledge bases, lectures, courses, and community sites. Jupyter Book 2.0 provides fully interactive and executable outputs powered by JupyterHub/Binder, browser-based Python execution through Pyodide/JupyterLite, and rich hover preview features. Built on the MyST-MD document engine, it's evolving as a next-generation tool for sharing computational content. Integration with Sphinx-Thebe enables readers to edit and execute code directly in their browsers.
Advantages and Disadvantages
Advantages
- Jupyter Notebook Integration: Unified handling of notebooks and Markdown with executable content
- High-Quality Output: Multiple publication-quality formats including HTML, PDF, ePub
- MyST Markdown: Full Sphinx functionality available in Markdown
- Interactive Features: Browser-based code execution and live interaction
- Sphinx Foundation: Rich Sphinx extensions and theme system utilization
- Academic Features: Mathematical equations, citations, cross-references, indexes for academic publishing
- Open Source: Free for commercial use with active community support
Disadvantages
- Python Dependency: Requires knowledge of Python and Jupyter ecosystem
- Learning Curve: Time needed to understand MyST Markdown syntax and Sphinx
- Build Time: Increased build time when executing large numbers of notebooks
- Configuration Complexity: Detailed configuration knowledge needed for advanced customization
- Version Compatibility: Configuration changes required for Jupyter Book 2.0 migration
- Resource Requirements: High memory and CPU usage for large-scale projects
Key Links
- Jupyter Book Official Site
- Jupyter Book 2.0 Documentation
- GitHub Repository
- Executable Books Project
- MyST Markdown Documentation
- Sphinx Book Theme
Usage Examples
Project Initialization
# Install Jupyter Book
pip install jupyter-book
# Create new book project
jupyter-book create my-book
# Project structure
my-book/
├── _config.yml # Configuration file
├── _toc.yml # Table of contents
├── intro.md # Introduction page
├── notebooks.ipynb # Sample notebook
├── markdown.md # Markdown page
├── markdown-notebooks.md # Jupyter notebooks in Markdown
└── references.bib # Bibliography
Configuration File (_config.yml)
# _config.yml - Jupyter Book configuration
title: "Computational Science Textbook"
author: "Researcher Name"
copyright: "2025"
logo: logo.png
# Force re-execution of notebooks on each build
execute:
execute_notebooks: force
# Define the name of the latex output file for PDF builds
latex:
latex_documents:
targetname: book.tex
# Add a bibtex file so that we can create citations
bibtex_bibfiles:
- references.bib
# Information about where the book exists on the web
repository:
url: https://github.com/user/my-book
path_to_book: docs
branch: main
# Configure your Binder links
launch_buttons:
notebook_interface: "classic"
binderhub_url: "https://mybinder.org"
colab_url: "https://colab.research.google.com"
jupyterhub_url: "https://datahub.berkeley.edu"
thebe: true
# Configure Sphinx extensions
sphinx:
extra_extensions:
- sphinx_inline_tabs
- sphinx_proof
- sphinx_examples
config:
html_show_sourcelink: false
html_js_files:
- https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js
# HTML-specific settings
html:
favicon: favicon.ico
home_page_in_navbar: false
use_repository_button: true
use_issues_button: true
use_edit_page_button: true
navbar_number_sections: false
announcement: "📢 This textbook is currently under development!"
google_analytics_id: G-XXXXXXXXXX
# Interact link settings
launch_buttons:
colab_url: https://colab.research.google.com
notebook_interface: classic
binderhub_url: https://mybinder.org
jupyterhub_url: https://datahub.berkeley.edu
thebe: true
# Parse and render settings
parse:
myst_enable_extensions:
- amsmath
- colon_fence
- deflist
- dollarmath
- html_image
- html_admonition
- linkify
- replacements
- smartquotes
- substitution
- tasklist
myst_url_schemes: [mailto, http, https]
Table of Contents File (_toc.yml)
# _toc.yml - Table of contents structure
format: jb-book
root: intro
title: Table of Contents
chapters:
- file: chapter1/overview
title: Chapter 1: Overview
sections:
- file: chapter1/introduction
title: 1.1 Introduction
- file: chapter1/setup
title: 1.2 Environment Setup
- file: chapter2/basics
title: Chapter 2: Fundamentals
sections:
- file: chapter2/theory
title: 2.1 Theory
- file: chapter2/examples
title: 2.2 Examples
- file: chapter2/exercises
title: 2.3 Exercises
- file: notebooks/data-analysis
title: Chapter 3: Data Analysis
sections:
- file: notebooks/numpy-tutorial
title: 3.1 NumPy Introduction
- file: notebooks/pandas-tutorial
title: 3.2 Pandas Introduction
- file: notebooks/visualization
title: 3.3 Data Visualization
- file: advanced/index
title: Chapter 4: Advanced Applications
sections:
- file: advanced/machine-learning
title: 4.1 Machine Learning
- file: advanced/deep-learning
title: 4.2 Deep Learning
- file: references
title: References
MyST Markdown Usage
# Introduction to Computational Science
```{epigraph}
All science is computational science.
-- John von Neumann
Mathematical Equations and Code
Inline Mathematics
The Gaussian function is represented as $f(x) = \frac{1}{\sqrt{2\pi\sigma^2}}e^{-\frac{(x-\mu)^2}{2\sigma^2}}$.
Block Mathematics
:label: gaussian
f(x) = \frac{1}{\sqrt{2\pi\sigma^2}}e^{-\frac{(x-\mu)^2}{2\sigma^2}}
Code Blocks
:tags: [hide-input]
import numpy as np
import matplotlib.pyplot as plt
# Gaussian function implementation
def gaussian(x, mu=0, sigma=1):
return (1 / np.sqrt(2 * np.pi * sigma**2)) * np.exp(-0.5 * ((x - mu) / sigma)**2)
# Plotting
x = np.linspace(-5, 5, 100)
y = gaussian(x)
plt.figure(figsize=(8, 5))
plt.plot(x, y, 'b-', linewidth=2, label='Gaussian Function')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.title('Gaussian Function Plot')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
Admonitions and Boxes
This is an important note.
This operation requires caution.
Here's a useful tip for you.
This is important information.
Executable Content
:tags: [hide-output]
# Interactive example
import ipywidgets as widgets
from IPython.display import display
def f(x):
return x ** 2
interactive_plot = widgets.interactive(f, x=10)
display(interactive_plot)
References and Citations
Please refer to equation {eq}gaussian
. For details, see {cite}author2023book
.
Proofs and Theorems
:label: clt
For independent and identically distributed random variables $X_1, X_2, \ldots, X_n$
with finite mean $\mu$ and variance $\sigma^2$, as $n \to \infty$,
the distribution of the sample mean converges to a normal distribution.
The proof is omitted. Please refer to probability theory textbooks for details.
Tabs and Panels
````{tab-item} Python
```python
def hello():
print("Hello, Python!")
````{tab-item} R
```r
hello <- function() {
print("Hello, R!")
}
```
```julia
function hello()
println("Hello, Julia!")
end
```
## Figures and Captions
```{figure} images/diagram.png
:height: 300px
:name: system-diagram
Overall system architecture diagram. This figure visually explains important concepts.
As shown in {numref}system-diagram
, the system consists of three main components.
### Interactive Content Configuration
```python
# content.py - Interactive content configuration
from IPython.display import display, HTML
import ipywidgets as widgets
import matplotlib.pyplot as plt
import numpy as np
# Thebe configuration for live code execution
def setup_thebe():
"""Configure Thebe for live code execution"""
thebe_html = """
<script type="text/x-thebe-config">
{
requestKernel: true,
binderOptions: {
repo: "binder-examples/jupyter-stacks-datascience",
ref: "master",
},
codeMirrorConfig: {
theme: "abcdef",
lineNumbers: true
},
kernelOptions: {
kernelName: "python3",
path: "./content"
},
predefinedOutput: true
}
</script>
<script type="text/javascript" src="https://unpkg.com/thebe@latest/lib/index.js"></script>
"""
return HTML(thebe_html)
# Interactive visualization
def interactive_plot():
"""Create interactive plot"""
def plot_function(freq, amplitude, phase):
x = np.linspace(0, 4*np.pi, 100)
y = amplitude * np.sin(freq * x + phase)
plt.figure(figsize=(8, 4))
plt.plot(x, y, 'b-', linewidth=2)
plt.title(f'sin({freq}x + {phase:.2f}) × {amplitude}')
plt.xlabel('x')
plt.ylabel('y')
plt.grid(True, alpha=0.3)
plt.show()
# Create widgets
freq_slider = widgets.FloatSlider(
value=1.0, min=0.1, max=5.0, step=0.1,
description='Frequency:', style={'description_width': 'initial'}
)
amp_slider = widgets.FloatSlider(
value=1.0, min=0.1, max=3.0, step=0.1,
description='Amplitude:', style={'description_width': 'initial'}
)
phase_slider = widgets.FloatSlider(
value=0.0, min=0, max=2*np.pi, step=0.1,
description='Phase:', style={'description_width': 'initial'}
)
# Interactive plot
interactive_widget = widgets.interactive(
plot_function,
freq=freq_slider,
amplitude=amp_slider,
phase=phase_slider
)
return interactive_widget
# Data analysis dashboard
def data_dashboard():
"""Data analysis dashboard"""
import pandas as pd
# Sample data
data = pd.DataFrame({
'x': np.random.randn(100),
'y': np.random.randn(100),
'category': np.random.choice(['A', 'B', 'C'], 100)
})
def update_plot(category, plot_type):
filtered_data = data[data['category'] == category] if category != 'All' else data
plt.figure(figsize=(8, 5))
if plot_type == 'Scatter':
plt.scatter(filtered_data['x'], filtered_data['y'], alpha=0.7)
elif plot_type == 'Histogram':
plt.hist(filtered_data['x'], bins=20, alpha=0.7)
plt.title(f'{plot_type} Plot - Category: {category}')
plt.xlabel('X Value')
plt.ylabel('Y Value' if plot_type == 'Scatter' else 'Frequency')
plt.grid(True, alpha=0.3)
plt.show()
category_dropdown = widgets.Dropdown(
options=['All', 'A', 'B', 'C'],
value='All',
description='Category:'
)
plot_type_dropdown = widgets.Dropdown(
options=['Scatter', 'Histogram'],
value='Scatter',
description='Plot Type:'
)
return widgets.interactive(update_plot, category=category_dropdown, plot_type=plot_type_dropdown)
Advanced Configuration and Customization
# advanced_config.py - Advanced Jupyter Book configuration
import os
from jupyter_book.config import Config
class CustomJupyterBookConfig:
"""Custom Jupyter Book configuration class"""
def __init__(self, book_path):
self.book_path = book_path
self.config = self.load_config()
def load_config(self):
"""Load configuration file"""
config_path = os.path.join(self.book_path, '_config.yml')
return Config(config_path)
def setup_custom_css(self):
"""Setup custom CSS"""
custom_css = """
/* Custom styles */
.jupyter-book-container {
max-width: 1200px;
}
.code-cell {
border-left: 3px solid #3498db;
padding-left: 10px;
}
.output-area {
background-color: #f8f9fa;
border-radius: 5px;
padding: 10px;
margin-top: 10px;
}
.admonition {
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.math {
font-size: 1.1em;
}
/* Responsive design */
@media (max-width: 768px) {
.jupyter-book-container {
max-width: 100%;
padding: 0 15px;
}
}
"""
css_path = os.path.join(self.book_path, '_static', 'custom.css')
os.makedirs(os.path.dirname(css_path), exist_ok=True)
with open(css_path, 'w', encoding='utf-8') as f:
f.write(custom_css)
return css_path
def setup_custom_javascript(self):
"""Setup custom JavaScript"""
custom_js = """
// Custom JavaScript
document.addEventListener('DOMContentLoaded', function() {
// Add copy functionality to code cells
addCopyButtons();
// Improve math rendering
improveMathRendering();
// Initialize interactive elements
initializeInteractiveElements();
});
function addCopyButtons() {
const codeBlocks = document.querySelectorAll('pre code');
codeBlocks.forEach(function(block) {
const button = document.createElement('button');
button.textContent = 'Copy';
button.className = 'copy-button';
button.onclick = function() {
navigator.clipboard.writeText(block.textContent);
button.textContent = 'Copied!';
setTimeout(() => {
button.textContent = 'Copy';
}, 2000);
};
block.parentNode.appendChild(button);
});
}
function improveMathRendering() {
// Improve MathJax configuration
if (window.MathJax) {
MathJax.Hub.Config({
tex2jax: {
inlineMath: [['$', '$'], ['\\(', '\\)']],
displayMath: [['$$', '$$'], ['\\[', '\\]']],
processEscapes: true
}
});
}
}
function initializeInteractiveElements() {
// Initialize Thebe buttons
if (window.thebelab) {
thebelab.bootstrap();
}
// Improve tab functionality
const tabs = document.querySelectorAll('.tab-set');
tabs.forEach(initializeTabSet);
}
function initializeTabSet(tabSet) {
const tabButtons = tabSet.querySelectorAll('.tab-button');
const tabContents = tabSet.querySelectorAll('.tab-content');
tabButtons.forEach((button, index) => {
button.addEventListener('click', () => {
// Deactivate all tabs
tabButtons.forEach(btn => btn.classList.remove('active'));
tabContents.forEach(content => content.classList.remove('active'));
// Activate clicked tab
button.classList.add('active');
tabContents[index].classList.add('active');
});
});
}
"""
js_path = os.path.join(self.book_path, '_static', 'custom.js')
with open(js_path, 'w', encoding='utf-8') as f:
f.write(custom_js)
return js_path
def generate_bibliography(self):
"""Generate bibliography automatically"""
bib_content = """
@book{author2023book,
title={Introduction to Computational Science},
author={Researcher, Taro},
year={2023},
publisher={Academic Press}
}
@article{smith2024analysis,
title={Data Analysis with Python},
author={Smith, John and Johnson, Mary},
journal={Journal of Computational Science},
volume={15},
pages={123--145},
year={2024}
}
@inproceedings{tanaka2023machine,
title={Recent Trends in Machine Learning},
author={Tanaka, Hanako and Sato, Jiro},
booktitle={Proceedings of AI Conference},
pages={A1-01},
year={2023}
}
"""
bib_path = os.path.join(self.book_path, 'references.bib')
with open(bib_path, 'w', encoding='utf-8') as f:
f.write(bib_content)
return bib_path
Build and Deployment Automation
# .github/workflows/deploy-book.yml
name: Build and Deploy Jupyter Book
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: 3.9
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install jupyter-book
- name: Build the book
run: |
jupyter-book build .
- name: Deploy to GitHub Pages
if: github.ref == 'refs/heads/main'
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./_build/html
force_orphan: true
Development and Build Commands
# Basic build commands
jupyter-book build my-book/
# Clean build (clear cache)
jupyter-book clean my-book/
jupyter-book build my-book/
# Build specific pages only
jupyter-book build my-book/ --path-output ./output
# Development server with live reload
pip install sphinx-autobuild
sphinx-autobuild my-book/_build/html my-book/ --port 8000
# PDF generation
jupyter-book build my-book/ --builder pdflatex
# Build both HTML and PDF
jupyter-book build my-book/ --all
# Cache management
jupyter-book cache clear my-book/
jupyter-book cache show my-book/
# Configuration validation
jupyter-book config sphinx my-book/
# Debug mode
jupyter-book build my-book/ --verbose
# Parallel execution for faster builds
jupyter-book build my-book/ -j 4