Announcing jupyter-builder: A Standalone Build System for JupyterLab Extensions

Jupyter Builder logo

We’re excited to announce the first stable release of jupyter-builder on PyPI and @jupyter/builder on npm. A standalone, configurable build system for JupyterLab and its extensions.

If you build or maintain a JupyterLab extension, this release is for you.

Motivation

For a long time, building a JupyterLab extension has meant installing all of JupyterLab. Take a look at any extension’s build dependencies and you’ll see jupyterlab listed there, not because the extension needs JupyterLab at runtime to be built, but because the build tooling lives inside the JupyterLab repository. The builder/ folder, the jlpm command, the helper scripts, they’re all coupled to the JupyterLab core.

This setup has caused real friction over the years:

The need to separate the build system was identified back in jupyterlab#13456, and initial work began during GSoC 2024. With the support of the Jupyter Foundation’s first community-funded proposal, we’ve now brought that work to a stable release.

What jupyter-builder does

jupyter-builder extracts all the Node.js-based build tooling out of JupyterLab into a dedicated package. You install it on its own, and it builds your extension, no full JupyterLab installation required.

It ships in two parts:

Instead of jupyter labextension build ., you now run:

jupyter-builder build .

Build compatibility without JupyterLab installed

One interesting problem we had to solve: if JupyterLab isn’t installed, how does the builder verify that an extension is compatible with a given JupyterLab version?

The answer is @jupyterlab/core-meta, a small npm package that publishes JupyterLab’s core metadata on its own. @jupyter/builder declares a dependency on a specific @jupyterlab/core-meta version, so by default your extension is checked for compatibility against whatever JupyterLab version that pin corresponds to. In general, the latest @jupyter/builder will track the latest JupyterLab.

If you want to build against a different JupyterLab version, pass --core-version:

jupyter-builder build . --core-version 4.4.x

We’ll download that version’s metadata from @jupyterlab/core-meta on npm and check compatibility against it.

Migrating an existing extension

If you’re starting a new extension with the extension template, you’ll get all of this set up automatically. For existing extensions, there are two changes to make.

1. Update the Python build dependencies

In your pyproject.toml, swap jupyterlab for jupyter-builder:

# Before
requires = ["hatchling>=1.5.0", "jupyterlab>=4.0.0,<5", "hatch-nodejs-version>=0.3.2"]
# After
requires = ["hatchling>=1.5.0", "jupyter-builder>=1.0.0", "hatch-nodejs-version>=0.3.2"]

Then update the scripts section of your package.json to use the new CLI:

"build:labextension": "jupyter-builder build .",
"build:labextension:dev": "jupyter-builder build --development True .",
"watch:labextension": "jupyter-builder watch ."

Your build no longer pulls in all of JupyterLab.

2. Update the npm builder dependency

Replace @jupyterlab/builder with @jupyter/builder in your package.json:

"@jupyter/builder": "^1.0.0"

jupyter-builder is backwards-compatible with @jupyterlab/builder, so things will keep working if you don’t migrate immediately. That said, we strongly recommend switching: @jupyterlab/builder is no longer being actively developed, and all new work is happening in @jupyter/builder.

Note that as part of this transition JupyterLab has also moved from Webpack to Rspack. Most extensions won’t need any changes, but if yours uses a custom webpackConfig see the Rspack migration notes.

What’s next

This release is the first stable foundation. We’re continuing to:

If you maintain an extension, please try the migration and let us know how it goes. Feedback from real extensions is the best way to make sure the migration path stays smooth.

Acknowledgements

This work was funded under the first round of Jupyter Community Funded Proposals. We want to thank the Jupyter Foundation and everyone involved in setting up this funding mechanism.

A huge thank you to Nicholas Bollweg for many thoughtful discussions on the design and packaging of jupyter-builder, and to Jeremy Tuloup for helping us resolve issues and for guiding the adoption of jupyter-builder in Jupyter Notebook.

This package was initially created during GSoC 2024 by Ronan Coutinho, mentored by Frédéric Collonval. Their work laid the foundation that made this release possible.

About the developers

Darshan Paudyal is an intern at OpenTeams and a member of the Jupyter Frontend Council. Darshan led the work to bring jupyter-builder to a stable release, completing the separation from JupyterLab core and shepherding the package through to its first published version.

Michał Krassowski is a Senior Software Engineer at OpenTeams. Mike provided guidance and technical direction throughout the development of jupyter-builder, helping shape its architecture and roadmap.