41c072cjupyterlite-numbl-kernel: MATLAB-syntax kernel for JupyterLiteJeremy Magland 1# jupyterlite-numbl-kernel
3A MATLAB-syntax kernel for [JupyterLite](https://jupyterlite.readthedocs.io/) —
4notebooks that run **entirely in the browser**, with no server, no kernel
5process, and nothing for the reader to install.
7The language engine is [numbl](https://github.com/flatironinstitute/numbl), an
8open-source MATLAB-syntax implementation in TypeScript. Each kernel runs a
9numbl session in a Web Worker in the page: variables persist across cells,
10console output streams into the running cell, MATLAB plotting commands render
6b31a9aSync .m workspace files from the notebook directory into the sessionJeremy Magland 11as figures in cell outputs (including interactive 3-D), the `mip` package
12manager can install MATLAB-syntax packages from GitHub, and `.m` files next
13to the notebook are part of the workspace (named functions, called from
14cells) — all client-side.
16**Demo site:**
17<https://concept-collection.github.io/jupyterlite-numbl-kernel/> (deployed
18from this repo via GitHub Pages — see `.github/workflows/deploy.yml`)
20## Why
22Existing MATLAB/Octave Jupyter kernels require the real product installed
23behind a server. This kernel is a proof of concept that a MATLAB-syntax
24notebook can be a static web page: hostable on GitHub Pages, shareable as a
25link, and executable by anyone with a browser.
27## How it works
29Three small pieces, all in this repo:
31- **Kernel** (`src/kernel.ts`) — implements JupyterLite's `BaseKernel` from
6b31a9aSync .m workspace files from the notebook directory into the sessionJeremy Magland 32 `@jupyterlite/services`. Before each `execute_request`, `.m` files in the
33 notebook's directory (read via the JupyterLite contents manager) are
34 synced into the numbl session; the cell source then runs against the
35 session's persistent workspace (`createNumblSession` /
36 `session.execute` from `numbl/browser`, a Web Worker that numbl manages).
37 Output streams back as `stream` messages; the run's plot instructions are
38 published as `display_data` with the mime type
39 `application/vnd.numbl.figure+json`.
41c072cjupyterlite-numbl-kernel: MATLAB-syntax kernel for JupyterLiteJeremy Magland 40- **Figure renderer** (`src/mime.tsx`) — a JupyterLab mime renderer for that
41 mime type: it replays the instructions through numbl's figures reducer and
42 mounts numbl's React `FigureView` (from `numbl/graphics`). Outputs are
43 plain JSON, so saved notebooks re-render wherever the extension is
44 installed.
45- **Kernel registration** (`src/index.ts`) — registers the kernelspec with
46 JupyterLite's `IKernelSpecs`.
48## Build a site with it
50```bash
51pip install jupyterlite-core jupyterlite-numbl-kernel
52jupyter lite build --contents my-notebooks --output-dir dist
53# dist/ is a static site — serve it anywhere
54```
56The `demo/` directory in this repo contains the demo site sources
57(notebooks + requirements); `.github/workflows/deploy.yml` builds and
58deploys it to GitHub Pages.
60## Limitations (proof of concept)
62- **No interrupt**: a runaway cell can only be stopped by restarting the
63 kernel (restart works and gives a fresh workspace). Cooperative
64 cancellation exists in numbl but needs `SharedArrayBuffer`, i.e.
65 cross-origin isolation headers, which plain GitHub Pages doesn't set.
66- **No `input()`** (stdin), for the same reason.
67- **Figures are per-cell** (like inline matplotlib): each cell renders the
68 figures its own commands produce; `hold on` does not span cells.
69- **Named function definitions are not supported inside cells** (a numbl
70 REPL limitation) — anonymous functions work; named functions belong in
6b31a9aSync .m workspace files from the notebook directory into the sessionJeremy Magland 71 `.m` files next to the notebook (see `demo/content/statsutils.m`), which
72 this kernel syncs into the session automatically.
73- The `.m`-file sync is **one-way**: deleting a `.m` file from the file
74 browser leaves its function defined until the kernel restarts, and files
75 written by cell code (e.g. via `fopen`) don't appear back in the file
76 browser.
41c072cjupyterlite-numbl-kernel: MATLAB-syntax kernel for JupyterLiteJeremy Magland 77- **uihtml** components render display-only; the MATLAB↔HTML event bridge
78 is not wired into outputs yet.
79- numbl itself is not MATLAB: it covers a large, tested subset of the
80 language and toolbox surface. See the
81 [numbl repo](https://github.com/flatironinstitute/numbl) for scope.
83## Development
85Requires Python ≥ 3.9 and NodeJS ≥ 20, and `numbl >= 0.4.14` on npm (the
86first release with the incremental `session.execute` browser API). To
87develop against an unreleased numbl checkout, run `npm pack` there and
88point the `numbl` dependency at the tarball.
90```bash
91python -m venv .venv && source .venv/bin/activate
92pip install "jupyterlab~=4.6.0" "jupyterlite-core==0.8.1"
94jlpm install
95jlpm build # tsc + labextension (dev)
96pip install -e . # editable install, registers the labextension
98# Build and serve the demo site locally
99pip install -r demo/requirements.txt
100jupyter lite build --lite-dir demo --contents content --output-dir demo/_output
101python -m http.server -d demo/_output 8000
102```
104`jlpm watch` rebuilds on change during development.
106## License
108Apache-2.0. Built on [numbl](https://github.com/flatironinstitute/numbl) and
109the [JupyterLite](https://github.com/jupyterlite/jupyterlite) kernel API;
110scaffolding follows the
111[jupyterlite/echo-kernel](https://github.com/jupyterlite/echo-kernel)
112template.