All skills
mapbox avatar

/mapbox-web-performance-patterns

@f5ae7de official
by mapboxmapbox/mapbox-agent-skills80 stars
17

Performance optimization patterns for Mapbox GL JS web applications. Covers initialization waterfalls, bundle size, rendering performance, memory management, and web optimization. Prioritized by impact on user experience.

Use this Skill: https://skilld.dev/gh/mapbox/mapbox-agent-skills/mapbox-web-performance-patterns

This session only. Nothing lands on disk.

referenceslayers-styles.md

≈837 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Layer and Style Performance

Consolidate Layers

// ❌ BAD: 20 separate layers for restaurant types
restaurantTypes.forEach((type) => {
  map.addLayer({
    id: `restaurants-${type}`,
    type: 'symbol',
    source: 'restaurants',
    filter: ['==', ['get', 'type'], type],
    layout: { 'icon-image': `${type}-icon` }
  });
});

// ✅ GOOD: Single layer with data-driven styling
map.addLayer({
  id: 'restaurants',
  type: 'symbol',
  source: 'restaurants',
  layout: {
    'icon-image': [
      'match',
      ['get', 'type'],
      'pizza',
      'pizza-icon',
      'burger',
      'burger-icon',
      'sushi',
      'sushi-icon',
      'default-icon' // fallback
    ]
  }
});

Impact: Fewer layers means less rendering overhead. Each layer has fixed per-layer cost regardless of feature count.

Simplify Expressions for Large Datasets

For datasets with 100,000+ features, simpler expressions reduce per-feature evaluation cost. For smaller datasets, the expression engine is fast enough that this won't be noticeable.

// Zoom-dependent paint properties MUST use step or interpolate, not comparisons
// ❌ WRONG: Cannot use comparison operators on ['zoom'] in paint properties
// paint: { 'fill-extrusion-height': ['case', ['>', ['zoom'], 16], ...] }

// ✅ CORRECT: Use step for discrete zoom breakpoints
map.addLayer({
  id: 'buildings',
  type: 'fill-extrusion',
  source: 'buildings',
  paint: {
    'fill-extrusion-color': ['interpolate', ['linear'], ['get', 'height'], 0, '#dedede', 50, '#a0a0a0', 100, '#606060'],
    'fill-extrusion-height': [
      'step',
      ['zoom'],
      ['get', 'height'], // Default: use raw height
      16,
      ['*', ['get', 'height'], 1.5] // At zoom 16+: scale up
    ]
  }
});

For very large GeoJSON datasets, pre-computing static property derivations (like color categories) into the source data can reduce per-feature expression work:

// ✅ Pre-compute STATIC derivations for large datasets (100K+ features)
const buildingsWithColor = {
  type: 'FeatureCollection',
  features: buildings.features.map((f) => ({
    ...f,
    properties: {
      ...f.properties,
      heightColor: getColorForHeight(f.properties.height) // Pre-computed once
    }
  }))
};

map.addSource('buildings', { type: 'geojson', data: buildingsWithColor });

map.addLayer({
  id: 'buildings',
  type: 'fill-extrusion',
  source: 'buildings',
  paint: {
    'fill-extrusion-color': ['get', 'heightColor'], // Simple property lookup
    'fill-extrusion-height': ['get', 'height']
  }
});

Use Zoom-Based Layer Visibility

// ✅ Only render layers at appropriate zoom levels
map.addLayer({
  id: 'building-details',
  type: 'fill',
  source: 'buildings',
  minzoom: 15, // Render at zoom 15 and above
  paint: { 'fill-color': '#aaa' }
});

map.addLayer({
  id: 'poi-labels',
  type: 'symbol',
  source: 'pois',
  minzoom: 12, // Hide at low zoom levels where labels would overlap heavily
  layout: {
    'text-field': ['get', 'name'],
    visibility: 'visible'
  }
});

Note: minzoom is inclusive (layer visible at that zoom), maxzoom is exclusive (layer hidden at that zoom). A layer with maxzoom: 16 is visible up to but not including zoom 16.

Impact: Reduces GPU work at zoom levels where layers aren't useful

Source: SKILL.md on GitHub

No alerts17d5 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    The skill provides a comprehensive set of performance optimization patterns and documentation for Mapbox GL JS applications. It focuses on legitimate development practices such as parallel data loading, bundle size optimization, and efficient marker rendering. No security risks or malicious patterns were detected.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer6mo

    1/2 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at f5ae7de. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 8 hours ago.

Activeupdated 2 months ago
  • Performance
  • mapbox
  • web
  • rendering
  • bundle-size
  • markers
  • geojson
  • memory
  • optimization

README badge

README badge for mapbox/mapbox-agent-skills/mapbox-web-performance-patterns

Provides performance optimization patterns for Mapbox GL JS applications, covering initialization waterfalls, bundle size, marker rendering, and memory management. Addresses critical issues like parallel data loading, symbol layers for large feature sets, and clustering strategies, with actionable code examples and performance thresholds.

Generated from the current SKILL.md.

Does this skill cover Mapbox GL JS only, or other Mapbox libraries?
This skill focuses on Mapbox GL JS web applications. It does not cover native mobile SDKs or server-side optimization.
What are the main performance bottlenecks this skill addresses?
The skill prioritizes initialization waterfalls (sequential data loading), bundle size, marker rendering (HTML vs symbol layers), and memory management. It covers the most impactful issues first, then optional optimizations.
When should I switch from HTML markers to symbol layers?
Use HTML markers for fewer than 100 markers. Switch to GPU-accelerated symbol layers for 100-10,000 markers, and add clustering for 10,000+ markers.
Does this skill provide code examples?
Yes. The skill includes concrete before/after code examples for initialization waterfalls, bundle optimization, marker strategies, and clustering patterns.

Generated from the current SKILL.md. These answers refresh after source changes.