Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Anywidget Experiments

Warning: Most of the text and code in this repository has been created with heavy LLM-use. If you want to read an introduction written by a human (me), please start here.

Anywidget Experiments

Custom anywidget widgets that interoperate, render statically without a kernel, and play nicely with lonboard.

Live demo: https://batpad.github.io/anywidget-experiments/

Background: What is this and why — the motivation, what’s weird about it, and what it isn’t.

The pages on the live site are static HTML — no kernel running, no server, just a mystmd build. Click the buttons, scrub the counters, watch lonboard’s points resize. All of it is JS-only at runtime.

Walkthrough

  1. An anywidget, statically — a single CounterWidget. Click +/-/Reset; the count updates locally with no kernel.

  2. Anywidgets talking to each other — two widgets on the same page, wired through a shared in-page registry.

  3. Lonboard, statically — a minimal lonboard.Map rendered with binary Parquet buffers preserved through MyST’s build pipeline.

  4. Lonboard ↔ anywidget interop — a counter drives a lonboard layer’s point radius via a generic binder widget.

Showcase notebooks

These two stretch the toolchain into something more polished — real data, custom UI, and the kind of “wow, that’s a notebook?” reaction we wanted to demonstrate. Both ship as static pages, no kernel.

  1. What happened to your name? — type your name. A 144-year SSA-baby-names trajectory animates across a sweeping playhead, your birth year is marked, four “trajectory twins” appear below, and a small surprise fires when the playhead hits your name’s peak year. The custom NameExplorer widget is one ~500-line vanilla-JS file with an inlined confetti routine and an Easter egg.

  2. Hurricane Helene, 48 hours later — Asheville disaster-response demo. A lonboard map with MODIS basemap, hand-authored Sentinel-1-style flood polygon, OSM building footprints (~41K), and hospitals. The HurricaneDashboard widget toggles layers and drives a flood-depth threshold slider that filters which buildings are shown — counters tween live as you drag.

These two notebooks pull external data (SSA names ZIP via Wayback, OSM via Overpass, MODIS via NASA GIBS, NOAA HURDAT2). The fetched files are .gitignored. To regenerate them locally before re-executing the notebooks, run bash data/names/fetch.sh and python data/helene/fetch.py. CI does not re-execute these — their widget state is committed in the .ipynb outputs, so a normal myst build is enough on push.

How it works

A small mystmd plugin at plugins/anywidget-static-export.mjs rewrites notebook widget outputs into AST nodes the @myst-theme/anywidget renderer can mount, with a runtime shim that no-ops the kernel-sync calls and hydrates binary buffers (Apache Parquet for lonboard) at page load. The plugin’s README has the full catalogue of workarounds — they touch mystmd, myst-theme, @jupyter-widgets/base, and lonboard itself — and the docs/ folder has a write-up per upstream fix.

Local development

git clone https://github.com/batpad/anywidget-experiments.git
cd anywidget-experiments

python -m venv venv
source venv/bin/activate
pip install -r requirements.txt

npm install
npm run build      # runs prebuild (executes lonboard notebooks via nbclient) then myst build
npm run serve      # python -m http.server on _build/html

For a development loop on a single notebook:

jupyter lab notebooks/04_lonboard_interop.ipynb
# edit, "Restart Kernel and Run All", save with widget state, then `npm run build`

Repo structure

notebooks/   Walkthrough (01–04) + showcase (05–06) notebooks.
widgets/     CounterWidget, LinkedCounterWidget, WidgetBinder, NameExplorer, HurricaneDashboard.
plugins/     The static-export mystmd plugin + README explaining each hack.
data/        Datasets fetched at prebuild for the showcase notebooks (mostly .gitignored — see data/*/fetch.py / fetch.sh).
docs/        Per-upstream-fix write-ups + parking-lot example-ideas-*.md for sister notebooks.
.github/     GitHub Actions workflow that builds + deploys the site to Pages on every push to main.

Acknowledgments

License

MIT