
Mapbox Style Quality
Validate Mapbox GL style JSON for errors, WCAG contrast, colorblind safety, and mobile touch targets before shipping a map UI.
Overview
Mapbox Style Quality is an agent skill for the Build phase that guides solo builders through Mapbox style validation, accessibility standards, and performance-oriented map UI checks.
Install
npx skills add https://github.com/mapbox/mapbox-agent-skills --skill mapbox-style-qualityWhat is this skill?
- Style validation rules: version 8 spec, sources, layers, and valid paint values
- WCAG 2.1 contrast targets for labels and UI (4.5:1 text, 3:1 large text and components)
- Colorblind accessibility checklist (deuteranopia, protanopia, tritanopia) with pattern and label guidance
- Mobile touch target minimums (44px iOS, 48px Material recommendation)
- Common error patterns such as missing sources and invalid fill-color values
- WCAG 2.1 contrast: 4.5:1 normal text, 3:1 large text and UI components
- Colorblind prevalence called out: ~8% deuteranopia, ~1% protanopia among males
- Touch targets: 44×44px minimum iOS, 48×48px recommended Material
Adoption & trust: 980 installs on skills.sh; 64 GitHub stars; 2/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your Mapbox style looks fine in dev but breaks validation, fails contrast, or confuses colorblind users once real data and labels appear.
Who is it for?
Indie builders shipping Mapbox-powered maps who want a checklist-driven review without hiring a dedicated cartography QA pass.
Skip if: Projects using non-Mapbox map stacks or static map images with no editable style JSON.
When should I use this skill?
Editing or reviewing Mapbox style JSON for validation errors, accessibility (contrast, colorblind), or mobile touch targets before release.
What do I get? / Deliverables
You get actionable rules and corrected layer examples so your style spec passes structural checks and meets accessibility and touch-target expectations.
- Corrected layer/source examples
- Accessibility-oriented paint and text-halo settings
- Validation checklist applied to your style
Recommended Skills
Journey fit
Map styles are front-end artifacts built alongside the product UI, so the canonical shelf is Build even when you re-check quality before launch. Frontend covers map layers, paint properties, and client-side style specs that ship in the app bundle or CDN.
How it compares
Use as a style-and-a11y checker for Mapbox JSON, not as a generic GIS data pipeline or tile-hosting skill.
Common Questions / FAQ
Who is mapbox-style-quality for?
Solo developers and small teams building Mapbox GL experiences who own style JSON and need validation plus accessibility guardrails in the agent workflow.
When should I use mapbox-style-quality?
Use it in Build while editing frontend map styles, and again at Ship or Launch when you run a final accessibility and contrast review before users see the map.
Is mapbox-style-quality safe to install?
The skill is documentation and patterns only; it does not call external APIs by itself. Review the Security Audits panel on this Prism page for the parent skill package trust signals.
SKILL.md
READMESKILL.md - Mapbox Style Quality
# Mapbox Style Quality Guide Quick reference for style validation, accessibility, performance optimization, and testing. ## Style Validation Rules ### Required Elements ✅ Valid version 8 style specification ✅ At least one source defined ✅ At least one layer defined ✅ Valid layer types and properties ✅ Proper source references in layers ### Common Errors ```javascript // ❌ Layer references non-existent source { "id": "layer", "source": "missing-source" // Error! } // ❌ Invalid property values { "paint": { "fill-color": "not-a-color" // Error! } } // ✅ Valid layer { "id": "layer", "source": "valid-source", "type": "fill", "paint": { "fill-color": "#ff0000" } } ``` ## Accessibility Standards ### Color Contrast (WCAG 2.1) **Requirements:** - Normal text: 4.5:1 contrast ratio - Large text (18pt+): 3:1 contrast ratio - UI components: 3:1 contrast ratio ```javascript // ✅ Good contrast for labels 'text-color': '#222222', 'text-halo-color': '#ffffff', 'text-halo-width': 2, 'text-halo-blur': 1 ``` ### Colorblind Accessibility **Test for:** - Deuteranopia (red-green, 8% of males) - Protanopia (red-green, 1% of males) - Tritanopia (blue-yellow, rare) **Rules:** - ❌ Don't rely on color alone - ✅ Add patterns, labels, or symbols - ✅ Use colorblind-safe palettes - ✅ Test with colorblind simulators ### Touch Targets **Mobile requirements:** - Minimum: 44x44 pixels (iOS) - Recommended: 48x48 pixels (Material Design) ```javascript // ✅ Large enough tap targets 'icon-size': 1.2, // Larger icons 'icon-allow-overlap': false, // No overlapping 'symbol-spacing': 250 // Space between symbols ``` ## Performance Optimization ### Layer Count **Rule:** Minimize layer count - **Good:** < 50 layers - **Warning:** 50-100 layers - **Problem:** > 100 layers **Optimization:** ```javascript // ❌ Multiple layers for categories map.addLayer({ id: 'parks', filter: ['==', 'type', 'park'] }); map.addLayer({ id: 'water', filter: ['==', 'type', 'water'] }); // ✅ One layer with data-driven styling map.addLayer({ id: 'features', paint: { 'fill-color': ['match', ['get', 'type'], 'park', '#90EE90', 'water', '#87CEEB', '#CCCCCC'] } }); ``` ### Source Optimization ```javascript // ✅ Set appropriate zoom ranges { "type": "vector", "tiles": ["https://..."], "minzoom": 0, "maxzoom": 14 // Don't over-fetch } // ✅ Use generateId for feature state { "type": "geojson", "data": geojson, "generateId": true // Better performance } ``` ### Paint Properties ```javascript // ✅ Use data-driven expressions efficiently 'circle-radius': [ 'interpolate', ['linear'], ['zoom'], 8, 2, 16, 8 ] // ❌ Avoid expensive operations in expressions 'circle-radius': [ 'sqrt', // Expensive! ['*', ['get', 'value'], ['get', 'multiplier']] ] ``` ## Style Testing Checklist ### Visual Testing ✅ Test at multiple zoom levels (0, 5, 10, 15, 20) ✅ Test with different data densities ✅ Check label collisions ✅ Verify symbol/icon rendering ✅ Test on desktop and mobile viewports ✅ Check dark mode compatibility ### Functional Testing ```javascript // ✅ Validate style loads map.on('style.load', () => { console.log('Style loaded successfully'); }); // ✅ Check for missing resources map.on('error', (e) => { console.error('Style error:', e); }); // ✅ Validate sources const sources = map.getStyle().sources; Object.keys(sources).forEach((id) => { console.log('Source:', id, sources[id]); }); // ✅ Validate layers const layers = map.getStyle().layers; layers.forEach((layer) => { console.log('Layer:', layer.id, 'Type:', layer.type); }); ``` ### Performance Testing ```javascript // ✅ Measure style load time const startTime = performance.now(); map.setStyle(style); map.once('idle', () => { console.log('Style load time:', performance.now() - startTime, 'ms'); }); // ✅ Monitor frame rate const fps = map.getFPS(); console.log('FPS:', fps); // Should be close to 60 // ✅ Check layer count console.log('Layer count:',