We built a full navigation app on MapMap
MapMap Nav is a complete turn-by-turn navigation app for iOS and Android, built from one Expo React Native codebase using only our published SDKs and public docs. It is a reference product you can run, test and build your own app on top of. This post is what it does, how it is put together, and where the rough edges still are.
Why build an app instead of writing another feature list
The fastest way to find out whether a routing and maps platform is any good is to ship a real product on it. So we did, as an outside developer would: no private repositories, no internal endpoints, just the SDKs and docs any customer gets. Building MapMap Nav told us exactly where the platform is strong and exactly where it hurts to integrate, and we have been fixing the second list in the open.
The app is twelve screens: onboarding, an explore map, search, route preview, turn-by-turn guidance, arrival, settings, territory management and licences. It is not a proof of concept with three buttons. It is the shape of a product a fleet operator or a consumer nav startup would actually ship.
What is in it
The feature set is what a driver expects from Google or Apple Maps, plus the things only MapMap can do.
- Real maps, your brand. MapMap vector tiles rendered natively with MapLibre, styled with MapMap Studio: 3D buildings, points of interest, a light and dark theme, and your own logo on the map. © OpenStreetMap contributors.
- Turn-by-turn that talks. Road-following routes from our engine, spoken guidance, lane assist, rerouting, a live ETA and a chase camera that tilts into the turn.
- Truck and ADR routing. A lorry profile where vehicle dimensions and a dangerous-goods declaration shape the route, rather than filtering it afterwards.
- Tap to go. Tap anywhere on the map to drop a pin and route there, save Home and Work, avoid tolls, motorways or ferries, and see how far you can reach in 10 or 20 minutes.
- Offline first. Signed, verified territory packages keep navigating with the radios off. Navigation happens on the device, so there is no location trail on a server.
What does the truck profile actually change
A 44-tonne artic that is 4.2 m high does not take the same roads as a car, and MapMap plans for that in the costing, not in a post-filter. The app sends a truck costing with a costing_options.truck block carrying height, weight, length, width and a hazmat flag, plus an ADR tunnel_code when the load is restricted. Low bridges, weight limits and forbidden tunnel categories are avoided while the route is being computed.
curl -X POST https://api.mapmap.ai/route \
-H "Authorization: Bearer snk_..." \
-H "Content-Type: application/json" \
-d '{
"costing": "truck",
"costing_options": { "truck": {
"height": 4.2, "weight": 44, "hazmat": true, "use_tolls": 0
}},
"locations": [
{ "lat": 53.4808, "lon": -2.2426 },
{ "lat": 53.4631, "lon": -2.2913 }
]
}'
The response is Valhalla-shaped: a trip with legs, a summary and turn-by-turn manoeuvres. In our test the toll-avoiding truck route came back with has_toll: false, because the exclusion is applied in costing. This is the differentiator the app leads with, and it is two taps in the UI: pick Lorry, set the vehicle and the ADR category.
How is the app put together
One Expo dev client, one React Native codebase, and a thin native bridge to the platform SDKs. The map is @maplibre/maplibre-react-native drawing MapMap tiles. Everything routing, guidance and territory related goes through a local Expo module, mapmap-react-native, that wraps the native Swift MapMapKit and Kotlin ai.mapmap:core SDKs and exposes one typed surface to JavaScript.
The bridge is the interesting part, because MapMap does not yet ship an official React Native module. We wrote one. It is roughly 2,000 lines of Swift and Kotlin covering territory install and verification, on-device routing, a guidance event stream, and voice. The app talks to it through a single TypeScript contract:
interface MapmapNavModule {
init(apiKey: string, gatewayBaseUrl?: string): Promise<void>;
installTerritory(id: string): Promise<void>;
search(query: string, near?: LatLng): Promise<SearchResult[]>;
computeRoute(req: RouteRequest): Promise<RouteResult>;
startGuidance(opts: GuidanceOptions): Promise<void>;
setVoiceMuted(muted: boolean): Promise<void>;
}
RouteRequest carries the profile (car, bicycle, walking or truck), optional truck dimensions, avoid preferences and waypoints. Guidance arrives as an event stream of banner instructions, snapped position, distance to the next turn and a live ETA. If you are building on React Native, this bridge is the seed of the @mapmap/react-native package we should publish, and you can fork it today.
What it costs
The app runs on the same free tier as everything else: an email-verified key gets 50,000 calls a month. Routing is metered per call, from 0.05p for a standard car request and 1p for truck and ADR. Prices are on /pricing.json and the pricing page, and if this post and /pricing.json ever disagree, /pricing.json is right.
One honest note on maps. Serving interactive vector tiles through a per-call, rate-limited API is not the right model for a busy map, because one map view fetches dozens of tiles at once. For a production app you install a signed offline territory and render locally, which is the design intent and costs nothing per pan. Online tiles are for getting started without a download.
What it does not do yet
We would rather you hear the limits from us than find them mid-integration.
- There is no official React Native module. You write the native bridge, or you reuse the one in this app. Building the official
@mapmap/react-nativeis the single highest-value thing on our list. - iOS distribution needs a helping hand. The SDK is a Swift package. A CocoaPods pod cannot consume a Swift package directly, so an Expo module has to vendor it. A prebuilt
MapMapKit.xcframeworkand a CocoaPods podspec are on the roadmap. - Android is on GitHub Packages. That needs a personal access token today. Maven Central is the next step, so
implementation "ai.mapmap:core"just works. - Signed offline territories are being republished. The rendering tiles are live for online maps now; the signed packages the mobile SDK installs are being rebuilt onto the hosted channel.
None of these are the app's fault, and all of them are packaging rather than capability. The routing, the guidance and the maps work.
Try it
The build guide explains the architecture, the bridge contract and how to run it on a device.
- Read the build guide for the full architecture and the
mapmap-react-nativebridge. - Explore the SDKs and the quickstart to get a key and make your first request.
- Want an internal test build for iOS or Android, or a hand forking it into your own product? Email hello@mapmap.ai.
A competent React Native team could ship a branded navigation app in about a fortnight on top of this. That is the whole point of building it.
