skills/mapbox-ops/SKILL.md
Mapbox GL JS v3 (web) toolkit: custom markers, symbol/geojson layers, clustering, style expressions, 3D terrain/fill-extrusion, heatmaps, choropleths, camera animation, and performance gotchas. Use for any Mapbox GL JS work — markers, layers, style, 3D, or headless map verification.
npx skillsauth add 0xDarkMatter/claude-mods mapbox-opsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
An advanced toolkit for building production Mapbox GL JS map experiences on the web:
markers, thematic dataviz, 3D, terrain, cinematic camera, style composition, performance,
and the hard-won gotchas that bite. Scope: mapbox-gl-js v3.x in the browser (CDN
mapbox-gl-js/v3.x/) — not the native iOS/Android SDKs (different APIs). Plain GL JS,
framework-agnostic. Several patterns were distilled from a production trail map; adapt the
constants to your own design.
mapboxgl.accessToken before new mapboxgl.Map(...).'load' before adding sources/layers/images. In a throttled
or background tab 'load' can be missed — also bind 'idle' as a one-shot
fallback guarded by an _inited flag (see verification.md)..env: read the token FIRST (that triggers the
.env load), THEN read MAPBOX_STYLE. Reading the style before the token load
silently falls back to the default style. See palette.md.getStyle().layers walk) assume a classic style
(Streets/Outdoors/Light/Dark …-v12). The v3 default Standard style has no
enumerable named layers — use slots + setConfigProperty instead. See
v3-standard-style.md before porting to Standard.Read the matching reference file only when the task needs it:
| Task | Reference |
|------|-----------|
| Custom SVG/canvas markers, addImage/updateImage, namespacing, AA/fringing, circular image masks, anchoring | references/markers.md |
| Dashed/cased trail lines, line-dasharray units, translucency over hillshade, colour-by-attribute, line-gradient/lineMetrics | references/lines-and-trails.md |
| Hillshade, dense contours, 3D terrain (setTerrain), boost-or-add an existing style's terrain | references/terrain.md |
| Symbol-layer text labels that never hide icons (text-optional), AllTrails-style placement | references/labels.md |
| Recolour a base style's land/vegetation fills (palette shift / choropleth-style match) | references/palette.md |
| Custom popups, circular photo cards, zoom-scaled offsets | references/popups.md |
| Style expressions — interpolate/step/match/case, the zoom-outermost rule, feature-state in expressions | references/expressions.md |
| Hover/select via feature-state (not setData), queryRenderedFeatures caveats, clustering, GeoJSON perf, event hygiene | references/interaction-and-performance.md |
| Data viz & 3D — fill-extrusion buildings/extruded data, heatmap layer, data-join choropleth (feature-state/match), proportional symbols, sky/fog | references/dataviz-and-3d.md |
| three.js in the map — CustomLayerInterface + shared GL context, animated 3D objects/models, the baked-matrix vs reconstructed-camera (Threebox CameraSync) fork, raycast picking, ENU-metre scene space, constant screen-size actors, terrain elevation, far-plane clipping at pitch | references/three-custom-layer.md |
| Camera & animation — flyTo/easeTo/fitBounds padding, freeCameraOptions cinematics/orbit, flight/first-person camera (bearing+pitch choreography; roll is MapLibre-only), animated day–night cycle (setLights), HUD synced to camera, point-along-line, draw-in lines, paint transitions, spinning globe, the essential/reduced-motion gotcha | references/camera-and-animation.md |
| Style library & composition — first-party style catalog, choosing a base by use case, custom/third-party styles, style switcher, light/dark, hand-rolled style JSON | references/styles.md (+ assets/style-catalog.json) |
| setStyle wiping custom layers, the 0×0 resize() bug, SPA teardown / WebGL-context cap, token security, readiness events | references/lifecycle.md |
| v3 Standard style — slots vs beforeId, setConfigProperty/lightPreset, why layer-walking (palette/terrain) breaks; localisation, RTL, globe | references/v3-standard-style.md |
| Headless screenshot + pixel-accurate marker-alignment checks (Playwright, map.project) | references/verification.md |
Starter code — assets/circular_image_marker.js:
copy into a page to register a circular photo marker (canvas → premultiplied
ImageBitmap, destination-in mask, contact + drop shadow). Browser-only snippet,
not a CLI — adapt the frameColor/box constants to your design.
Verifier script — scripts/screenshot_map.py: drive headless Chromium to screenshot a served map page, assert a marker projects to its lng/lat, and surface console errors. Run it:
python -m http.server 8777 --directory <site-dir> & # serve the page
uv run --with playwright scripts/screenshot_map.py \
http://localhost:8777/preview/index.html out.png --expect 146.9 -36.1
# exit 0 = no console errors; 10 = errors found; 5 = playwright missing; 7 = map never ready
uv run --with playwright scripts/screenshot_map.py URL out.png --json | jq '.data'
Staleness verifier — scripts/check-mapbox-facts.py:
stdlib-only (no Playwright), guards the fast-moving facts this skill encodes
(SKILL-RESOURCE-PROTOCOL §7). --offline (default) asserts internal consistency —
the v3 Standard config enums (lightPreset/theme), terrain tileset IDs, the weather
(≥3.7) version gate, the no-native-camera-roll fact (roll is MapLibre GL JS v5, not
Mapbox), and every style URL/id in
assets/style-catalog.json. --live resolves the
third-party style URLs and probes whether Mapbox GL JS has shipped a major past v3.
python scripts/check-mapbox-facts.py --offline # exit 0 ok, 4 inconsistency
python scripts/check-mapbox-facts.py --live --json # exit 7 network, 10 drift
addImage name (e.g. "rcpin-<glyph>"). Mapbox styles ship
sprite icons literally named parking/toilet/etc — an un-namespaced
hasImage() returns true for those and your icon is silently dropped.createImageBitmap(), not a raw
HTMLImageElement/ImageData — straight-alpha sources make Mapbox fringe a
white halo around anti-aliased edges. updateImage(name, bmp) recolours in place.icon-offset is silently ignored in GL JS v3. Use a constant
icon-offset (it scales with icon-size) or split markers into separate symbol
layers, each with its own constant anchor/offset.testing
Audit any repo against the agentic-quality doctrine — score entry docs, structure, and enforcement gates, then map each finding to its fix. Triggers on: repo doctor, repo audit, agentic quality, is this repo agent-friendly, doc drift, stale AGENTS.md, monorepo structure, nested CLAUDE.md.
data-ai
Router for parallel or recurring agent work across six skills. Covers: parallel agents, fan out work, delegate to workers, run overnight, scheduled loop, land branches, mixed-model fleet, orchestrate workers, background agents at scale. Triggers on: which skill for parallel work, fan out agents, spawn workers, run this overnight, schedule a loop, land my branches, heterogeneous fleet, delegate to cheaper model, autonomous loop.
tools
Heterogeneous cross-provider fleet - GLM (z.ai), Codex (OpenAI), Grok (xAI), Anthropic Sonnet/Opus/Haiku - from one session, porting the native Workflow tool's patterns (adversarial verify, judge panels, journal resume) to OS-process workers. Triggers: fleetflow, heterogeneous/mixed-model fleet, codex worker, grok worker, cross-provider fan-out, cross-model verify.
development
Application/game-scale three.js: ES modules, GLTF pipeline (DRACO/KTX2/meshopt), AnimationMixer, physics (rapier/cannon-es), react-three-fiber, and performance at scale (InstancedMesh, LOD, draw calls). Triggers on: three.js, GLTFLoader, r3f, game loop, WebGL memory leak, boids.