One API for every map
Display and customize markers, popups, store locators, routes and clustering on top of the map client of your choice. Switch providers by changing one option — your code stays the same.
npm install map-trix
npm install leaflet # or maplibre-gl / mapbox-gl
Why map-trix
A thin, typed abstraction (Facade + Adapter) over the map libraries you already know.
Provider-agnostic
The same API on Google, Leaflet, MapLibre and Mapbox. Migrate or A/B test without rewriting.
Batteries included
Markers, popups, polylines, store locator, routing and clustering out of the box.
Lazy & light
SDKs are optional peer dependencies, loaded on demand. You only ship what you use.
Typed & escape-hatched
Full TypeScript types, plus access to the native map object whenever you need it.
Live demo
Pick a provider and try the features. Leaflet and MapLibre need no key; Google and Mapbox ask for your own key/token (used only in your browser).
Quick start
Create a map, add a marker, fit the view. Coordinates accept { lat, lng }, { latitude, longitude } or [lng, lat].
import { createMap } from 'map-trix'
const map = await createMap({
provider: 'leaflet', // 'google' | 'leaflet' | 'maplibre' | 'mapbox'
container: '#map',
center: { lat: 48.8566, lng: 2.3522 },
zoom: 12,
// apiKey: '…' // Google
// accessToken: '…' // Mapbox
})
const marker = map.addMarker({
position: { lat: 48.8584, lng: 2.2945 },
popup: 'Eiffel Tower',
data: { id: 1 },
})
map.fitBounds() // fit to all markers
import 'leaflet/dist/leaflet.css') or let the provider inject it:
createMap({ provider: 'leaflet', css: true, … }).Per-provider entry points
Import a provider explicitly for full control over bundling.
import { createMap } from 'map-trix'
import MapLibreProvider from 'map-trix/maplibre'
const map = await createMap({ provider: new MapLibreProvider(), container: '#map' })
Markers & popups
const m = map.addMarker({
position: [2.2945, 48.8584], // [lng, lat]
title: 'HQ',
icon: { url: '/pin.png', size: [32, 32], anchor: [16, 32] },
popup: { content: 'Hello', maxWidth: 240 },
openPopupOnClick: true, // default when popup is set
})
m.on('click', (e) => console.log(e.position))
m.openPopup()
map.removeMarker(m)
map.clearMarkers()
Store locator
A provider-agnostic helper for “find the nearest store” experiences — built on markers and haversine distance.
import { StoreLocator } from 'map-trix'
const locator = new StoreLocator(map, {
locations: stores, // [{ position, popup, data }, …]
onSelect: ({ location }) => console.log('picked', location.data),
})
const nearest = locator.findNearest({ lat: 48.86, lng: 2.35 }, 3)
locator.filter((s) => s.data.open) // show a subset
const me = await locator.locateUser() // browser geolocation
Routing
Native directions on Google, OSRM elsewhere. Draws the route and returns a normalized result.
const route = await map.traceDirection(
{ lat: 48.8584, lng: 2.2945 },
{ lat: 48.8530, lng: 2.3499 },
'driving', // 'driving' | 'walking' | 'cycling' | 'transit'
)
console.log(route.distance, route.duration, route.geometry)
// Point routing at your own OSRM server:
map.setRoutingOptions({ osrmEndpoint: 'https://my-osrm.example.com' })
Clustering
One call, per-provider implementation (MarkerClusterer, leaflet.markercluster, or native GL clustering).
await map.enableClustering({ radius: 60 })
map.disableClustering()
Providers at a glance
| Feature | Leaflet | MapLibre | Mapbox | |
|---|---|---|---|---|
| Markers & popups | ✅ | ✅ | ✅ | ✅ |
| Polylines | ✅ | ✅ | ✅ | ✅ |
| Store locator | ✅ | ✅ | ✅ | ✅ |
| Routing | native | OSRM | OSRM | OSRM |
| Clustering | ✅ | ✅ | ✅ | ✅ |
| Requires key | API key | – | – | token |
API reference
createMap(options)
provider, container, center, zoom, minZoom, maxZoom, style, apiKey, accessToken, osrmEndpoint, providerOptions.
MapTrix
addMarker, removeMarker, clearMarkers, getMarkers, fitBounds, setCenter, getCenter, setZoom, getZoom, addPolyline, on, traceDirection, enableClustering, getProvider, getNativeMap, destroy.
Escape hatch
map.getNativeMap() // native Map instance
marker.getNative() // native marker
map.getProvider().capabilities
Legacy (Google, pre-2.0)
import { createMapTrix } from 'map-trix'
const mt = await createMapTrix(API_KEY, { language: 'fr' })
mt.init('#map')
mt.addMarker({ latitude: 48.8584, longitude: 2.2945, content: 'Hi' }, true)