The plugin marketplace registry for GeoLibre.
This repository is published to GitHub Pages at https://plugins.geolibre.app and hosts:
plugin-registry.json— the curated index the GeoLibre Manage Plugins dialog reads (https://plugins.geolibre.app/plugin-registry.json).- A
plugins/directory with one folder per plugin (e.g.plugins/sample/), each containing itsplugin.jsonmanifest and built assets.
GitHub Pages serves these files with permissive CORS, so the GeoLibre app (running on a different origin) can fetch the registry and each plugin bundle.
plugin-registry.json is an object with a plugins array. Each entry:
{
"id": "my-plugin",
"name": "My Plugin",
"version": "1.0.0",
"description": "Optional short description",
"author": "Author name",
"homepage": "https://github.com/owner/my-plugin",
"manifestUrl": "plugins/my-plugin/plugin.json",
"categories": ["Example"],
"minGeoLibreVersion": "0.9.0"
}id,name,version, andmanifestUrlare required; the rest are optional.manifestUrlmay be relative (resolved against this registry's URL, so a plugin hosted here uses e.g.plugins/my-plugin/plugin.json) or an absolute HTTPS URL pointing at a plugin hosted elsewhere.homepagemust behttp(s); other schemes are dropped by the app.minGeoLibreVersiongates installation against the running app version.
Each plugin folder has a plugin.json (the same contract GeoLibre's external
plugin loader expects):
{
"id": "my-plugin",
"name": "My Plugin",
"version": "1.0.0",
"entry": "index.js",
"style": "style.css"
}entry must be a self-contained ES module exporting a GeoLibrePlugin as the
default or a named plugin export, with id/name/version matching the
manifest. entry and style are resolved relative to the manifest, so keep
them inside the plugin's own folder. See sample/ for a minimal,
copy-ready template.
Plugins are trusted code that runs with full app privileges, so the registry is curated: open a pull request and a maintainer reviews it before it ships.
Start from the template: the geolibre-plugin-template is the recommended starting point for plugin development. It includes a MapLibre control wrapper, a
plugin.jsonmanifest, a GeoLibre plugin entry point, and a build that produces the bundle layout below. Thesample/plugin here is a minimal in-repo example.
Your entry is a single self-contained ES module — bundle your dependencies in;
relative imports are not resolved by the loader. It must export a
GeoLibrePlugin as the default export or a named plugin export, and its
id / name / version must match the plugin.json manifest. The minimal
shape:
export const plugin = {
id: "my-plugin",
name: "My Plugin",
version: "1.0.0",
activate(app) {
// add a control, layer, etc. using the app API
},
deactivate(app) {
// tear down whatever activate added
},
};
export default plugin;External plugins must not set activeByDefault. The optional style CSS is
injected globally, so scope your selectors (e.g. a plugin-specific class prefix);
hsl(var(--foreground)) and the other GeoLibre design tokens are available so a
control can match the in-app light/dark theme. Copy sample/ as a
starting point.
Create plugins/<id>/ containing plugin.json, the built entry JS, and any
style CSS. Keep entry/style paths relative and inside the folder.
Commit the bundle as your build emits it. The
Minify plugin bundles workflow
whitespace-minifies every committed plugins/**/*.js — worth about 73% of the
line count here, since most plugin builds mangle identifiers but leave the
whitespace in. It only strips whitespace: no identifier mangling, no syntax
rewriting, no tree shaking, and dependency license headers are kept.
On a branch in this repository the workflow pushes the result back to your
branch. From a fork it cannot (the Actions token has no write access to your
fork), so it fails and you run it yourself — or download the minified-bundles
artifact it uploads and commit that:
npm ci
npm run minify # rewrite the bundles in place
npm run minify:check # what CI checksAdd an entry to plugin-registry.json with manifestUrl pointing at
plugins/<id>/plugin.json (relative) — or an absolute HTTPS URL if you host the
plugin elsewhere. Set minGeoLibreVersion to the lowest GeoLibre version you
support.
Point a local GeoLibre build at your branch's registry, then open Settings → Manage Plugins and install it:
# serve this repo with CORS on http://localhost:8090, then build GeoLibre with:
VITE_GEOLIBRE_PLUGIN_REGISTRY_URL=http://localhost:8090/plugin-registry.jsonhttp://localhost and HTTPS registries are accepted; other schemes are rejected.
On merge to main, the
Deploy to GitHub Pages workflow publishes
the update to plugins.geolibre.app.
Bump version in both the plugin's plugin.json and its registry entry,
update the built assets, and open a PR. GeoLibre shows an Update action to
users whose installed version is older than the registry version; uninstalling
removes it at runtime.
Pushing to main runs the Pages workflow, which uploads the repository root as
the site. The custom domain is set by the CNAME file
(plugins.geolibre.app); .nojekyll disables Jekyll so files are served
verbatim.
One-time setup: enable Settings → Pages → Source: GitHub Actions, and add a DNS
CNAMErecord forplugins.geolibre.apppointing atopengeos.github.io.