@minmaps-dev/mm-web-sdk
v1.0.0-rc.26
Published
MinuteMaps indoor mapping SDK for MapLibre GL - render venues, floors, POIs, and wayfinding routes
Downloads
1,895
Readme
MinuteMaps Web SDK
Render indoor venues — floors, POIs, amenities, destinations, and wayfinding routes — on top of MapLibre GL JS.
@minmaps-dev/mm-web-sdk is the official MinuteMaps SDK for the web. It loads venues from JACS, manages floors, POIs, amenities, destinations, and the camera, and gives you a small, well-typed surface for building modern kiosks and indoor mapping web apps.
npm install @minmaps-dev/mm-web-sdk maplibre-gl @turf/turfimport { MinuteMaps } from '@minmaps-dev/mm-web-sdk'
import 'maplibre-gl/dist/maplibre-gl.css'
const sdk = new MinuteMaps({
container: 'map',
jmap: { host: '', customerId: 123, venueId: 456 },
jacs: { mode: 'proxy', proxyBaseUrl: '/api/jacs' },
options: { styleMode: 'sdkTemplate' },
})
sdk.on('ready', ({ venue }) => console.log('venue ready', venue?.name))
await sdk.init()Status
This SDK is on a pre-1.0 release candidate (1.0.0-rc.24). A few capabilities remain dormant pending backend support — they are not yet functional in the published build:
| Area | Status | Notes |
| --- | --- | --- |
| Floors, POIs, amenities, destinations | ✅ Shipped | Loads via JACS building/full + venue/full. |
| Camera + view modes (3D/2D/flat) | ✅ Shipped | Style toggles work against the bundled alt3-hybrid-style.json. |
| Wayfinding | ✅ Shipped | Built-in JACS path-graph routing (rc.18). JacsWayfindingProvider is wired by default; route computation runs inside the SDK (src/data/wayfinding/). No provider injection needed. |
| Contextual map APIs | ✅ Shipped | highlightPOI/highlightAmenity/clearHighlight, setPOIFilter/clearPOIFilter, amenities.getDistinct, findClosestWaypoint, searchAllPOIs, navigateFromKioskToPOI, refit. See docs/API.md#contextual-map. |
| Venue-served stylesheets | 🚧 Roadmap | SDK currently uses its bundled style; loadAndPatchVenueStyle() is bypassed. |
| Polygon layers + 3D map templates | 🚧 Roadmap | buildPolygonLayers / applyMapTemplate3d imports are commented in src/sdk.ts. |
Track re-enable points by grepping // TODO: Re-enable in src/sdk.ts and src/data/jacsDataProvider.ts.
What's in the box
- Venue + floors — load a venue by
customerId/venueId, switch active floor, let the SDK manage layer visibility. - POIs, amenities, destinations — query by floor, run keyword searches, find the kiosk's "You are here" location.
- View modes — toggle 3D extrusion, flat (top-down), and 2D-units modes at runtime.
- Camera control —
setView/resetView/getCameraPosition, plus a livecameraChangeevent for compass UIs. - React entrypoint — drop-in
<MinuteMapsView />for React 18/19. - JACS proxy or direct mode — keep credentials server-side (recommended) or call JACS directly from trusted environments.
Documentation
The lean root README intentionally stops here. For depth, see:
docs/ARCHITECTURE.md— module map, init flow, JACS data path, style patching, dormant 3D notes.docs/API.md— full public API surface grouped by lifecycle, floors, POIs, amenities, wayfinding, camera, events.docs/KIOSK.md— kiosk integration patterns (You-Are-Here, kiosk-to-destination wayfinding once enabled, view-mode UX, sprite hosting, idle reset).
External integrators will usually only need the API and Kiosk docs. Internal MTS engineers should also read Architecture before touching src/sdk.ts or the JACS provider.
Quick start (vanilla)
import { MinuteMaps } from '@minmaps-dev/mm-web-sdk'
import 'maplibre-gl/dist/maplibre-gl.css'
const sdk = new MinuteMaps({
container: 'map', // element or element id
jmap: {
host: '', // unused in proxy mode
customerId: 123,
venueId: 456,
},
jacs: {
mode: 'proxy', // recommended for browser apps
proxyBaseUrl: '/api/jacs',
},
options: {
customSprite: '/sprites/sprite', // your icon sprite (no extension)
minIndoorZoom: 16,
debug: true,
styleMode: 'sdkTemplate',
},
})
sdk.on('ready', ({ venue }) => console.log('venue ready', venue?.name))
sdk.on('floorChanged', ({ floor }) => console.log('now showing', floor?.name))
await sdk.init()Quick start (React)
import { MinuteMapsView } from '@minmaps-dev/mm-web-sdk/react'
import 'maplibre-gl/dist/maplibre-gl.css'
export function Map() {
return (
<MinuteMapsView
className="h-screen w-screen"
config={{
container: '', // ignored — the component owns the element
jmap: { host: '', customerId: 123, venueId: 456 },
jacs: { mode: 'proxy', proxyBaseUrl: '/api/jacs' },
options: { styleMode: 'sdkTemplate' },
}}
/>
)
}The React entry is intentionally minimal: it owns its own <div>, calls init() on mount, and destroy() on unmount. Reach for the vanilla MinuteMaps class when you need imperative control (floor switching from a side panel, camera animations driven by Redux, etc.).
Configuration at a glance
type SDKConfig = {
container: HTMLElement | string
jmap: {
host: string
customerId: number
venueId: number
locale?: string
auth?: { clientId: string; clientSecret: string }
}
jacs: {
mode: 'proxy' | 'direct'
host?: string // 'direct' only
auth?: { clientId: string; username: string; password: string } // 'direct' only
proxyBaseUrl?: string // default '/api/jacs'
}
options?: SDKOptions
}Full option reference and an annotated SDKOptions shape live in docs/API.md.
JACS proxy mode (recommended)
Browser apps should use mode: 'proxy' and forward requests through your own server so JACS credentials never reach the client. Your proxy should:
- Read
JACS_HOST,JACS_CLIENT_ID,JACS_USERNAME,JACS_PASSWORDfrom server env. - Exchange the password grant for a bearer token (cache until expiry).
- Forward
GET /api/jacs/<path>to${JACS_HOST}/JACS/api/<path>with the token attached.
A reference Next.js route handler ships in the example app at apps/example/app/api/jacs/[...path]/route.ts. Copy it into your own backend or adapt it to your framework, then point jacs.proxyBaseUrl at it.
JACS direct mode
For trusted environments — server-rendered pages, Electron kiosks, internal tools — call JACS directly:
jacs: {
mode: 'direct',
host: 'https://jacs.example.com',
auth: { clientId, username, password },
}⚠ Never ship
directmode to a public browser bundle. Your JACS credentials would be visible to anyone with devtools.
Sprites
options.customSprite is a sprite URL prefix without extension — MapLibre appends .json and .png (and @2x variants) automatically. The example app serves its sprite from apps/example/public/sprites/.
Development
Run commands from the monorepo root through pnpm/turbo (install pnpm via npm, not corepack):
pnpm install # once, at the root — one lockfile for the whole monorepo
pnpm dev # turbo: SDK rollup --watch + example next dev together
pnpm build # turbo: production build of all packages
pnpm typecheck # turbo: tsc --noEmit
pnpm test # turbo: vitest runSDK-only build: pnpm --filter @minmaps-dev/mm-web-sdk build. Per-package scripts (dev:sdk, test:watch, test:coverage) still exist and can be run with pnpm --filter @minmaps-dev/mm-web-sdk <script>.
The build emits ESM, CJS, and types under dist/ for both the root entry and the /react entry. Tests live in tests/ and target the three highest-leverage modules: JacsProvider, WayfindingManager, and ViewModeController. Coverage thresholds are gated in vitest.config.ts (currently 60% lines/funcs/stmts, 50% branches).
Continuous integration
CI lives at the monorepo root in .github/workflows/:
ci.yml— runs typecheck, vitest with coverage, and the production build on every push and pull request tomain/dev.release.yml— Changesets-driven releases. Write a changeset, merge tomain, and a "Version Packages" PR is opened; merging it runschangeset publishto npm (accesspublic). There is no tag-based publish workflow and no provenance flag.deploy-example.yml— deploys the example app.
Internal note: future Claude sessions get oriented from
CLAUDE.md. Subagents at the monorepo-root.claude/agents/cover API doc sync, release notes, and style/template edits.
Browser + framework support
| Target | Version |
| --- | --- |
| Node (build/dev) | ≥ 18 |
| maplibre-gl | ^4 |
| @turf/turf | ^7 |
| react / react-dom | ^18 or ^19 (only required for /react entry) |
Modern evergreen browsers. Kiosk targets are typically pinned Chromium builds — if you need to support a specific minimum, open an issue.
License
MIT — see LICENSE.
