# GeoLibre `.geolibre.json` Project Format Schema and Serialization Guide

> Learn the .geolibre.json project format schema and serialization for the GeoLibre workspace. Understand how to store and parse your project state efficiently.

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

---

**The [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) format is a JSON-based project file that stores the complete GeoLibre workspace state, serialized via `JSON.stringify` with optional pretty-printing and parsed back through `parseProject` with automatic normalization and validation.**

GeoLibre uses a single file to persist entire mapping projects—layers, styles, camera position, plugins, and dashboard widgets. Understanding the [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) schema and serialization API is essential for building integrations, automating workflows, or manipulating projects programmatically. This guide covers the complete schema structure and the serialization helpers implemented in the core package.

## Top-Level Schema Structure

A [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) file contains a flat JSON object with the following fields. Optional sections are omitted when empty to minimize file size.

| Field | Type | Description |
|-------|------|-------------|
| `version` | **string** | Project format version, e.g., `"0.1.0"`. |
| `name` | **string** | Human-readable project title. |
| `mapView` | **object** | Camera state: `center` (lng,lat), `zoom`, `bearing`, `pitch`, and optional `bbox`. |
| `basemapStyleUrl` | **string** | URL to a MapLibre style JSON; empty string means blank background. |
| `basemapVisible` | **boolean** | Whether the background layer renders. |
| `basemapOpacity` | **number** (0–1) | Opacity of the background layer. |
| `layers` | **array** | Ordered list of layer objects (see Layer Object section below). |
| `styles` | **object** | Map of layer IDs to `LayerStyle` definitions. |
| `plugins` | **object** *(optional)* | Plugin manifests, active IDs, UI positions, and settings. |
| `legend` | **object** *(optional)* | Print-layout legend customizations: title, ordering, per-item overrides. |
| `storymap` | **object** *(optional)* | Scroll-driven narrative with chapters and map animations. |
| `widgets` | **array** *(optional)* | Dashboard chart widgets: histogram, bar, scatter, etc. |
| `dashboardColumns` | **number** *(optional)* | Grid columns for dashboard (1–6, default 2). |
| `styleLibrary` | **array** *(optional)* | Project-scoped style manager entries. |
| `metadata` | **object** | Free-form key/value pairs for custom data. |

The authoritative documentation lives in [[`docs/project-format.md`](https://github.com/opengeos/GeoLibre/blob/main/docs/project-format.md)](https://github.com/opengeos/GeoLibre/blob/main/docs/project-format.md) in the source repository.

## Layer Object Schema

Each entry in the `layers` array follows a unified structure. The `type` field determines how `source` and data properties are interpreted.

```json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Buildings",
  "type": "geojson",
  "source": { "type": "geojson" },
  "visible": true,
  "opacity": 1,
  "style": {
    "minZoom": 0,
    "maxZoom": 24,
    "fillColor": "#3b82f6",
    "strokeColor": "#1e40af",
    "strokeWidth": 2,
    "strokeWidthUnit": "pixels",
    "fillOpacity": 0.6,
    "circleRadius": 6,
    "rasterBrightnessMin": 0,
    "rasterBrightnessMax": 1,
    "rasterSaturation": 0,
    "rasterContrast": 0,
    "rasterHueRotate": 0
  },
  "metadata": {},
  "geojson": {
    "type": "FeatureCollection",
    "features": []
  },
  "sourcePath": "/data/buildings.geojson"
}

```

Supported `type` values include: `geojson`, `xyz`, `wms`, `vector-tiles`, `mbtiles`, `cog`, `zarr`, and `3d-tiles`. Raster-specific style properties are ignored for vector layers and vice versa.

## How GeoLibre Serializes Projects

Serialization and deserialization are handled by three core functions in `@geolibre/core`. The implementation is intentionally thin—projects are plain JSON objects.

```ts
import {
  createEmptyProject,
  parseProject,
  serializeProject,
} from "@geolibre/core";

// 1. Create or modify a project
const project = createEmptyProject("My Analysis");

// 2. Serialize to formatted JSON string
const json = serializeProject(project);
// Internally: JSON.stringify(project, null, 2)
// Source: packages/core/src/project.ts lines 109-111

// 3. Parse back with validation and normalization
const restored = parseProject(json);

```

### `serializeProject` Implementation

In [[`packages/core/src/project.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/project.ts)](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/project.ts#L109-L111), the function is defined as:

```ts
export function serializeProject(project: GeoLibreProject): string {
  return JSON.stringify(project, null, 2);
}

```

The `null, 2` arguments enable two-space indentation for human readability. No custom encoding or binary transformation occurs—any language with JSON support can produce or consume [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) files.

### `parseProject` Normalization Pipeline

`parseProject` performs several safety steps when loading hand-edited or legacy files:

- **Version migration**: Upgrades old `version` strings to current schema.
- **Default injection**: Fills missing optional fields (`metadata`, `style`, etc.).
- **UUID validation**: Ensures all layer IDs are valid UUIDs.
- **Source reconstruction**: Rebuilds `source` objects from shorthand properties.

This pipeline protects downstream code from malformed inputs without rejecting valid JSON.

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

### Create and Save a New Project

```ts
import { createEmptyProject, serializeProject } from "@geolibre/core";
import { writeFile } from "fs/promises";

async function saveNewProject() {
  const project = createEmptyProject("Demo Project");
  const json = serializeProject(project);
  await writeFile("demo.geolibre.json", json);
}

saveNewProject();

```

### Load and Inspect an Existing Project

```ts
import { readFile } from "fs/promises";
import { parseProject } from "@geolibre/core";

async function loadProject(path: string) {
  const json = await readFile(path, "utf-8");
  const project = parseProject(json);
  console.log(`Loaded: ${project.name} with ${project.layers.length} layers`);
}

loadProject("demo.geolibre.json");

```

### Add a GeoJSON Layer and Serialize

```ts
import { createEmptyProject, serializeProject } from "@geolibre/core";
import { v4 as uuid } from "uuid";

const project = createEmptyProject("With Layer");

project.layers.push({
  id: uuid(),
  name: "Sensor Locations",
  type: "geojson",
  source: { type: "geojson" },
  visible: true,
  opacity: 0.9,
  style: {
    circleRadius: 8,
    fillColor: "#ef4444",
    strokeColor: "#991b1b",
    strokeWidth: 1
  },
  metadata: { department: "Environmental" },
  geojson: {
    type: "FeatureCollection",
    features: []
  }
});

const output = serializeProject(project);
console.log(output);

```

## Cross-Language Interoperability

Because [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) is pure JSON, Python, Rust, and other ecosystems can manipulate projects without native GeoLibre bindings. The Python sidecar demonstrates this pattern:

```python
import geolibre

m = geolibre.Map()
m.add_geojson("data.geojson")
m.save_project("output.geolibre.json")  # Writes identical JSON structure

```

See [[`python/README.md`](https://github.com/opengeos/GeoLibre/blob/main/python/README.md)](https://github.com/opengeos/GeoLibre/blob/main/python/README.md) for the full Python API.

## Key Source Files

| File | Purpose |
|------|---------|
| [[`docs/project-format.md`](https://github.com/opengeos/GeoLibre/blob/main/docs/project-format.md)](https://github.com/opengeos/GeoLibre/blob/main/docs/project-format.md) | Human-readable schema specification for all fields and layer types. |
| [[`packages/core/src/project.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/project.ts)](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/project.ts) | `serializeProject`, `parseProject`, and validation logic. |
| [[`packages/core/src/types.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/types.ts)](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/types.ts) | TypeScript definitions: `GeoLibreProject`, `Layer`, `LayerStyle`, `PluginState`. |
| [[`apps/geolibre-desktop/src/lib/tauri-io.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/lib/tauri-io.ts)](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/lib/tauri-io.ts) | Desktop file I/O using Tauri's filesystem API. |

## Summary

- **[`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json)** stores complete GeoLibre projects as flat JSON with a versioned, extensible schema.
- **Top-level fields** cover workspace state: `mapView`, `layers`, `styles`, `plugins`, `legend`, `storymap`, `widgets`, and `metadata`.
- **`serializeProject`** outputs pretty-printed JSON via standard `JSON.stringify`—no proprietary encoding.
- **`parseProject`** normalizes and validates on load, enabling robust handling of hand-edited or legacy files.
- **Layer objects** unify heterogeneous data sources under a common structure with typed `source` and optional data embedding.

## Frequently Asked Questions

### What is the current version of the [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) format?

The current version is `"0.1.0"`. The `version` field in the top-level object enables forward migration through `parseProject`. Future releases will increment this string and include automated upgrade paths.

### Can I edit [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) files by hand?

Yes. Because the format is plain JSON, any text editor or programmatic tool can modify projects. `parseProject` validates and normalizes on load, so minor omissions like missing `metadata` or partial `style` objects are automatically repaired.

### How do I add custom data to a project?

Use the `metadata` object at the top level or on individual layers. This free-form key/value map accepts any JSON-serializable data and is preserved through load/save cycles without schema enforcement.

### Does GeoLibre support binary or compressed project formats?

Not natively. `serializeProject` outputs uncompressed UTF-8 JSON. For large projects with embedded GeoJSON, standard file-system compression (gzip, zstd) can be applied externally. The desktop app handles this transparently when saving to `.geolibre.json.gz` extensions.