Back to Articles

Inside JupyterLab: How TypeScript and Lumino Power the Future of Computational Notebooks

[ View on GitHub ]

Inside JupyterLab: How TypeScript and Lumino Power the Future of Computational Notebooks

Hook

While millions of data scientists use JupyterLab daily, few realize it’s not a Python application—it’s a TypeScript-powered web framework that happens to run Python code through a sophisticated message-passing protocol.

Context

The classic Jupyter Notebook transformed how researchers and data scientists work by combining executable code, visualizations, and narrative text in a single document. But as workflows grew more complex, its monolithic architecture became limiting. Users wanted multiple notebooks open side-by-side, integrated terminals, custom file viewers, and extensibility beyond simple plugins. The classic notebook’s server-rendered interface and limited extension points couldn’t accommodate these needs without fundamental changes.

JupyterLab emerged as a complete reimagining of the computational notebook environment. Rather than incrementally patching the classic notebook, the Project Jupyter team built a modern, browser-based IDE from the ground up using TypeScript and a dedicated UI framework called Lumino. With over 15,000 GitHub stars and adoption across academia and industry, JupyterLab has become the de facto standard for interactive computing, supporting multiple programming languages through its kernel architecture.

Technical Insight

Backend

Frontend

WebSocket/HTTP

Execution Results

Kernel Messages

File Operations

Service APIs

Browser UI

Lumino Framework

Plugin System

Jupyter Server

Python Backend

Compute Kernels

File System

Core Plugins

Notebook, Editor, etc

Third-party Extensions

System architecture — auto-generated

JupyterLab’s architecture separates concerns cleanly between a Python backend (the Jupyter server) that manages kernels and file operations, and a TypeScript frontend that handles all user interface concerns. This separation enables the browser-based UI to remain responsive even during heavy computation, since code execution happens in isolated kernel processes that communicate via messaging protocols.

The frontend’s plugin-based architecture is built on Lumino, a framework for building extensible applications with complex, dockable layouts. Every feature in JupyterLab—from the file browser to the notebook editor—is implemented as a plugin that depends on and provides services through a dependency injection system. This means third-party extensions integrate at the same level as core features, not as second-class additions.

Installing JupyterLab is straightforward using standard Python package managers:

# Using pip
pip install jupyterlab

# Using conda
conda install -c conda-forge jupyterlab

# Using mamba
mamba install -c conda-forge jupyterlab

Once installed, launch it with jupyter lab, and it opens automatically in your browser. If you’re on a Unix-like system and used pip install --user, you may need to add the user-level bin directory to your PATH: export PATH="$HOME/.local/bin:$PATH".

The extension ecosystem supports two distribution models. Prebuilt extensions are bundled as Python packages distributed via PyPI or conda, requiring no additional build steps for end users. These extensions include compiled JavaScript that JupyterLab loads directly. Source extensions, distributed through npm, require a build step that compiles TypeScript and bundles assets. You can find extensions by searching PyPI for ‘jupyterlab’, npm for ‘jupyterlab-extension’, or browsing the GitHub topic jupyterlab-extension.

This dual packaging model addresses different developer needs: Python-native teams can distribute extensions through familiar channels without requiring Node.js in their deployment pipeline, while TypeScript-first developers can leverage npm’s ecosystem. The trade-off is complexity—extension authors must understand both ecosystems to choose the right distribution strategy.

The kernel architecture is particularly elegant. JupyterLab doesn’t execute code itself; it sends execution requests to language-specific kernels (like IPython for Python or IRkernel for R) over a standardized message protocol. This protocol-based design is why JupyterLab can support multiple languages without changing its core—each language just needs a kernel implementation.

The Lumino framework provides the widget system that powers JupyterLab’s sophisticated layouts, including drag-and-drop tabs, split panels, and sidebars. Extensions tap into this by creating Lumino widgets and registering them with the application shell, giving them native integration with the layout system.

Gotcha

JupyterLab 3 reached end of maintenance on May 15, 2024, with critical fixes backported only until December 31, 2024. If you’re still running version 3, upgrading to version 4 is now essential, but this migration can break existing extensions and custom workflows. Extension authors need to update their packages for compatibility, and organizations with large extension ecosystems may face significant migration effort.

Extension development has a steep learning curve. You need proficiency in TypeScript, understanding of the Lumino framework’s widget system, and familiarity with JupyterLab’s plugin APIs. Source extensions add build complexity with TypeScript compilation requirements. The documentation is comprehensive but assumes comfort with modern JavaScript tooling. For teams primarily working in Python, this context switch to a TypeScript-heavy development environment can be jarring. Additionally, while JupyterLab runs in the browser, it requires a Jupyter server backend—whether local or remote—for code execution. This means deployment involves both Python server management and serving the frontend assets, adding operational complexity.

Verdict

Use JupyterLab if you need a powerful, extensible environment for interactive computing and data science where notebooks are central to your workflow. It’s the clear choice when you want advanced features like multiple document layouts, simultaneous editing of notebooks and scripts, integrated terminals, or custom visualizations. If you’re building data science platforms or internal tools where extensibility matters, JupyterLab’s plugin architecture and 15,000+ GitHub stars provide a solid foundation. It’s also ideal for teams working across multiple languages who want a consistent interface. Skip it if you only need basic notebook editing and the classic Jupyter Notebook meets your needs—it’s lighter and simpler. Avoid JupyterLab if you require a desktop application without browser dependencies, or if your team can’t invest in TypeScript skills for extension development. Also reconsider if you’re locked into JupyterLab 3 and can’t commit resources to migrating extensions to version 4, as support has ended.

// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/developer-tools/jupyterlab-jupyterlab.svg)](https://starlog.is/api/badge-click/developer-tools/jupyterlab-jupyterlab)