How to Interact with GeoLibre Files Programmatically: 3 Methods Explained
You can interact with GeoLibre project files programmatically via the front-end Zustand store API for in-app manipulation, the embed API for cross-frame communication, or the FastAPI side-car for server-side operations.
GeoLibre stores complete project state in .geolibre.json files—JSON documents containing layers, styles, view settings, legends, story-map chapters, and widgets. Whether you're building automation scripts, embedding maps in third-party applications, or creating custom workflows, understanding how to read and write these files programmatically unlocks the full potential of the open-source mapping platform. This guide covers three interaction patterns based on the actual source implementation in opengeos/GeoLibre.
Front-End Store API: Direct In-App Manipulation
The primary interface for programmatic interaction is the Zustand store defined in packages/core/src/store.ts. This store holds all project state and exposes methods for loading, creating, and modifying .geolibre.json content.
Core Store Methods for File Operations
| Method | Purpose | Source Location |
|---|---|---|
newProject(options?) |
Creates fresh project with defaults from packages/core/src/project.ts |
store.ts |
loadProject(project, path?, options?) |
Replaces store state with a GeoLibreProject object |
store.ts |
addGeoJsonLayer(name, geojson, sourcePath?, beforeLayerId?) |
Adds vector layer from parsed GeoJSON | store.ts |
addTileLayer(name, options, beforeLayerId?) |
Adds raster or vector tile layer from URL template | store.ts |
setProjectPath(path) / setProjectName(name) |
Updates stored location or title | store.ts |
markSaved() |
Clears dirty flag after successful write | store.ts |
Loading a Remote Project File
import { useAppStore } from "@geolibre/core";
async function loadFromUrl(url: string) {
const response = await fetch(url);
if (!response.ok) throw new Error(`Failed to fetch ${url}`);
const project = (await response.json()) as GeoLibreProject;
useAppStore.getState().loadProject(project, url, {
rememberRecent: true
});
}
The rememberRecent: true option adds the file to the recent projects list in the UI.
Creating a New Project and Adding Layers
import { useAppStore } from "@geolibre/core";
const store = useAppStore.getState();
// Initialize clean project
store.newProject({ name: "My New Map" });
// Add GeoJSON layer from parsed data
const geojson = {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: { type: "Point", coordinates: [-122.4, 37.8] },
properties: {}
},
],
};
store.addGeoJsonLayer("Points of Interest", geojson);
For raster sources, substitute store.addTileLayer() with appropriate URL template options.
Exporting Current Project to File
function exportCurrentProject() {
const state = useAppStore.getState();
const project: GeoLibreProject = {
name: state.projectName,
version: 1,
layers: state.layers,
// Include additional fields per GeoLibreProject schema (packages/core/src/types.ts)
};
const blob = new Blob(
[JSON.stringify(project, null, 2)],
{ type: "application/json" }
);
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = `${state.projectName || "Untitled"}.geolibre.json`;
a.click();
URL.revokeObjectURL(url);
}
Embed API: Cross-Frame and Desktop Integration
When GeoLibre runs in an iframe or Tauri desktop shell, external applications communicate via postMessage commands defined in packages/embed/src/index.ts. This enables programmatic control without direct access to the store.
LoadProject Command Structure
The embed protocol defines command shapes as TypeScript types. The loadProject command accepts a URL string:
// From packages/embed/src/index.ts
type LoadProjectCommand = {
type: "loadProject";
url: string
};
Sending Commands from Parent Page
<iframe id="geoLibreFrame" src="https://web.geolibre.app/"></iframe>
const iframe = document.getElementById("geoLibreFrame");
// Load remote project file into embedded viewer
iframe.contentWindow.postMessage(
{
type: "loadProject",
url: "https://example.com/maps/myMap.geolibre.json"
},
"*"
);
// Handle errors from embed
window.addEventListener("message", e => {
if (e.data?.type === "error") console.error(e.data.message);
});
Embed Validation and Routing
Before executing commands, GeoLibre validates URLs through isFetchableUrl in apps/geolibre-desktop/src/lib/embed-api.ts (line 420). This allow-list restricts loadProject to http(s) and root-relative URLs for security. Valid commands are delegated to useAppStore.loadProject() via apps/geolibre-desktop/src/hooks/useEmbedApi.ts.
FastAPI Side-Car: Server-Side Operations
The Python FastAPI backend (backend/geolibre_server) provides HTTP endpoints for scenarios requiring server-side file handling—conversions, validation, or multi-user coordination.
Available Endpoints
| Endpoint | Method | Description | Source |
|---|---|---|---|
/project |
GET | Retrieves project JSON by URL (local path or remote) | backend/geolibre_server/app/main.py |
/project |
POST | Accepts GeoLibreProject payload and persists to path |
backend/geolibre_server/app/main.py |
Python Client Example
import requests
BASE_URL = "http://127.0.0.1:8765"
# 1. Read project from local file via side-car
resp = requests.get(
f"{BASE_URL}/project",
params={"url": "/tmp/myMap.geolibre.json"}
)
project = resp.json()
# 2. Modify project structure
project["name"] = "Edited Map"
# 3. Persist modifications
requests.post(f"{BASE_URL}/project", json=project)
The side-car's project utilities in backend/geolibre_server/app/project.py handle file I/O and path resolution, making this pattern suitable for headless automation and CI/CD pipelines.
Utility Helpers for File Handling
Several convenience functions assist with .geolibre.json file operations:
ensureProjectFileName(name)— Appends.geolibre.jsonextension if missing. Source:tests/file-names.test.tsprojectPathLabel(path)— Extracts human-readable label from full path or URL. Source:packages/core/src/store.ts(line 331)isFetchableUrl(url)— Validates URL against security allow-list. Source:apps/geolibre-desktop/src/lib/embed-api.ts(line 420)
Complete Interaction Workflow
The typical programmatic workflow follows five steps:
- Obtain
.geolibre.jsonvia download, side-car request, or file system read - Parse JSON into
GeoLibreProjecttype (defined inpackages/core/src/types.ts) - Load via
useAppStore.loadProject(project, path?, { rememberRecent: true }) - Manipulate through store methods—layers, styles, view, widgets
- Export modified state to JSON or push to side-car for persistence
This pattern scales from browser-based React components to Python automation scripts without changing core semantics.
Summary
- Store API (
packages/core/src/store.ts) provides direct TypeScript/JavaScript control for in-app scenarios - Embed API (
packages/embed/src/index.ts) enables cross-frame and desktop shell integration via postMessage - FastAPI side-car (
backend/geolibre_server/app/main.py) offers HTTP endpoints for server-side operations - All paths use the same
GeoLibreProjecttype defined inpackages/core/src/types.ts - Validation helpers ensure consistent file naming and URL security across environments
Frequently Asked Questions
What file format does GeoLibre use for projects?
GeoLibre uses .geolibre.json files—JSON documents containing complete project state including layers, styles, view configuration, legends, story-map chapters, and widgets. The schema is defined in TypeScript at packages/core/src/types.ts.
Can I load a GeoLibre project from a custom web application?
Yes. For iframe embeds, send a loadProject command via postMessage to the GeoLibre frame. For tighter integration, import @geolibre/core and call useAppStore.loadProject() directly after fetching and parsing the JSON file.
How do I validate a project file before loading it?
The side-car's POST /project endpoint performs server-side validation. Client-side, check the TypeScript GeoLibreProject interface from packages/core/src/types.ts—the store methods assume well-formed input and will throw if required fields are missing.
Is programmatic access available in the desktop application?
Yes. The Tauri-based desktop app exposes the embed API through apps/geolibre-desktop/src/hooks/useEmbedApi.ts, and the FastAPI side-car runs as a local HTTP server on port 8765, enabling external scripts to read and write project files even when the UI is headless.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →