GeoLibreLayer Type Structure: How Layer Kinds Are Represented in GeoLibre

The GeoLibreLayer interface defined in 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) declares the schema that all layers must satisfy:

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

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

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

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

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

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

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

Key Source Files

File Role
packages/core/src/types.ts Defines GeoLibreLayer, LayerType, LayerStyle, VectorRule, LabelStyle, LayerGroup, LayerConnection, and helper functions like isDuckDBQueryLayer
packages/core/src/layer-library.ts CRUD helpers for layers (add, remove, update, reorder)
packages/core/src/layer-defaults.ts Provides DEFAULT_LAYER_STYLE and initialization defaults
packages/map/src/layer-sync.ts Synchronizes GeoLibreLayer objects to MapLibre and Deck.gl sources
packages/plugins/src/plugins/arcgis-layer.ts Implements ArcGIS source handling based on layer.type === "arcgis"
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 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) and rendered via the synchronization engine in 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 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 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.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →