Shiny
Input and output
Use output_maplibregl in the UI and render_maplibregl in the server section of your Shiny for Python app:
from shiny import App, ui
from maplibre import output_maplibregl, render_maplibregl, Map
app_ui = ui.page_fluid(
    ui.panel_title("MapLibre"),
    output_maplibregl("maplibre", height=600)
)
def server(input, output, session):
    @render_maplibregl
    def maplibre():
        m = Map()
        return m
app = App(app_ui, server)
Reactivity
Input events
MapLibre for Python provides the following reactive inputs:
input.{output_id}_clicked: Sends coordinates of the clicked location on the map.input.{output_id}_feature_clicked: Sends the properties of the clicked feature and its layer id.input.{output_id}_view_state: Sends the current view state. Fired when the view state is changed.
Map updates
Use MapContext to update your Map object.
Example
import json
from maplibre import (
    Layer,
    LayerType,
    Map,
    MapContext,
    output_maplibregl,
    render_maplibregl,
)
from maplibre.controls import NavigationControl
from maplibre.sources import GeoJSONSource
from shiny import App, reactive, render, ui
LAYER_ID = "earthquakes"
CIRCLE_RADIUS = 5
app_ui = ui.page_fluid(
    ui.panel_title("MapLibre for Python"),
    output_maplibregl("mapgl", height=600),
    ui.div("Click on the map to print the coords.", style="padding: 10px;"),
    ui.output_text_verbatim("coords", placeholder=True),
    ui.div("Click on a feature to print its props.", style="padding: 10px;"),
    ui.output_text_verbatim("props", placeholder=True),
    ui.div("Move map or zoom to update view state.", style="padding: 10px;"),
    ui.output_text_verbatim("view_state", placeholder=True),
    ui.input_slider("radius", "Radius", value=CIRCLE_RADIUS, min=1, max=10),
)
circle_layer = Layer(
    type=LayerType.CIRCLE,
    id=LAYER_ID,
    source=GeoJSONSource(
        data="https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson"
    ),
    paint={"circle-color": "yellow"},
)
def server(input, output, session):
    @render_maplibregl
    def mapgl():
        m = Map(zoom=3, pitch=40)
        m.add_control(NavigationControl())
        m.add_layer(circle_layer)
        return m
    @render.text
    def coords():
        return str(input.mapgl_clicked())
    @render.text
    def view_state():
        return json.dumps(input.mapgl_view_state(), indent=2)
    @render.text
    def props():
        return str(input.mapgl_feature_clicked())
    @reactive.Effect
    @reactive.event(input.radius)
    async def radius():
        async with MapContext("mapgl") as m:
            m.set_paint_property(LAYER_ID, "circle-radius", input.radius())
app = App(app_ui, server)
Run this example: