# GeoLibreLayer Type Structure: How Layer Kinds Are Represented in GeoLibre

> Explore the GeoLibreLayer type structure. Understand how GeoLibre unifies 20 layer kinds including GeoJSON, vector tiles, and 3D Gaussian splats in a single extensible TypeScript data model.

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

---

**The `GeoLibreLayer` interface defined in [`packages/core/src/types.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/types.ts) serves as a unified TypeScript data model that combines generic metadata with a discriminated `type` field to represent 20 distinct layer kinds—from GeoJSON and vector tiles to DuckDB queries and 3D Gaussian splats—within a single extensible structure.**

The `opengeos/GeoLibre` repository manages diverse geospatial data through this centralized type system. The `GeoLibreLayer` type structure determines how every layer, whether a simple static file or a complex ArcGIS service, is stored, styled, and synchronized across the application's state management and rendering engines.

## Core Interface Definition

The `GeoLibreLayer` interface (line 5555 in [`packages/core/src/types.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/types.ts)) declares the schema that all layers must satisfy:

```typescript
export interface GeoLibreLayer {
  id: string;                     // Stable UUID used throughout the store
  name: string;                   // Human-readable label shown in the UI
  type: LayerType;                // One of the supported layer "kinds"
  source: Record<string, unknown>; // Raw MapLibre source definition (varies by kind)
  visible: boolean;               // UI toggle – true = rendered
  opacity: number;                // Global opacity multiplier (0…1)
  style: LayerStyle;              // Full symbology definition (vector & raster)
  metadata: Record<string, unknown>; // Arbitrary plugin- or UI-specific data
  beforeId?: string;              // Insert order relative to another layer
  geojson?: FeatureCollection;    // Cached GeoJSON for vector sources
  attributeForm?: AttributeFormConfig; // Form widget & validation settings
  joins?: LayerJoin[];            // Persistent attribute joins (QGIS-style)
  virtualFields?: LayerVirtualField[]; // Expression-backed computed columns
  timeFilter?: unknown[];         // Temporal filter injected by the Time-Slider plugin
  embedFilter?: unknown[];        // Filter added by the iframe embed API
  sourcePath?: string;            // Path to the original data file (if any)
  groupId?: string;               // ID of the LayerGroup this layer belongs to
  connection?: LayerConnection;   // Auto-refresh policy for remote layers
}

```

This structure captures both **generic layer properties**—such as visibility, opacity, and styling—and **type-specific source definitions** via the flexible `source` object and `metadata` bag.

## Layer Kinds and the LayerType Discriminator

The `type` field is constrained by the runtime list `LAYER_TYPES` (lines 62-83), which enumerates every supported layer kind:

| Index | Kind | Typical Source Shape |
|-------|------|----------------------|
| 0 | **geojson** | `source: { type: "geojson", data: … }` |
| 1 | **raster** | Tile source (XYZ/WMTS/WMS) without vector styling |
| 2 | **wms** | `source: { type: "raster", tiles: [], … }` with WMS parameters |
| 3 | **wmts** | Same as raster but WMTS-specific query parameters |
| 4 | **xyz** | Simple XYZ tile source |
| 5 | **vector-tiles** | `source: { type: "vector", tiles: … }` |
| 6 | **arcgis** | ArcGIS-REST service (feature or tile) |
| 7 | **pmtiles** | Portable MBTiles container |
| 8 | **mbtiles** | Traditional MBTiles file |
| 9 | **zarr** | Multi-dimensional array (e.g., climate data) |
| 10 | **lidar** | Point-cloud data (LAS/LAZ) |
| 11 | **gaussian-splat** | 3-D splat rendering format |
| 12 | **3d-tiles** | Cesium 3D Tiles |
| 13 | **cog** | Cloud-Optimized GeoTIFF |
| 14 | **flatgeobuf** | FlatGeobuf vector format |
| 15 | **geoparquet** | Parquet-based vector storage |
| 16 | **duckdb-query** | Result of a DuckDB SQL query (metadata flag `sourceKind = "duckdb-query"`) |
| 17 | **deckgl-viz** | Custom Deck.gl overlay |
| 18 | **video** | Video overlay source |
| 19 | **image** | Static raster image overlay |

Each kind is represented by the same `GeoLibreLayer` interface; the concrete implementation varies based on the `type` discriminator.

## Type-Specific Data Representations

While the interface remains constant, different layer kinds populate specific fields to store their unique requirements.

### Vector Data Layers

Kinds such as `geojson`, `vector-tiles`, `flatgeobuf`, `geoparquet`, and `duckdb-query` store cached geometry in the optional `geojson` property and leverage the extensive `LayerStyle` block (lines 368-525) for symbology. These layers support advanced vector rendering modes including `single`, `graduated`, `categorized`, `rule-based`, and `expression` styling with color ramps and classification schemes.

### Raster and Tile Sources

Types including `raster`, `xyz`, `wms`, `wmts`, `pmtiles`, `mbtiles`, and `cog` rely on MapLibre raster source fields within the `source` object—such as `tiles`, `tileSize`, `scheme`, and `bounds`. Only a subset of `LayerStyle` applies to these layers, typically `rasterBrightnessMin`, `rasterBrightnessMax`, `rasterSaturation`, `rasterContrast`, and `rasterHueRotate`.

### Specialized Plugin Layers

Advanced kinds like `arcgis`, `3d-tiles`, `lidar`, `gaussian-splat`, and `deckgl-viz` add specific keys to `metadata` to signal handling requirements. For example, ArcGIS layers set `metadata.sourceKind = "arcgis"`, while DuckDB query layers use `metadata.sourceKind = SQL_QUERY_SOURCE_KIND` (detected via the `isDuckDBQueryLayer` helper at lines 998-1004). These flags instruct specialized plugins in `packages/plugins/src/plugins/` to manage rendering and data fetching.

## Styling and Auxiliary Structures

### LayerStyle Configuration

All visual styling lives in the `LayerStyle` type (lines 368-525), which covers:

- **Fill and stroke** colors, opacity, patterns, and marker shapes
- **Advanced rendering** modes with `VectorRule` tables for rule-based symbology
- **3-D extrusion**, elevation settings, and geometry generators (centroid, buffer, convex-hull)
- **Diagram overlays** (pie, bar, donut charts) and `LabelStyle` configuration

### Grouping and Connections

The `groupId` field references a `LayerGroup` (lines 970-981), which creates collapsible folders for organizing contiguous layers. The optional `connection` field stores a `LayerConnection` object defining auto-refresh policies for remote layers, including sync intervals, last-synced timestamps, and error handling strategies.

## Practical Implementation Examples

### 1. Simple GeoJSON Vector Layer

```typescript
import type { GeoLibreLayer } from '@geolibre/core';
import type { FeatureCollection } from 'geojson';

const myGeoJSON: FeatureCollection = { type: 'FeatureCollection', features: [] };

const vectorLayer: GeoLibreLayer = {
  id: 'layer-01',
  name: 'Parcels',
  type: 'geojson',
  source: { type: 'geojson', data: myGeoJSON },
  visible: true,
  opacity: 1,
  style: { ...DEFAULT_LAYER_STYLE, fillColor: '#4caf50' },
  metadata: {},
};

```

### 2. XYZ Raster Tile Layer

```typescript
import { DEFAULT_LAYER_STYLE } from '@geolibre/core';

const rasterLayer: GeoLibreLayer = {
  id: 'layer-02',
  name: 'Satellite',
  type: 'xyz',
  source: {
    type: 'raster',
    tiles: ['https://tiles.example.com/sat/{z}/{x}/{y}.png'],
    tileSize: 256,
  },
  visible: true,
  opacity: 0.9,
  style: { ...DEFAULT_LAYER_STYLE, rasterBrightnessMin: 0, rasterBrightnessMax: 1 },
  metadata: {},
};

```

### 3. DuckDB-SQL Query Layer

```typescript
import { SQL_QUERY_SOURCE_KIND, isDuckDBQueryLayer } from '@geolibre/core';

const sqlLayer: GeoLibreLayer = {
  id: 'layer-03',
  name: 'Population Query',
  type: 'duckdb-query',
  source: { type: 'geojson' },   // Populated by plugin after execution
  visible: true,
  opacity: 1,
  style: { ...DEFAULT_LAYER_STYLE, fillColor: '#ff5722' },
  metadata: {
    sourceKind: SQL_QUERY_SOURCE_KIND,
    externalDeckLayer: true,               // Signals Deck.gl overlay usage
    sql: 'SELECT * FROM population WHERE year = 2020',
  },
  connection: {
    layerId: 'layer-03',
    interval: 300,               // Auto-refresh every 5 min
    lastSyncedAt: null,
    lastError: null,
    onFailure: 'keep-last',
  },
};

// Detection helper returns true for this layer
isDuckDBQueryLayer(sqlLayer);

```

### 4. ArcGIS Feature Service Layer

```typescript
const arcgisLayer: GeoLibreLayer = {
  id: 'layer-04',
  name: 'Roads (ArcGIS)',
  type: 'arcgis',
  source: {
    type: 'vector',
    url: 'https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer/0',
  },
  visible: true,
  opacity: 0.8,
  style: { ...DEFAULT_LAYER_STYLE, strokeColor: '#000' },
  metadata: { sourceKind: 'arcgis' },
};

```

### 5. Adding a Layer to the Store

```typescript
import { useAppStore } from '@geolibre/core';

// Assuming `vectorLayer` from example 1
useAppStore.getState().addLayer(vectorLayer);

```

## Key Source Files

| File | Role |
|------|------|
| **[`packages/core/src/types.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/types.ts)** | Defines `GeoLibreLayer`, `LayerType`, `LayerStyle`, `VectorRule`, `LabelStyle`, `LayerGroup`, `LayerConnection`, and helper functions like `isDuckDBQueryLayer` |
| **[`packages/core/src/layer-library.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/layer-library.ts)** | CRUD helpers for layers (add, remove, update, reorder) |
| **[`packages/core/src/layer-defaults.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/layer-defaults.ts)** | Provides `DEFAULT_LAYER_STYLE` and initialization defaults |
| **[`packages/map/src/layer-sync.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/map/src/layer-sync.ts)** | Synchronizes `GeoLibreLayer` objects to MapLibre and Deck.gl sources |
| **[`packages/plugins/src/plugins/arcgis-layer.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugins/arcgis-layer.ts)** | Implements ArcGIS source handling based on `layer.type === "arcgis"` |
| **[`packages/plugins/src/plugins/duckdb-query.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugins/duckdb-query.ts)** | Handles DuckDB query execution and populates the layer's GeoJSON data |

## Summary

- **Unified Interface**: `GeoLibreLayer` in [`packages/core/src/types.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/types.ts) provides a single, extensible data model for all 20 supported layer kinds, from basic GeoJSON to complex SQL queries and 3D tiles.
- **Discriminated Union**: The `type: LayerType` field (constrained by `LAYER_TYPES` lines 62-83) determines how the `source` object and `metadata` are interpreted without requiring separate interfaces.
- **Flexible Styling**: The `LayerStyle` block (lines 368-525) accommodates both vector symbology (fills, strokes, labels, diagrams) and raster adjustments (brightness, contrast, saturation).
- **Plugin Extensibility**: Special layer kinds like `arcgis` and `duckdb-query` use `metadata` flags and helper functions (e.g., `isDuckDBQueryLayer` at lines 998-1004) to trigger specialized handling without breaking the core type contract.
- **State Integration**: Layers are managed through the core store ([`layer-library.ts`](https://github.com/opengeos/GeoLibre/blob/main/layer-library.ts)) and rendered via the synchronization engine in [`layer-sync.ts`](https://github.com/opengeos/GeoLibre/blob/main/layer-sync.ts).

## Frequently Asked Questions

### What fields are required when creating a GeoLibreLayer?

Every `GeoLibreLayer` object must include `id` (string UUID), `name` (display label), `type` (LayerType), `source` (MapLibre source definition), `visible` (boolean), `opacity` (number 0-1), `style` (LayerStyle object), and `metadata` (Record). Optional fields like `geojson`, `connection`, `groupId`, and `beforeId` enable advanced features such as caching, auto-refresh, grouping, and layer ordering.

### How does GeoLibre distinguish between vector and raster layer types?

The system inspects the `type` field against the `LAYER_TYPES` enumeration. Vector kinds (`geojson`, `vector-tiles`, `flatgeobuf`, etc.) typically populate the `geojson` cache and use full `LayerStyle` symbology, while raster kinds (`xyz`, `wms`, `cog`, etc.) configure `source` with tile URLs and use only raster-specific style properties. The [`layer-sync.ts`](https://github.com/opengeos/GeoLibre/blob/main/layer-sync.ts) module routes each type to the appropriate MapLibre or Deck.gl renderer.

### Can I extend GeoLibreLayer with custom layer kinds?

While the `LAYER_TYPES` list is fixed at 20 entries in the core types, you can implement custom behavior using the `deckgl-viz` type or by adding discriminator flags to `metadata` (e.g., `metadata.customRenderer = "my-plugin"`). The helper function pattern used by `isDuckDBQueryLayer` demonstrates how to detect and handle these extensions without modifying the base interface.

### Where is the layer rendering logic implemented?

The [`packages/map/src/layer-sync.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/map/src/layer-sync.ts) module handles the bidirectional synchronization between `GeoLibreLayer` state objects and the actual MapLibre GL JS and Deck.gl rendering instances. This file converts the abstract `source` and `style` properties into concrete map sources and layers, applying visibility, opacity, and filter settings in real-time.