Skip to content
Documentation
Skill

/maplibre-sprites-icons

Sprites and icon images for MapLibre GL JS — choosing a `Marker`, a sprite, or `addImage`; the `sprite` base URL and its `{id, url}` array form for several sheets; self-hosting and building sprites; runtime images, SVGs included, with `addImage`; finding a missing icon with the

BOOST
From plugin
maplibre-agent-skills
15511 skills
Install
$ npx -y skills add maplibre/maplibre-agent-skills --skill maplibre-sprites-icons --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-sprites-icons

Context preview

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

Sprites and icon images for MapLibre GL JS — choosing a `Marker`, a sprite, or `addImage`; the `sprite` base URL and its `{id, url}` array form for several sheets; self-hosting and building sprites; runtime images, SVGs included, with `addImage`; finding a missing icon with the

SKILL.md

maplibre-sprites-icons.SKILL.md
name: maplibre-sprites-icons
description: Sprites and icon images for MapLibre GL JS — choosing a `Marker`, a sprite, or `addImage`; the `sprite` base URL and its `{id, url}` array form for several sheets; self-hosting and building sprites; runtime images, SVGs included, with `addImage`; finding a missing icon with the console warning and `hasImage`; and route shields that render as bare numbers. Use when deciding how to put icons on a map, when a symbol layer's icons never appear, when adding your own icons to a style whose sprite you do not control, or when shields are missing their badge.
status: verified

MapLibre Sprites and Icons

An icon on a MapLibre GL JS map is either part of the map, drawn by a symbol layer from a **sprite** (a PNG atlas plus a JSON index served from the style's `sprite` URL) or from an image registered at runtime with `addImage`, or on top of the map as a `Marker`, outside the style. For icon color, halos, and figure-ground against imagery, see [maplibre-cartography](../maplibre-cartography/SKILL.md); for text and glyph setup, see [maplibre-fonts-glyphs](../maplibre-fonts-glyphs/SKILL.md).

When to Use This Skill

  • Choosing between a `Marker`, a sprite, and `addImage` for icons on a map
  • A symbol layer's icons do not render
  • Adding your own icon sheet to a style whose `sprite` you do not control
  • Setting up, self-hosting, or building a `sprite` from SVGs (for `glyphs`, see [maplibre-fonts-glyphs](../maplibre-fonts-glyphs/SKILL.md))
  • Registering icons, including SVGs, for a layer your app adds at runtime
  • Route shields render as bare numbers or missing badges
  • Writing tooling that reads or generates symbol layers and has to recognize a shield

Choosing a `Marker`, a sprite, or `addImage`

Two questions, in order; the sections below follow them.

1. **Is the icon part of the map, or on top of it?** Part of the map means a symbol layer's `icon-image`: placed together with the labels, hidden when it collides, and drawn in layer order, for a point dataset of any size. A small number of annotations on top of the map, that people drag or that need their own HTML, are [`Marker`s](#markers). 2. **For a symbol layer, where does the image come from?**

  • **The style.** POIs, town spots, shields, pattern textures, and any other icon or texture layered into the style, where it takes part in the visual hierarchy and collisions: a [sprite](#sprites). Your own set on a basemap whose sprite you do not control is a [second sheet](#multiple-sprite-sheets-in-one-style), still a sprite.
  • **Your app, at runtime.** Icons for a layer the app adds, such as a GeoJSON source, that no sheet carries: [`addImage`](#runtime-images-with-addimage). Use it deliberately. Each image is its own request and `addImage` call, where a sprite arrives as one PNG and one JSON, and its icons collide with the style's labels and with each other like sprite icons.

Sprites

The style's `sprite` value is a **base URL with no file extension**; MapLibre appends `.json`, `.png`, and `@2x` variants itself.[1] A symbol layer names a sprite image in `icon-image` (other layers in their `*-pattern` property), and the name must exactly match an ID in the sprite JSON index or the icon is not drawn.

{
  "sprite": "https://example.com/sprites/poi",
  "layers": [
    {
      "id": "cafes",
      "type": "symbol",
      "source": "places",
      "source-layer": "poi",
      "layout": { "icon-image": "cafe" }
    }
  ]
}

`https://demotiles.maplibre.org/styles/osm-bright-gl-style/sprite` works for testing; do not use it in production.

Multiple sprite sheets in one style

`sprite` is not limited to a single string. Since MapLibre GL JS 3.0 ([#1805](https://github.com/maplibre/maplibre-gl-js/pull/1805)) it also accepts an **array of `{id, url}` objects**,[1] so a style can load its own icons alongside a basemap provider's sheet. Before 3.0 a style could name only one sprite, so adding your own icons meant merging them into the provider's sheet; with the array form, each sheet stays where it is hosted.

{
  "sprite": [
    { "id": "default", "url": "https://tiles.openfreemap.org/sprites/ofm_f384/ofm" },
    { "id": "my-icons", "url": "https://example.com/sprites/poi" }
  ]
}

Rules that follow from that form:

  • **Reference images by `id:image-name`** — `"icon-image": "my-icons:cafe"`. An unprefixed `"cafe"` resolves against the `default` sheet only.
  • **The `id` `default` is the one exception**: its images take no prefix, which is what keeps an existing style's `icon-image` values working when you convert its string `sprite` to the array form. Give the basemap's sheet `id: "default"` and the shield and POI layers already in the style keep resolving unchanged.
  • **All ids and all URLs must be unique.** Duplicates are a validation error (`all the sprites' ids must be unique, but <id> is duplicated`), not a last-one-wins merge.
  • **Each URL is still extension-less** — MapLibre appends `.json`, `.png`, and the `@2x` variants per entry, exactly as for the string form.
  • **From code, `map.addSprite('my-icons', 'https://example.com/sprites/poi')` adds a sheet** once the style has loaded; a string `sprite` becomes the array's `default` entry.[3]
  • ❌ `{ "id": "my-icons", "url": "https://example.com/sprites/poi.json" }` → requests `poi.json.json`
  • ❌ Typing `sprite` as `string` in your own tooling: an array value stringifies to `[object Object]`, and the loader rejects it with `Invalid sprite URL "[object Object]", must be absolute`. Handle both shapes wherever you read a style's `sprite`.

Self-hosted sprites

To avoid third-party dependencies, copy an existing sprite directory (PNG + JSON, plus any @2x files) from a style or tileset provider and host it under your own domain, pointing the style's `sprite` property at its base URL. Always check the provider's license before republishing and add attribution if required.

Host sprite assets on a static host you control

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.