← All @molecule/* packages · App templates

@molecule/app-maps-leaflet

Provider bond · maps · App (browser) · v1.0.1 · Apache-2.0

Leaflet + OpenStreetMap provider for @molecule/app-maps — renders real slippy maps with markers/popups/overlays, no API key (the built-in default draws a grey placeholder)

npm install @molecule/app-maps-leaflet

npm · Source on GitHub · Implements @molecule/app-maps

How it works

@molecule/app-maps-leaflet is a provider bond on the app (browser) side: it implements the maps core interface (@molecule/app-maps) with a concrete vendor or library behind it.

Your code calls the core; you wire this provider once at startup. Swapping vendors later is one line in that wiring, not a rewrite.

// In your app entry, ONCE — REQUIRED: import 'leaflet/dist/leaflet.css'
// (without that CSS the tiles + markers are mispositioned):
import { setProvider, createMap } from '@molecule/app-maps'
import { provider } from '@molecule/app-maps-leaflet'
setProvider(provider)

// then anywhere (the container element needs an explicit height):
const el = document.getElementById('map') as HTMLElement
const map = await createMap({ container: el, center: { lat: 51.5, lng: -0.12 }, zoom: 12 })
map.addMarker({ id: 'a', position: { lat: 51.5, lng: -0.12 }, popup: 'Here' })
// …later, on unmount: map.destroy()

Works with: @molecule/app-maps

Reference

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

@molecule/app-maps-leaflet — a Leaflet-backed provider for @molecule/app-maps. Renders real slippy maps with OpenStreetMap tiles (NO API key). Bond it once at startup and every createMap call shows a real map — the built-in default only paints a grey placeholder panel.

Quick Start

// In your app entry, ONCE — REQUIRED: import 'leaflet/dist/leaflet.css'
// (without that CSS the tiles + markers are mispositioned):
import { setProvider, createMap } from '@molecule/app-maps'
import { provider } from '@molecule/app-maps-leaflet'
setProvider(provider)

// then anywhere (the container element needs an explicit height):
const el = document.getElementById('map') as HTMLElement
const map = await createMap({ container: el, center: { lat: 51.5, lng: -0.12 }, zoom: 12 })
map.addMarker({ id: 'a', position: { lat: 51.5, lng: -0.12 }, popup: 'Here' })
// …later, on unmount: map.destroy()

Type

provider

Installation

npm install @molecule/app-maps-leaflet @molecule/app-maps leaflet
npm install -D @types/leaflet

API

Functions

createProvider()

Creates a Leaflet-backed MapProvider.

function createProvider(): MapProvider

Returns: A MapProvider that renders real OpenStreetMap-tiled maps.

Constants

provider

The default Leaflet map provider, ready to bond with setProvider(provider).

const provider: MapProvider

Core Interface

Implements @molecule/app-maps interface.

Bond Wiring

Setup function to register this provider with the core interface:

import { setProvider } from '@molecule/app-maps'
import { provider } from '@molecule/app-maps-leaflet'

export function setupMapsLeaflet(): void {
  setProvider(provider)
}

Injection Notes

Requirements

Peer dependencies:

  • @molecule/app-maps ^1.0.1

Runtime Dependencies

  • @molecule/app-maps
  • leaflet

TWO gotchas that decide whether the map is visible at all:

  • Import leaflet/dist/leaflet.css once (app entry). Without it, tiles and markers are mispositioned — the #1 "my Leaflet map looks broken" cause.
  • The container needs an explicit height (e.g. style={{ height: 400 }}); a zero-height container renders a blank map.

Markers use a self-contained inline-SVG pin by default (no image-asset wiring — this sidesteps Leaflet's default-icon 404 under bundlers); pass icon for a custom URL. ALWAYS destroy() on unmount — Leaflet attaches DOM + resize listeners, and re-initialising over a live container throws "Map container is already initialized".

getSnapshot() rejects (Leaflet has no built-in export) and getCanvas() returns a best-effort surface — both are WebGL-provider (Mapbox/MapLibre) concepts. Everything else (markers/polylines/polygons/circles/popups/viewport/ fitBounds/project/events) renders for real.

BROWSER-ONLY: draws to the DOM via Leaflet. Import + wire from app/client code.