maps-geolocation
Build location-based features with mapping APIs. Use when a user asks to integrate Google Maps, Mapbox, or Leaflet, implement geocoding and reverse geocoding, calculate routes and distances, build store locators, add interactive maps to web apps, implement geofencing, work with GeoJSON, build delivery tracking systems, optimize routes for fleets, display heatmaps, implement address autocomplete, or build any location-aware application. Covers Google Maps Platform, Mapbox, Leaflet, and OpenStreetMap/Nominatim.
What this skill does
# Maps & Geolocation ## Overview Build location-based applications using mapping and geolocation APIs. This skill covers four major platforms — Google Maps Platform, Mapbox, Leaflet (open-source), and OpenStreetMap/Nominatim (free) — for geocoding, routing, interactive maps, geofencing, heatmaps, store locators, fleet tracking, and address autocomplete. Choose based on budget: Google Maps for full-featured commercial use, Mapbox for custom styling, Leaflet+OSM for zero-cost self-hosted solutions. ## Instructions ### Step 1: Platform Selection & Setup **Google Maps Platform** ($200/month free credit): ```bash # Enable: Maps JS API, Geocoding API, Directions API, Places API, Distance Matrix API export GOOGLE_MAPS_API_KEY="AIzaSy..." ``` **Mapbox** (50,000 free map loads/month): ```bash export MAPBOX_ACCESS_TOKEN="pk.eyJ1..." ``` **Leaflet + OpenStreetMap** (completely free, no API key): ```html <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" /> <script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script> ``` **Nominatim** (free geocoding, 1 req/sec rate limit, no key needed). ### Step 2: Geocoding & Reverse Geocoding ```typescript // Google Geocoding async function geocode(address: string) { const res = await fetch( `https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent(address)}&key=${API_KEY}` ); const data = await res.json(); const r = data.results[0]; return { lat: r.geometry.location.lat, lng: r.geometry.location.lng, formatted: r.formatted_address }; } // Nominatim (free, no key — requires User-Agent header per TOS) async function nominatimGeocode(query: string) { const res = await fetch( `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(query)}&format=json&limit=5`, { headers: { "User-Agent": "MyApp/1.0 ([email protected])" } } ); return res.json(); } // Batch geocoding with rate limiting async function batchGeocode(addresses: string[], delayMs = 100) { const results = []; for (const addr of addresses) { try { results.push({ address: addr, ...await geocode(addr) }); } catch (err) { results.push({ address: addr, lat: null, lng: null, error: err.message }); } await new Promise(r => setTimeout(r, delayMs)); } return results; } ``` ### Step 3: Interactive Maps **Leaflet + OpenStreetMap (free):** ```javascript const map = L.map("map").setView([48.8566, 2.3522], 12); L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { attribution: '© OpenStreetMap contributors', }).addTo(map); L.marker([48.8584, 2.2945]).addTo(map) .bindPopup("<b>Eiffel Tower</b><br>Paris, France").openPopup(); // Load GeoJSON layer fetch("/data/zones.geojson").then(r => r.json()).then(data => { L.geoJSON(data, { style: { color: "#ef4444", weight: 2, fillOpacity: 0.1 }, onEachFeature: (feature, layer) => layer.bindPopup(feature.properties.name), }).addTo(map); }); ``` **Mapbox GL JS** (vector tiles, custom styles): ```javascript mapboxgl.accessToken = "pk.eyJ1..."; const map = new mapboxgl.Map({ container: "map", style: "mapbox://styles/mapbox/streets-v12", center: [2.3522, 48.8566], zoom: 12, }); new mapboxgl.Marker({ color: "#ef4444" }) .setLngLat([2.2945, 48.8584]) .setPopup(new mapboxgl.Popup().setHTML("<h3>Eiffel Tower</h3>")) .addTo(map); map.addControl(new mapboxgl.NavigationControl()); ``` ### Step 4: Routing & Distance Matrix ```typescript // Google Directions async function getRoute(origin: string, destination: string, mode = "driving") { const res = await fetch( `https://maps.googleapis.com/maps/api/directions/json?origin=${encodeURIComponent(origin)}&destination=${encodeURIComponent(destination)}&mode=${mode}&key=${API_KEY}` ); const data = await res.json(); const leg = data.routes[0].legs[0]; return { distance: leg.distance.text, duration: leg.duration.text, polyline: data.routes[0].overview_polyline.points }; } // Distance Matrix (many-to-many) async function distanceMatrix(origins: string[], destinations: string[]) { const res = await fetch( `https://maps.googleapis.com/maps/api/distancematrix/json?origins=${origins.map(encodeURIComponent).join("|")}&destinations=${destinations.map(encodeURIComponent).join("|")}&key=${API_KEY}` ); return res.json(); } // OSRM (free, no key) async function osrmRoute(coords: [number, number][]) { const wp = coords.map(c => c.join(",")).join(";"); const res = await fetch(`https://router.project-osrm.org/route/v1/driving/${wp}?overview=full&geometries=geojson`); const data = await res.json(); return { distance: data.routes[0].distance, duration: data.routes[0].duration, geometry: data.routes[0].geometry }; } ``` ### Step 5: Geofencing & Utilities ```typescript // Haversine distance (meters) function haversineDistance(lat1: number, lng1: number, lat2: number, lng2: number): number { const R = 6371000; const dLat = ((lat2 - lat1) * Math.PI) / 180; const dLng = ((lng2 - lng1) * Math.PI) / 180; const a = Math.sin(dLat / 2) ** 2 + Math.cos((lat1 * Math.PI) / 180) * Math.cos((lat2 * Math.PI) / 180) * Math.sin(dLng / 2) ** 2; return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); } // Point-in-polygon check function pointInPolygon(point: [number, number], polygon: [number, number][]): boolean { const [x, y] = point; let inside = false; for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) { const [xi, yi] = polygon[i], [xj, yj] = polygon[j]; if ((yi > y) !== (yj > y) && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi) inside = !inside; } return inside; } // Circular geofence check function isInRadius(point: [number, number], center: [number, number], radiusMeters: number): boolean { return haversineDistance(point[0], point[1], center[0], center[1]) <= radiusMeters; } ``` ### Step 6: Store Locator & Route Optimization **Nearby search with PostGIS:** ```sql SELECT id, name, address, lat, lng, ST_DistanceSphere(ST_MakePoint(lng, lat), ST_MakePoint($1, $2)) AS distance_meters FROM stores WHERE ST_DWithin(ST_MakePoint(lng, lat)::geography, ST_MakePoint($1, $2)::geography, $3) ORDER BY distance_meters LIMIT $4; ``` **Route optimization** (Google Directions with waypoint reordering): ```typescript async function optimizeRoute(origin: string, destination: string, waypoints: string[]) { const res = await fetch( `https://maps.googleapis.com/maps/api/directions/json?origin=${encodeURIComponent(origin)}&destination=${encodeURIComponent(destination)}&waypoints=optimize:true|${waypoints.map(encodeURIComponent).join("|")}&key=${API_KEY}` ); const route = (await res.json()).routes[0]; return { optimizedOrder: route.waypoint_order, totalDistance: route.legs.reduce((s: number, l: any) => s + l.distance.value, 0), totalDuration: route.legs.reduce((s: number, l: any) => s + l.duration.value, 0), }; } ``` ## Examples ### Example 1: Store locator with address search for a coffee chain **User prompt:** "Build a store locator for our coffee shops. The user types an address, we geocode it, find the 5 nearest stores within 10km from our PostgreSQL database, and display them on a Leaflet map with distance labels." The agent will create a geocoding function using Google Geocoding API (or Nominatim for free) to convert the user's address input to coordinates. It will write a PostGIS SQL query using `ST_DWithin` to find the 5 nearest stores within 10,000 meters, returning name, address, coordinates, and distance. On the frontend, it will initialize a Leaflet map centered on the searched location, add a marker for each store with a popup showing name, address, and distance in km, and fit the map bounds to show all results. ### Example 2: Delivery fleet route optimization with geofence alerts **User prompt:** "Optimize the delivery route for a driver starting from our Berlin warehouse with 6 drop-off addresses, then set up a 200m geofence around each stop that log
Related in Data & Analytics
clawarr-suite
IncludedComprehensive management for self-hosted media stacks (Sonarr, Radarr, Lidarr, Readarr, Prowlarr, Bazarr, Overseerr, Plex, Tautulli, SABnzbd, Recyclarr, Unpackerr, Notifiarr, Maintainerr, Kometa, FlareSolverr). Deep library exploration, analytics, dashboard generation, content management, request handling, subtitle management, indexer control, download monitoring, quality profile sync, library cleanup automation, notification routing, collection/overlay management, and media tracker integration (Trakt, Letterboxd, Simkl).
querying-soql
IncludedSOQL query generation, optimization, and analysis with 100-point scoring. Use this skill when the user needs SOQL/SOSL authoring or optimization: natural-language-to-query generation, relationship queries, aggregates, query-plan analysis, and performance or safety improvements for Salesforce queries. TRIGGER when: user writes, optimizes, or debugs SOQL/SOSL queries, touches .soql files, or asks about relationship queries, aggregates, or query performance. DO NOT TRIGGER when: bulk data operations (use handling-sf-data), Apex DML logic (use generating-apex), or report/dashboard queries.
app-store-optimization
IncludedApp Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklists, and tracking ranking changes.
habit-flow
IncludedAI-powered atomic habit tracker with natural language logging, streak tracking, smart reminders, and coaching. Use for creating habits, logging completions naturally ("I meditated today"), viewing progress, and getting personalized coaching.
app-store-optimization
IncludedApp Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklists, and tracking ranking changes.
visualizing-data
IncludedBuilds dashboards, reports, and data-driven interfaces requiring charts, graphs, or visual analytics. Provides systematic framework for selecting appropriate visualizations based on data characteristics and analytical purpose. Includes 24+ visualization types organized by purpose (trends, comparisons, distributions, relationships, flows, hierarchies, geospatial), accessibility patterns (WCAG 2.1 AA compliance), colorblind-safe palettes, and performance optimization strategies. Use when creating visualizations, choosing chart types, displaying data graphically, or designing data interfaces.