From HERE
HERE is a platform object, a set of JavaScript map classes, and a family of REST APIs (Geocoding & Search v7, Routing v8, Isoline). unmap is one key and three clients. The jobs map cleanly. The object model does not: you will throw away H.Map, H.service.Platform, and the HERE UI toolkit.
Stay on HERE if you need coverage outside Canada, HERE's fleet extras (tolls, live traffic as a product, EV routing), or a map that is not a GL vector map. Truck routing exists on both sides; unmap's truck profile is documented on the Routing API and is only as good as OpenStreetMap's restriction tags.
The map
HERE constructs a Platform, asks it for a default layer, then constructs an H.Map. unmap constructs the map in one call.
const platform = new H.service.Platform({ apikey: "HERE_API_KEY" });
const layers = platform.createDefaultLayers();
const map = new H.Map(document.getElementById("map"), layers.vector.normal.map, {
center: { lat: 51.0447, lng: -114.0719 },
zoom: 11,
});
new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
H.ui.UI.createDefault(map, layers);import { Unmap } from "@unmap/sdk";
const unmap = new Unmap({
key: "um_live_...",
container: "map",
center: [-114.0719, 51.0447],
zoom: 11,
});import { Unmap } from "@unmap/sdk";
const unmap = new Unmap({
key: "um_live_...",
container: "map",
center: [-114.0719, 51.0447],
zoom: 11,
});HERE's vector.normal.map is style: "base". Night and grey layers are mode: "dark" and style: "muted". There is no satellite layer. Zoom and compass land on the map by default; controls: false takes them off.
HERE's JS API takes { lat, lng }. unmap takes [lng, lat]. REST on HERE also tends to write lat,lng (at=51.04,-114.07). Flip both.
Markers
H.map.Marker plus H.ui.InfoBubble become MapLibre Marker and Popup.
const marker = new H.map.Marker({ lat: 51.0447, lng: -114.0719 });
map.addObject(marker);import { maplibregl } from "@unmap/sdk";
new maplibregl.Marker()
.setLngLat([-114.0719, 51.0447])
.setPopup(new maplibregl.Popup().setHTML("<p>Calgary Tower</p>"))
.addTo(unmap.map!);import { Unmap, maplibregl } from "@unmap/sdk";
const unmap = new Unmap({
key: "um_live_...",
container: "map",
center: [-114.0719, 51.0447],
zoom: 11,
});
const [place] = await unmap.geocoder.search("Calgary Tower");
new maplibregl.Marker({ color: "#FF3E9A" })
.setLngLat([place.lng, place.lat])
.setPopup(new maplibregl.Popup().setText(place.name))
.addTo(unmap.map!);map.addObject / map.removeObject become marker.addTo(map) / marker.remove(). A group of markers is a GeoJSON source, not an H.map.Group.
Geocoding and autosuggest
HERE Geocoding & Search v7 (/v1/geocode, /v1/autosuggest, /v1/revgeocode, /v1/browse) become four methods on unmap.geocoder. HERE's at and in are near and bbox, and the coordinate order flips.
const url = new URL("https://geocode.search.hereapi.com/v1/geocode");
url.searchParams.set("q", "Calgary Tower");
url.searchParams.set("apiKey", "HERE_API_KEY");
const data = await (await fetch(url)).json();
const { lat, lng } = data.items[0].position;
map.setCenter({ lat, lng });const results = await unmap.geocoder.search("Calgary Tower");
const [first] = results;
if (first) unmap.map!.setCenter([first.lng, first.lat]);const hints = await unmap.geocoder.autocomplete("calgary tow", { limit: 5 });
const here = await unmap.geocoder.reverse(-114.07, 51.05);
const nearby = await unmap.geocoder.nearby("pharmacy", {
near: [-114.07, 51.05],
radius: 1000,
});import { Unmap } from "@unmap/sdk";
const unmap = new Unmap({ key: "um_live_..." });
const results = await unmap.geocoder.search("Calgary Tower", { limit: 3 });HERE items carry id, title, address, position, and a rich categories / contacts / openingHours block when Discover or Browse hits a POI. unmap results carry id, name, layer, lng, lat, names, and a flat address. There are no contacts, hours, or HERE ids you can round-trip. Browse-by-category is nearby. The Geocoding API is the contract.
Routing and isoline
HERE Routing v8 (/v8/routes) and Isoline become router.route and router.isochrone. HERE's polyline codec goes away: the geometry is GeoJSON.
const url = new URL("https://router.hereapi.com/v8/routes");
url.searchParams.set("origin", "51.0447,-114.0719");
url.searchParams.set("destination", "51.0899,-113.9871");
url.searchParams.set("transportMode", "car");
url.searchParams.set("return", "polyline,summary");
url.searchParams.set("apiKey", "HERE_API_KEY");
const data = await (await fetch(url)).json();const route = await unmap.router.route([-114.0719, 51.0447], [-113.9871, 51.0899], {
mode: "auto",
});
unmap.map!.addSource("route", {
type: "geojson",
data: { type: "Feature", properties: {}, geometry: route.geometry },
});
unmap.map!.addLayer({
id: "route",
type: "line",
source: "route",
paint: { "line-color": "#3887be", "line-width": 4 },
});import { Unmap } from "@unmap/sdk";
const unmap = new Unmap({
key: "um_live_...",
container: "map",
center: [-114.03, 51.07],
zoom: 11,
});
const route = await unmap.router.route([-114.0719, 51.0447], [-113.9871, 51.0899], { mode: "auto" });
unmap.map!.on("load", () => {
unmap.map!.addSource("route", {
type: "geojson",
data: { type: "Feature", properties: {}, geometry: route.geometry },
});
unmap.map!.addLayer({
id: "route-line",
type: "line",
source: "route",
layout: { "line-cap": "round", "line-join": "round" },
paint: { "line-color": "#FF3E9A", "line-width": 3 },
});
});transportMode=car is auto. pedestrian and bicycle keep those names. truck takes a vehicle profile in metres and tonnes (height, width, length, weight, …), not HERE's truck[grossWeight] kilograms. There are no via points, no return=polyline to request, and no flexible-polyline to decode.
Isoline is the same idea as HERE's Isoline API, with a smaller surface: up to four contours, 120 minutes each.
const bands = await unmap.router.isochrone([-114.07, 51.05], {
minutes: [10, 20],
mode: "auto",
});What has no equivalent
- Coverage outside Canada.
- Live traffic as a product, tolls, EV, and public transit. Truck exists; it is OSM tags, not a permit check.
- HERE identifiers, contacts, opening hours, and Place photos.
- The HERE UI toolkit and
H.service.Platform. - Waypoint routing, matrix routing, and fleet telematics.
- Satellite imagery.
Checklist
- HERE API key replaced with
um_live_.../um_test_... -
{ lat, lng }andlat,lngquery params flipped to[lng, lat] -
H.Mapreplaced withnew Unmap({ container, ... }) - Geocode, autosuggest, revgeocode, and browse pointed at
unmap.geocoder - Routing v8 and Isoline pointed at
unmap.router, with the line drawn as GeoJSON - Flexible-polyline decoding deleted
- Fleet-only features either dropped or left on HERE
- Origin configured for production traffic (Plans & Limits)
The Quickstart is the same map built from scratch. Truck defaults and the limits of the OSM restriction data are on the Routing API.