mapbox-store-locator-patterns
This skill provides patterns for building store locators and location-based search applications using Mapbox GL JS.
Identity proven by GitHub's verified organisation badge (mapbox)
- Agents
- Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode, claude.ai and API
- License
- MIT (permissive)
- Pin
- f71cd72pinned Oct 9, 2026
- Context cost
- about 2,500 tokenswhen the skill loads
- GitHub stars
- 80on mapbox/mapbox-agent-skills
- Scripts
- None found
What it does
“Common patterns for building store locators, restaurant finders, and location-based search applications with Mapbox. Covers marker display, filtering, distance calculation, and interactive lists.”
Generated summary from the skill's own text
This skill provides patterns for building store locators and location-based search applications using Mapbox GL JS. It covers marker display strategies for different location counts, interactive lists, filtering, distance calculations with Turf.js, and directions integration. The skill includes implementations from basic map setup through popup creation and list synchronization.
When to use it
- Building store locators, restaurant finders, or office location searches
- Displaying 100 to 1,000 locations on a map with symbol layers
- Creating interactive lists synced with map markers and popups
- Implementing distance-based filtering from user location
When not to
- Displaying fewer than 100 locations where HTML markers suffice
- Visualizing over 1,000 locations without clustering support
- Applications not using Mapbox GL JS or GeoJSON data format
Install
These commands install from the publisher's repository and need no account.
skills CLI
npx skills add mapbox/mapbox-agent-skills --skill mapbox-store-locator-patternsInstalls from the repository's default branch, which may have changed since the commit we checked.
GitHub CLI 2.90 or later
gh skill install mapbox/mapbox-agent-skills mapbox-store-locator-patterns@f71cd72b8d8937b06db440538bd65559eb792c49Installs the commit we checked (f71cd72).
Copy by hand
Download the folder at f71cd72 and put it in .claude/skills/mapbox-store-locator-patterns for Claude Code and in .agents/skills/mapbox-store-locator-patterns for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode.
Claude Code plugin
/plugin install mapbox@claude-plugins-officialThe publisher's plugin in Claude's official marketplace. It may hold more than this skill, and we have not pinned it.
Copy for your agent
A prompt for any coding agent. It installs this skill from GitHub at the pinned commit, copies the files as they are, and runs nothing unless you ask.
Prompt
Install the agent skill "mapbox-store-locator-patterns" by Mapbox. Source, pinned to commit f71cd72b8d8937b06db440538bd65559eb792c49: https://github.com/mapbox/mapbox-agent-skills/tree/f71cd72b8d8937b06db440538bd65559eb792c49/skills/mapbox-store-locator-patterns 1. Download that folder at exactly this commit. Do not use the default branch. 2. Copy every file unchanged, keeping the folder structure, into .claude/skills/mapbox-store-locator-patterns/ for Claude Code and .agents/skills/mapbox-store-locator-patterns/ for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode. Create the folders if they do not exist. 3. Do not edit the files, and do not run any script in the folder unless I ask you to. 4. When you are done, list the files you copied and where you put them. Listing and checks: https://www.agentnative.dev/skills/mapbox/mapbox-store-locator-patterns
SKILL.md at the pin
---
name: mapbox-store-locator-patterns
description: Common patterns for building store locators, restaurant finders, and location-based search applications with Mapbox. Covers marker display, filtering, distance calculation, and interactive lists.
---
# Store Locator Patterns Skill
Comprehensive patterns for building store locators, restaurant finders, and location-based search applications with Mapbox GL JS. Covers marker display, filtering, distance calculation, interactive lists, and directions integration.
## When to Use This Skill
Use this skill when building applications that:
- Display multiple locations on a map (stores, restaurants, offices, etc.)
- Allow users to filter or search locations
- Calculate distances from user location
- Provide interactive lists synced with map markers
- Show location details in popups or side panels
- Integrate directions to selected locations
## Dependencies
**Required:**
- Mapbox GL JS v3.x
- [@turf/turf](https://turfjs.org/) - For spatial calculations (distance, area, etc.)
**Installation:**
```bash
npm install mapbox-gl @turf/turf
```
## Core Architecture
### Pattern Overview
A typical store locator consists of:
1. **Map Display** - Shows all locations as markers
2. **Location Data** - GeoJSON with store/location information
3. **Interactive List** - Side panel listing all locations
4. **Filtering** - Search, category filters, distance filters
5. **Detail View** - Popup or panel with location details
6. **User Location** - Geolocation for distance calculation. For the blue dot location indicator, use the built-in `mapboxgl.GeolocateControl` — simpler than custom markers.
7. **Directions** - Route to selected location (optional)
### Data Structure
**GeoJSON format for locations:**
```json
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-77.034084, 38.909671]
},
"properties": {
"id": "store-001",
"name": "Downtown Store",
"address": "123 Main St, Washington, DC 20001",
"phone": "(202) 555-0123",
"hours": "Mon-Sat: 9am-9pm, Sun: 10am-6pm",
"category": "retail",
"website": "https://example.com/downtown"
}
}
]
}
```
**Key properties:**
- `id` - Unique identifier for each location
- `name` - Display name
- `address` - Full address for display and geocoding
- `coordinates` - `[longitude, latitude]` format
- `category` - For filtering (retail, restaurant, office, etc.)
- Custom properties as needed (hours, phone, website, etc.)
## Basic Store Locator Implementation
### Step 1: Initialize Map and Data
```javascript
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';
// Store locations data
const stores = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [-77.034084, 38.909671]
},
properties: {
id: 'store-001',
name: 'Downtown Store',
address: '123 Main St, Washington, DC 20001',
phone: '(202) 555-0123',
category: 'retail'
}
}
// ... more stores
]
};
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/standard',
center: [-77.034084, 38.909671],
zoom: 11
});
```
### Step 2: Add Markers to Map
**Marker strategy by location count:**
| Count | Strategy | Reason |
| ------------------- | -------------------------- | ------------------------------------------------------------------------------ |
| **Fewer than 100** | HTML Markers | Full DOM/CSS control; DOM node count is manageable |
| **100–1,000** | **Symbol Layer** (default) | Renders on the **GPU via WebGL** — one `<canvas>`, zero per-point DOM elements |
| **More than 1,000** | Clustering | Reduces visual clutter at large scale |
> HTML Markers create one DOM element per point. Beyond ~100 locations the browser spends too much time on layout/paint. Symbol layers bypass the DOM entirely — the GPU draws all points in a single WebGL draw call.
**Symbol Layer implementation** (best for 100–1,000 locations). For HTML Markers (fewer than 100) or Clustering (more than 1,000), see `references/markers.md`.
```javascript
map.on('load', () => {
// Add store data as source
map.addSource('stores', {
type: 'geojson',
data: stores
});
// Add custom marker image
map.loadImage('/marker-icon.png', (error, image) => {
if (error) throw error;
map.addImage('custom-marker', image);
// Add symbol layer
map.addLayer({
id: 'stores-layer',
type: 'symbol',
source: 'stores',
layout: {
'icon-image': 'custom-marker',
'icon-size': 0.8,
'icon-allow-overlap': true,
'text-field': ['get', 'name'],
'text-font': ['Open Sans Bold', 'Arial Unicode MS Bold'],
'text-offset': [0, 1.5],
'text-anchor': 'top',
'text-size': 12
}
});
});
// Handle marker clicks using Interactions API (recommended)
map.addInteraction('store-click', {
type: 'click',
target: { layerId: 'stores-layer' },
handler: (e) => {
const store = e.feature;
flyToStore(store);
createPopup(store);
}
});
// Or using traditional event listener:
// map.on('click', 'stores-layer', (e) => {
// const store = e.features[0];
// flyToStore(store);
// createPopup(store);
// });
//
// For why addInteraction is preferred over map.on(), and how to pair it with
// setFeatureState/appearances for hover and selection styling, see the
// "interactions" reference file in the mapbox-style-patterns skill.
// Change cursor on hover
map.on('mouseenter', 'stores-layer', () => {
map.getCanvas().style.cursor = 'pointer';
});
map.on('mouseleave', 'stores-layer', () => {
map.getCanvas().style.cursor = '';
});
});
```
### Step 3: Build Interactive Location List
```javascript
function buildLocationList(stores) {
const listingContainer = document.getElementById('listings');
stores.features.forEach((store, index) => {
const listing = listingContainer.appendChild(document.createElement('div'));
listing.id = `listing-${store.properties.id}`;
listing.className = 'listing';
const link = listing.appendChild(document.createElement('a'));
link.href = '#';
link.className = 'title';
link.id = `link-${store.properties.id}`;
link.innerHTML = store.properties.name;
const details = listing.appendChild(document.createElement('div'));
details.innerHTML = `
<p>${store.properties.address}</p>
<p>${store.properties.phone || ''}</p>
`;
// Handle listing click
link.addEventListener('click', (e) => {
e.preventDefault();
flyToStore(store);
createPopup(store);
highlightListing(store.properties.id);
});
});
}
function flyToStore(store) {
map.flyTo({
center: store.geometry.coordinates,
zoom: 15,
duration: 1000
});
}
function createPopup(store) {
const popups = document.getElementsByClassName('mapboxgl-popup');
// Remove existing popups
if (popups[0]) popups[0].remove();
new mapboxgl.Popup({ closeOnClick: true })
.setLngLat(store.geometry.coordinates)
.setHTML(
`<h3>${store.properties.name}</h3>
<p>${store.properties.address}</p>
<p>${store.properties.phone}</p>
${store.properties.website ? `<a href="${store.properties.website}" target="_blank">Visit Website</a>` : ''}`
)
.addTo(map);
}
// IMPORTANT: highlightListing MUST include scrollIntoView — without it,
// selecting a marker on the map won't scroll the sidebar to the listing.
function highlightListing(id) {
// Remove existing highlights
const activeItem = document.getElementsByClassName('active');
if (activeItem[0]) {
activeItem[0].classList.remove('active');
}
// Add highlight to selected listing
const listing = document.getElementById(`listing-${id}`);
listing.classList.add('active');
// Scroll the selected listing into view (critical UX requirement)
listing.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
// Build the list on load
map.on('load', () => {
buildLocationList(stores);
});
```
## Reference Files
Load these references for additional patterns as needed:
| Reference | File | Contents |
| ------------------------- | -------------------------------------- | ---------------------------------------------------------------- |
| HTML Markers & Clustering | `references/markers.md` | HTML Markers (< 100 locations), Clustering (> 1000 locations) |
| Search & Filter | `references/search-filter.md` | Text search, category filter |
| Geolocation & Directions | `references/geolocation-directions.md` | User location, distance calculation, route directions |
| Styling & Layout | `references/styling-layout.md` | Full HTML/CSS layout, custom marker CSS |
| Performance & A11y | `references/optimization-a11y.md` | Debounced search, data management, error handling, accessibility |
| Variations & React | `references/variations-react.md` | Mobile-first, fullscreen, map-only, React implementation |
## Resources
- [Turf.js](https://turfjs.org/) - Spatial analysis library (recommended for distance calculations)
- [Mapbox GL JS API](https://docs.mapbox.com/mapbox-gl-js/)
- [Interactions API Guide](https://docs.mapbox.com/mapbox-gl-js/guides/user-interactions/interactions/)
- [GeoJSON Specification](https://geojson.org/)
- [Directions API](https://docs.mapbox.com/api/navigation/directions/)
- [Store Locator Tutorial](https://docs.mapbox.com/help/tutorials/building-a-store-locator/)
From mapbox/mapbox-agent-skills at f71cd72, shown as plain text under its license: MIT (permissive). The license text is in LICENSE.md.
View SKILL.md on GitHub at f71cd72Files
- SKILL.md10 KB · acff8e88d959
- AGENTS.md8.7 KB · 38bbc7d4ad2a
- evals/
- evals.json3.7 KB · e343c3878b9a
- references/
- geolocation-directions.md5.4 KB · 4bf799e42f22
- markers.md4.4 KB · fb54d0209bf4
- optimization-a11y.md2.9 KB · a354d81b6f6d
- search-filter.md1.7 KB · 26bf834444f7
- styling-layout.md4.4 KB · 874a2055731b
- variations-react.md3.4 KB · 73f3a1c35ff8
9 files, 45 KB in total. Each file has a sha256 in the pin's manifest; the first 12 characters are shown.
Skill folder on GitHub at f71cd72More from Mapbox
mapbox-android-patterns
This skill provides official patterns for integrating Mapbox Maps SDK v11 on Android, covering setup, map initialization, markers, user location display…
Claude Code, Codex, Cursor +4 · about 2.5K tokens · pinned 6 days ago
mapbox-cartography
This skill provides cartographic expertise for designing effective maps with Mapbox, covering visual hierarchy, color theory, typography, and zoom strategies.
Claude Code, Codex, Cursor +4 · about 1.7K tokens · pinned 6 days ago
mapbox-data-visualization-patterns
This skill teaches the agent to implement data visualization patterns on Mapbox maps, including choropleth maps, heat maps, 3D extrusions, and animated data…
Claude Code, Codex, Cursor +4 · about 2.1K tokens · pinned 6 days ago
mapbox-flutter-patterns
This skill teaches agents the standard patterns for integrating the Mapbox Maps Flutter SDK into iOS and Android apps written in Dart.
Claude Code, Codex, Cursor +4 · about 2.3K tokens · pinned 6 days ago
mapbox-geospatial-operations
This skill guides agents on selecting appropriate geospatial tools from the Mapbox MCP Server based on problem requirements.
Claude Code, Codex, Cursor +4 · about 4.8K tokens · pinned 6 days ago
mapbox-google-maps-migration
This skill guides developers migrating from Google Maps Platform to Mapbox GL JS by comparing APIs, translating patterns, and highlighting architectural…
Claude Code, Codex, Cursor +4 · about 2.9K tokens · pinned 6 days ago
Related in Frontend and design
next-bundle-optimizer
Audits Next.js applications to identify and reduce browser bundle size and initial-load work by analyzing routes, dependencies and client outputs.
by VercelOfficial publisher
Claude Code, Codex, Cursor +4 · about 2.3K tokens · pinned 6 days ago
next-cache-components-optimizer
Optimize Next.js routes to display meaningful UI instantly on initial load or client navigation by encoding the optimization goal as a failing…
by VercelOfficial publisher
Claude Code, Codex, Cursor +4 · about 5.6K tokens · pinned 6 days ago
next-partial-prefetching-adoption
Enables Partial Prefetching in Next.js 16.3+ apps and guides adoption through auditing Link prefetch behavior, preserving UI in tests or manually, and…
by VercelOfficial publisher
Claude Code, Codex, Cursor +4 · about 6.7K tokens · pinned 6 days ago
remotion-interactivity
This skill teaches how to structure Remotion code so the Studio IDE recognizes and makes it interactive.
by RemotionOfficial publisher
Claude Code, Codex, Cursor +3 · about 2.4K tokens · pinned 6 days ago
remotion-interactivity
This skill teaches how to structure Remotion video components to unlock Studio interactivity features like click selection, drag-and-drop, resizing, rotation…
by RemotionOfficial publisher
Claude Code, Codex, Cursor +3 · about 4.8K tokens · pinned 6 days ago
remotion-maps
This skill enables creating map-based animations with Remotion using four different mapping libraries: Mapbox, MapLibre, MapTiler, or CesiumJS.
by RemotionOfficial publisher
Contains scripts
Claude Code, Codex, Cursor +3 · about 240 tokens · pinned 6 days ago