Store and office locator
A locator is the highest-intent map on any site: somebody is trying to come to you. The usual build pulls in a tiles-and-API-key mapping service, a consent banner and 400 KB of JavaScript for what is, at country scale, seven dots and a list.
The code
import { createGlobe } from "canvas-globe";
const branches = [
{ label: "Ahmedabad", lat: 23.03, lon: 72.58, slug: "ahmedabad", hours: "9-7 Mon-Sat" },
{ label: "Mumbai", lat: 19.08, lon: 72.88, slug: "mumbai", hours: "10-8 daily" },
// …
];
const globe = createGlobe(canvas, {
mode: "map",
preset: "atlas",
projection: "mercator",
autoRotate: false,
center: { lon: 78, lat: 22 },
zoom: 3.4,
zoomable: true,
minZoom: 1,
maxZoom: 8,
markers: branches,
labels: "markers",
tooltip: (m) => `${m.label}: ${m.hours}`,
onClick: (m) => m && selectBranch(m.slug),
onHover: (m) => (canvas.style.cursor = m ? "pointer" : "grab"),
});
// Start where the visitor is. `locateViewer` only resolves the place: // moving the camera is yours to decide.
const place = globe.locateViewer();
if (place) globe.flyTo(place.lon, place.lat, { zoom: 4 });
Mercator, for once
Everywhere else in these docs Mercator gets a warning. Here it is the right answer: at city and regional zoom it preserves local angles and matches the maps most visitors already use. For a locator, that familiarity is more useful than area accuracy over a 500 km view.
Switch to naturalEarth if the locator spans continents.
Starting where they are
locateViewer() resolves the visitor's country and region from their IANA time zone. No
permission prompt, no network request, no consent banner entry, and it always returns something,
which is more than the Geolocation API can promise.
It is accurate to a country, not a street. That is exactly right for choosing an initial view and completely wrong for "your nearest branch is 2.1 km away". For that, ask:
const place = await globe.locateViewer({ precise: true }); // prompts for GPS
if (place) {
const nearest = nearestBranch(place, branches);
globe.flyTo(nearest.lon, nearest.lat, { zoom: 6 });
highlight(nearest);
}
If the visitor declines, the time-zone estimate is kept. Nothing breaks. See Viewer location.
:::caution Never claim precision you do not have A time-zone estimate can be 1,000 km out. The library draws a dashed accuracy circle for exactly this reason: do not remove it and then label the pin "You are here". :::
The list is the real interface
On a phone, nobody finds a branch by pinching a map. They scroll a list. Build the list first and let the map follow it:
<ul>
{branches.map((b) => (
<li key={b.slug}>
<button
onMouseEnter={() => globe.flyTo(b.lon, b.lat, { zoom: 5 })}
onClick={() => (window.location.href = `/stores/${b.slug}`)}
>
<strong>{b.label}</strong>
<span>{b.address}</span>
<span>{b.hours}</span>
</button>
</li>
))}
</ul>
This gets you three things a canvas alone cannot: crawlable addresses, working browser search, and a locator that still functions if the canvas never paints.
Mark the list up with LocalBusiness structured data while you
are there: local SEO cares about the markup, not the map.
Clusters when there are hundreds
For a dealer network or a franchise, turn clustering on and let it collapse by zoom:
{ cluster: true, clusterRadius: 42 }
Markers within clusterRadius screen pixels merge into a counted bubble that splits as you zoom in.
Because clustering happens in screen space, density adapts automatically rather than needing a
per-zoom configuration. See Clustering.
What this is not
Be clear with yourself about the trade:
| Need | This library | A tile map |
|---|---|---|
| Country and regional view | ✅ | ✅ |
| Street-level detail | ❌ | ✅ |
| Turn-by-turn directions | ❌ | ✅ |
| Address search | ❌ (bring your own) | ✅ |
| Works offline, no key, no consent banner | ✅ | ❌ |
If someone needs to see which side of the road the door is on, link out to a mapping service for that one branch. Use this for the overview, which is where 90% of the interactions happen anyway.
<a href={`https://www.google.com/maps/search/?api=1&query=${lat},${lon}`}>Directions</a>
Next
- Clustering: screen-space grouping and drill-down
- Viewer location: time zone, GPS and accuracy
- Projections: when Mercator is and is not the answer