# GeoLibre Plugin APIs: The Complete Developer Guide to Custom Extensions

> Explore the GeoLibre Plugin APIs for custom extensions. Discover how to control maps, manage layers, register UI components, and coordinate plugins with the GeoLibrePlugin interface and GeoLibreAppAPI.

- Repository: [Open Geospatial Solutions/GeoLibre](https://github.com/opengeos/GeoLibre)
- Tags: developer-guide
- Published: 2026-07-31

---

**GeoLibre exposes a typed JavaScript API built around the `GeoLibrePlugin` interface and `GeoLibreAppAPI` object, enabling developers to control maps, manage layers, register UI components, and coordinate between plugins.**

GeoLibre is an open-source geospatial platform designed for desktop, web, and Jupyter environments. The **GeoLibre plugin APIs** provide a comprehensive contract that allows third-party developers to extend functionality without modifying core source code. This guide documents the full API surface available in the `opengeos/GeoLibre` repository, from lifecycle management to cloud-native data integration.

## Core Plugin Interface

Every plugin must implement the `GeoLibrePlugin` interface defined in [`docs/plugin-api.md`](https://github.com/opengeos/GeoLibre/blob/main/docs/plugin-api.md). This contract declares the plugin’s identity and lifecycle hooks.

Key properties include:

- **`id`**, **`name`**, **`version`** – Unique identifiers and versioning metadata.
- **`activeByDefault`** – Optional boolean to auto-activate on startup.
- **`activate(app)`** – Called by the host to initialize the plugin, receiving a `GeoLibreAppAPI` instance.
- **`deactivate(app)`** – Cleanup hook invoked when the plugin is disabled or unloaded.
- **`handleUrlParameters`** – Optional method for deep-linking support when `urlParameterNames` is declared.

The `GeoLibreAppAPI` object passed to `activate` contains the full surface area of available methods, which are typed as potentially `undefined` to accommodate host variants that may not implement specific features. The recommended calling pattern uses optional chaining:

```typescript
app.addTileLayer?.('My Tiles', 'https://my.tiles/{z}/{x}/{y}.png');

```

## Map Control and Basemap APIs

Plugins have granular control over the map viewport and built-in controls through the following methods:

- **`setBasemap(styleUrl)`** – Switches the base style using a MapLibre GL style URL.
- **`getActiveBasemap()`** – Returns the currently active base-style URL.
- **`addMapControl(control, position?)`** – Adds a custom MapLibre `IControl` instance to the map. The `position` parameter accepts `GeoLibreMapControlPosition` values (`top-left`, `top-right`, `bottom-left`, `bottom-right`).
- **`removeMapControl(control)`** – Removes a previously added custom control.
- **`setBuiltInMapControlVisible(control, visible)`** – Toggles visibility of built-in controls (navigation, fullscreen, terrain).
- **`setBuiltInMapControlPosition(control, position)`** – Repositions built-in controls to a different corner.

These methods are implemented in the host application and documented in [`docs/plugin-api.md`](https://github.com/opengeos/GeoLibre/blob/main/docs/plugin-api.md) under the App API section.

## Layer Management APIs

GeoLibre plugins can programmatically add and manage geospatial data layers, which automatically appear in the Layers panel and persist in project files.

### Vector Data

- **`addGeoJsonLayer(name, data, sourcePath?)`** – Registers a GeoJSON feature collection as a native layer. The layer appears in the UI and is stored in the global Zustand state store.

### Raster and Tile Layers

- **`addTileLayer(name, url, options?)`** – Adds an XYZ tile source (e.g., satellite imagery).
- **`addWmtsLayer(name, url, options?)`** – Adds a WMTS source.
- **`addWmsLayer(name, options)`** – Adds a WMS source with configuration for `url`, `layers`, `styles`, and other parameters.

### Cloud-Native Formats

- **`addCogLayer(name, url, options?)`** – Loads a Cloud-Optimized GeoTIFF client-side. Supports band selection, colormaps, and nodata handling. Returns a `Promise<string>` resolving to the layer ID.
- **`addZarrLayer(name, url, options)`** – Registers a Zarr store (v2/v3) as a raster layer. Returns a `Promise<string>`.
- **`setZarrLayerSelector(layerId, selector)`** – Updates the non-spatial slice of a Zarr layer (e.g., time dimension).
- **`queryZarrLayer(layerId, geometry, selector?, options?)`** – Reads values under a point or polygon for identify operations or zonal statistics.

### Custom WebGL Layers

- **`registerExternalNativeLayer(registration)`** – Mirrors a layer added directly via MapLibre’s `CustomLayerInterface` into GeoLibre’s layer store. This enables UI panel integration and project persistence for custom WebGL layers.
- **`unregisterExternalNativeLayer(id)`** – Removes the external layer registration.

## UI Extension APIs

Plugins can extend the GeoLibre interface by registering panels and menus that render in isolated DOM containers.

### Right-Sidebar Panels

- **`registerRightPanel(panel)`** – Creates a dockable panel beside the built-in Style/Layers sidebars. Returns an unregister function.
- **`unregisterRightPanel(id)`** – Removes the panel registration.
- **`openRightPanel(id)`**, **`closeRightPanel(id)`**, **`collapseRightPanel(id)`** – Control panel visibility and docking state.

The `panel` object requires an `id`, `title`, `defaultWidth`, and a `render(container: HTMLElement)` function that returns a cleanup callback.

### Floating Panels

- **`registerFloatingPanel(panel)`** – Adds a draggable overlay card that does not resize the map canvas.
- **`unregisterFloatingPanel(id)`** – Removes the floating panel.
- **`openFloatingPanel(id)`**, **`closeFloatingPanel(id)`**, **`getOpenFloatingPanels()`** – Manage floating panels at runtime.

### Toolbar Menus

- **`registerToolbarMenu(menu)`** – Adds a top-level menu to the GeoLibre banner, supporting submenus, actions, and separators.
- **`unregisterToolbarMenu(id)`** – Removes the menu.

### Map Controls

Custom MapLibre controls added via `addMapControl` integrate directly with the map canvas, while the built-in control methods manage the standard navigation widgets.

## Advanced Integration Features

### Temporal Data Support

- **`registerTemporalLayer(layerId, adapter, options?)`** – Links a layer’s time dimension to the global Time Slider. Accepts a `bind` option for custom frame-based animations.
- **`unregisterTemporalLayer(layerId)`** – Disconnects the layer from temporal controls.

### Plugin Coordination

- **`activatePlugin(id, projectState?)`** – Programmatically enables another plugin, optionally supplying a state patch applied after activation.
- **`deactivatePlugin(id)`** – Disables a target plugin.

### Deck.gl Integration

- **`getDeckGL()`** – Returns a promise resolving to the host’s shared Deck.gl modules (`core`, `layers`, `geoLayers`, `meshLayers`, `mapbox`). Plugins must render on this single instance to avoid version conflicts.

### Project State Persistence

- **`getProjectState()`** – Serializes the current plugin-specific settings.
- **`applyProjectState(state)`** – Restores settings from a `.geolibre` project file during load.

### Utility Methods

- **`fetchArrayBuffer(url)`** – Low-level fetch helper returning an `ArrayBuffer` for binary assets like COG headers.
- **`fitBounds(bounds)`** – Zooms and pans to a `[west, south, east, north]` extent.
- **`getMap()`** – Returns the underlying MapLibre `Map` instance (or `null` if not ready).

## Plugin Architecture and Lifecycle

The plugin system is orchestrated by the `PluginManager` class in [`packages/plugins/src/plugin-manager.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugin-manager.ts). This manager maintains a map of `PluginRegistryEntry` objects defined in [`apps/geolibre-desktop/src/lib/plugin-registry.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/lib/plugin-registry.ts).

The lifecycle follows this sequence:

1. **Registration** – Built-in plugins are loaded from [`packages/plugins/src/index.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/index.ts), while external plugins are discovered as zip archives or directory bundles containing a [`plugin.json`](https://github.com/opengeos/GeoLibre/blob/main/plugin.json) manifest.
2. **Activation** – The host calls `plugin.activate(app)`, supplying a fully populated `GeoLibreAppAPI` instance. The plugin immediately gains access to all API methods.
3. **State Synchronization** – Layers added via `addGeoJsonLayer`, `addCogLayer`, or similar methods are automatically recorded in the global store, enabling persistence and interaction with the style editor and time slider.
4. **Cleanup** – When disabled, `plugin.deactivate(app)` is invoked, allowing removal of controls, panels, and event listeners.

Security and trust for external plugins are handled by [`apps/geolibre-desktop/src/lib/plugin-integrity.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/lib/plugin-integrity.ts) (hashing and manifest validation) and [`apps/geolibre-desktop/src/lib/plugin-trust.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/lib/plugin-trust.ts) (sandboxing and permissions). The startup hook in [`apps/geolibre-desktop/src/hooks/usePlugins.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/hooks/usePlugins.ts) coordinates loading of built-in and external bundles.

## Summary

- The **GeoLibre plugin APIs** center on the `GeoLibrePlugin` interface and the `GeoLibreAppAPI` object provided during activation.
- Plugins can add **vector**, **raster**, **COG**, and **Zarr** layers that automatically integrate with the Layers panel and project persistence.
- UI extensions include **right-sidebar panels**, **floating panels**, and **toolbar menus** that render in isolated DOM containers without sharing React context.
- Advanced features support **temporal animations**, **Deck.gl** visualization, **cross-plugin activation**, and **URL parameter handling**.
- All API methods are optional (`undefined`-able) to support host variants; use optional chaining for defensive coding.

## Frequently Asked Questions

### What programming languages are supported for GeoLibre plugins?

GeoLibre plugins are written in **TypeScript** or **JavaScript**. The API is fully typed and distributed via the `@geolibre/plugins` package, providing IntelliSense for the `GeoLibrePlugin` interface and `GeoLibreAppAPI` methods.

### How do I persist plugin settings across sessions?

Use the **`getProjectState`** and **`applyProjectState`** methods available on the `GeoLibreAppAPI` object. These allow you to serialize plugin-specific configuration into the `.geolibre` project file and restore it when the project is reopened or the plugin is reactivated.

### Can plugins activate or communicate with each other?

Yes. Plugins can programmatically control each other using **`activatePlugin(id)`** and **`deactivatePlugin(id)`**, optionally passing state patches during activation. They can also share data indirectly through the project state JSON or by registering layers that other plugins can query.

### How do I add a custom UI panel to the GeoLibre interface?

Register a **right-sidebar panel** using `registerRightPanel` for dockable sidebars, or a **floating panel** using `registerFloatingPanel` for draggable overlays. Both methods accept a `render` function that receives an `HTMLElement` container where you can mount your UI, and return a cleanup function for resource management.