Install

jupyter/notebook

Jupyter Notebook v7 Wiki

Last updated on Dec 17, 2025 (Commit: 9836de4)

Overview

Relevant Files
  • README.md
  • pyproject.toml
  • package.json
  • CONTRIBUTING.md
  • notebook/app.py
  • packages/application/src/app.ts
  • app/index.template.js

Jupyter Notebook is a web-based interactive computing environment that enables users to create and share documents containing live code, equations, visualizations, and narrative text. The project maintains two major versions: Notebook v7 (modern, actively developed) and Classic Notebook v6 (maintenance-only).

Architecture Overview

Jupyter Notebook v7 represents a significant architectural shift from earlier versions. It combines two core components:

  • Python Backend: Built on Jupyter Server, providing the HTTP API, kernel management, and file operations
  • JavaScript/TypeScript Frontend: Built on JupyterLab components, delivering the interactive user interface
Loading diagram...

Monorepo Structure

The project uses a monorepo architecture with Lerna and Yarn workspaces:

  • notebook/ - Python package containing the server extension and configuration
  • packages/ - TypeScript/JavaScript packages for frontend components:
    • application - Core NotebookApp and shell
    • notebook-extension - Notebook-specific plugins (checkpoints, metadata, etc.)
    • tree-extension - File browser and tree view
    • ui-components - Shared UI components
    • console-extension, terminal-extension, help-extension - Additional features
  • app/ - Main application entry point and build configuration
  • tests/ - Python backend tests
  • ui-tests/ - End-to-end UI tests using Playwright

Key Technologies

Backend (Python):

  • Jupyter Server (>=2.4.0) - HTTP server and extension system
  • Tornado (>=6.2.0) - Async web framework
  • Python 3.9+ support

Frontend (TypeScript/JavaScript):

  • JupyterLab (>=4.6.0) - UI framework and components
  • React 18 - Component library
  • Lumino - Widget system
  • Rspack - Module bundler

Development Workflow

The project requires both Python and Node.js environments. Key commands:

  • jlpm - JupyterLab's pinned Yarn version (recommended over npm)
  • jlpm build - Build all packages
  • jlpm watch - Watch mode for development
  • jlpm develop - Link extensions for local development
  • jupyter notebook - Launch the application

Multi-Page Architecture

Notebook v7 supports multiple pages (tree, notebook, console, terminal, edit) with page-specific plugins. The app dynamically loads plugins based on the current page, enabling efficient resource usage and modular feature development.

Architecture & Data Flow

Relevant Files
  • notebook/app.py - Python backend server application
  • app/index.template.js - Frontend entry point and plugin loader
  • packages/application/src/app.ts - NotebookApp class (frontend)
  • packages/application/src/shell.ts - NotebookShell UI layout manager
  • app/package.json - Frontend dependencies and plugin configuration

Jupyter Notebook v7 is a full-stack web application with a clear separation between Python backend and TypeScript frontend. The architecture follows a plugin-based design where the server delivers configuration and the client dynamically loads extensions.

Backend Server (Python)

The Python backend is built on Jupyter Server and JupyterLab Server. The main entry point is JupyterNotebookApp in notebook/app.py, which extends LabServerApp. It serves multiple HTTP handlers for different routes:

  • /tree - File browser and directory listing
  • /notebooks - Notebook editor interface
  • /edit - File editor for non-notebook files
  • /consoles - Console interface
  • /terminals - Terminal interface

Each handler extends NotebookBaseHandler and renders an HTML template with embedded page configuration. The get_page_config() method assembles configuration data including app version, base URLs, authentication tokens, and JupyterHub metadata (if applicable).

Frontend Bootstrap

When a user navigates to any route, the server renders an HTML template containing a <script> tag with page configuration as JSON. The template loads app/index.template.js, which is the frontend entry point.

The bootstrap process:

  1. Load plugins - Fetch federated extension modules from the server
  2. Initialize plugin registry - Register base plugins and federated extensions
  3. Create service manager - Establish connection to Jupyter Server APIs
  4. Instantiate NotebookApp - Create the main application instance with the plugin registry and service manager
  5. Start application - Call app.start() to initialize all plugins and render the UI

Frontend Application Architecture

The NotebookApp class (in packages/application/src/app.ts) extends JupyterFrontEnd and manages the overall application lifecycle. It:

  • Registers MIME renderer plugins for different output types
  • Maintains a document registry for file type handlers
  • Provides a plugin system for extensions to hook into the application
  • Exposes application info and paths to plugins via PageConfig

The NotebookShell class (in packages/application/src/shell.ts) manages the UI layout with six distinct areas:

  • top - Header and toolbar area
  • menu - Menu bar
  • main - Central content area (single widget)
  • left - Left sidebar (collapsible)
  • right - Right sidebar (collapsible)
  • down - Bottom panel (tabs for console, terminal, etc.)

Plugins add widgets to these areas using the add() method, which respects user layout customizations stored in _userLayout.

Data Flow

Loading diagram...

The frontend communicates with the server via REST APIs and WebSockets. The IServiceManager (from JupyterLab services) handles all server communication, including notebook content, kernel execution, and settings management.

Plugin System

Plugins are registered in app/package.json under the jupyterlab.plugins section, organized by page route (/, /tree, /notebooks, etc.). Each plugin declares its dependencies, optional services, and provided tokens. The plugin registry resolves dependencies and initializes plugins in the correct order, enabling a modular and extensible architecture.

Python Backend & Server Extension

Relevant Files
  • notebook/app.py
  • notebook/init.py
  • notebook/main.py
  • app/templates/tree_template.html
  • app/templates/notebooks_template.html

The Python backend serves as the Jupyter Notebook server extension, built on top of JupyterLab's server infrastructure. It provides HTTP handlers for rendering notebook pages, managing file navigation, and configuring the frontend application.

Core Architecture

The backend is structured around a single main application class, JupyterNotebookApp, which extends LabServerApp from jupyterlab_server. This class inherits configuration management, static file serving, and extension loading capabilities from the JupyterLab ecosystem.

class JupyterNotebookApp(NotebookConfigShimMixin, LabServerApp):
    """The notebook server extension app."""
    name = "notebook"
    default_url = Unicode("/tree", config=True)
    extension_url = "/"

The app is registered as a Jupyter server extension through entry points defined in notebook/__init__.py, allowing it to be discovered and loaded by the Jupyter server automatically.

HTTP Request Handlers

The backend defines six specialized request handlers, all inheriting from NotebookBaseHandler:

  • TreeHandler (/tree) - Displays directory listings or redirects to notebooks/files
  • NotebookHandler (/notebooks) - Renders the notebook editor interface
  • FileHandler (/edit) - Renders the file editor interface
  • ConsoleHandler (/consoles) - Renders the console interface
  • TerminalHandler (/terminals) - Renders the terminal interface
  • CustomCssHandler (/custom/custom.css) - Serves custom CSS from the Jupyter config directory

Each handler is decorated with @web.authenticated to enforce authentication and uses Jinja2 templates to render HTML pages.

Page Configuration System

The NotebookBaseHandler.get_page_config() method constructs a comprehensive configuration object passed to the frontend as JSON. This includes:

  • Application metadata (version, base URL, token)
  • Feature flags (terminals available, custom CSS enabled)
  • JupyterHub integration settings (if running under JupyterHub)
  • MathJax configuration for equation rendering
  • All LabConfig traits converted to camelCase for JavaScript consumption
  • Extension-provided configuration from labextensions paths
page_config = {
    "appVersion": version,
    "baseUrl": self.base_url,
    "terminalsAvailable": self.settings.get("terminals_available", False),
    "token": self.settings["token"],
    # ... additional config
}

Template Rendering

HTML templates in app/templates/ use Jinja2 to embed the page configuration as JSON in a <script> tag with id jupyter-config-data. The frontend JavaScript reads this configuration to initialize the application. Templates also include token removal logic to prevent tokens from appearing in browser history.

Entry Points

The application can be started via:

  • CLI: jupyter-notebook command (defined in pyproject.toml)
  • Module: python -m notebook (via __main__.py)
  • Programmatic: JupyterNotebookApp.launch_instance()

Dependencies

The backend relies on:

  • jupyter_server (>=2.4.0) - Core server infrastructure
  • jupyterlab_server (>=2.28.0) - Lab-specific server features
  • jupyterlab (>=4.6.0a0) - Frontend build and configuration
  • notebook_shim (>=0.2) - Backward compatibility layer
  • tornado (>=6.2.0) - Async web framework

Frontend Application & Plugin System

Relevant Files
  • packages/application/src/index.ts
  • packages/application/src/app.ts
  • packages/application/src/shell.ts
  • packages/application/src/tokens.ts
  • packages/application/src/panelhandler.ts
  • packages/application/src/pathopener.ts

Overview

The Jupyter Notebook frontend is built on a plugin-based architecture using JupyterLab's application framework. The core application package (@jupyter-notebook/application) provides the main application class, shell layout system, and token-based dependency injection for extensions.

Core Components

NotebookApp is the main application class that extends JupyterFrontEnd. It manages the document registry, plugin system, and application lifecycle. The app is instantiated once and shared across all plugins.

NotebookShell implements the JupyterFrontEnd.IShell interface and defines the visual layout with six distinct areas where widgets can be placed:

  • main – Central content area (typically for notebooks)
  • top – Header region
  • menu – Menu bar region
  • left – Left sidebar
  • right – Right sidebar
  • down – Bottom panel

Shell Layout Architecture

Loading diagram...

Panel Management

PanelHandler manages ranked widget insertion. Widgets are sorted by rank (default 900), allowing plugins to control their display order. The handler maintains a sorted list and automatically positions new widgets.

SidePanelHandler extends PanelHandler for sidebar-specific behavior. It manages a stacked panel where only one widget is visible at a time, with expand/collapse functionality. Sidebars can be hidden by the user and remember the last active widget.

Plugin System Integration

Plugins interact with the shell through the INotebookShell token. They can:

  1. Add widgets to any shell area using shell.add(widget, area, options)
  2. Listen to currentChanged signals when the active widget changes
  3. Activate widgets by ID using shell.activateById(id)
  4. Query widgets in specific areas using shell.widgets(area)

Example plugin pattern:

const myPlugin: JupyterFrontEndPlugin<void> = {
  id: '@my-org/my-extension:plugin',
  autoStart: true,
  requires: [INotebookShell],
  activate: (app: JupyterFrontEnd, shell: INotebookShell) => {
    const widget = new MyWidget();
    shell.add(widget, 'right', { rank: 500 });
  }
};

Path Opening & Navigation

The INotebookPathOpener token provides a standardized interface for opening paths in new browser tabs. The DefaultNotebookPathOpener implementation handles URL construction with proper encoding and supports custom search parameters and window options. This allows extensions to override default navigation behavior.

User Layout Persistence

The shell supports custom layout configurations through IUserLayout. Plugins can save widget positions and restore them on application restart, enabling persistent UI customization per user.

Built-in Extensions

Relevant Files
  • packages/notebook-extension/src/index.ts
  • packages/tree-extension/src/index.ts
  • packages/console-extension/src/index.ts
  • packages/terminal-extension/src/index.ts
  • packages/docmanager-extension/src/index.ts
  • packages/documentsearch-extension/src/index.ts
  • packages/application-extension/src/index.ts

Jupyter Notebook 7 is built on a plugin architecture where built-in extensions provide core functionality. Each extension is a collection of JupyterLab plugins that activate automatically and integrate with the application shell.

Architecture Overview

Loading diagram...

Core Extensions

Notebook Extension provides notebook-specific features:

  • Checkpoint indicator showing last save time
  • Kernel status display with visual indicators
  • Kernel logo in the toolbar
  • Full-width notebook toggle
  • Auto-scrolling for large outputs
  • Trusted notebook indicator
  • Tab icon updates based on kernel state

Tree Extension manages the file browser interface:

  • File browser widget with tabs for Files and Running sessions
  • Create new notebooks, files, consoles, and terminals
  • File action buttons (upload, download, delete)
  • File browser settings with sensible defaults
  • Plugin loader for settings visibility

Console Extension handles console routing:

  • Opens consoles in new browser tabs
  • Routes console URLs to the correct handler
  • Manages console session creation

Terminal Extension manages terminal sessions:

  • Opens terminals in new browser tabs
  • Routes terminal URLs to handlers
  • Configures terminal options like close-on-exit behavior

Document Manager Extension controls document opening:

  • Opens documents in new tabs or current page
  • Routes notebooks to the edit view
  • Handles factory selection for different document types
  • Manages widget lifecycle and disposal

Document Search Extension adds search capabilities:

  • Detects searchable widgets
  • Applies CSS classes for search UI visibility
  • Updates searchability when providers change

Plugin Lifecycle

Each extension exports an array of JupyterFrontEndPlugin objects. Plugins declare their dependencies using requires and optional arrays, allowing the framework to resolve them in the correct order. The activate function runs when dependencies are satisfied, typically registering commands, adding UI widgets, or connecting to signals.

Key Patterns

Signal Connections: Plugins listen to shell events like currentChanged to react when the active widget changes, enabling dynamic UI updates.

Settings Integration: Many plugins load configuration from ISettingRegistry, allowing users to customize behavior through settings files.

Toolbar Registration: Plugins register toolbar items using IToolbarWidgetRegistry, creating a modular toolbar system.

Command Registration: Commands are registered with the application and exposed to the command palette, making features discoverable and keyboard-accessible.

UI Components & Styling

Relevant Files
  • packages/ui-components/src/index.ts
  • packages/ui-components/src/icon/index.ts
  • packages/ui-components/src/icon/iconimports.ts
  • packages/ui-components/style/index.css
  • packages/application/style/index.css
  • packages/application/style/base.css
  • notebook/custom/custom.css

Overview

The UI components system provides reusable interface elements and styling infrastructure for the Jupyter Notebook application. It leverages JupyterLab's component library while adding custom icons and application-specific styling. The system is organized into two main layers: component exports and CSS styling.

Component Architecture

The @jupyter-notebook/ui-components package exports UI components through a modular structure:

  • Icon System: Custom SVG icons are wrapped using JupyterLab's LabIcon class, enabling consistent icon rendering across the application. The jupyterIcon is defined in iconimports.ts and exported through the package's public API.

  • Dependencies: The package depends on @jupyterlab/ui-components (v4.6.0-alpha.0) and React (v18.2.0), providing a foundation of pre-built components and modern UI patterns.

  • Build Output: TypeScript sources compile to lib/ directory with full type definitions, making components available for both runtime and development-time type checking.

Styling System

The styling architecture uses a cascading import pattern with CSS custom properties (CSS variables) for theming:

Application Styles
├── JupyterLab Core Styles
├── JupyterLab UI Components Styles
├── JupyterLab Main Menu Styles
├── Application Base Styles
└── Application Side Panel Styles

Key CSS Variables defined in packages/application/style/base.css:

  • --jp-private-topbar-height: Controls top bar dimensions (28px)
  • --jp-notebook-max-width: Sets maximum notebook width (1200px)
  • --md-grey-800: Dark theme color override (#323232)

Layout Patterns:

  • Responsive Containers: The #main-panel and #menu-panel use max-width constraints with auto margins for centered layouts on large screens.
  • Data Attributes: Pages use data-notebook attributes (e.g., data-notebook='notebooks') to apply context-specific styles without class proliferation.
  • Elevation System: JupyterLab's elevation variables (--jp-elevation-z1, --jp-elevation-z4) provide consistent shadow depths for visual hierarchy.

Custom Styling

The notebook/custom/custom.css file serves as a placeholder for user customizations. It's designed to be overridden in user profiles without modifying core application files, following Jupyter's extensibility pattern.

Integration Points

  • Style Modules: Both ui-components and application packages export style/index.js files that import CSS, enabling bundlers to include styles as side effects.
  • SVG Assets: SVG icons are imported as strings via TypeScript module declarations, allowing them to be embedded directly in LabIcon instances without external file references.
  • Theme Support: All styling uses CSS variables from JupyterLab's theme system, ensuring automatic adaptation to light and dark themes.

Build System & Development Setup

Relevant Files
  • app/rspack.config.js - Development bundler configuration
  • app/rspack.prod.config.js - Production bundler configuration
  • packages/application/tsconfig.json - TypeScript configuration for application package
  • buildutils/src - Build utility scripts (develop, release, upgrade)
  • lerna.json - Monorepo workspace configuration
  • nx.json - Nx task runner configuration
  • tsconfigbase.json - Base TypeScript compiler options
  • package.json - Root workspace scripts and dependencies

Architecture Overview

This is a monorepo using Yarn workspaces with Lerna for package management and Nx for task orchestration. The build system compiles TypeScript packages and bundles the frontend application using Rspack (a Rust-based webpack alternative).

Loading diagram...

Monorepo Structure

The repository uses Yarn workspaces with the following layout:

  • Root workspace (package.json) - Orchestrates all packages
  • app/ - Frontend application entry point (Rspack bundler)
  • packages/* - Individual packages (application, extensions, UI components)
  • buildutils/ - Build and release utilities

Lerna manages independent versioning across packages ("version": "independent" in lerna.json). Nx caches build outputs for faster rebuilds.

Build Pipeline

Development Build

npm run build

Runs lerna run build across all packages:

  1. TypeScript Compilation - Each package compiles via tsc using tsconfigbase.json
  2. Rspack Bundling - app/rspack.config.js bundles the frontend with:
    • Module Federation for plugin loading
    • Dynamic extension discovery from package.json metadata
    • HTML template generation via Handlebars
    • Output to notebook/static/

Production Build

npm run build:prod

Uses app/rspack.prod.config.js which:

  • Enables source maps for debugging
  • Adds version query parameters to filenames for cache busting
  • Disables minification (handled separately)
  • Generates license information via JSONLicenseWebpackPlugin

Development Setup

npm run develop

Runs buildutils/lib/develop.js which:

  1. Links notebook schemas to the Python environment
  2. Sets up JupyterLab extension development mode
  3. Enables hot-reload for frontend changes

Watch mode for active development:

npm run watch

Runs both watch:lib (package compilation) and watch:app (Rspack bundler) in parallel.

Key Build Concepts

Module Federation - Rspack's ModuleFederationPlugin enables dynamic loading of JupyterLab extensions as federated modules. Shared dependencies are configured via createShared() function to prevent version conflicts.

Singleton Packages - Critical packages (React, Lumino, CodeMirror) are marked as singletons in app/package.json to ensure only one instance loads globally.

TypeScript Configuration - Base config (tsconfigbase.json) enforces strict mode, ES2018 target, and composite builds for incremental compilation across packages.

Build Caching - Nx caches outputs for build, build:prod, build:lib, and build:labextension tasks, significantly speeding up rebuilds when dependencies haven't changed.

Multi-Page Routing & Handlers

Relevant Files
  • notebook/app.py
  • app/templates/tree_template.html
  • app/templates/notebooks_template.html
  • app/templates/consoles_template.html
  • app/templates/terminals_template.html
  • app/templates/edit_template.html
  • packages/application-extension/src/index.ts

Backend Route Handlers

The Jupyter Notebook application uses Tornado web handlers to manage multi-page routing. Each route is registered in the JupyterNotebookApp.initialize_handlers() method and maps to a specific handler class that extends NotebookBaseHandler.

The main routes are:

  1. /tree(.*) - TreeHandler: Displays directory listings or redirects to notebooks/files
  2. /notebooks(.*) - NotebookHandler: Renders the notebook editor interface
  3. /edit(.*) - FileHandler: Renders the file editor interface
  4. /consoles/(.*) - ConsoleHandler: Renders the console interface
  5. /terminals/(.*) - TerminalHandler: Renders the terminal interface
  6. /custom/custom.css - CustomCssHandler: Serves custom CSS from the Jupyter config directory

All handlers are decorated with @web.authenticated to enforce authentication.

Handler Logic & Redirects

The TreeHandler implements intelligent routing logic. When a user navigates to /tree/path, it checks if the path is a directory, notebook, or other file type:

  • If it's a directory, it renders the tree template with treePath set in the page config
  • If it's a notebook file, it redirects to /notebooks/path
  • If it's any other file, it redirects to /files/path

The NotebookHandler similarly validates paths. If a user tries to access /notebooks/path where path is a directory, it redirects to /tree/path instead.

The ConsoleHandler, TerminalHandler, and FileHandler are simpler—they render their respective templates without path-based logic.

Page Configuration System

Each handler calls get_page_config() to build a configuration object that is embedded in the HTML template as JSON. This configuration includes:

  • Application metadata (version, base URL, app name)
  • Server settings (terminals available, token, static URLs)
  • User preferences (preferred directory path)
  • MathJax configuration
  • JupyterHub integration details (if applicable)
  • Extension configuration from labextensions

The page config is injected into the template via a <script id="jupyter-config-data"> tag, making it available to the frontend JavaScript application.

Template Structure

All templates follow a consistent pattern:

  1. HTML head with favicon and optional custom CSS link
  2. Body with jp-ThemedContainer class for styling
  3. Page config JSON embedded in a script tag
  4. A notebookPage sentinel value identifying the current page type (tree, notebooks, consoles, terminals, or edit)
  5. Token removal script to clean up authentication tokens from the URL

Frontend Routing Integration

The frontend uses JupyterLab's router system to handle client-side navigation. The TREE_PATTERN regex (/(notebooks|edit)/(.*)) matches notebook and file editor routes. When a route matches, the opener plugin extracts the file path and opens it in the document manager with the appropriate factory.

The pages plugin registers commands like openTree and openLab that navigate between different pages. When on the tree page, these commands activate local UI components; when on other pages, they open new browser tabs to navigate to the target page.

Loading diagram...

Authentication & Security

All page handlers require authentication via the @web.authenticated decorator. The authentication token is passed in the page config but is automatically removed from the URL by a client-side script to prevent token leakage in browser history or logs.

JupyterHub integration is detected during initialization. If running under JupyterHub, additional metadata (hub prefix, host, user, server name) is added to the page config for proper URL construction and user context.