deck.gl visualization library for marimo notebooks — interactive maps with 33 layer types
Project description
deckgl-marimo
Interactive deck.gl visualization library for marimo notebooks. Render GPU-accelerated maps with 33 layer types, powered by MapLibre GL and anywidget.
Features
- 33 deck.gl layer types — scatter plots, hexagonal bins, heatmaps, arcs, paths, polygons, GeoJSON, 3D columns, and more
- Multi-layer maps — compose multiple layers on a single map
- Standalone layers — display any layer directly without explicit map setup
- Marimo-native reactivity — bind layer properties to sliders, dropdowns, and other widgets
- Multiple data sources — pandas, polars, geopandas, DuckDB, GeoJSON dicts, and URLs
- Fully offline — all JavaScript bundled in the package, no CDN dependencies
- Viewport readback — read the current map center, zoom, pitch, and bearing from Python
- Click & hover events — inspect picked objects reactively in downstream cells
Installation
pip install deckgl-marimo
# or
uv add deckgl-marimo
Quickstart
Standalone layer
import marimo as mo
import deckgl_marimo as dgl
layer = dgl.ScatterplotLayer(
data=df,
get_position=["longitude", "latitude"],
get_fill_color=[255, 140, 0],
get_radius="population",
radius_scale=10,
)
# Displays a map with one layer
widget = mo.ui.anywidget(layer)
Multi-layer map
m = dgl.Map(
layers=[
dgl.ScatterplotLayer(
data=cities_df,
get_position=["lon", "lat"],
get_fill_color=[255, 140, 0],
get_radius=5,
radius_min_pixels=3,
),
dgl.ArcLayer(
data=flights_df,
get_source_position=["src_lon", "src_lat"],
get_target_position=["dst_lon", "dst_lat"],
get_source_color=[0, 128, 255],
get_target_color=[255, 0, 128],
),
],
basemap="dark-matter",
center=(-98.5, 39.8),
zoom=4,
pitch=45,
)
widget = mo.ui.anywidget(m)
Reactive controls
Important: Create the
Mapwidget in a cell that does not depend on slider values. Update layers by assigning tomap_widget.layer_specsin a separate cell. This keeps the map instance stable — sliders update layers via traitlet sync instead of recreating the entire map, which would cause tile reloads and a black screen flash.
# Cell 1 — sliders
radius = mo.ui.slider(200, 5000, value=1000, label="Radius")
# Cell 2 — create map widget (NO slider deps — stable, never re-executes)
map_widget = dgl.Map(basemap="dark-matter", center=(-1.4, 52.2), zoom=6, pitch=40)
widget = mo.ui.anywidget(map_widget)
# Cell 3 — display
widget
# Cell 4 — update layers reactively (re-executes when slider changes)
map_widget.layer_specs = [
dgl.HexagonLayer(
data=df,
get_position=["lon", "lat"],
radius=radius.value,
extruded=True,
elevation_scale=250,
).to_spec()
]
# Cell 5 — viewport readback
vp = widget.value.get("viewport", {})
mo.md(f"Zoom: {vp.get('zoom', 'N/A'):.1f}")
DuckDB integration
import duckdb
rel = duckdb.sql("SELECT lon, lat, value FROM 'data.parquet' WHERE value > 100")
layer = dgl.ScatterplotLayer(data=rel, get_position=["lon", "lat"])
Available layers
Fully tested (10)
| Layer | Use case |
|---|---|
ScatterplotLayer |
Point data |
GeoJsonLayer |
Polygons, lines, points from GeoJSON/GeoDataFrame |
ArcLayer |
Origin-destination flows |
PathLayer |
Routes, trajectories |
PolygonLayer |
Filled regions |
IconLayer |
Marker icons |
TextLayer |
Labels |
ColumnLayer |
3D bars on map |
HexagonLayer |
Hexagonal binning |
HeatmapLayer |
Density visualization |
Experimental (23)
All additional deck.gl layers are available as experimental stubs via deckgl_marimo.layers:
from deckgl_marimo.layers import TripsLayer, MVTLayer, H3HexagonLayer, ContourLayer
# ... and 19 more
Basemaps
dgl.Basemaps.list_available()
# ['bright', 'dark', 'dark-matter', 'embedded', 'liberty', 'light', 'none', 'osm', 'positron', 'voyager']
# Use any MapLibre-compatible style URL
dgl.Map(basemap="https://my-tileserver.example.com/style.json")
Troubleshooting
Content-Length errors in the marimo console
You may see h11._util.LocalProtocolError: Too little data for declared Content-Length
in the server console when a notebook loads. This is a known issue with uvicorn's
default h11 HTTP parser serving the large JS bundle. The map still works correctly.
To suppress it, install httptools so uvicorn uses a faster HTTP parser, then
fully restart marimo (kill and relaunch):
uv add httptools
# then restart marimo
uv run marimo edit your_notebook.py
License
MIT
Project details
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 deckgl_marimo-0.2.0.tar.gz.
File metadata
- Download URL: deckgl_marimo-0.2.0.tar.gz
- Upload date:
- Size: 822.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7269a3722eee8c2956ddc88fa60cf09ebb784e69d636a994220e8e30c06ff737
|
|
| MD5 |
0252dd93439454acc409e6b42725c1f9
|
|
| BLAKE2b-256 |
e5b8e7dfecbf6a9cd65c1d62f083dc7074063429b3aa3f8356033d9db51cf9c8
|
Provenance
The following attestation bundles were made for deckgl_marimo-0.2.0.tar.gz:
Publisher:
publish.yml on kihaji/deckgl-marimo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
deckgl_marimo-0.2.0.tar.gz -
Subject digest:
7269a3722eee8c2956ddc88fa60cf09ebb784e69d636a994220e8e30c06ff737 - Sigstore transparency entry: 1191496563
- Sigstore integration time:
-
Permalink:
kihaji/deckgl-marimo@881d4baf73cf14a8759171beba224d789eaa067b -
Branch / Tag:
refs/tags/0.2.0 - Owner: https://github.com/kihaji
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@881d4baf73cf14a8759171beba224d789eaa067b -
Trigger Event:
release
-
Statement type:
File details
Details for the file deckgl_marimo-0.2.0-py3-none-any.whl.
File metadata
- Download URL: deckgl_marimo-0.2.0-py3-none-any.whl
- Upload date:
- Size: 668.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d4e8755a66f57f10a04c6930b912f33a9238a1e07f00b4f5eb34af27295ba819
|
|
| MD5 |
667f4a666e425459532a897da84f1c58
|
|
| BLAKE2b-256 |
98f9103fdc2a1461bf65fb0b5ef60e8f0867288d1f75a33fa01499261420159a
|
Provenance
The following attestation bundles were made for deckgl_marimo-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on kihaji/deckgl-marimo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
deckgl_marimo-0.2.0-py3-none-any.whl -
Subject digest:
d4e8755a66f57f10a04c6930b912f33a9238a1e07f00b4f5eb34af27295ba819 - Sigstore transparency entry: 1191496568
- Sigstore integration time:
-
Permalink:
kihaji/deckgl-marimo@881d4baf73cf14a8759171beba224d789eaa067b -
Branch / Tag:
refs/tags/0.2.0 - Owner: https://github.com/kihaji
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@881d4baf73cf14a8759171beba224d789eaa067b -
Trigger Event:
release
-
Statement type: