TypeScript Google · Leaflet · MapLibre · Mapbox Zero-config Leaflet & MapLibre

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
Leaflet, MapLibre and Mapbox need their stylesheet. Import it in your app (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

FeatureGoogleLeafletMapLibreMapbox
Markers & popups✅✅✅✅
Polylines✅✅✅✅
Store locator✅✅✅✅
RoutingnativeOSRMOSRMOSRM
Clustering✅✅✅✅
Requires keyAPI 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)