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
VectorRuletables for rule-based symbology - 3-D extrusion, elevation settings, and geometry generators (centroid, buffer, convex-hull)
- Diagram overlays (pie, bar, donut charts) and
LabelStyleconfiguration
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:
GeoLibreLayerinpackages/core/src/types.tsprovides 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: LayerTypefield (constrained byLAYER_TYPESlines 62-83) determines how thesourceobject andmetadataare interpreted without requiring separate interfaces. - Flexible Styling: The
LayerStyleblock (lines 368-525) accommodates both vector symbology (fills, strokes, labels, diagrams) and raster adjustments (brightness, contrast, saturation). - Plugin Extensibility: Special layer kinds like
arcgisandduckdb-queryusemetadataflags and helper functions (e.g.,isDuckDBQueryLayerat 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 inlayer-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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →