Build reproducible Jupyter Lite sites with jupyterlite-pyodide-kernel and pyodide-lock.
| docs | install | build |
|---|---|---|
View the full documentation on ReadTheDocs.
jupyterlite-pyodide-lock avoids run time jupyterlite-pyodide-kernel
package management ambiguity with a build time
pyodide-lock.json.
jupyterlite-pyodide-lock is distributed on PyPI, for use with pip or uv, and
conda-forge, for use with conda, mamba, micromamba, or pixi.
pip install jupyterlite-pyodide-lock
# or
conda install jupyterlite-pyodide-lockSeveral JupyterLite addons extend a build, and are configured in
jupyter_lite_config.json.
| addon | features |
|---|---|
PyodideLockAddon |
re-configure jupyterlite-pyodide-kernel with a custom pyodide-lock.json |
PyodideLockOfflineAddon |
replace remote CDN URLs with local packages to be served with the site |
FixHtmlAddon |
fix paths in HTML generated by third-pary JupyterLite addons |
Several additional installable packages provide configurable lockers, or approaches for
resolving pyodide-lock.json; see the documentation for more information.
| package | lockers | key dependencies |
|---|---|---|
jupyterlite-pyodide-lock |
BrowserLocker |
tornado |
jupyterlite-pyodide-lock-webdriver |
WebDriverLocker |
selenium |
jupyterlite-pyodide-lock-uv |
UvLocker |
uv |
jupyterlite-pyodide-lock works by:
- downloading a
pyodidedistribution - using a
pyodide-aware solver, either- the build environment with
uv - in a browser, with
micropipand a minimalpyodideruntime, managed by Python'swebbrowserorselenium
- the build environment with
- compiling a set of packages from the build environment, PyPI, or elsewhere
- (optional) limiting to packages to ones built before a given date for reproducibility
- returning the list to build a new
pyodide-lock.json- (optional) copying all downloaded wheels to be served along with the site
- configuring
jupyterlite-pyodide-kernelto use the newpyodide-lock.json- (optional) rewriting other generated
jupyter-config-datain JupyterLite app pages
- (optional) rewriting other generated
Use jupyterlite-pyodide-lock to minimally provide a more
predictable baseline pyodide runtime environment, or ensure complex dependencies like
widgets are consistent over time.
Ensure pyodide-kernel's dependencies are locked, assuming
pip.
-
make a
requirements.txtjupyterlite-core ==0.7.0 jupyterlite-pyodide-kernel ==0.7.0 jupyterlite-pyodide-lock ==0.2.0 jupyterlite-pyodide-lock-uv ==0.2.0 -
Run:
pip install -r requirements.txt
-
build a
jupyter_lite_config.json:{ "PyodideLockAddon": { "enabled": true, "locker": "UvLocker" } }
-
build a
jupyter_lite_config.json:jupyter lite build
-
start a simple, local development server
cd _output python -m http.server -b 127.0.0.1 -
visit the site at
http://127.0.0.1:8000/ -
make a new Notebook
- use basic
pythonfeatures
- use basic
Build a JupyterLite site with all the packages needed to run
ipywidgets in a Notebook, assuming mamba.
-
make an
environment.ymlchannels: - conda-forge - nodefaults dependencies: - ipywidgets ==8.1.8 - jupyterlite-core ==0.7.0 - jupyterlite-pyodide-kernel ==0.7.0 - jupyterlite-pyodide-lock-recommended ==0.2.0
- the
-recommendedpackage includesfirefoxandgeckodriver - optionally use a tool like
conda-lockorpixito create a lockfile for the build environment
- the
-
Run:
mamba env update --file environment.yml --prefix .venv source activate .venv # or just `activate .venv` on windows
-
build a
jupyter_lite_config.json:{ "PyodideLockAddon": { "enabled": true, "constraints": ["traitlets ==5.14.3"], "specs": ["ipywidgets ==8.1.8"], "extra_preload_packages": ["ipywidgets"] }, "PyodideLockOfflineAddon": { "enabled": true } }- note the tight
ipywidgetspin, ensuring compatibility with the build environment - while not required, the
constraintsoption allows for controlling transitive dependencies- this feature requires
micropip >=0.9.0, which is only compatible withpyodide >=0.27
- this feature requires
- note the tight
-
build a
jupyter_lite_config.json:jupyter lite build
-
disconnect from the internet
✈️ - this step is optional, but is the most reliable way to validate a reproducible site
-
start a simple, local development server
cd _output python -m http.server -b 127.0.0.1 -
visit the site at
http://127.0.0.1:8000/ -
make a new Notebook
-
see that
ipywidgetscan be imported, and widgets work:import ipywidgets ipywidgets.FloatSlider()
-
-
By default, a
pyodidedistribution provides a precise set of hundreds of package versions known to work together in the browser, described in itspyodide-lock.json. -
Among these packages is
micropip, which gives site users the ability to install packages not included inpyodide-lock.json. These may be served along with an HTML page, downloaded from PyPI, or anywhere on the internet.jupyterlite-pyodide-kerneluses this capability to install itself, and its dependencies.- At run time,
pipliteprovides amicropip-based shim for the IPython%pipmagic, the most portable approach for interactive package management in Notebook documents.
- At run time,
-
micropip(and%pip) are powerful for interactive usage, but can cause headaches when upstream versions (or their dependencies) change in ways that either no longer provide the same API expected by the exact versions ofpyodide,pyodide-kernel, and JupyterLab extensions in a deployed JupyterLite site.
jupyterlite-pyodide-lock gives content authors tools to manage their effective
pyodide distribution, making it easier to build, verify, and maintain predictable,
interactive computing environments for future site visitors.