# .geolibre.json Project File Structure: A Complete Guide to GeoLibre's Core Format

> Explore the .geolibre.json project file structure, a comprehensive guide to GeoLibre's core format. Understand map layers, plugin states, view settings, and global preferences in this MapLibre compatible descriptor.

- Repository: [Open Geospatial Solutions/GeoLibre](https://github.com/opengeos/GeoLibre)
- Tags: api-reference
- Published: 2026-08-22

---

**The [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) file is a JSON-based project descriptor that stores map layers, plugin states, view settings, and global preferences in a round-trippable format compatible with the MapLibre style specification.**

GeoLibre uses the [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) extension to persist complete map projects. This file format serves as the single source of truth for reconstructing a map, from layer styling and visibility to camera position and plugin configurations. Understanding this structure is essential for developers building automation tools, custom plugins, or server-side generators that interact with the opengeos/GeoLibre codebase.

## Top-Level Keys in a [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) File

A valid [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) file contains several required top-level keys that define the project state. According to [`docs/project-format.md`](https://github.com/opengeos/GeoLibre/blob/main/docs/project-format.md) and the TypeScript definitions in [`packages/core/src/types.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/types.ts), the schema includes:

- **`name`** – Human-readable project title displayed in the UI.
- **`layers`** – Ordered array of layer definitions describing vector, raster, tile, GeoJSON, or plugin-based layers.
- **`plugins`** – Array of plugin state objects storing configuration for both built-in and third-party extensions.
- **`view`** – Camera viewport settings including center coordinates, zoom, bearing, and pitch.
- **`settings`** – Global UI and processing preferences such as measurement units, language, and map style.
- **`metadata`** *(optional)* – Free-form object for arbitrary project-specific data like author information or provenance.
- **`version`** *(optional)* – Schema version identifier to aid forward compatibility when absent.

## Deep Dive into the Layers Array

The `layers` array is the heart of the [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) structure. Each element follows the Layer interface defined in [`packages/core/src/types.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/types.ts) and supports properties compatible with the MapLibre GL style specification.

### Layer Types and Source Configuration

Every layer object requires an `id`, `type`, and `source` field:

```typescript
{
  "id": "countries-layer",
  "type": "geojson",
  "source": {
    "url": "https://example.com/countries.geojson"
  },
  "visible": true,
  "opacity": 1.0
}

```

Supported `type` values include `"vector"`, `"raster"`, `"tile"`, `"geojson"`, and `"plugin"`. The `source` object varies by type, accepting URLs, file paths, or DuckDB queries depending on the data provider.

### Styling with layout and paint Properties

Layer styling uses `layout` and `paint` objects that mirror the MapLibre style spec:

```json
{
  "layout": {
    "visibility": "visible"
  },
  "paint": {
    "fill-color": "#88c0d0",
    "fill-opacity": 0.8
  }
}

```

These properties control rendering behavior, allowing the same styling logic used in pure MapLibre applications to apply directly to GeoLibre projects.

## Plugin State Management

The `plugins` array stores serialized state for extensions, enabling third-party tools to survive export and import cycles. As defined in [`packages/plugins/src/types.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/types.ts), each entry contains:

- **`id`** – Plugin identifier (e.g., `"draw"`, `"measure"`, `"my-plugin"`).
- **`enabled`** – Boolean flag indicating whether the plugin is active.
- **`config`** – Arbitrary JSON object defined by the plugin's internal schema.

```typescript
{
  "id": "my-plugin",
  "enabled": true,
  "config": {
    "threshold": 0.75,
    "colorScheme": "viridis"
  }
}

```

The core application stores these objects verbatim in `useAppStore`, allowing plugins to declare their own schema extensions without core modifications.

## View and Settings Configuration

The `view` object captures camera state using the `ViewState` interface:

```json
{
  "view": {
    "center": [0, 0],
    "zoom": 2,
    "bearing": 0,
    "pitch": 0
  }
}

```

The `settings` object contains global preferences defined in the `Settings` interface:

- **`units`** – `"metric"` or `"imperial"`.
- **`language`** – I18n locale code (e.g., `"en"`).
- **`mapStyle`** – MapLibre style URL or built-in style name.
- **`maxZoom`** / **`minZoom`** – Zoom constraints.
- **Feature toggles** – Such as `enableMCP` or `showLegend`.

## Working with [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) Files Programmatically

GeoLibre provides several APIs for programmatic project manipulation across different environments.

### Loading Projects via Embed URLs

The `@geolibre/embed` package exposes `parseEmbedRequest` for handling external project URLs:

```typescript
import { useEffect } from 'react';
import { parseEmbedRequest } from '@geolibre/embed';

useEffect(() => {
  const message = {
    type: 'loadProject',
    url: 'https://example.com/my-map.geolibre.json'
  };
  const embedMessage = parseEmbedRequest(message);
  // embedMessage.command contains { type: 'loadProject', url: '...' }
  // The core store validates the JSON against the schema and populates the UI
}, []);

```

This pattern allows web applications to initialize GeoLibre with a specific [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) file via query parameters or postMessage APIs.

### Generating Projects in Python

Server-side applications can construct valid project files using standard JSON libraries:

```python
import json

project = {
    "name": "Server-Generated Demo",
    "layers": [
        {
            "id": "urban-areas",
            "type": "vector",
            "source": {"url": "mbtiles://data/cities.mbtiles"},
            "layout": {"visibility": "visible"},
            "paint": {"fill-color": "#5e81ac"},
            "visible": True,
            "opacity": 0.9
        }
    ],
    "view": {"center": [10.0, 59.0], "zoom": 10, "bearing": 0, "pitch": 0},
    "settings": {"language": "en", "units": "metric", "mapStyle": "streets"}
}

with open("output.geolibre.json", "w") as f:
    json.dump(project, f, indent=2)

```

### Persisting Plugin Configuration

Custom plugins interact with the global store to persist state:

```typescript
useAppStore.getState().addPlugin({
  id: "custom-analytics",
  enabled: true,
  config: {
    autoRefresh: 300,
    dataSource: "duckdb://analytics.db"
  }
});

```

This state is automatically included in the next project save operation.

## File Naming and Validation

When saving projects through the desktop interface, the helper function `ensureProjectFileName` (tested in [`tests/file-names.test.ts`](https://github.com/opengeos/GeoLibre/blob/main/tests/file-names.test.ts)) automatically appends the [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) suffix if the user omits it. The loading logic in [`apps/geolibre-desktop/src/hooks/useProjects.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/hooks/useProjects.ts) validates incoming JSON against the TypeScript interfaces, ensuring that malformed files trigger appropriate error handling before corrupting the application state.

## Summary

- The [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) format stores **layers**, **plugins**, **view**, and **settings** in a single JSON object.
- Layer definitions use **MapLibre-compatible** `layout` and `paint` properties for styling.
- The format is **extension-friendly**, allowing plugins to store arbitrary configuration objects under the `plugins` array.
- Projects are **round-trippable**, meaning saved files can be reloaded without loss of UI state, camera position, or layer visibility.
- Source definitions reside in [`packages/core/src/types.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/types.ts) and [`packages/plugins/src/types.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/types.ts), while file handling logic lives in [`apps/geolibre-desktop/src/hooks/useProjects.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/hooks/useProjects.ts).

## Frequently Asked Questions

### What is the difference between [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) and MapLibre Style JSON?

While both use similar styling objects, [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) is a project wrapper that includes UI state (layer visibility, opacity, plugin configurations, and camera view) whereas MapLibre Style JSON focuses strictly on rendering rules and data sources. GeoLibre projects can reference external MapLibre styles via the `settings.mapStyle` property while maintaining additional project-specific metadata.

### How do I add a custom layer to a [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) file?

Add a new object to the `layers` array with a unique `id`, valid `type` (such as `"geojson"` or `"vector"`), and appropriate `source` configuration. Include `visible` and `opacity` flags for UI control, plus `layout` and `paint` objects following the MapLibre specification. The application will render the layer immediately upon loading the project.

### Can I manually edit a [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) file in a text editor?

Yes, the format is plain JSON and human-readable. However, you must preserve the schema structure defined in [`packages/core/src/types.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/types.ts) to ensure the file loads correctly. Invalid JSON or missing required fields (like `id` for layers) will cause validation errors when the application attempts to import the project.

### How does GeoLibre handle backward compatibility for older project files?

The optional `version` field at the top level of the JSON indicates the schema version used when creating the file. When this field is absent, the application assumes the current schema version. The loading logic in [`useProjects.ts`](https://github.com/opengeos/GeoLibre/blob/main/useProjects.ts) includes migration handlers that upgrade legacy structures to the current format, ensuring older [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) files remain functional across application updates.