Schema Overview
The maplibre-yaml schema is built on Zod, providing type-safe configuration with automatic validation and TypeScript type inference.
Architecture
Section titled “Architecture”The schema follows a hierarchical structure:
RootSchema├── GlobalConfig (optional)├── Layers (optional, named definitions)├── Sources (optional, named definitions)└── Pages (array, required) └── PageSchema ├── path ├── title └── blocks (array) ├── ContentBlock ├── MapBlock ├── ScrollytellingBlock └── MixedBlockCore Concepts
Section titled “Core Concepts”Type Safety
Section titled “Type Safety”All configuration is validated at parse time:
import { YAMLParser } from '@maplibre-yaml/core';
const result = YAMLParser.safeParse(yaml);if (result.success) { // result.data is fully typed console.log(result.data.pages[0].title);} else { // result.errors contains detailed validation errors console.error(result.errors);}Schema Composition
Section titled “Schema Composition”Schemas are composed from smaller, reusable schemas:
- Base schemas: LngLat, ZoomLevel, Color, Expression
- Source schemas: GeoJSON, Vector, Raster, Image, Video
- Layer schemas: Circle, Line, Fill, Symbol, Heatmap, etc.
- Block schemas: Content, Map, Scrollytelling, Mixed
- Page schemas: Page, Root, GlobalConfig
Default Values
Section titled “Default Values”Many properties have sensible defaults:
config: center: [0, 0] zoom: 2 # pitch defaults to 0 # bearing defaults to 0 # interactive defaults to trueOptional vs Required
Section titled “Optional vs Required”Required properties will cause validation errors if missing:
# ✅ Valid - all required fields presenttype: mapid: my-mapconfig: center: [0, 0] zoom: 2 mapStyle: "https://example.com/style.json"
# ❌ Invalid - missing required 'mapStyle'type: mapid: my-mapconfig: center: [0, 0] zoom: 2Validation
Section titled “Validation”Error Messages
Section titled “Error Messages”The schema provides detailed, human-readable error messages:
const result = YAMLParser.safeParse(invalidYaml);if (!result.success) { result.errors.forEach(err => { console.log(`${err.path}: ${err.message}`); });}Example errors:
pages[0].blocks[0].config.zoom: Expected number, got stringpages[0].blocks[1].layers[0].type: Invalid enum value. Expected 'circle' | 'line' | 'fill' | 'symbol' | 'raster' | 'hillshade' | 'heatmap' | 'fill-extrusion' | 'background', received 'invalid'Custom Validation
Section titled “Custom Validation”Some schemas include custom validation rules:
// Zoom level must be 0-24zoom: z.number().min(0).max(24)
// LngLat must be [lon, lat] where lon is -180 to 180, lat is -90 to 90center: z.tuple([ z.number().min(-180).max(180), z.number().min(-90).max(90)])Reference Resolution
Section titled “Reference Resolution”The schema supports $ref pointers to reuse layers and sources:
# Define oncelayers: myLayer: id: shared-layer type: circle source: {...}
# Reference multiple timespages: - path: "/" blocks: - type: map id: map1 layers: - $ref: "#/layers/myLayer" - type: map id: map2 layers: - $ref: "#/layers/myLayer"Type Inference
Section titled “Type Inference”Use Zod’s type inference for TypeScript projects:
import { RootSchema, type z } from '@maplibre-yaml/core/schemas';
type RootConfig = z.infer<typeof RootSchema>;type PageConfig = RootConfig['pages'][number];type MapBlock = Extract<PageConfig['blocks'][number], { type: 'map' }>;Next Steps
Section titled “Next Steps”Explore specific schema sections:
- Root Configuration - Top-level configuration
- Pages & Blocks - Page and block structure
- Map Configuration - Map settings and properties
- Data Sources - GeoJSON, Vector, Raster sources
- Layer Types - All layer types and styling
- Interactivity - Events, popups, and controls
- Scrollytelling - Narrative maps with chapters