gis-maps-integration
Google Maps + Mapbox Integration
Use When
- Use when integrating Google Maps JavaScript API or Mapbox GL into a web app — setup, markers, info windows, geocoding, places autocomplete, routing/directions, styling, offline, accessibility, and cost control. Complements gis-mapping (Leaflet).
- The task needs reusable judgment, domain constraints, or a proven workflow rather than ad hoc advice.
Do Not Use When
- The task is unrelated to
gis-maps-integrationor would be better handled by a more specific companion skill. - The request only needs a trivial answer and none of this skill's constraints or references materially help.
Required Inputs
- Gather relevant project context, constraints, and the concrete problem to solve; load
referencesonly as needed. - Confirm the desired deliverable: design, code, review, migration plan, audit, or documentation.
Workflow
- Read this
SKILL.mdfirst, then load only the referenced deep-dive files that are necessary for the task. - Apply the ordered guidance, checklists, and decision rules in this skill instead of cherry-picking isolated snippets.
- Produce the deliverable with assumptions, risks, and follow-up work made explicit when they matter.
Quality Standards
- Keep outputs execution-oriented, concise, and aligned with the repository's baseline engineering standards.
- Preserve compatibility with existing project conventions unless the skill explicitly requires a stronger standard.
- Prefer deterministic, reviewable steps over vague advice or tool-specific magic.
Anti-Patterns
- Treating examples as copy-paste truth without checking fit, constraints, or failure modes.
- Loading every reference file by default instead of using progressive disclosure.
Outputs
- A concrete result that fits the task: implementation guidance, review findings, architecture decisions, templates, or generated artifacts.
- Clear assumptions, tradeoffs, or unresolved gaps when the task cannot be completed from available context alone.
- References used, companion skills, or follow-up actions when they materially improve execution.
Evidence Produced
| Category | Artifact | Format | Example |
|---|---|---|---|
| Correctness | Maps provider integration test plan | Markdown doc covering markers, info windows, geocoding, and rate-limit handling for Google/Mapbox/MapLibre | docs/gis/provider-tests.md |
| Security | API key handling note | Markdown doc covering provider key storage, referrer restrictions, and quota policies | docs/gis/maps-key-handling.md |
References
- Use the
references/directory for deep detail after reading the core workflow below.
When Leaflet isn't enough — Google Maps for ecosystem + Places + Directions, Mapbox GL for WebGL performance, styling, 3D, and offline.
Prerequisites: Load gis-mapping for the Leaflet baseline and data storage patterns. Load gis-postgis-backend for server-side spatial.
When this skill applies
- Adding a map to a web app where Leaflet doesn't deliver (Places autocomplete, turn-by-turn, Street View, 3D, advanced styling).
- Building property search, store locator, logistics, fleet, or booking flows.
- Replacing a Leaflet map because the feature set is insufficient.
- Keeping Leaflet for basic maps and adding Google/Mapbox for specific features.
Leaflet vs Google Maps vs Mapbox — decision rule
Simple display + markers + basic layers, cost-sensitive -> Leaflet (existing gis-mapping)
Places autocomplete, Google ecosystem, directions with traffic -> Google Maps JS API
Custom styling, 3D buildings, offline on mobile, WebGL perf -> Mapbox GL
Vector tiles you serve yourself (MVT from PostGIS) -> Mapbox GL or MapLibre (OSS Mapbox fork)
Open-source stack preference, no vendor lock-in -> MapLibre
MapLibre GL is the OSS fork of Mapbox GL v1. Same API, no vendor keys, compatible with MVT tiles you host yourself. Strong default for cost-conscious SaaS.
See references/leaflet-vs-google-vs-mapbox.md.
Google Maps JavaScript API setup
Keys and restrictions (do not skip):
1. Create a key per environment (dev, staging, prod).
2. Restrict by HTTP referrer (exact domains).
3. Restrict by API (enable only Maps JS + what you use).
4. Set daily quota caps per key.
5. Budget alerts at 50% and 80% of monthly cap.
Unrestricted keys get abused within hours of exposure. Every public key must be restricted.
Loader (@googlemaps/js-api-loader):
import { Loader } from "@googlemaps/js-api-loader";
const loader = new Loader({
apiKey: import.meta.env.VITE_GMAPS_KEY,
version: "weekly",
libraries: ["places", "geometry"],
});
const { Map, Marker } = await loader.importLibrary("maps");
const map = new Map(el, { center: { lat: 0.3476, lng: 32.5825 }, zoom: 13 });
new Marker({ map, position: { lat: 0.3476, lng: 32.5825 }, title: "Kampala" });
See references/google-maps-setup-keys.md.
Markers, InfoWindows, overlays
- AdvancedMarkerElement — modern replacement for Marker. Full HTML custom styling.
- InfoWindow — popup. Single at a time for accessibility.
- Polyline / Polygon — drawn on top of map.
- Data Layer — load GeoJSON for bulk rendering.
Clustering for >~200 markers (@googlemaps/markerclusterer). Beyond a few thousand, switch to vector tiles.
Places autocomplete
Cost-controlled pattern: debounce input, cache recent results, restrict bounds/country:
const ac = new google.maps.places.Autocomplete(inputEl, {
componentRestrictions: { country: ["ug", "ke", "tz"] },
fields: ["place_id", "formatted_address", "geometry.location"],
types: ["address"],
});
ac.addListener("place_changed", () => {
const p = ac.getPlace();
onAddressSelected({ address: p.formatted_address, lat: p.geometry!.location!.lat(), lng: p.geometry!.location!.lng() });
});
Fields parameter is critical — requesting fields you don't use multiplies cost. See references/google-places-autocomplete.md.
Directions + routes
- Directions API gives JSON; Directions Service renders on the map.
- Modes: driving, walking, bicycling, transit.
- Waypoints can be reordered (
optimizeWaypoints: true). - For turn-by-turn, use Navigation SDK (Android/iOS) or Mapbox.
const service = new google.maps.DirectionsService();
const renderer = new google.maps.DirectionsRenderer({ map });
const result = await service.route({
origin, destination,
travelMode: google.maps.TravelMode.DRIVING,
provideRouteAlternatives: true,
});
renderer.setDirections(result);
See references/google-routing-directions.md.
Styling
- Cloud-based Map Styles (Map IDs) — style in Google Cloud Console, reference by ID. Change style without redeploy.
- In-code JSON styles — legacy, still works. Harder to iterate.
- Pick cloud styles for any serious branding work.
Mapbox GL basics
import mapboxgl from "mapbox-gl";
mapboxgl.accessToken = import.meta.env.VITE_MAPBOX_TOKEN!;
const map = new mapboxgl.Map({
container: "map",
style: "mapbox://styles/mapbox/streets-v12",
center: [32.5825, 0.3476],
zoom: 13,
});
map.on("load", () => {
map.addSource("listings", { type: "vector", url: "https://tiles.example.com/listings.json" });
map.addLayer({
id: "listings-circle",
source: "listings",
"source-layer": "listings",
type: "circle",
paint: { "circle-color": "#E11D48", "circle-radius": 6 },
});
});
Vector tile sources beat raster for zoom and performance. Style with simple expressions; drive layout from data without re-rendering.
See references/mapbox-gl-basics.md.
Mapbox offline (mobile)
Mobile SDKs (iOS/Android) support offline region downloads. Web Mapbox GL does not have native offline but can use service workers to cache tiles.
See references/mapbox-offline.md.
Styling comparison (quick)
| Need | Winner |
|---|---|
| Rapid branded style iteration | Mapbox Studio |
| Minimal setup, Google-native look | Google Maps cloud styles |
| Custom map with 3D buildings | Mapbox GL |
| Free tier for small apps | MapLibre + OSM |
| Turn-by-turn in mobile | Mapbox Navigation SDK or Google Navigation SDK |
Cost control
Track by:
- Per-key quota caps.
- Daily alert thresholds.
- Client-side caching of geocode + places results.
- Server-proxy the API key for server-side calls (hide the key, rate-limit, cache).
- Switch to MapLibre + OSM tiles for open-source cost-free baseline.
Rule: every map provider request costs real money. Review monthly spend; compare to alternatives yearly.
See references/cost-control-quotas.md.
Accessibility
- Map is a decorative image to screen readers by default — not acceptable.
- Provide a text alternative: list of markers, search with autocomplete, address lookup.
- Keyboard navigation: focusable markers, arrow-key pan/zoom, ESC close popup.
- Labels on interactive elements (
aria-label). - Never require drag-to-place without an alternative address input.
- Don't rely solely on colour for differentiation.
See references/a11y-maps.md.
Anti-patterns
- Hardcoding API keys in committed frontend bundles (use env + restrict key).
- Requesting every Places field by default — silent cost multiplier.
- Geocoding repeatedly for the same address — cache it.
- Using raster tiles where a vector tile source would do.
- Cluster markers without clustering at >500 markers.
- No offline plan for mobile.
- No keyboard accessibility.
- Switching providers without an abstraction layer — plan for provider change.
Read next
gis-mapping— Leaflet baseline.gis-postgis-backend— MVT tiles from your own data.gis-enterprise-domain— real-estate and ArcGIS enterprise patterns.
References
references/leaflet-vs-google-vs-mapbox.mdreferences/google-maps-setup-keys.mdreferences/google-places-autocomplete.mdreferences/google-routing-directions.mdreferences/mapbox-gl-basics.mdreferences/mapbox-offline.mdreferences/styling-comparison.mdreferences/cost-control-quotas.mdreferences/a11y-maps.mdreferences/vector-tile-pipeline.md— MVT vs raster decision, tippecanoe flags, zoom strategy, Mapbox GL per-layer performance rules, self-hosted sprites/glyphs
More from peterbamuhigire/skills-web-dev
google-play-store-review
Google Play Store compliance and review readiness for Android apps. Use
77multi-tenant-saas-architecture
Use when designing or reviewing a multi-tenant SaaS platform — tenant
65jetpack-compose-ui
Jetpack Compose UI standards for beautiful, sleek, minimalistic Android
49gis-mapping
Use for web apps that need Leaflet-first GIS mapping, location selection,
49saas-accounting-system
Implement a complete double-entry accounting system inside any SaaS app.
47manual-guide
Generate end-user manuals and reference guides for ERP modules. Use when
39