Creating JupyterLab Extensions - Faster

16 Sep 2020

I will be giving a talk in October at JupyterCon 2020 about how you and your team can get started with JupyterLab extensions.

I’ll post that talk once it’s available - but in the meantime, I’ve compiled the following list of tips and guides to get you started developing JupyterLab extensions quickly.


You’re going to need to get familiar with conda, fast.

Quick tips:

  • Install mamba
    • Mamba is a reimplementation of the conda package manager in C++. It solves environments quickly - it crushes conda’s performance.
  • Use condametachannel
    • Long story short, when conda checks conda-forge for packages, it’s scanning tens (maybe hundreds at this point?) of thousands of packages each time. Using condametachannel, you can cut down on the number of packages being searched.
  • Distribute environment.yaml files with pinned dependencies to your users, and instructions on how to use conda to install and activate the environment.
    • Don’t expect them to set up their environment themselves.

It always helps to ensure that your conda installation is up to date.

# Update conda
conda update -n base conda

# If you run into issues, try fixes suggested here:
conda clean --all
conda config --remove channels conda-forge
conda update -n base conda

Further reading on conda performance:

Don’t Start From Scratch - Use a Boilerplate

Use cookiecutter-ts to get started, generally.

You can try using my boilerplate repository as well - instructions and tutorial. It’s a bit dated at this point (a few months old) and I’ve learned a lot since then.

I will be announcing some news around a new boilerplate repository I’ve been working on. Stay tuned for that. It is much better than either option above.

Project Structure/Naming Conventions

When a JupyterLab file or directory has_underscores_in_the_name, it is related to Python/server extension side of things.

Files and directories with dashes-in-the-name are related to the TypeScript side of things.

Naming ConventionHyphenation

General guidelines:

  • Keep all TypeScript files in /src/
  • Keep all *.css files in style/* (and @import them into index.css)
  • Keep all *.svg files in style/icons/


Keep your labextension version (located in package.json) and your serverextension version (located in in sync at all times.


I recommend pinning all @jupyterlab/* dependencies in package.json, as well as the version of jupyterlab required in

It is very easy to accidentally break compatibility if version numbers are allowed to float. Even minor changes to the jupyterlab Python package can (and will) wreak havoc on your package.json dependencies.

Occasionally, @jupyterlab packages will disagree with each other on which packages they should rely on. The resolutions section of package.json is used to force the various packages to use the same versions of their dependencies.

Other JupyterLab Resources

Looking ahead

Stay tuned for my upcoming JupyterCon 2020 talk :)

I will elaborate on best practices, future plans, and lessons learned over months and months of hard work.