Skip to content

authoring

Widget-free operations on whole GeoLibre project dicts.

project.py builds pieces (a layer, a plugin-state blob). This module applies them to a project: adding and restyling layers, moving the camera, composing the map controls, and reading a project back as a summary.

Everything here is pure Python on plain dicts, with no widget, no browser, and no network. geolibre.Map delegates to these functions so the Jupyter widget and the MCP server (geolibre.mcp) share one implementation rather than growing two copies of the same composition rules.

load_project

load_project(path: str | Path) -> dict[str, Any]

Read a .geolibre.json file into a project dict.

Parameters:

Name Type Description Default
path str | Path

Path to the project file.

required

Returns:

Type Description
dict[str, Any]

The parsed project dict.

Raises:

Type Description
ValueError

If the file is missing, oversized, not JSON, or not a project object.

save_project

save_project(path: str | Path, project: dict[str, Any]) -> Path

Write a project dict to disk as formatted JSON.

Parent directories are created. The file is written with a trailing newline and two-space indentation so it reads and diffs like the rest of the repo's JSON.

The write goes to a temporary file alongside the destination and is then moved into place, so an interrupted write cannot leave a half-written project where a complete one used to be. A project inlines its GeoJSON and can approach MAX_PROJECT_BYTES, and the MCP server rewrites the whole file on every edit, so a truncating write is a real way to lose work.

Note

This writes verbatim, credentials included. It is the lossless primitive the MCP server round-trips a user's own project file through, where stripping an API key on every small edit would quietly destroy the file's usefulness. geolibre.Map.save_project is the counterpart for producing a file to share: it redacts unless keep_credentials=True. Run a project through geolibre.project.redact_credentials before calling this if the result is going anywhere untrusted.

Parameters:

Name Type Description Default
path str | Path

Destination path.

required
project dict[str, Any]

The project dict to serialize, written as given.

required

Returns:

Type Description
Path

The resolved path written to.

layers_of

layers_of(project: dict[str, Any]) -> list[dict[str, Any]]

Return the project's layer list, creating it when absent.

find_layer

find_layer(project: dict[str, Any], ref: str) -> dict[str, Any]

Resolve a layer by id or by display name.

An exact id match wins outright, so a layer whose name happens to equal another layer's id cannot shadow it. Name matching is tried next, exact first and then case-insensitively.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict.

required
ref str

A layer id or display name.

required

Returns:

Type Description
dict[str, Any]

The matching layer dict (the live object, not a copy).

Raises:

Type Description
ValueError

If nothing matches, or if a name matches several layers.

resolve_layer_ids

resolve_layer_ids(project: dict[str, Any], refs: Iterable[str]) -> list[str]

Resolve layer ids/names to ids, passing the basemap pseudo-id through.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict.

required
refs Iterable[str]

Layer ids, layer names, or "__basemap__".

required

Returns:

Type Description
list[str]

The resolved layer ids, in input order.

Raises:

Type Description
ValueError

If a reference matches no layer or several.

layer_summary

layer_summary(layer: dict[str, Any]) -> dict[str, Any]

Summarize one layer for display, omitting any inlined data.

A GeoJSON layer's geojson blob can be tens of megabytes, so it is reported as a feature count rather than echoed back. The source URL is reported with its credentials stripped: a summary exists to be shown, and both callers show it somewhere untrusted (a notebook cell that gets committed, an MCP tool result that goes to a model client).

Parameters:

Name Type Description Default
layer dict[str, Any]

A layer dict.

required

Returns:

Type Description
dict[str, Any]

A small dict of the layer's identity, visibility, and source.

describe_project

describe_project(project: dict[str, Any]) -> dict[str, Any]

Summarize a project: its camera, basemap, layers, and map controls.

URLs come back with their credentials stripped, as in layer_summary; several basemap providers put an API key in the style URL itself.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict.

required

Returns:

Type Description
dict[str, Any]

A compact, JSON-serializable overview.

layer_properties

layer_properties(layer: dict[str, Any]) -> dict[str, list[Any]]

Collect the distinct property values of an inlined GeoJSON layer.

Lets a caller discover what a layer can be styled or filtered by without reading the whole feature collection back.

Parameters:

Name Type Description Default
layer dict[str, Any]

A layer dict carrying an inlined geojson FeatureCollection.

required

Returns:

Type Description
dict[str, list[Any]]

A mapping of property name to up to 25 sample values (in first-seen

dict[str, list[Any]]

order).

Raises:

Type Description
ValueError

If the layer carries no inlined GeoJSON.

column_values

column_values(layer: dict[str, Any], column: str) -> list[Any]

Read one property's values across an inlined GeoJSON layer's features.

Parameters:

Name Type Description Default
layer dict[str, Any]

A layer dict carrying an inlined geojson FeatureCollection.

required
column str

The feature property name.

required

Returns:

Type Description
list[Any]

The raw values, one per feature (None where the property is absent).

Raises:

Type Description
ValueError

If the layer has no inlined GeoJSON, or the property is absent from every feature, or present but null in all of them.

add_layer

add_layer(project: dict[str, Any], layer: dict[str, Any], *, index: int | None = None) -> str

Insert a built layer into the project's draw order.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
layer dict[str, Any]

A layer dict from one of the project.py builders.

required
index int | None

Draw-order position; appended (drawn on top) when omitted.

None

Returns:

Type Description
str

The layer's id.

Raises:

Type Description
ValueError

If the layer's name is the reserved basemap pseudo-id.

remove_layer

remove_layer(project: dict[str, Any], ref: str) -> str

Remove a layer by id or name.

Any swipe control referencing the layer drops it from its side, so the saved project cannot carry a split pointing at a layer that is gone.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
ref str

A layer id or display name.

required

Returns:

Type Description
str

The removed layer's id.

Raises:

Type Description
ValueError

If the reference does not resolve to exactly one layer.

update_layer

update_layer(project: dict[str, Any], ref: str, *, name: str | None = None, visible: bool | None = None, opacity: float | None = None, index: int | None = None) -> dict[str, Any]

Change a layer's identity, visibility, or draw order.

Only the arguments you pass are applied; the rest are left alone.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
ref str

A layer id or display name.

required
name str | None

New display name.

None
visible bool | None

New visibility.

None
opacity float | None

New opacity, clamped to [0, 1].

None
index int | None

New draw-order position, clamped to the layer list's bounds.

None

Returns:

Type Description
dict[str, Any]

A summary of the updated layer.

Raises:

Type Description
ValueError

If the reference does not resolve to exactly one layer, or name is the reserved basemap pseudo-id.

apply_style

apply_style(project: dict[str, Any], ref: str, style: dict[str, Any]) -> dict[str, Any]

Merge style overrides into a layer's existing style.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
ref str

A layer id or display name.

required
style dict[str, Any]

Style keys to set (e.g. {"fillColor": "#ff0000"}). Keys not mentioned keep their current values.

required

Returns:

Type Description
dict[str, Any]

The layer's full style after the merge.

Raises:

Type Description
ValueError

If the reference does not resolve to exactly one layer, or style is not a mapping.

set_popup

set_popup(project: dict[str, Any], ref: str, fields: Any = None, *, click: bool | None = None, hover: bool | None = None, title: str | None = None, title_expression: str | None = None, body_expression: str | None = None, show_feature_id: bool | None = None, max_width: int | None = None, image_height: int | None = None, tooltip: Any = None, merge: bool = False) -> dict[str, Any]

Configure what a layer shows when a feature is clicked or hovered.

A layer with no popup config keeps the app's default: the layer name as the heading, then every visible property as a key/value row, and no hover tooltip. Configuring one narrows and formats that -- see geolibre.project.popup_config for the field vocabulary.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
ref str

A layer id or display name.

required
fields Any

The fields to show and their order; property names and/or geolibre.project.popup_field mappings.

None
click bool | None

False suppresses the click popup.

None
hover bool | None

True shows a hover tooltip built from the hover fields.

None
title str | None

Property whose value titles the popup.

None
title_expression str | None

MapLibre expression source producing the title.

None
body_expression str | None

MapLibre expression source producing the popup body.

None
show_feature_id bool | None

False drops the synthetic id row.

None
max_width int | None

Widest the click popup may draw, in CSS pixels.

None
image_height int | None

Tallest an "image" field may draw, in CSS pixels.

None
tooltip Any

Hover shorthand -- a property name, a sequence of names, True to flag every configured field, or False to turn the tooltip off.

None
merge bool

Merge into the layer's existing popup config instead of replacing it, so a tooltip can be added without restating the fields.

False

Returns:

Type Description
dict[str, Any]

The layer's popup config after the change.

Raises:

Type Description
ValueError

If the reference does not resolve to exactly one layer, or the popup specification is unusable.

clear_popup

clear_popup(project: dict[str, Any], ref: str) -> dict[str, Any]

Drop a layer's popup config, restoring the app's default popup.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
ref str

A layer id or display name.

required

Returns:

Type Description
dict[str, Any]

A summary of the updated layer.

Raises:

Type Description
ValueError

If the reference does not resolve to exactly one layer.

set_layer_metadata

set_layer_metadata(project: dict[str, Any], ref: str, *, merge: bool = False, **fields: Any) -> dict[str, Any] | None

Set a layer's descriptive (catalog) metadata.

This is what the app's layer Metadata dialog edits and exports as a STAC Item: title, abstract, keywords, license, attribution, contact, lineage, temporal extent and links. See geolibre.project.layer_metadata.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
ref str

A layer id or display name.

required
merge bool

Keep the layer's existing fields that fields does not name, instead of replacing the whole block.

False
**fields Any

Keyword arguments of geolibre.project.layer_metadata (title, abstract, keywords, license, attribution, contact, lineage, temporal_extent, links).

{}

Returns:

Type Description
dict[str, Any] | None

The layer's metadata block after the change, or None when it ended

dict[str, Any] | None

up empty (and was removed).

Raises:

Type Description
ValueError

If the reference does not resolve to exactly one layer, a field name is unknown, or a value fails validation.

clear_layer_metadata

clear_layer_metadata(project: dict[str, Any], ref: str) -> dict[str, Any]

Drop a layer's descriptive metadata.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
ref str

A layer id or display name.

required

Returns:

Type Description
dict[str, Any]

A summary of the updated layer.

Raises:

Type Description
ValueError

If the reference does not resolve to exactly one layer.

build_choropleth_style

build_choropleth_style(values: list[Any], column: str, *, class_count: int = 5, colormap: str = 'viridis', scheme: str = 'equal-interval') -> dict[str, Any]

Build the vectorStyle* keys for a graduated (choropleth) symbology.

Mirrors what the app's Style panel writes for a graduated fill, so a classification computed here renders the same as one built in the UI.

Parameters:

Name Type Description Default
values list[Any]

The column's raw values across the features.

required
column str

The feature property being classified.

required
class_count int

Number of classes (clamped to 2-12 by the stop builder).

5
colormap str

A ramp name from geolibre.color_ramp.VECTOR_COLOR_RAMPS.

'viridis'
scheme str

"equal-interval" or "quantile".

'equal-interval'

Returns:

Type Description
dict[str, Any]

A style fragment to merge into a layer's style.

Raises:

Type Description
ValueError

If no value is numeric, or scheme is unsupported.

classify_layer

classify_layer(project: dict[str, Any], ref: str, column: str, *, class_count: int = 5, colormap: str = 'viridis', scheme: str = 'equal-interval') -> dict[str, Any]

Symbolize an inlined GeoJSON layer as a choropleth on one column.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
ref str

A layer id or display name.

required
column str

The numeric feature property to classify.

required
class_count int

Number of classes.

5
colormap str

A ramp name.

'viridis'
scheme str

"equal-interval" or "quantile".

'equal-interval'

Returns:

Type Description
dict[str, Any]

The computed vectorStyle* fragment.

Raises:

Type Description
ValueError

If the layer has no inlined GeoJSON, the column is missing or non-numeric, or scheme is unsupported.

secondary_panes

secondary_panes(project: dict[str, Any]) -> list[dict[str, Any]]

Return secondaryMapViews validated as a list of renderable panes.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict.

required

Returns:

Type Description
list[dict[str, Any]]

The pane list (empty when the project has none).

Raises:

Type Description
ValueError

If the field is not a list of pane objects carrying a unique string id and, when present, a maplibre/cesium/mapbox/ arcgis viewKind (an omitted viewKind means maplibre), e.g. from a hand-edited project file.

set_renderer

set_renderer(project: dict[str, Any], renderer: str, *, pane_id: str | None = None) -> str

Select maplibre, cesium, mapbox, or arcgis for the primary map or a pane.

set_map_layout

set_map_layout(project: dict[str, Any], rows: int, cols: int, *, view_kinds: list[str] | None = None, sync_view: bool = True) -> list[dict[str, Any]]

Set a 1–4 row/column grid. view_kinds lists every pane, primary first.

set_view

set_view(project: dict[str, Any], *, center: Iterable[float] | None = None, zoom: float | None = None, bearing: float | None = None, pitch: float | None = None) -> dict[str, Any]

Set the saved camera the project opens at.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
center Iterable[float] | None

[lng, lat].

None
zoom float | None

Zoom level, clamped to [0, 24].

None
bearing float | None

Rotation in degrees.

None
pitch float | None

Tilt in degrees, clamped to [0, 85].

None
Note

Setting center or zoom clears any bbox a previous fit_bounds recorded, since it no longer describes the camera.

Returns:

Type Description
dict[str, Any]

The project's mapView after the change.

Raises:

Type Description
ValueError

If center is not a 2-element [lng, lat], or any value is not finite.

fit_bounds

fit_bounds(project: dict[str, Any], bbox: Iterable[float], *, padding: int = _FIT_PADDING_PX) -> dict[str, Any]

Frame a bounding box by computing a center and zoom for it.

The saved project records a center/zoom, not a bbox to fit: the app applies mapView.center/zoom verbatim when it opens a project and never fits the stored bbox. So this resolves the box to a camera here, using an assumed viewport (see _FIT_VIEWPORT), and records the box alongside it for reference. The result is approximate by construction; expect the app's own "zoom to layer" to land within roughly half a zoom level.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
bbox Iterable[float]

[min_lng, min_lat, max_lng, max_lat]. Per RFC 7946 section 5.2, min_lng > max_lng means the box crosses the antimeridian (Fiji is [170, -20, -170, -10]) and is framed as such.

required
padding int

Pixels of margin to leave around the box.

_FIT_PADDING_PX

Returns:

Type Description
dict[str, Any]

The project's mapView after the change.

Raises:

Type Description
ValueError

If the box is not 4 finite numbers, has its latitudes inverted, or falls outside the Web Mercator latitude limits.

set_basemap

set_basemap(project: dict[str, Any], basemap: str) -> str

Set the project's background basemap style.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
basemap str

A known basemap name (see geolibre.basemaps.BASEMAPS) or a MapLibre style JSON URL.

required

Returns:

Type Description
str

The resolved style URL.

Raises:

Type Description
ValueError

If the name is unknown and the value is not a URL.

basemap_catalog

basemap_catalog() -> dict[str, str]

Return the named basemaps, mapping friendly name to style URL.

color_ramp_names

color_ramp_names() -> list[str]

Return the color-ramp names accepted for choropleths and colorbars.

set_point_cloud_classes

set_point_cloud_classes(project: dict[str, Any], classes: list[dict[str, Any]]) -> list[dict[str, Any]]

Set the point cloud annotator's custom classes (its label schema).

Replaces the custom classes and keeps the saved point labels, instance ids and 3D boxes. The annotator applies them when the project opens, so the LiDAR layer draws those codes in their colour and names them in its legend, and the classes can be assigned from the annotator's panel.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
classes list[dict[str, Any]]

{"code", "name", "color"} dicts; see geolibre.project.point_cloud_class_schema. An empty list clears them.

required

Returns:

Type Description
list[dict[str, Any]]

The validated classes as saved.

Raises:

Type Description
ValueError

For an invalid class.

lidar_source_urls

lidar_source_urls(project: dict[str, Any]) -> list[str]

The URLs of the project's LiDAR point cloud layers.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict.

required

Returns:

Type Description
list[str]

Each LiDAR layer's source URL, in layer order.

merge_point_labels

merge_point_labels(project: dict[str, Any], url: str, labels: dict[str, dict[int, int]], instances: dict[str, dict[int, int]] | None = None) -> int

Merge point labels into the annotator's saved state for one source.

New edits override any saved edit for the same point; other saved labels, boxes, vectors and custom classes are kept.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
url str

The point cloud's source URL (its LiDAR layer's URL).

required
labels dict[str, dict[int, int]]

Node key -> {index within node: class}.

required
instances dict[str, dict[int, int]] | None

Node key -> {index within node: instance id}, optional.

None

Returns:

Type Description
int

How many point edits were merged.

merge_components_state

merge_components_state(project: dict[str, Any], key: str, entry_state_builder: Callable[[Any], dict[str, Any]]) -> None

Merge one feature's state into the Components plugin settings.

The Components plugin (legend / colorbar / html) stores all its features under a single settings blob keyed by feature name, so a new legend must be merged in without dropping an existing colorbar (and vice versa).

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
key str

The feature key ("legend" or "colorbar").

required
entry_state_builder Callable[[Any], dict[str, Any]]

Called with the feature's current state (or None) and returns its new state.

required

add_legend

add_legend(project: dict[str, Any], title: str | None = None, *, legend_dict: dict[str, str] | None = None, labels: list[str] | None = None, colors: list[str] | None = None, builtin: str | None = None, position: str = 'bottom-left', shape: str = 'square') -> dict[str, Any]

Add a legend control to the project.

Supply the entries exactly one of three ways: a built-in preset (builtin), a {label: color} mapping (legend_dict), or parallel labels and colors lists. Each call adds another legend.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
title str | None

Legend title. Defaults to "Legend", or the preset's title when builtin is given without one.

None
legend_dict dict[str, str] | None

A mapping of label to CSS color (order preserved).

None
labels list[str] | None

Item labels, paired position-wise with colors.

None
colors list[str] | None

Item CSS colors, paired position-wise with labels.

None
builtin str | None

A preset name (e.g. "nlcd", "esa_worldcover").

None
position str

One of CONTROL_POSITIONS.

'bottom-left'
shape str

Swatch shape for every item; one of LEGEND_SHAPES.

'square'

Returns:

Type Description
dict[str, Any]

The legend entry that was added.

Raises:

Type Description
ValueError

If no entries are supplied, several sources are combined, labels/colors lengths differ, or position/shape/ builtin is invalid.

set_map_legend

set_map_legend(project: dict[str, Any], title: str | None = None, *, position: str | None = None, group_by_layer: bool | None = None, visible: bool | None = None, collapsed: bool | None = None) -> dict[str, Any]

Show the map legend, the panel behind the app's Controls -> Legend.

Unlike add_legend, which draws hand-written entries, the map legend derives its rows from each visible layer's symbology (graduated classes, categories, heatmap ramps, ...), so it stays in step with the layers without restating their colors. A project has one; calling this again updates it and keeps any item order, label overrides, and custom entries already saved on it.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
title str | None

Heading drawn above the entries. Keeps the current one (the app default is "Legend") when omitted.

None
position str | None

Map corner, one of CONTROL_POSITIONS. Keeps the current one (the app default is "top-left") when omitted.

None
group_by_layer bool | None

Group each layer's classes under a layer heading. Keeps the current setting (the app default groups) when omitted.

None
visible bool | None

Whether the on-map panel is open. Keeps the current state when omitted, and opens it when the project has no legend yet.

None
collapsed bool | None

Whether the open panel is collapsed to its header bar. Keeps the current state when omitted.

None

Returns:

Type Description
dict[str, Any]

The project's legend config.

Raises:

Type Description
ValueError

If position is not a map corner.

add_colorbar

add_colorbar(project: dict[str, Any], *, colormap: str = 'viridis', vmin: float = 0.0, vmax: float = 1.0, label: str = '', units: str = '', colors: list[str] | None = None, orientation: str = 'vertical', position: str = 'bottom-right') -> dict[str, Any]

Add a colorbar control for a continuous (single-band) raster.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
colormap str

A named colormap. Ignored when colors is given.

'viridis'
vmin float

Value at the low end.

0.0
vmax float

Value at the high end.

1.0
label str

Title shown alongside the colorbar.

''
units str

Units suffix shown with the values.

''
colors list[str] | None

Optional CSS colors defining a custom gradient.

None
orientation str

One of ORIENTATIONS.

'vertical'
position str

One of CONTROL_POSITIONS.

'bottom-right'

Returns:

Type Description
dict[str, Any]

The colorbar entry that was added.

Raises:

Type Description
ValueError

If orientation or position is invalid, vmin is not less than vmax, or colors is given but empty.

add_swipe

add_swipe(project: dict[str, Any], *, left_layers: list[str], right_layers: list[str], orientation: str = 'vertical', position: float = 50, control_position: str = 'top-right') -> dict[str, Any]

Configure the split-map (swipe) control.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
left_layers list[str]

Layer ids shown on the left/top of the slider. "__basemap__" selects the basemap.

required
right_layers list[str]

Layer ids shown on the right/bottom of the slider.

required
orientation str

One of ORIENTATIONS.

'vertical'
position float

Initial slider position as a percentage, clamped to [0, 100].

50
control_position str

One of CONTROL_POSITIONS.

'top-right'

Returns:

Type Description
dict[str, Any]

The swipe plugin state that was written.

Raises:

Type Description
ValueError

If orientation or control_position is invalid.

set_layer_filter

set_layer_filter(project: dict[str, Any], ref: str, expression: Any) -> dict[str, Any]

Set or clear a layer's persistent feature filter.

The filter is the project's filterExpression -- the same one the app's Select by Expression -> Filter layer writes. It hides the features that do not match without changing the data, and combines with quick filters and the Time Slider window.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
ref str

A layer id or display name.

required
expression Any

A boolean MapLibre expression (list or JSON string), e.g. [">=", ["get", "population"], 100000]; None or [] clears the filter.

required

Returns:

Type Description
dict[str, Any]

A summary of the layer, with the filter that is now set (or None).

Raises:

Type Description
ValueError

If the reference does not resolve to exactly one layer, or the expression is not a boolean expression array.

set_floor_picker

set_floor_picker(project: dict[str, Any], ref: str, field: str | None, level: Any = None, *, mode: str | None = None) -> dict[str, Any]

Link a multi-floor layer to the app's on-map floor picker, or unlink it.

The floor picker lists the floors found in field across every linked layer and draws one floor (mode="only") or a floor and the ones below it (mode="below"). It reads OpenStreetMap level values such as "0;1" and "-1-0", plain numbers, and IMDF ordinals. The choice is shared, so level and mode apply to every linked layer.

The matching values are resolved from a layer's inline GeoJSON. A layer without inline features is linked unresolved: the app resolves it once it loads the layer's features (a local file re-read on open), and a layer the app holds no features for (vector tiles) is not narrowed.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
ref str

A layer id or display name.

required
field str | None

The feature property holding the floor, e.g. "level"; None unlinks the layer.

required
level Any

The floor to show, e.g. "0" or -1. None keeps the floor the picker already shows (a layer linked later joins it, as in the app); with mode="all" it shows every floor.

None
mode str | None

"only" (the default for a level), "below", or "all".

None

Returns:

Type Description
dict[str, Any]

A summary of the layer with its levelFilter (or None).

Raises:

Type Description
ValueError

If the reference does not resolve to exactly one layer, or the field, level or mode is invalid.

set_labels

set_labels(project: dict[str, Any], ref: str, field: str | None = None, *, expression: Any = None, enabled: bool | None = None, **options: Any) -> dict[str, Any]

Label a vector layer's features from an attribute or an expression.

Unspecified options keep the layer's current label settings, so a call can restyle labels without restating the field.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
ref str

A layer id or display name.

required
field str | None

Property whose value becomes the label text.

None
expression Any

MapLibre expression (list or JSON string) for the label text; overrides field. "" clears it.

None
enabled bool | None

False hides the labels but keeps their settings, True shows them; omitted, labels keep their current state (on for a layer that had none).

None
**options Any

Label options; see geolibre.project.label_style.

{}

Returns:

Type Description
dict[str, Any]

The layer's labels object after the change.

Raises:

Type Description
ValueError

If the reference does not resolve to exactly one layer, or an option is invalid.

set_plugin_state

set_plugin_state(project: dict[str, Any], plugin_id: str, state: Any = None, *, position: str | None = None, activate: bool = True, allow_unknown: bool = False, clear: bool = False) -> dict[str, Any]

Store a plugin's saved state in the project, the way the app saves it.

The blob is opaque to GeoLibre: each plugin reads its own shape in applyProjectState (for example the Time Slider's timeline config). The swipe, legend and colorbar have dedicated, validated builders -- add_swipe, add_legend, add_colorbar -- and are the better choice for those.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
plugin_id str

A built-in plugin id from geolibre.project.PLUGIN_STATE_IDS, or an external plugin's id with allow_unknown=True.

required
state Any

The plugin's settings blob; must be plain JSON. None keeps the stored settings, so position/activate can be changed without resending them.

None
position str | None

Optional control corner, one of CONTROL_POSITIONS.

None
activate bool

Add the plugin to activePluginIds so it starts active.

True
allow_unknown bool

Accept an id that is not a built-in plugin with saved state (an external plugin loaded from a manifest URL).

False
clear bool

Remove the stored settings and nothing else (state, position and activate are then not applied, so clearing cannot switch the plugin on).

False

Returns:

Type Description
dict[str, Any]

{"pluginId", "active", "position", "state"} as now stored.

Raises:

Type Description
ValueError

If the id is unknown (and not allowed), the position is invalid, the state is not plain JSON, or clear is combined with a state.

find_story_chapter

find_story_chapter(project: dict[str, Any], ref: str | int) -> int

Resolve a story chapter by id, title, or 0-based position.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict.

required
ref str | int

A chapter id, a chapter title (exact, then case-insensitive), or an integer index.

required

Returns:

Type Description
int

The chapter's index in storymap.chapters.

Raises:

Type Description
ValueError

If nothing matches, or a title matches several chapters.

set_story_map

set_story_map(project: dict[str, Any], **settings: Any) -> dict[str, Any]

Set the story map's title block and presentation settings.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
**settings Any

Any of geolibre.project.STORY_SETTING_NAMES -- title, subtitle, byline, footer, theme ("light"/"dark"), show_markers, marker_color, inset, inset_position, hide_chapter_nav, start_slide and end_slide ("none", "blank", "black", "global", "adjacent").

{}

Returns:

Type Description
dict[str, Any]

A summary of the story map (settings plus chapter ids and titles).

Raises:

Type Description
ValueError

If a setting is unknown or invalid.

add_story_chapter

add_story_chapter(project: dict[str, Any], title: str, *, description: str = '', center: Iterable[float] | None = None, zoom: float | None = None, pitch: float | None = None, bearing: float | None = None, image: str | None = None, alignment: str = 'left', hidden: bool = False, map_animation: str = 'flyTo', rotate_animation: bool = False, on_enter: Any = None, on_exit: Any = None, index: int | None = None, chapter_id: str | None = None) -> dict[str, Any]

Add a chapter to the project's story map (Project -> Story Map).

A camera value left out is taken from the project's saved view, the way the app's Add chapter button captures the current map.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
title str

Chapter heading.

required
description str

Chapter body text.

''
center Iterable[float] | None

Camera target [lng, lat].

None
zoom float | None

Camera zoom, 0-24.

None
pitch float | None

Camera tilt in degrees, 0-85.

None
bearing float | None

Camera rotation in degrees.

None
image str | None

Optional image URL shown in the chapter panel.

None
alignment str

"left", "center", "right", or "full".

'left'
hidden bool

Hide the text panel while still moving the map.

False
map_animation str

"flyTo", "easeTo", or "jumpTo".

'flyTo'
rotate_animation bool

Slowly rotate the camera once the move settles.

False
on_enter Any

Layer opacity changes on entering, as {"layer": <id or name>, "opacity": 0-1, "duration": ms} entries.

None
on_exit Any

Layer opacity changes on leaving, in the same form.

None
index int | None

Position to insert at (clamped); appended when omitted.

None
chapter_id str | None

Explicit chapter id; a UUID by default.

None

Returns:

Type Description
dict[str, Any]

The chapter that was added.

Raises:

Type Description
ValueError

If a value is invalid, a layer reference does not resolve, or chapter_id is already used.

remove_story_chapter

remove_story_chapter(project: dict[str, Any], ref: str | int) -> dict[str, Any]

Remove a story chapter by id, title, or index.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
ref str | int

A chapter id, title, or 0-based index.

required

Returns:

Type Description
dict[str, Any]

A summary of the story map after the removal.

Raises:

Type Description
ValueError

If the reference does not resolve to exactly one chapter.

move_story_chapter

move_story_chapter(project: dict[str, Any], ref: str | int, index: int) -> dict[str, Any]

Move a story chapter to a new position.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
ref str | int

A chapter id, title, or 0-based index.

required
index int

The destination position (clamped to the chapter list).

required

Returns:

Type Description
dict[str, Any]

A summary of the story map after the move.

Raises:

Type Description
ValueError

If the reference does not resolve to exactly one chapter.

bookmark_summary

bookmark_summary(project: dict[str, Any]) -> list[dict[str, Any]]

List the project's bookmarks with the name of the folder each is in.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict.

required

Returns:

Type Description
list[dict[str, Any]]

{"id", "name", "folder"} entries in panel order.

find_bookmark

find_bookmark(project: dict[str, Any], ref: str | int) -> int

Resolve a bookmark by id, name, or 0-based position.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict.

required
ref str | int

A bookmark id, a bookmark name (exact, then case-insensitive), or an integer index.

required

Returns:

Type Description
int

The bookmark's index in bookmarks.

Raises:

Type Description
ValueError

If nothing matches, or a name matches several bookmarks.

add_bookmark

add_bookmark(project: dict[str, Any], name: str, *, center: Iterable[float] | None = None, zoom: float | None = None, pitch: float | None = None, bearing: float | None = None, folder: str | None = None, visible_layers: Iterable[str] | None = None, bookmark_id: str | None = None, created_at: int | None = None) -> dict[str, Any]

Add a saved map view to the project's Bookmarks panel.

A camera value left out is taken from the project's saved view, the way the panel's Add button captures the current map.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
name str

Bookmark name.

required
center Iterable[float] | None

Camera target [lng, lat].

None
zoom float | None

Camera zoom, 0-24.

None
pitch float | None

Camera tilt in degrees, 0-85.

None
bearing float | None

Camera rotation in degrees.

None
folder str | None

A folder id or name to file it under; a new name creates the folder. Ungrouped when omitted.

None
visible_layers Iterable[str] | None

Layers (ids or names) to show when the bookmark is opened; the others are hidden. Omit to leave visibility alone.

None
bookmark_id str | None

Explicit bookmark id; a UUID by default.

None
created_at int | None

Creation time in milliseconds since the epoch; now by default.

None

Returns:

Type Description
dict[str, Any]

The bookmark that was added.

Raises:

Type Description
ValueError

If a value is invalid, a layer does not resolve, bookmark_id is already used, or the project already holds geolibre.project.MAX_BOOKMARKS bookmarks.

remove_bookmark

remove_bookmark(project: dict[str, Any], ref: str | int) -> list[dict[str, Any]]

Remove a bookmark by id, name, or index.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict (mutated in place).

required
ref str | int

A bookmark id, name, or 0-based index.

required

Returns:

Type Description
list[dict[str, Any]]

The remaining bookmarks, as bookmark_summary lists them.

Raises:

Type Description
ValueError

If the reference does not resolve to exactly one bookmark.