A composable set of anywidget-based widgets for data analysis and geospatial work in notebooks — works well with lonboard, and renders statically (no kernel) via the myst-anywidget-static-export plugin.
Project description
manywidgets
A composable set of anywidget-based widgets for data
analysis and geospatial work in notebooks. They're self-contained, link and
compose, work well with lonboard, and
render statically (no kernel) via the
myst-anywidget-static-export
MyST plugin.
Status: early but feature-complete for v1 —
Chart, input controls (Slider,RangeSlider,Dropdown,Toggle,Button,NumberInput), value displays (Stat,NumberDisplay,Text), layout containers (Row,Column,Grid), theBinderlinking primitive, and optional lonboard interop (LayerToggle,FilterBinder,LayerFilter).
Install
pip install manywidgets
# optional lonboard interop widgets:
pip install "manywidgets[lonboard]"
Quick start
from manywidgets import Chart, Slider, Binder
import numpy as np
chart = Chart(title="Demo", x_label="x", y_label="y", height=320)
chart.add_series(x=np.linspace(0, 10, 100), y=np.sin(np.linspace(0, 10, 100)), name="sin")
chart
Widgets
from manywidgets import (
Chart, # Chart.js charts
Slider, RangeSlider, Dropdown, Toggle, Button, NumberInput, # input controls
Stat, NumberDisplay, Text, Legend, # value displays
Row, Column, Grid, # layout (arrange + keep children linked)
Binder, # linking with transforms / nested paths
)
# Optional lonboard interop (pip install "manywidgets[lonboard]")
from manywidgets.lonboard import LayerToggle, FilterBinder, LayerFilter
Linking widgets
Two complementary tools — see docs/guides/linking.md:
from ipywidgets import jsdlink
# 1. jslink / jsdlink — the canonical, kernel-free pass-through link.
slider = Slider(label="Amplitude", min=0, max=5, value=1)
jsdlink((slider, "value"), (chart, "title")) # browser-side, works live + static
# 2. Binder — for transforms / nested paths jslink can't express.
Binder(source=slider, source_field="value",
target=chart, target_field="height",
multiplier=100, offset=200)
Agent skill
manywidgets ships an agent skill so coding agents can help you build widgets and dashboards. Install it into a location your agent discovers:
manywidgets install-skill # ./.claude/skills/manywidgets/ (this project)
manywidgets install-skill --user # ~/.claude/skills/manywidgets/ (all projects)
manywidgets install-skill --path DIR # anywhere else (other agents)
The skill (an entrypoint plus references/ on widget API, usage, and authoring)
travels inside the wheel, so it always matches the installed version. The
per-widget API reference is generated from widget traits — never hand-edited.
How it works / design
Every widget extends a thin BaseWidget (auto-assigns a stable widget_id) and
follows the TypeScript "golden example" structure: src/index.ts bundled by
esbuild into dist/widget.js, styling via the _css trait. Cross-widget
resolution and the static-export safety rules live once in a shared
@manywidgets/core TypeScript module that esbuild inlines into each widget.
This package has no code dependency on the static-export plugin — it just
follows the rules the plugin needs (wrap save_changes, never inject <link>
into the mount element, vanilla DOM, buffer-free core widgets, link via
jslink/Binder). The docs site references the plugin by release URL only.
Development
npm install
npm run build # esbuild every widget src/index.ts -> dist/widget.js
npm run typecheck # tsc --noEmit
npm test # vitest (JS unit tests)
pip install -e ".[dev]"
pytest
Docs
Each widget owns its docs in src/manywidgets/<name>/doc.md (prose + a
{code-cell} example + an {api-table} placeholder). npm run docs:gen builds
docs/widgets/<name>.ipynb from those — auto-generating the API table from trait
introspection — so the per-widget pages are generated build artifacts
(gitignored), not hand-maintained. The agent skill's API reference is generated
the same way (npm run skill:gen → src/manywidgets/skill/references/widgets-api.md,
which is committed and CI-checked for drift) — regenerate it after changing
any widget's traits. Build and view:
# lonboard + geopandas + pyarrow are only needed for the lonboard interop example
pip install -e ".[numpy,lonboard]" ipykernel nbconvert nbformat geopandas pyarrow
python -m ipykernel install --user --name manywidgets-venv
npm run docs:gen # generate docs/widgets/*.ipynb from each widget's doc.md
jupyter nbconvert --to notebook --execute --inplace docs/examples/*.ipynb docs/widgets/*.ipynb
cd docs && npx myst build --html && cd ..
npm run serve # serve over HTTP at http://localhost:8000 (NOT file://)
Serve the built site over HTTP — opening the HTML via
file://breaks asset and widget loading (absolute paths + dynamicimport()).
Releases are cut by publishing a GitHub Release (CI builds the wheel — with JS compiled by the build hook — and publishes to PyPI). The JS bundles are gitignored and rebuilt by the build; they ship inside the wheel.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file manywidgets-0.1.0.tar.gz.
File metadata
- Download URL: manywidgets-0.1.0.tar.gz
- Upload date:
- Size: 218.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bcf36884a41b3fccccc0d41ab316486ffff8d687b826b6afef2e6c9552a10173
|
|
| MD5 |
5baa72b640667af67f7c4a2a38977f24
|
|
| BLAKE2b-256 |
fa934a27b7aebe9cbaa9ffcb2daab3d73474a1924986e800751f92f56a0e75ce
|
Provenance
The following attestation bundles were made for manywidgets-0.1.0.tar.gz:
Publisher:
release.yml on developmentseed/manywidgets
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
manywidgets-0.1.0.tar.gz -
Subject digest:
bcf36884a41b3fccccc0d41ab316486ffff8d687b826b6afef2e6c9552a10173 - Sigstore transparency entry: 2166774870
- Sigstore integration time:
-
Permalink:
developmentseed/manywidgets@dfbc0d70d1b5652578273fc2785619f62c517684 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/developmentseed
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@dfbc0d70d1b5652578273fc2785619f62c517684 -
Trigger Event:
push
-
Statement type:
File details
Details for the file manywidgets-0.1.0-py3-none-any.whl.
File metadata
- Download URL: manywidgets-0.1.0-py3-none-any.whl
- Upload date:
- Size: 228.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
696b85e55a1c5559728a4924860776361e635ceca38d2deebc3a6b1dac24f285
|
|
| MD5 |
2aeecfd81cbcb78a3fdae60c13e3c121
|
|
| BLAKE2b-256 |
9b2b91dc43f7d0c2e3caadb1f1050972953430b9745a32bd4449a4af17edfa37
|
Provenance
The following attestation bundles were made for manywidgets-0.1.0-py3-none-any.whl:
Publisher:
release.yml on developmentseed/manywidgets
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
manywidgets-0.1.0-py3-none-any.whl -
Subject digest:
696b85e55a1c5559728a4924860776361e635ceca38d2deebc3a6b1dac24f285 - Sigstore transparency entry: 2166774892
- Sigstore integration time:
-
Permalink:
developmentseed/manywidgets@dfbc0d70d1b5652578273fc2785619f62c517684 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/developmentseed
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@dfbc0d70d1b5652578273fc2785619f62c517684 -
Trigger Event:
push
-
Statement type: