Skip to content
Documentation
Skill

/maplibre-source-wiring

Getting a MapLibre GL JS source to actually render — TileJSON `url` versus hand-wired `tiles` templates, matching `source-layer` names to the tile schema, layer order and inserting below labels, `promoteId` and the feature ids that feature state needs, and the CORS and glyph

BOOST
From plugin
maplibre-agent-skills
15511 skills
Install
$ npx -y skills add maplibre/maplibre-agent-skills --skill maplibre-source-wiring --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/maplibre-source-wiring

Context preview

The summary Claude sees to decide when to auto-load this skill.

Getting a MapLibre GL JS source to actually render — TileJSON `url` versus hand-wired `tiles` templates, matching `source-layer` names to the tile schema, layer order and inserting below labels, `promoteId` and the feature ids that feature state needs, and the CORS and glyph

SKILL.md

maplibre-source-wiring.SKILL.md
name: maplibre-source-wiring
description: Getting a MapLibre GL JS source to actually render — TileJSON `url` versus hand-wired `tiles` templates, matching `source-layer` names to the tile schema, layer order and inserting below labels, `promoteId` and the feature ids that feature state needs, and the CORS and glyph failures behind a blank map. Use when a source is configured but nothing is drawing, or when setFeatureState does nothing.
status: verified

MapLibre Source Wiring

You have a tile URL or a data file and a style, and the map is blank, drawing at the wrong scale, or drawing in the wrong order. This skill covers connecting a source to a style correctly, and the failure modes that look identical from the outside.

When to Use This Skill

The source is already configured and the map is wrong in a way that produces no error. These are symptoms as you would observe them, before you know the cause:

  • The map is blank, or a layer you added draws nothing, and the console is clean
  • A custom style renders nothing against a tile source that works with the provider's own style
  • The basemap is blurry, or sits at a different scale than everything drawn on top of it
  • Data you added has covered the street names
  • Icons are missing while the rest of the map draws fine
  • Hover or click highlighting does nothing at all, and no error is raised
  • You have a tile endpoint and are unsure which source type it needs, or whether to point `url`

at its TileJSON instead of hand-writing `tiles`

**Not this skill.** Text in the wrong font, missing scripts, or self-hosting glyph PBFs — [maplibre-fonts-glyphs](../maplibre-fonts-glyphs/SKILL.md). Deciding the colors, type, and drawing order of a style you are designing — [maplibre-cartography](../maplibre-cartography/SKILL.md). Deciding whether a dataset belongs in GeoJSON or vector tiles at all — [maplibre-tile-sources](../maplibre-tile-sources/SKILL.md).

Referencing tiles: `url` vs `tiles`

Tiles are addressed by zoom (Z), column (X), and row (Y) — a universal scheme across raster and vector tile sources (see [the OpenStreetMap wiki](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames) for more information). In a MapLibre source, you reference tiles either directly via a `tiles` URL template or via a `url` pointing to a TileJSON endpoint.

**When a TileJSON endpoint is available, prefer `url`.** MapLibre fetches the document and reads the tile URL template, zoom range, bounds, attribution, and (for vector tiles) the available source-layers automatically. Tile servers like Martin and tileserver-gl generate TileJSON endpoints for every tileset they serve, as do many hosted providers.

When no TileJSON endpoint exists — for example, a raw raster tile service that gives you a URL template directly — use the `tiles` array and specify any metadata (minzoom, maxzoom, attribution) in the source definition yourself.

**`url` to a TileJSON endpoint:**

{
  "type": "vector",
  "url": "https://example.com/tiles.json"
}

**`tiles` array:**

{
  "type": "vector",
  "tiles": ["https://example.com/tiles/{z}/{x}/{y}.pbf"],
  "minzoom": 0,
  "maxzoom": 14
}

`{z}`, `{x}` and `{y}` are tokens MapLibre replaces with each tile's zoom, column and row before it makes a request. A template pasted into a browser with the braces still in it asks for no real tile, so its status code says nothing about the server. To check the server by hand, request a real tile inside the source's zoom range, such as `/0/0/0.pbf`.

The cost of hand-wiring `tiles` is that MapLibre has no zoom range unless you supply one, and will assume `maxzoom: 22` — requesting zoom levels the tileset doesn't contain, which come back empty. This is why `url` is the default advice wherever a TileJSON endpoint exists. (For PMTiles specifically the same rule applies and the consequence is sharper — see [maplibre-pmtiles-patterns](../maplibre-pmtiles-patterns/SKILL.md).)

Nothing renders: `source-layer` and the tile schema

The most common cause of a custom style rendering nothing against a working tile source is a `source-layer` mismatch.

A vector tile source contains named layers — `transportation`, `water`, `landuse` and so on — and every style layer that draws from it must name one exactly:

{
  "id": "roads",
  "type": "line",
  "source": "basemap",
  "source-layer": "transportation"
}

`source-layer` is required for vector sources and must match the tile schema exactly. A typo or a name from a different schema produces no error and no output — the layer simply draws nothing.

**Find the real names in the TileJSON.** For vector sources, the TileJSON `vector_layers` field lists each available `source-layer`, its attribute fields, and its zoom range. This is the authoritative reference **when it is present** — TileJSON 3.0 requires it for vector tilesets, but 2.x documents predate it and providers are inconsistent about supplying it. Its absence does not mean there is no schema: identify the schema by name (below) and work from its published layer list. If you use a provider's pre-built style URL, the schema is already matched for you; the mismatch only appears when you write your own layers.

Pre-defined tile schemas

When building a custom style you need to know the **tile schema** — the source-layer names and their properties. Common schemas:

  • **OpenMapTiles** — the most widely adopted schema, based on OpenStreetMap data. Rich and detailed, with source-layers like `transportation`, `water`, `landuse`, `poi`. The largest ecosystem of community styles targets this schema.
  • **Shortbread** — an open standard designed to be minimal and interoperable, not tied to any single vendor. Simpler structure than OpenMapTiles; a clean foundation if you're building styles from scratch.
  • **Protomaps** — purpose-built for the Protomaps PMTiles basemap ecosystem. Flat, simple structure with source-layers like `earth`, `water`, `roads`, `places`; optimized for
Read more
Ships withmaplibre-agent-skills

Curated guidance for AI assistants building MapLibre applications — covering ecosystem and open-source best practices. Agent skills are markdown files that AI coding assistants read as context.

Get the whole plugin

Other skills on maplibre-agent-skills.