GeoLibre in Jupyter: the full GeoLibre GIS app as an anywidget, with a leafmap-style Python API.
The widget embeds the complete GeoLibre app (menus, panels, processing tools)
inside a notebook cell. State syncs both ways through a single
.geolibre.json project, so data you add from Python appears in the UI, and
edits you make in the UI are readable back from Python.
pip install geolibreOr with conda from conda-forge:
conda install -c conda-forge geolibrefrom geolibre import Map
m = Map(center=(-100, 40), zoom=4)
m.add_geojson("https://example.com/data.geojson", name="Data")
mAdd more data and drive the view:
m.add_tile_layer(
"https://tile.openstreetmap.org/{z}/{x}/{y}.png",
name="OpenStreetMap",
attribution="(c) OpenStreetMap contributors",
)
m.add_cog("https://example.com/dem.tif", name="DEM", colormap="terrain")
m.add_basemap("dark")
m.set_center(-120, 47, zoom=8)Round-trip the project:
m.save_project("my-map.geolibre.json")
m2 = Map()
m2.load_project("my-map.geolibre.json")
# Read state edited in the UI (e.g. after panning/zooming):
m.to_project()["mapView"]["center"]| Method | Description |
|---|---|
Map(center, zoom, basemap=, height=, layout=, theme=) |
Create a map. layout is "embed", "full", or "maponly". |
add_geojson(data, name=, **style) |
Add GeoJSON (dict, path, URL, JSON, or GeoDataFrame). |
add_gdf(gdf, name=, column=None, **style) |
Add a GeoDataFrame, optionally as a choropleth. |
add_csv / add_xy_data (data, x=, y=, name=, **style) |
Add points from CSV, a DataFrame, or row mappings. |
add_heatmap(points, name=, radius=, intensity=, **style) |
Add a point density heatmap. |
add_vector(data, name=, render_mode=, data_format=, source_layer=, **style) |
Add a vector dataset from a URL (GeoParquet, FlatGeobuf, zipped Shapefile, GeoJSON) or a local file (read via GeoPandas, inlined). |
add_geoparquet / add_flatgeobuf / add_shp / add_kml / add_gpkg |
Format-specific wrappers over add_vector. |
add_vector_tiles(url, name=, source_layers=, source_layer=, **style) |
Add vector tiles from a TileJSON endpoint. |
add_pmtiles(url, name=, tile_type=, source_layers=, **style) |
Add a PMTiles archive (vector or raster). |
add_tile_layer(url, name=, tile_size=, attribution=) |
Add a raster XYZ tile layer. |
add_wms(endpoint, layers, name=, styles=, image_format=, transparent=, tile_size=, **style) |
Add a WMS (GetMap) tiled raster layer. |
add_wmts(url, name=, tile_size=, **style) |
Add a WMTS tile URL template. |
add_wfs(endpoint, type_name, name=, version=, output_format=, srs_name=, max_features=, **style) |
Add a WFS layer (GeoJSON, fetched and inlined). |
add_cog(url, name=, bands=, colormap=, rescale=) |
Add a Cloud Optimized GeoTIFF. |
add_raster(url, name=, bands=, colormap=, rescale=) |
Add a raster (alias of add_cog). |
add_3d_tiles(url, name=, altitude_offset=, request_headers=, **style) |
Add a 3D Tiles tileset.json. |
add_video(urls, coordinates, name=, **style) |
Add a georeferenced video (four [lng, lat] corners). |
add_basemap(basemap) |
Set the background basemap. |
set_center(lng, lat, zoom=None) |
Center (and optionally zoom) the map. |
set_center_zoom(lng, lat, zoom=None) |
Alias of set_center (leafmap compatibility). |
zoom_to_bounds(bounds) / zoom_to_layer(layer) |
Fit the view to bounds or a layer id/name/handle. |
layer_names / find_layer(name) / set_layer_visibility / set_layer_opacity |
Inspect and update layers conveniently. |
rename_layer / move_layer / duplicate_layer / show_layer / hide_layer |
Manage layers by id, name, or Layer handle. |
layer_properties(layer) / column_values(layer, column) / describe() |
Inspect inlined data and summarize a project without a browser round trip. |
remove_layer(layer) / clear_layers() |
Remove one layer by id, name, or handle, or remove all layers. |
center / zoom / basemap / name |
Read persisted project and camera state; name is writable. |
set_zoom / set_bearing / set_pitch / fit_project_bounds |
Persist camera changes without requiring the widget to be displayed. |
to_project() / load_project(src) / save_project(path) |
Project I/O. |
Layer handles provide the same operations in an object-oriented form:
m.add_geojson("https://example.com/roads.geojson", name="Roads")
roads = m.find_layer("Roads") # None when no layer has that name
roads.opacity = 0.6
roads.set_style(lineColor="#e63946", lineWidth=3)
roads.move(0)
print(roads.properties()) # sampled values for every property
print(roads.column("highway")) # one value per feature
roads_copy = roads.duplicate(name="Roads (proposed)")For headless authoring and scripts that do not need a widget, commonly used project utilities are available directly from the top-level package:
from geolibre import (
basemap_catalog,
builtin_legend_names,
color_ramp_names,
describe_project,
load_project,
save_project,
)
project = load_project("my-map.geolibre.json")
print(describe_project(project))
save_project("copy.geolibre.json", project)- The bundled app is served from a localhost HTTP server, so the interactive
widget works in local Jupyter and VS Code directly. Google Colab routes
through its built-in port proxy automatically. On JupyterHub (including
managed/shared hubs) the front-end tries two same-origin routes and uses
whichever is live, so a host needs only one of them: the Jupyter Server
extension bundled with
geolibreat{base_url}geolibre/app/(enabled automatically onpip install geolibre, but registered only after the Jupyter server restarts), andjupyter-server-proxyat{base_url}proxy/{port}/(works in the running server with no restart where it is installed). On other remote servers (Binder, remote JupyterLab), passMap(server_proxy=True)to use that same remote path;Map(server_proxy=False)forces the direct path. - Optional extras:
pip install "geolibre[all]"adds GeoPandas/Shapely support foradd_geojson(geodataframe)and for reading local vector files (add_vector/add_geoparquet/add_flatgeobuf/add_shp/add_kml/add_gpkg), which the kernel reads and inlines as GeoJSON. Remote URLs for the same formats stream through the in-browser vector control and need no extras. add_geojsoninlines file/URL data into the project (up to 50 MB), so a large dataset is held in memory and re-synced on every project update. For very large layers, prefer a tile or COG source (add_tile_layer/add_cog) the app fetches directly.
The package also ships a headless MCP server
that authors .geolibre.json projects from an AI client:
pip install "geolibre[mcp]"
geolibre-mcp --root ~/mapsIt confines every read and write to the roots you pass (--root, repeatable, or
GEOLIBRE_MCP_ROOTS) and builds projects through the same builders this package
uses, so anything it writes opens in the widget unchanged. See
docs/mcp.md for the tool list and client
configuration.