# GeoLibre Repository File Management Tools: A Complete Technical Guide

> Explore the GeoLibre repository file management tools. Learn how to centralize geospatial files with a unified API for efficient data handling and integration.

- Repository: [Open Geospatial Solutions/GeoLibre](https://github.com/opengeos/GeoLibre)
- Tags: how-to-guide
- Published: 2026-08-18

---

**GeoLibre manages geospatial files through a centralized Zustand store with a unified `addGeoJsonLayer` API that handles client-side ingestion, backend conversion, and plugin-driven data sources.**

GeoLibre is a modern, **store-driven** web-desktop GIS application in the opengeos/GeoLibre repository. Every piece of geospatial data is treated as a "layer" stored in a central state container, with file operations funneled through a small, well-defined API exposed to plugins, the UI, and a Python side-car. Understanding these **GeoLibre file management tools** is essential for developers extending the platform or integrating custom data pipelines.

## Core Store Architecture

The foundation of GeoLibre's file management is a **single source of truth** implemented in Zustand.

### The Zustand Store

The store lives in [`packages/core/src/store.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/store.ts). It maintains a map of **GeoLibreLayer** records, each containing:

- Unique layer **ID**
- Human-readable **name**
- **Source type** (`geojson`, `vector`, `raster`, etc.)
- Reference to **raw data**
- **UI style defaults**

When any file is imported—whether through drag-and-drop, file picker, or programmatic plugin—the UI calls `addGeoJsonLayer` (or raster/tile equivalents). This function performs three atomic operations:

1. Generates a unique layer ID
2. Inserts a new **GeoLibreLayer** entry into the store
3. Seeds the layer with `DEFAULT_LAYER_STYLE` for immediate rendering

The public API signature is defined in [`packages/plugins/src/types.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/types.ts):

```ts
addGeoJsonLayer: (name: string, data: FeatureCollection, sourcePath?: string) => string;

```

## Client-Side File Ingestion

GeoLibre handles most vector formats directly in the browser without server round-trips.

### In-Browser Vector Processing

**Vector files** (Shapefile, GeoJSON, Parquet, FlatGeobuf) are read by **DuckDB-WASM Spatial** using its `ST_Read` function. The `addGeoJsonLayer` helper converts raw data to a standard **GeoCollection** and writes it to the store. The UI then triggers `MapCanvas → MapController.syncLayers` to materialize the layer in MapLibre GL.

Key implementation files:

- [`packages/plugins/src/plugins/maplibre-open-data-catalogs.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugins/maplibre-open-data-catalogs.ts) — adds remote datasets as GeoJSON layers at line 287
- [`packages/plugins/src/plugins/maplibre-stac.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugins/maplibre-stac.ts) — extracts STAC assets and calls `store.addGeoJsonLayer` at line 462

### Client-Side Example

```ts
// Add a local GeoJSON file (client-side)
import { useAppStore } from '@geolibre/core';
import myData from './my-data.geojson';

const layerId = useAppStore.getState().addGeoJsonLayer('My Layer', myData);
// The layer now appears on the map with default styling.

```

## Backend Side-Car for Heavy-Weight Formats

For formats exceeding browser capabilities, GeoLibre runs a **FastAPI side-car** in `backend/geolibre_server`.

### Server-Side Conversion Pipeline

The side-car exposes `/vector` and `/raster` endpoints accepting **multipart/form-data** uploads. The client uploads files via `fetch` or the built-in "Conversion" dialog; the server returns converted GeoJSON or MBTiles that `addGeoJsonLayer` or `addRasterLayer` consumes.

Key implementation: [`backend/geolibre_server/app/conversion.py`](https://github.com/opengeos/GeoLibre/blob/main/backend/geolibre_server/app/conversion.py)

### Backend Upload Example

```python

# Upload a large raster to the side-car (backend)

import requests

files = {'file': open('large.tif', 'rb')}
resp = requests.post('http://127.0.0.1:8765/raster', files=files)
raster_id = resp.json()['layerId']

# After the server finishes conversion you can call:

useAppStore.getState().addRasterLayer('Large Raster', raster_id)

```

## Plugin-Driven File Sources

Plugins extend GeoLibre's file management to external services without duplicating core logic.

### Consistent Layer Model

Plugins for STAC, OGC services, and custom APIs all call the same core API, ensuring uniform behavior. The plugin interface in [`packages/plugins/src/types.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/types.ts) guarantees this consistency.

```ts
// Example from the STAC plugin
const layerId = store.addGeoJsonLayer(labels.footprintLayerName, geojson);

```

### STAC Plugin Example

```ts
// Add a remote STAC asset via the STAC plugin
import { useAppStore } from '@geolibre/core';
import { fetchStacItem } from '@geolibre/plugins';

async function addStacAsset(url: string) {
  const { geojson } = await fetchStacItem(url);
  useAppStore.getState().addGeoJsonLayer('STAC Footprint', geojson);
}

```

## Persistence and Project Files

GeoLibre projects serialize layer state for reproducibility.

### .geolibre.json Format

Projects are stored as [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) files per [`docs/project-format.md`](https://github.com/opengeos/GeoLibre/blob/main/docs/project-format.md). When saving, the store's layer list—including source paths—is serialized, enabling reload without re-importing raw data.

### Project Persistence Example

```ts
// Persist a project (frontend)
import { saveProject } from '@geolibre/core';

const json = saveProject();               // returns .geolibre.json content
download('my-project.geolibre', json);    // invoke a browser download

```

## Key Implementation Files

| Path | Role |
|------|------|
| [`packages/core/src/store.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/store.ts) | Central Zustand store where every layer is recorded |
| [`packages/plugins/src/types.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/types.ts) | Public API surface—defines `addGeoJsonLayer` and helpers |
| [`packages/plugins/src/plugins/maplibre-stac.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugins/maplibre-stac.ts) | Plugin loading external files via core API |
| [`backend/geolibre_server/app/conversion.py`](https://github.com/opengeos/GeoLibre/blob/main/backend/geolibre_server/app/conversion.py) | Server-side conversion for heavy formats |
| [`apps/geolibre-desktop/src/hooks/usePlugins.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/hooks/usePlugins.ts) | Registers built-in plugins and wires to store |
| [`docs/project-format.md`](https://github.com/opengeos/GeoLibre/blob/main/docs/project-format.md) | Specification for [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) project files |

## Summary

- **Centralized state**: All layers live in [`packages/core/src/store.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/store.ts) via Zustand
- **Unified API**: `addGeoJsonLayer` in [`packages/plugins/src/types.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/types.ts) is the entry point for all vector data
- **Dual-path ingestion**: Browser handles light formats via DuckDB-WASM; heavy formats route through FastAPI side-car
- **Plugin compatibility**: External services integrate through the same API surface
- **Project portability**: [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) files serialize layer metadata for reproducible sessions

## Frequently Asked Questions

### How does GeoLibre handle large raster files that won't fit in browser memory?

GeoLibre delegates to a **FastAPI side-car** (`backend/geolibre_server`). The client uploads via `/raster` endpoint, the server converts to MBTiles or COG, and returns a reference that `addRasterLayer` consumes. This keeps the UI responsive while processing occurs server-side.

### Can custom plugins add files from proprietary APIs?

Yes. Plugins implement the interface in [`packages/plugins/src/types.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/types.ts) and call `store.addGeoJsonLayer` with their fetched data. The STAC plugin ([`maplibre-stac.ts`](https://github.com/opengeos/GeoLibre/blob/main/maplibre-stac.ts)) demonstrates this pattern—extract assets, convert to GeoJSON, and register through the core API.

### What happens to file paths when a project is shared?

The [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) format stores source paths relative to the project root where possible. Absolute paths are preserved for side-car references. Recipients must ensure referenced files are accessible at those paths, or GeoLibre will prompt for re-location on project open.