Skip to content

GeoLeaf — JSON Schema Documentation

Source of truth: profiles/schemas/


Overview

The schema files themselves are stored in profiles/schemas/, not in this directory. This page is the documentation entry point for every GeoLeaf JSON Schema (draft-07).

The schemas validate the JSON configuration files of the active profile. They enable autocompletion and inline validation in VSCode through the $schema property.


Available schemas

SchemaValidated JSON fileDescription
geoleaf-config.schema.jsongeoleaf.config.jsonRoot configuration (debug, branding, data, pwa, security, logging, modules)
profile.schema.jsonprofile.jsonProfile manifest (id, label, version, map, Files, modules)
geoleaf-profile.schema.json(out of contract — not applied)Orphan: UI block vocabulary for panels.detail.layout[]. No profile uses it, and the runtime never reads it.
basemaps.schema.jsonbasemaps.jsonRaster and vector tile sources
ui.schema.jsonui.jsonUI controls, permalink, scale bar, filters
features.schema.jsonconfig/core/features.jsonCore features (clustering, geocoding, performance, POI, mapOptions)
layers.schema.jsonlayers.jsonLayer references of the profile
layer-config.schema.jsonlayers/*/[id]_config.jsonPer-layer configuration (data, styles, popup, sidepanelConfig, clustering)
style.schema.jsonlayers/*/styles/*.jsonRendering styles (flat format, styleRules, expressionPaint)
taxonomy.schema.jsontaxonomy.jsonPOI taxonomy (categories, icons, colors)
themes.schema.jsonthemes.jsonLayer visibility presets
mapping.schema.jsonmapping.jsonNormalization of external POI data

Usage

Inline validation (VSCode)

Add $schema at the top of the JSON file:

json
{
    "$schema": "../../schemas/style.schema.json",
    "id": "mon-style",
    "style": {
        "fillColor": "#4681cb",
        "fillOpacity": 0.6,
        "color": "#2a5599",
        "weight": 1
    }
}

Command-line validation (ajv-cli)

bash
npm install -g ajv-cli

# Validate every style of the tourism profile
ajv validate -s profiles/schemas/style.schema.json \
  -d "profiles/tourism/layers/**/styles/*.json" \
  --all-errors

# Validate the layer configurations
ajv validate -s profiles/schemas/layer-config.schema.json \
  -d "profiles/tourism/layers/**/*_config.json" \
  --all-errors

Style format (flat)

GeoLeaf styles use the flat format — every property sits at the root of the style object. The nested format { fill: { color }, stroke: { color } } is no longer supported since v2.0.0.

Available properties

PropertyTypeDescription
fillColorstring (hex)Fill color (polygons)
fillOpacitynumber 0–1Fill opacity
colorstring (hex/CSS)Stroke / line color
weightnumber ≥ 0Stroke width in pixels
opacitynumber 0–1Stroke opacity
dashArraystringDashes, e.g. "5 10"
lineCap"butt" | "round" | "square"Line cap
lineJoin"bevel" | "miter" | "round"Line join
radiusnumber ≥ 0Circle radius (point layers)
shapestringPoint shape: "circle", "square", etc.
hatchobjectCanvas hatching (enabled, type, spacingPx, renderMode)
casingobjectDouble outline (enabled, color, opacity, widthPx)
expressionPaintobjectMapLibre GL properties passed through as-is (zoom, match expressions, etc.)

Complete example

json
{
    "id": "par_categorie",
    "label": "Par catégorie",
    "scaleConfig": { "minScale": 500000, "maxScale": 10000 },
    "style": {
        "fillColor": "#4681cb",
        "fillOpacity": 0.6,
        "color": "#2a5599",
        "weight": 1.5,
        "opacity": 1
    },
    "styleRules": [
        {
            "when": { "field": "properties.categorie", "operator": "==", "value": "A" },
            "style": { "fillColor": "#e74c3c" },
            "legend": { "label": "Catégorie A" }
        }
    ]
}

Conditional style rules (styleRules)

styleRules provide data-driven styling. The first rule whose condition is true is applied.

Available operators (16)

OperatorDescription
== / === / eqEqual to
!= / !== / neqNot equal to
>Greater than
>=Greater than or equal to
<Less than
<=Less than or equal to
containsContains the substring
startsWithStarts with
endsWithEnds with
inValue present in an array
notInValue absent from the array
betweenValue within a [min, max] range

Compound condition (AND)

json
{
    "when": {
        "all": [
            { "field": "properties.type", "operator": "==", "value": "parc" },
            { "field": "properties.surface", "operator": ">=", "value": 100 }
        ]
    },
    "style": { "fillColor": "#2ecc71" }
}

Labels (label object)

The label property in a style file can be either a string (display name) or an object configuring map labels.

json
{
    "label": {
        "enabled": true,
        "visibleByDefault": false,
        "field": "properties.nom",
        "font": {
            "family": "Arial",
            "sizePt": 11,
            "weight": 50,
            "bold": false,
            "italic": false
        },
        "color": "#333333",
        "opacity": 1,
        "buffer": {
            "enabled": true,
            "color": "#ffffff",
            "opacity": 0.8,
            "sizePx": 2
        },
        "background": {
            "enabled": false,
            "color": "#ffffff",
            "opacity": 0.9,
            "paddingPx": 3
        },
        "offset": {
            "distancePx": 8,
            "angleDeg": 0
        }
    }
}

expressionPaint (native MapLibre)

For complex cases (zoom interpolations, match expressions), use expressionPaint with MapLibre GL properties directly:

json
{
    "style": {
        "expressionPaint": {
            "fill-color": ["interpolate", ["linear"], ["zoom"], 5, "#aaa", 10, "#4681cb"],
            "fill-opacity": ["case", ["get", "actif"], 0.8, 0.3]
        }
    }
}

The keys are MapLibre GL paint property names (fill-color, line-width, circle-radius, etc.).


Released under the MIT License.