MEOS.js in JupyterLite

June 8, 2026 · View on GitHub

A fully in-browser JupyterLite site with a JavaScript kernel, demonstrating MEOS.js as an analytical library (not just a map renderer). Every cell runs in a Web Worker; MEOS.js (wasm included) is loaded straight from the jsDelivr CDN, so there is no build step for the library itself.

Like the deck.gl demos, this needs a browser with WebAssembly Memory64 (Chrome/Edge 133+ or a recent Firefox).

Notebooks

FileShows
content/meos-intro.ipynbLoad MEOS.js from the CDN, build a TGeomPoint, then length / speed / shiftScaleTime / atGeom.

Build & serve locally

JupyterLite is built with Python tooling (separate from the Vite project).

cd jupyterlite
python -m venv .venv && source .venv/bin/activate   # optional but recommended
pip install -r requirements.txt

# Build the static site (notebooks come from ./content)
jupyter lite build --contents content --output-dir _output

# Serve it
jupyter lite serve --output-dir _output

Open the printed URL, then go to JupyterLab -> meos-intro.ipynb and run the cells.

How it works

The JupyterLite JavaScript kernel (0.3.0) self.eval()s each cell synchronously: it does not accept the await keyword, and it does not await a Promise a cell returns (it inspects the result immediately). So cell 1 starts the wasm download in the background and stashes the modules on globalThis; the later cells guard on globalThis.meosLoaded and are re-run once loading has finished. MEOS operations themselves are synchronous.

const CDN = 'https://cdn.jsdelivr.net/npm/meos.js@1.0.2/dist';
globalThis.meosReady = globalThis.meosReady || import(`${CDN}/core/index.js`)
  .then((m) => { globalThis.meos = m; return globalThis.meos.initMeos(); })
  .then(() => { globalThis.meosLoaded = true; });
'⏳ Loading… run the next cells once this finishes';

Because the Emscripten loader resolves the binary with new URL('meos.wasm', import.meta.url), importing the ESM entry from the CDN makes the wasm fetch from the same CDN path automatically.