# Google Maps to Mapbox GL JS Migration Guide
Quick reference for migrating from Google Maps Platform to Mapbox GL JS with API equivalents and patterns.
## Critical Differences
| Aspect | Google Maps | Mapbox GL JS |
| ------------------ | ----------------------- | ------------------------- |
| **Coordinates** | `{lat, lng}` objects | `[lng, lat]` arrays |
| **Philosophy** | Imperative (objects) | Declarative (data-driven) |
| **Rendering** | DOM elements | WebGL (much faster) |
| **Performance** | Slow with 500+ markers | Fast with 10,000+ points |
| **Initialization** | `new google.maps.Map()` | `new mapboxgl.Map()` |
## Quick Migration Checklist
✅ Install `mapbox-gl` package
✅ Get Mapbox access token
✅ Swap coordinate order (lat,lng → lng,lat)
✅ Replace Google Maps API with Mapbox equivalents
✅ Use Symbol layers for 100+ markers (not HTML markers)
✅ Add clustering for 500+ points
✅ Update geocoding to Mapbox Geocoding API
✅ Test all functionality
## API Equivalents
### Map Initialization
```javascript
// Google Maps
const map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 37.7749, lng: -122.4194 },
zoom: 12
});
// Mapbox GL JS
mapboxgl.accessToken = 'pk.your_token';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [-122.4194, 37.7749], // Note: [lng, lat]
zoom: 12
});
```
### Individual Markers (< 50 points)
```javascript
// Google Maps
const marker = new google.maps.Marker({
position: { lat: 37.7749, lng: -122.4194 },
map: map
});
// Mapbox (equivalent approach)
const marker = new mapboxgl.Marker().setLngLat([-122.4194, 37.7749]).addTo(map);
```
### Many Markers (100+ points) - Performance Critical
```javascript
// ❌ Google Maps: DOM-based (slow with 500+ markers)
locations.forEach((loc) => {
new google.maps.Marker({
position: { lat: loc.lat, lng: loc.lng },
map: map
});
});
// ✅ Mapbox: WebGL-based (fast with 10,000+ points)
map.addSource('points', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: locations.map((loc) => ({
type: 'Feature',
geometry: { type: 'Point', coordinates: [loc.lng, loc.lat] }
}))
}
});
map.addLayer({
id: 'points',
type: 'symbol',
source: 'points',
layout: {
'icon-image': 'marker-15'
}
});
```
**Performance Note:** Google Maps renders ALL markers as DOM elements (even with Data Layer). Mapbox uses WebGL for Symbol/Circle layers = 10-100x faster for large datasets.
### Clustering (500+ points)
```javascript
// Google Maps (requires MarkerClusterer library)
import MarkerClusterer from '@googlemaps/markerclustererplus';
const clusterer = new MarkerClusterer(map, markers);
// Mapbox (built-in)
map.addSource('points', {
type: 'geojson',
data: geojson,
cluster: true,
clusterRadius: 50
});
```
### Info Windows / Popups
```javascript
// Google Maps
const infowindow = new google.maps.InfoWindow({
content: '
Title
'
});
infowindow.open(map, marker);
// Mapbox
const popup = new mapboxgl.Popup().setHTML('Title
').setLngLat([-122.4194, 37.7749]).addTo(map);
// Or attach to marker
marker.setPopup(popup);
```
### Events
```javascript
// Google Maps
marker.addListener('click', () => {
/* ... */
});
map.addListener('click', (e) => {
const lat = e.latLng.lat();
const lng = e.latLng.lng();
});
// Mapbox
marker.on('click', () => {
/* ... */
});
map.on('click', (e) => {
const [lng, lat] = [e.lngLat.lng, e.lngLat.lat];
});
```
### Geocoding
```javascript
// Google Maps
const geocoder = new google.maps.Geocoder();
geocoder.geocode({ address: '1600 Amphitheatre Parkway' }, (results) => {
map.setCenter(results[0].geometry.location);
});
// Mapbox
fetch(
`https://api.mapbox.com/search/geocode/v6/forward?q=1600+Amphitheatre+Parkway&access_token=${mapboxgl.accessToken}`
)
.then((r) => r.json())
.then((data) => {
const [lng, lat] = data.features[0].geometry.coordinates;
map.setCenter([lng, lat]);
});
```
### Directions
```javascript
// Google Maps
const directionsService = new google.maps.DirectionsService();
directionsService.route(
{
origin: 'San Francisco',
destination: 'Los Angeles',
travelMode: 'DRIVING'
},
(result) => {
/* ... */
}
);
// Mapbox
fetch(
`https://api.mapbox.com/directions/v5/mapbox/driving/-122.4194,37.7749;-118.2437,34.0522?access_token=${mapboxgl.accessToken}`
)
.then((r) => r.json())
.then((data) => {
const route = data.routes[0].geometry;
// Display route on map
});
```
### Polygons/Shapes
```javascript
// Google Maps
const polygon = new google.maps.Polygon({
paths: coordinates,
map: map
});
// Mapbox
map.addSource('polygon', {
type: 'geojson',
data: {
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [coordinates] // Note: Array of arrays
}
}
});
map.addLayer({
id: 'polygon',
type: 'fill',
source: 'polygon',
paint: {
'fill-color': '#088',
'fill-opacity': 0.5
}
});
```
## Coordinate Order - CRITICAL
**Most common migration bug:**
```javascript
// ❌ Google Maps order (lat, lng)
{ lat: 37.7749, lng: -122.4194 }
// ✅ Mapbox order (lng, lat)
[-122.4194, 37.7749]
// Remember: Mapbox follows GeoJSON standard (longitude first)
```
## Performance Advantages
**Mapbox is significantly faster for:**
1. **Large datasets:** 500+ markers (Symbol layers vs DOM markers)
2. **Data visualization:** Choropleth, heatmaps (WebGL rendering)
3. **Custom styling:** Full control over every visual element
4. **Vector tiles:** Efficient data loading and rendering
**When Mapbox wins:**
- Rendering 10,000+ points smoothly
- Custom map styles (not just pins on a map)
- Data-driven visualizations
- Performance-critical applications
**When Google Maps might be better:**
- Need Street View
- Heavy Google Workspace integration
- Places API is critical
- Team has deep Google Maps expertise
## Styling Comparison
```javascript
// Google Maps (limited styling)
const styledMapType = new google.maps.StyledMapType([{ elementType: 'geometry', stylers: [{ color: '#242f3e' }] }]);
// Mapbox (full control)
map.setStyle('mapbox://styles/mapbox/dark-v11');
// Or create custom styles in Mapbox Studio
```
**Mapbox Styles:**
- `streets-v12` - Standard streets
- `outdoors-v12` - Hiking/outdoor
- `light-v11` / `dark-v11` - Minimal
- `satellite-v9` / `satellite-streets-v12` - Imagery
- Custom styles via Mapbox Studio
## Common Migration Patterns
### Store Locator
**Google Maps:** Create marker for each store, add click listeners, show info windows
**Mapbox:** Use Symbol layer + click events + popups (much faster for 100+ stores)
### Route Display
**Google Maps:** DirectionsRenderer
**Mapbox:** Fetch route from Directions API, add as Line layer
### Heatmaps
**Google Maps:** HeatmapLayer (DOM-based)
**Mapbox:** Heatmap layer (WebGL-based, much faster)
## Token & Pricing
**Google Maps:**
- Requires API key
- Pay per map load + API calls
- Free tier: $200/month credit
**Mapbox:**
- Requires access token (pk.\* for client-side)
- Pay per map load + API calls
- Free tier: 50,000 map loads/month
**Token setup:**
```javascript
// Store in environment variables
mapboxgl.accessToken = process.env.NEXT_PUBLIC_MAPBOX_TOKEN;
```
## Testing Migration
**Checklist:**
1. ✅ Map displays at correct location
2. ✅ All markers/pins visible
3. ✅ Click events work
4. ✅ Popups display correctly
5. ✅ Geocoding returns results
6. ✅ Directions routing works
7. ✅ Performance improved (if using Symbol layers)
8. ✅ Mobile works (touch events)
## Migration Strategy
**Phase 1: Setup**
- Install Mapbox GL JS
- Get access token
- Create test page
**Phase 2: Core Migration**
- Initialize map
- Swap coordinate order
- Convert markers (use Symbol layers for 100+)
- Migrate popups/info windows
**Phase 3: Features**
- Geocoding
- Directions
- Custom styling
- Events
**Phase 4: Optimization**
- Add clustering (if 500+ points)
- Implement proper cleanup
- Test performance
- Mobile optimization
## Quick Wins
**Easy migrations (mostly drop-in replacements):**
- Basic map initialization
- Individual markers (< 50)
- Popups
- Map controls
- Click events
**Requires rethinking (but worth it):**
- Large marker sets → Symbol layers (10-100x faster)
- Custom styling → Mapbox Studio
- Heatmaps → Heatmap layers (WebGL)
## When NOT to Migrate
Consider staying with Google Maps if:
- Street View is critical
- Heavy Places API usage
- Team has deep Google Maps expertise
- Already heavily optimized
- Short-term project