Skip to content

Bundle extension examples in PyPI installs#105

Open
MUFFANUJ wants to merge 12 commits intojupyterlab:mainfrom
MUFFANUJ:noManualClone
Open

Bundle extension examples in PyPI installs#105
MUFFANUJ wants to merge 12 commits intojupyterlab:mainfrom
MUFFANUJ:noManualClone

Conversation

@MUFFANUJ
Copy link
Copy Markdown
Member

closes #88

This PR makes the bundled extension-examples available when jupyterlab-plugin-playground is installed from a built package, including the PyPI path. Instead of asking users to manually clone the examples repository after install, the package now includes the examples and populates them automatically when JupyterLab starts, so the examples are visible in the UI immediately.

This might be a better fit than “1-click fetch” for the installed-package case because it removes the extra user step entirely and does not depend on a post-install network fetch or additional setup from inside the UI. It keeps the experience simpler and more reliable for users who just install the package and expect the examples to already be there.

I tested this locally ina virtual environment.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 15, 2026

Binder JupyterLite 👈 Launch a Binder on branch MUFFANUJ/jupyterlab-plugin-playground/noManualClone

@MUFFANUJ MUFFANUJ added the enhancement New feature or request label Mar 15, 2026
@krassowski
Copy link
Copy Markdown
Member

Hmm, I like how it makes the examples "just work". I see two potential issues here:

  • when a bug gets fixed in extension-examples we need to release a new version of plugin-playground to pick it up
  • folks who want to use this plugin just for dynamic extensions without need for node dependencies get a much larger install bundle

We could consider publishing extension-examples to PyPI and then pulling it via optional dependencies (but then it requires user to opt-in to get examples), a meta package (like jupyter-collaboration includes multiple dependencies which can also be installed separately). But this adds a lot of overhead quickly, so I am not sure if it's worth it. Maybe, maybe not.

If we keep the approach proposed by this PR as-is, can we also drop submodule checkout step from binder/lite and centralize that in one place?

@MUFFANUJ
Copy link
Copy Markdown
Member Author

Not completely. The new packaged-install path solves the PyPI case, but Binder and Lite are still source-checkout workflows. In particular, Lite needs the examples during the docs build so docs/conf.py can copy them into docs/content/extension-examples, which happens before the installed-package startup hook would run. So I do not think we can drop those steps outright.

@krassowski
Copy link
Copy Markdown
Member

I posted on Zulip to check for dissent and ideas #jupyterlab > plugin playground to ship extension-examples in wheel

@krassowski
Copy link
Copy Markdown
Member

krassowski commented Mar 25, 2026

Next step here could be exploring how much we can trim the extension-examples directory before shipping it as it currently contributes a lot to the bundle size. I think this covers both this copy and the one that is used to build JupyterLite deployment (for faster loading), ideally using a configuration in a single source of truth across both:

  • drop .git and .github folders and other hidden files from extension-examples/ and subdirectories
  • drop playwright ui-tests, there is no way to run these in the browser
  • drop lockfiles as we are not installing anything
  • list all remaining files and check if there is something we could compress upstream in extension-examples repo (any screenshots which are too large or not compressed with trimage/opting already?)
  • anything else?

Starting point:

image

@MUFFANUJ
Copy link
Copy Markdown
Member Author

MUFFANUJ commented Mar 30, 2026

It now removes hidden files (.git/.github), ui-tests, lockfiles, Playwright configs, build/cache folders.

@MUFFANUJ
Copy link
Copy Markdown
Member Author

Should we merge this? I have excluded the images/gifs/vids and as per discussed i will update the compression workflow in the extension-examples. @krassowski

Copy link
Copy Markdown
Member

@krassowski krassowski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know what is responsible for the majority of the size? It looks like this till yields 30+ MB:

https://github.com/jupyterlab/plugin-playground/actions/runs/23755660059?pr=105

Image

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we end up with more scripts like that it would be worthwhile to put it under /scripts directory but since it is only one I think that's ok to keep as-is

@krassowski
Copy link
Copy Markdown
Member

Ok, it looks like we are not getting that much gain from compression... What if we removed .gif files and replaced the references in README files with raw.githubusercontent.com URLs so that these get etched by browser dynamically?

@krassowski
Copy link
Copy Markdown
Member

This is assuming that the answer to my earlier question:

Do you know what is responsible for the majority of the size?

is that it is the gif files.

@MUFFANUJ
Copy link
Copy Markdown
Member Author

MUFFANUJ commented Apr 6, 2026

is that it is the gif files.

Yes

@MUFFANUJ
Copy link
Copy Markdown
Member Author

MUFFANUJ commented Apr 6, 2026

Screen.Recording.2026-04-07.at.4.02.12.AM.mov

Along with .gif have also added the raw URLs for .png, the results look great

Screenshot 2026-04-07 at 3 58 57 AM

@MUFFANUJ
Copy link
Copy Markdown
Member Author

MUFFANUJ commented Apr 6, 2026

Have added the raw URL for the video as well, with a downloadable link, so those who want to try it out can download it and use it.

Screen.Recording.2026-04-07.at.4.22.19.AM.mov
Screenshot 2026-04-07 at 4 22 58 AM

@krassowski krassowski requested a review from Copilot April 7, 2026 10:36
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR bundles the extension-examples content into the Python distribution so that installs from built artifacts (including PyPI wheels) can surface examples immediately, without requiring users to manually clone the examples repository.

Changes:

  • Add a Hatch build hook to generate a trimmed, packaged copy of extension-examples during builds.
  • Enable a Jupyter Server extension that populates extension-examples/ into the server root on startup if missing.
  • Reuse the new syncing logic for building the docs Lite contents, and ensure release checks fetch submodules.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pyproject.toml Adds build artifact/config wiring, registers the custom build hook, and installs server config for auto-enabling the server extension.
jupyterlab_plugin_playground/__init__.py Implements the server extension entrypoints and startup-time copy of bundled examples into the Jupyter server root.
jupyter-config/jupyter_server_config.d/jupyterlab_plugin_playground.json Auto-enables the server extension via jpserver_extensions.
extension_examples_bundle.py New build hook + sync utilities to trim/copy example directories and rewrite README media references.
docs/conf.py Switches docs Lite sync to reuse sync_extension_examples() from the new module.
.github/workflows/check-release.yml Checks out git submodules in the release-check workflow.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

Add 1-click UX to fetch extension-examples without manual clone

3 participants