Summary
Publish a typed @geolibre/embed client package that wraps the v1 postMessage API, extend the protocol with the methods integrators actually need, and add a viewer embed preset that sits between maponly and the full app.
Why
The versioned postMessage API shipped in v2.4 (docs/user-guide/embedding.md) is the right foundation — origin-allowlisted in both directions, versioned envelopes, events coming back out. Two things keep it from being something people build on:
1. Hosts hand-write the protocol. Embedding today means constructing { v: 1, type: "setView", payload: {...} } envelopes by hand, wiring a message listener, filtering by origin, and correlating responses. Every integrator writes the same 80 lines, and gets the origin check subtly wrong at least once.
2. The surface is thin. setView, feature highlight, and open-a-processing-tool cover a narrow slice. The obvious next asks — toggle a layer, apply a filter, read the current viewport, add a layer at runtime, grab an image of the map — are all things the app can already do internally but cannot be asked to do from outside.
Separately, the embed presets are all-or-nothing: maponly hides everything, and the full app shows editing UI that makes no sense in a read-only embed.
Proposal
1. @geolibre/embed
A small dependency-free package published alongside the app:
import { connect } from "@geolibre/embed";
const map = await connect(iframeEl, { origin: "https://web.geolibre.app" });
await map.loadProject(url);
await map.setView({ center: [-95.7, 37.1], zoom: 5 });
await map.setLayerVisibility(layerId, false);
map.on("selectionChanged", ({ features }) => { /* ... */ });
Handles the handshake, origin checking, request/response correlation, versioning, and typed events. Ships the protocol types so both sides compile against one definition.
2. Protocol additions
setLayerVisibility(layerId, visible) / listLayers()
setFilter(layerId, expression) — reusing the expression shape the Expression Builder already produces
getViewport() alongside the existing viewChanged event
addLayer(spec) — the Add Data source specs the project format already describes
exportImage() — returns a rendered PNG of the current map
3. A viewer embed preset
Between maponly and the full app: legend, layer visibility toggles, place search, popups/identify, and basemap switching — with editing, processing, and data-management UI hidden. This is the shape most read-only embeds want, and today every deployment reconstructs it by hand out of layout, panels, and toolbar parameters.
Scope notes
- New protocol methods stay behind the same
GEOLIBRE_EMBED_ORIGINS allowlist; nothing here relaxes the default-off posture.
- Bump the protocol version and keep v1 handling intact — existing embeds must not break.
- The
viewer preset is worth shipping independently of the SDK; it needs no protocol work.
Effort
Medium.
Summary
Publish a typed
@geolibre/embedclient package that wraps the v1postMessageAPI, extend the protocol with the methods integrators actually need, and add a viewer embed preset that sits betweenmaponlyand the full app.Why
The versioned
postMessageAPI shipped in v2.4 (docs/user-guide/embedding.md) is the right foundation — origin-allowlisted in both directions, versioned envelopes, events coming back out. Two things keep it from being something people build on:1. Hosts hand-write the protocol. Embedding today means constructing
{ v: 1, type: "setView", payload: {...} }envelopes by hand, wiring amessagelistener, filtering by origin, and correlating responses. Every integrator writes the same 80 lines, and gets the origin check subtly wrong at least once.2. The surface is thin.
setView, feature highlight, and open-a-processing-tool cover a narrow slice. The obvious next asks — toggle a layer, apply a filter, read the current viewport, add a layer at runtime, grab an image of the map — are all things the app can already do internally but cannot be asked to do from outside.Separately, the embed presets are all-or-nothing:
maponlyhides everything, and the full app shows editing UI that makes no sense in a read-only embed.Proposal
1.
@geolibre/embedA small dependency-free package published alongside the app:
Handles the handshake, origin checking, request/response correlation, versioning, and typed events. Ships the protocol types so both sides compile against one definition.
2. Protocol additions
setLayerVisibility(layerId, visible)/listLayers()setFilter(layerId, expression)— reusing the expression shape the Expression Builder already producesgetViewport()alongside the existingviewChangedeventaddLayer(spec)— the Add Data source specs the project format already describesexportImage()— returns a rendered PNG of the current map3. A
viewerembed presetBetween
maponlyand the full app: legend, layer visibility toggles, place search, popups/identify, and basemap switching — with editing, processing, and data-management UI hidden. This is the shape most read-only embeds want, and today every deployment reconstructs it by hand out oflayout,panels, andtoolbarparameters.Scope notes
GEOLIBRE_EMBED_ORIGINSallowlist; nothing here relaxes the default-off posture.viewerpreset is worth shipping independently of the SDK; it needs no protocol work.Effort
Medium.