Jupyter Book

GitHub Overview

jupyter-book/jupyter-book

Create beautiful, publication-quality books and documents from computational content.

Stars4,092
Watchers59
Forks700
Created:June 14, 2018
Language:Python
License:BSD 3-Clause "New" or "Revised" License

Topics

documentation-generatorjupytersphinx-doc

Star History

jupyter-book/jupyter-book Star History
Data as of: 7/17/2025, 02:30 AM

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

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