Store Locator finds the nearest branch of a retail network. Search a city, postal code or address and the branches are ranked by real driving or walking time, with the straight-line distance beside it; pick one for its hours, turn-by-turn directions and the area you can reach from it in 10 or 20 minutes. It runs at apps.unmap.dev/store-locator, and its source is a standalone Next.js project you can clone and run with your own key.
The stores belong to Prairie Lantern Co., a fictional retailer with 20 branches placed at approximate points in real Calgary neighbourhoods. Every name, address, phone number, opening hour and service is sample data, and the app labels it as such wherever it appears. The map, the search, the travel times and the routes are live unmap. Replace the sample with your own stores and it is your locator.
What it does
- Search for a city, postal code or address, leaning towards Calgary, in English or French. Or use your location: the browser's geolocation, never stored.
- Rank by travel time, driving or walking, from one matrix request per 10 branches, sent together. The top of the order is badged "Closest". Ranking by distance is also there, worked out in the browser and labelled "in a straight line".
- Directions to a branch: time and distance, turn-by-turn steps in English or French, and any warning the API attaches, such as an endpoint moved to the nearest road. Hovering a step highlights its stretch of the route.
- Reachable area: 10- and 20-minute bands around a branch, by car or on foot.
- Branch details: address, phone, this week's hours with today marked, services, and whether it is open now. The list filters by service.
- Load your stores: open a GeoJSON file of your own. It is read and checked in your browser, labelled "Your file", and never uploaded.
Requests only when you act
Store Locator calls the API when you search, change the mode or press a branch's buttons, never when you move the map. A request that a newer one replaces is cancelled, and the app's browser tests fail if the same call is made twice.
Every failure is shown where its answer would have been, in English or French, with the gateway's own message and a retry when waiting could help. A branch the matrix has no time for says "No travel time", with a note that this is not proof there is no road. Where a deployment has the matrix switched off, the list falls back to straight-line order.
Built from the registry, unmodified
The map, the search box, the branch clusters, the popups, the route line and the steps are registry items copied in unmodified, and the app's own code calls the API only through @unmap/sdk. Installing the same pieces into your project is one command:
npx @unmap/cli add map geocoder cluster-layer marker-popup route-line route-steps geojson-layer map-controlsThe URL is the state
The search, the chosen branch, the travel mode, the sort and the language live in the query string (?from=&label=&store=&mode=&sort=&lang=), so a link reopens the same list and the same branch.
What it does not show
- Real business details. unmap does not supply store names, hours, phone numbers or services, so those are the sample. "Open" and "closed" are worked out in your browser from the sample hours, with no holiday hours.
- Live traffic. Travel times come from the road network without live traffic: they are typical, not current.
- Accounts, bookings and store management. It is a locator, not a store back office.
Search and routing cover Canada.
Run it yourself
You need Git, Node.js 24, pnpm and a browser key from the dashboard that allows http://localhost:3201.
git clone --depth 1 https://github.com/unmap-dev/store-locator.git
cd store-locator
pnpm install --frozen-lockfile
cp .env.example .env.localSet NEXT_PUBLIC_UNMAP_KEY in .env.local to your key, run pnpm dev, and open localhost:3201. Start by replacing data/stores.sample.json with your own stores: parseStores() in lib/stores.ts checks the file and lists every problem it finds, and STORE_TIME_ZONE sets the time zone your hours are in. The store locator tutorial builds the core of it step by step, and the Routing API reference covers the matrix behind the ranking.