Jupyter UI is an open-source React.js component library that bridges the gap between the Jupyter ecosystem and modern web development frameworks. It provides React components that are 100% compatible with Jupyter, allowing developers to build custom data products without being constrained by the traditional JupyterLab interface.
- Implemented plugin-based architecture for extensible collaboration
- Built-in providers:
JupyterCollaborationProvider,NoOpCollaborationProvider - Direct instantiation pattern for simplicity
- Added collaboration support to
Notebook2component
Traditional JupyterLab uses the Lumino widget toolkit, an imperative UI framework that isn't compatible with modern declarative frameworks like React. This forces developers to either:
- Use iframes to embed Jupyter notebooks (limiting integration)
- Work within the rigid extension system of JupyterLab
- Build entirely from scratch
Jupyter UI solves this by wrapping Jupyter functionality in React components, enabling seamless integration into any React application.
The project uses Lerna to manage a monorepo structure with the following organization:
jupyter-ui/
├── packages/ # Core library packages
│ ├── react/ # Main React component library (generic)
│ ├── lexical/ # Rich text editor integration
│ └── docusaurus-plugin/ # Docusaurus integration
├── examples/ # Framework integration examples
│ ├── vite/ # Vite example
│ ├── next-js/ # Next.js integration
│ ├── docusaurus/ # Docusaurus example
│ └── lexical/ # Lexical editor example
├── storybook/ # Component showcase
├── docs/ # Documentation site (Docusaurus)
├── dev/ # Development utilities
└── attic/ # Archived/experimental code
The main package providing React components for Jupyter functionality.
Key Components:
- Notebook Components: Full notebook interface with cells, outputs, toolbar
- Cell Components: Individual code/markdown cells with execution
- Console: Interactive Jupyter console
- Terminal: Web-based terminal interface
- FileBrowser: File system navigation
- Kernel Management: Kernel lifecycle and execution
- Output Rendering: Display of execution results, plots, widgets
Architecture:
- Uses JupyterLab's underlying services (kernels, sessions, contents)
- Provides React context providers for state management
- Supports both local and remote Jupyter servers
- Implements WebSocket communication for real-time updates
- Plugin-based collaboration provider system
- Extensible without platform-specific code
Key Files:
src/jupyter/JupyterContext.tsx- Core context providersrc/components/notebook/Notebook.tsx- Main notebook component (accepts collaborationProvider)src/providers/ServiceManagerProvider.tsx- Service managementsrc/jupyter/collaboration/ICollaborationProvider.ts- Provider interface
Integration with Meta's Lexical framework for rich text editing in notebooks.
Features:
- Rich text editing with Jupyter cell support
- Code highlighting and syntax support
- Equation rendering (KaTeX)
- Image and media embedding
- Collaborative editing capabilities
- Conversion between Lexical and nbformat
Components:
- Custom Lexical nodes for Jupyter cells
- Plugins for Jupyter-specific functionality
- Toolbar and formatting controls
- Output rendering within the editor
Plugin enabling Jupyter notebook integration in Docusaurus documentation sites.
Capabilities:
- Embed live notebooks in documentation
- Interactive code execution
- Syntax highlighting
- Theme integration
Technologies:
- TypeScript for type safety
- Webpack for bundling
- Gulp for resource management
- Babel for transpilation
- Lerna for monorepo management
- npm workspaces for dependency management
Build Process:
- Resource copying via Gulp
- TypeScript compilation
- Webpack bundling
- Package-specific builds
Pre-commit Hooks (Husky + lint-staged):
- ESLint for code quality (v9 flat config)
- Prettier for code formatting
- TypeScript type checking
- Conventional commit messages (commitlint)
Linting Stack:
- ESLint with TypeScript support
- React and React Hooks plugins
- Prettier integration
- Custom rules for JupyterLab compatibility
Available Scripts:
npm run lint- Check for linting issuesnpm run lint:fix- Auto-fix linting issuesnpm run format- Format all files with Prettiernpm run format:check- Check formattingnpm run type-check- TypeScript type checking
Jupyter Server Configuration:
- Port: 8686
- Token authentication enabled
- CORS configured for development
- WebSocket support for kernels
- Terminal support enabled
Frontend Development:
- Hot module replacement
- Port: 3208 (varies by example)
- Proxy configuration for API calls
- @storybook/test-runner for automated story testing
- Custom MDX documentation testing with Playwright
- 38 component stories with smoke tests
- 13 MDX documentation files verified
- CI integration with GitHub Actions
npm run test:storybook- Test all storiesnpm run test:mdx- Test MDX documentationnpm run test:all- Run both test suites
- Jest for unit testing
- Playwright for UI testing
- Coverage reporting
- Python tests for server components
- React 18.3.1 - UI framework
- TypeScript 5.8.3 - Type safety
- JupyterLab packages - Core Jupyter functionality
- Lumino - Widget toolkit (underlying layer)
- Primer - GitHub's design system components
- IPyWidgets - Interactive widget support
- CSS modules
- JupyterLab themes
- Tailwind CSS (v4 in lexical package)
- Custom theme providers
- WebSocket for kernel communication
- REST API for server operations
- Service Manager pattern
- Observable patterns for state
import { useJupyter, Notebook } from '@datalayer/jupyter-react';
function App() {
const { defaultKernel, serviceManager } = useJupyter({
jupyterServerUrl: "http://localhost:8686",
jupyterServerToken: "your-token",
startDefaultKernel: true,
});
return (
<Notebook
kernel={defaultKernel}
serviceManager={serviceManager}
/>
);
}The library uses nested context providers for state management:
- JupyterProvider - Server connection and configuration
- ServiceManagerProvider - Kernel and session management
- NotebookProvider - Notebook-specific state
- ThemeProvider - Visual theming
The project uses Zustand for global state management with the following stores:
- Kernel Store - Kernel lifecycle and execution state
- Notebook Store - Notebook content and metadata
- Cell Store - Individual cell states
- Output Store - Execution outputs
- Real-time sync with Jupyter server
- Collaborative editing support
- Undo/redo functionality
- Dirty state tracking
Developers can register custom output renderers:
registerRenderer({
mimeType: 'application/custom',
renderer: CustomComponent,
});The Lexical package supports plugins for:
- Custom cell types
- Toolbar extensions
- Keyboard shortcuts
- Output transformations
- Build-time notebook rendering
- Client-side kernel execution (Pyodide)
- No server required
- Full Jupyter server backend
- Multi-user support
- Persistent storage
- Real-time collaboration
- Static content with on-demand execution
- Serverless function backends
- Edge computing scenarios
- Lazy loading of components
- Virtual scrolling for large notebooks
- Code splitting per feature
- Memoization of expensive operations
- WebWorker for heavy computations
- Token-based authentication
- CORS configuration
- XSS protection in output rendering
- Sandboxed iframe execution
- Content Security Policy support
build.yml:
- Runs on main branch and PRs
- Build verification across packages
- Visual testing with Playwright
- Storybook story and MDX testing
- Docker container builds
- Uses npm instead of yarn
- TypeScript type checking
- ESLint error checking (no warnings)
- Prettier formatting validation
Key Jobs:
- build - Compiles all packages
- visual-test - Playwright visual regression tests
- storybook-test - Tests all stories and documentation
- docker-dev - Dev container verification
Other Workflows:
fix-license-header.yml- Automatic license header correctionspublish-dev.yml- Publishes dev versions to GitHub Packages
- ESLint v9 Flat Config: Migrated from deprecated .eslintignore to modern flat config format
- Prettier JSON Config: Replaced CommonJS config with .prettierrc.json
- Line Endings: Enforced LF line endings for cross-platform consistency
- Trailing Commas: Added support for better TypeScript compatibility
- Node.js 20+: Updated minimum requirement from Node 18 to Node 20
- NVM Support: Added .nvmrc file for consistent Node version management
- React 18 Migration: Fixed deprecated ReactDOM.render usage
- TypeScript Strictness: Replaced @ts-ignore with @ts-expect-error
- React Best Practices: Added missing key props in list renderings
- Security: Added rel="noreferrer" to external links
- Hook Rules: Fixed conditional hook calls
- MDX Comment Syntax: Fixed malformed comments in 13 MDX files from
{/_to{/** **/} - Prettier Exclusion: Added MDX files to .prettierignore to prevent comment corruption
- Missing Logo Files: Created patch for @jupyterlite/javascript-kernel-extension to fix missing logo references
- Webpack Warnings: Reduced source map warnings from 7 to 2 by excluding problematic packages
- Patch-Package: Added automatic patching of third-party modules during npm install
- GitHub Actions: Updated all workflows to use Node 20
- Build Stability: Fixed CI build failures in Storybook
- Storybook CI Testing: Fixed test runner connection issues with wait-on and explicit URL configuration
- Terminal Component: Fixed BoxPanel initialization error with proper direction setting and delayed widget addition
- Storybook Test Runner: Automated testing for all component stories
- MDX Documentation Testing: Verification of documentation examples
- CI Integration: Full test suite runs on every PR
- Problem: Test runner couldn't connect to Storybook static server (127.0.0.1 vs localhost mismatch)
- Solution:
- Created
test:all:ciscript with explicit--url http://localhost:6006 - Added
npx wait-onto ensure server is ready before tests - Removed fixed sleep duration for more reliable CI runs
- Created
- Problem:
TypeError: Cannot read properties of null (reading 'addWidget')in BoxPanel - Solution:
- Added
direction = 'top-to-bottom'to BoxPanel initialization - Added defensive check in
setThememethod - Implemented delayed widget addition with error handling
- Added error logging for better debugging
- Added
.github/workflows/build.yml- Updated Storybook test runner configurationstorybook/package.json- Added test:all:ci scriptpackages/react/src/components/terminal/TerminalAdapter.ts- Fixed BoxPanel initialization
Full support for interactive widgets with two-way communication between Python and JavaScript.
Real-time collaboration using Y.js for conflict-free replicated data types.
Simultaneous connections to different kernels (Python, R, Julia, etc.).
Support for various output types including:
- Plain text/HTML/Markdown
- Images (PNG, JPEG, SVG)
- Plots (Matplotlib, Plotly, Bokeh)
- DataFrames
- Interactive widgets
The repository includes several example implementations:
- Vite Example - Modern build tool integration
- Next.js Example - Server-side rendering support
- Docusaurus Example - Documentation site integration
- Lexical Example - Rich text editing capabilities
- MIT licensed
- Integration with major React frameworks
- Storybook for component documentation
- Comprehensive documentation site
- Active development by Datalayer, Inc.
- JupyterLite support (browser-based kernels)
- PyScript integration
- Enhanced collaborative features
- More framework integrations
- Performance improvements
- Extended widget support
Jupyter UI represents a significant advancement in making Jupyter notebooks accessible to modern web developers. By providing React components that wrap Jupyter functionality, it enables the creation of custom data products that leverage the full power of the Jupyter ecosystem while maintaining the flexibility and composability that React developers expect. The monorepo structure, comprehensive examples, and extensive documentation make it a robust solution for integrating computational notebooks into web applications.