From de70d2fe8e04777cf49adacd371848564523ed8c Mon Sep 17 00:00:00 2001 From: natinew77-creator Date: Wed, 27 May 2026 09:10:16 -0400 Subject: [PATCH 1/6] ENH: Add JupyterLite GitHub Actions workflow --- .github/workflows/jupyterlite.yml | 44 +++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .github/workflows/jupyterlite.yml diff --git a/.github/workflows/jupyterlite.yml b/.github/workflows/jupyterlite.yml new file mode 100644 index 00000000000..bce53fc8e7c --- /dev/null +++ b/.github/workflows/jupyterlite.yml @@ -0,0 +1,44 @@ +name: Build JupyterLite + +on: + push: + branches: + - jupyterlite-gh-actions + +permissions: + contents: read + +jobs: + build: + name: Build JupyterLite Site + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install JupyterLite & Build Tools + run: | + python -m pip install --upgrade pip + pip install jupyterlite-core jupyterlite-pyodide-kernel build + + - name: Build MNE-Python Wheel + run: | + python -m build --wheel + mkdir -p lite-wheels + cp dist/*.whl lite-wheels/ + + - name: Build JupyterLite Site + # We pass the local wheel to JupyterLite so the browser environment uses the exact code from this branch! + run: | + jupyter lite build --contents examples/ --output-dir dist_lite/ --piplite-wheel lite-wheels/*.whl + + - name: Upload Artifact + uses: actions/upload-artifact@v4 + with: + name: jupyterlite-build + path: dist_lite/ From e4e3e5f09e7a4b8d721ac8ac16a44c383aafb3b7 Mon Sep 17 00:00:00 2001 From: natinew77-creator Date: Wed, 27 May 2026 09:13:44 -0400 Subject: [PATCH 2/6] FIX: Install jupyter-server for jupyterlite build --- .github/workflows/jupyterlite.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/jupyterlite.yml b/.github/workflows/jupyterlite.yml index bce53fc8e7c..408fd0ac54b 100644 --- a/.github/workflows/jupyterlite.yml +++ b/.github/workflows/jupyterlite.yml @@ -24,7 +24,7 @@ jobs: - name: Install JupyterLite & Build Tools run: | python -m pip install --upgrade pip - pip install jupyterlite-core jupyterlite-pyodide-kernel build + pip install jupyterlite-core jupyterlite-pyodide-kernel build jupyter-server - name: Build MNE-Python Wheel run: | From 9900ee786fa39962f352f93aac1e7630510e69ef Mon Sep 17 00:00:00 2001 From: natinew77-creator Date: Wed, 27 May 2026 10:45:54 -0400 Subject: [PATCH 3/6] FIX: Add towncrier changelog and fix yamllint truthy error --- .github/workflows/jupyterlite.yml | 2 +- doc/changes/dev/13925.newfeature.rst | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 doc/changes/dev/13925.newfeature.rst diff --git a/.github/workflows/jupyterlite.yml b/.github/workflows/jupyterlite.yml index 408fd0ac54b..d4014b2b11c 100644 --- a/.github/workflows/jupyterlite.yml +++ b/.github/workflows/jupyterlite.yml @@ -1,6 +1,6 @@ name: Build JupyterLite -on: +on: # yamllint disable-line rule:truthy push: branches: - jupyterlite-gh-actions diff --git a/doc/changes/dev/13925.newfeature.rst b/doc/changes/dev/13925.newfeature.rst new file mode 100644 index 00000000000..7044e4cb1fb --- /dev/null +++ b/doc/changes/dev/13925.newfeature.rst @@ -0,0 +1 @@ +Added a JupyterLite GitHub Actions workflow to automatically build a Wasm-compatible interactive documentation site by :user:`natinew77-creator`. From 0af3e0a7c3e0148b90c7167e2ff0638ab2c3b2a2 Mon Sep 17 00:00:00 2001 From: natinew77-creator Date: Wed, 27 May 2026 10:53:51 -0400 Subject: [PATCH 4/6] FIX: Address pre-commit style and security checks --- .github/workflows/jupyterlite.yml | 2 ++ doc/changes/dev/13925.newfeature.rst | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/jupyterlite.yml b/.github/workflows/jupyterlite.yml index d4014b2b11c..c06af5601ae 100644 --- a/.github/workflows/jupyterlite.yml +++ b/.github/workflows/jupyterlite.yml @@ -15,6 +15,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + persist-credentials: false - name: Setup Python uses: actions/setup-python@v5 diff --git a/doc/changes/dev/13925.newfeature.rst b/doc/changes/dev/13925.newfeature.rst index 7044e4cb1fb..bcd3109e8d1 100644 --- a/doc/changes/dev/13925.newfeature.rst +++ b/doc/changes/dev/13925.newfeature.rst @@ -1 +1 @@ -Added a JupyterLite GitHub Actions workflow to automatically build a Wasm-compatible interactive documentation site by :user:`natinew77-creator`. +Added a JupyterLite GitHub Actions workflow to automatically build a Wasm-compatible interactive documentation site by Natneal Belete. From df8656da38fe1b1e3de80bec7f7dae3cbb0c7927 Mon Sep 17 00:00:00 2001 From: natinew77-creator Date: Thu, 11 Jun 2026 16:23:03 -0400 Subject: [PATCH 5/6] ENH: Integrate jupyterlite-sphinx for examples --- doc/conf.py | 23 +++++++++++++++++++++++ pyproject.toml | 2 ++ 2 files changed, 25 insertions(+) diff --git a/doc/conf.py b/doc/conf.py index e7f740db907..aaf7ce7a051 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -112,6 +112,7 @@ # contrib "matplotlib.sphinxext.plot_directive", "numpydoc", + "jupyterlite_sphinx", "sphinx_copybutton", "sphinx_design", "sphinx_gallery.gen_gallery", @@ -470,6 +471,28 @@ sphinx_gallery_parallel = int(os.getenv("MNE_DOC_BUILD_N_JOBS", "1")) sphinx_gallery_conf = { + "jupyterlite": { + "use_jupyter_lab": True, + }, + "first_notebook_cell": ( + "# 💡 This cell is automatically added to the start of each notebook.\n" + "import micropip\n" + "await micropip.install(['mne', 'pyodide-http'])\n" + "\n" + "# 1. Patch networking so pooch can download datasets\n" + "import pyodide_http\n" + "pyodide_http.patch_all()\n" + "\n" + "# 2. Patch MNEBrowseFigure to auto-display in Pyodide's inline backend\n" + "import mne\n" + "import matplotlib.pyplot as plt\n" + "orig_plt_show = mne.viz.utils.plt_show\n" + "def pyodide_plt_show(fig=None, **kwargs):\n" + " orig_plt_show(fig, **kwargs)\n" + " import IPython.display\n" + " IPython.display.display(plt.gcf())\n" + "mne.viz.utils.plt_show = pyodide_plt_show\n" + ), "doc_module": ("mne",), "reference_url": dict(mne=None), "examples_dirs": examples_dirs, diff --git a/pyproject.toml b/pyproject.toml index ae2120938ee..d756628af56 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,8 @@ doc = [ "graphviz", "intersphinx_registry >= 0.2405.27", "ipython != 8.7.0", # also in "full-no-qt" and "test" + "jupyterlite-pyodide-kernel", + "jupyterlite-sphinx", "memory_profiler >= 0.16", "mne-bids", "mne-connectivity", From 89072afc79dd2617504219c5482fd32d63c9db35 Mon Sep 17 00:00:00 2001 From: natinew77-creator Date: Thu, 11 Jun 2026 17:33:42 -0400 Subject: [PATCH 6/6] MAINT: explicitly import mne.viz.utils in jupyterlite cell to prevent lazy_loader AttributeError --- doc/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/conf.py b/doc/conf.py index 0b937edce52..fe241b94096 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -487,6 +487,7 @@ "\n" "# 2. Patch MNEBrowseFigure to auto-display in Pyodide's inline backend\n" "import mne\n" + "import mne.viz.utils\n" "import matplotlib.pyplot as plt\n" "orig_plt_show = mne.viz.utils.plt_show\n" "def pyodide_plt_show(fig=None, **kwargs):\n"