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.

The MyST AnyWidget Directive

Authors
Affiliations
Jupyter Book
Curvenote
Jupyter Book
2i2c
Jupyter Book
2i2c

Authors of MyST Markdown can now embed interactive JavaScript widgets directly in content using the new {anywidget} directive.

What this means

You can now add any javascript interactivity to your MyST Markdown website or Jupyter Book.

Here’s an example that creates a clickable button:

And here’s the directive that created it:

```{anywidget} https://github.com/jupyter-book/example-js-anywidget/releases/latest/download/widget.mjs
```

This directive has no parameters, so is very simple, pointing to an ESM module that just wraps the confetti.js library 🎉.

How we got here

The idea of a portable widget interface for interactive computing isn’t new: anywidget has been an emerging standard in the Jupyter community for a while, leveraging modern Javascript principles (via ESM Modules), and giving you a simple initialize({ model }); render({ model, el })[1] contract so that widgets can be written once and reused across notebooks. AnyWidget in Jupyter interfaces supports tight integration with the kernel, allowing interactions similar to ipywidgets[2].

From the MyST Markdown and Jupyter Book point of view, we’ve focussed on supporting the render() side of the AnyWidget interface (see AnyWidget Frontend Modules) to allow MyST users to bring any kind of javascript-based interactivity into their articles and books without having to lean on Jupyter at all.

That part of the story started at SciPy 2024 with Trevor Mantz and Steve Purves hacking through a proof of concept during the sprints. Curvenote built working support for AnyWidgets as a MyST Markdown extension while working with researchers to support domain specific visualizations, and then upstreamed the implementation to create the {anywidget} directive that has just been released in mystmd and jb2.

The new directive in mystmd and the respective supporting package in @myst-theme/anywidget evolved with input from the JupyterBook team. Here’s how it is currently structured:

Usage

From an author’s perspective, point the directive at an ESM module (either a URL to a hosted script or a local path) and the widget runs in the page with its own state and DOM. You may optionally pass in a CSS URL/path and a JSON body of props to initialize the widget model.

To understand how to build your own widgets, the MyST widgets guide walks through the render({ model, el }) signature, styling with Shadow DOM, and cleanup on unmount. It’s the same mental model as anywidget in Jupyter, so if you’ve written or seen Jupyter AnyWidgets, you’re already most of the way there.

If you want to try it, the example-widgets repo has small demos (confetti, div-map, etc. Contributions are welcome!), and the opensci.dev blog has some live examples using scientific datasets.

What’s next

Widget support in MyST is still marked experimental so the details may evolve. There are still some things on the roadmap for {anywidget} which will no doubt expand as we hear of new requirements from widget creators, but we expect the following to be close to the top of the stack:

The JupyterBook team is actively working on improving and evolving the widget model and integrating with Jupyter. We look forward to seeing what the community builds — visit the discord to showcase what you have built!

Footnotes
  1. The AnyWidget spec provides for a model that is both responsible for exposing the properties supplied within the {anywidget} directive and enables communication between widgets on the page at runtime.

  2. See the Modern Web Meets Jupyter blog post for an introduction on how AnyWidgets are used in Jupyter