essence.js calls each Basic's init then fina in a fixed order, with L_ acting as the ambient bus that ties imperative jQuery code, React islands, and the embed API together.
The deck.gl path in Map_ is partial — a scattering of `engineType !== LEAFLET` early-exits mark methods that haven't been ported yet, so a feature that works on Leaflet may silently no-op on deck.gl.
The core runtime is the spine of the frontend. Everything else — tools, ancillary
chrome, the embed API — hangs off the singletons defined here. All of it lives in
src/essence/Basics/.
Boot sequence
src/essence/essence.js
is the single composition root. It imports each Basic as an ES module default and
calls them in a fixed order on essence.init(config):
L_.init(config, missionsList, urlOnLayers)— parses the mission config into layer state.F_.setRadius(...)— sets planet radii used by all distance/projection math.Globe_.init(),Viewer_.init(),TimeControl.init(), thenMap_.init(fina).Map_.initinvokes thefinacallback once the map is ready, which callsfina()onGlobe_,L_,UserInterface_,Viewer_,TimeControl, and themmgisAPI_in that order, then runsComponentController_.initializeComponents().
init and fina are the two-phase pattern most engine and controller Basics
implement (F_ is a pure-function grab-bag with neither, and Map_.init is
itself the trigger that runs everyone else's fina): init constructs DOM and
reads config, fina wires cross-references between modules once they all exist. essence.swapMission re-runs init with swapping=true to
hot-reload a different mission without a page refresh — L_.clear() resets state,
the engines are recreated, and the UI re-finalizes.
L_: the global map state
Basics/Layers_/Layers_.js
exports the singleton L_ (mission name, view, radius, the full configData,
the layer registry, plus references back to Map_/Globe_/Viewer_). It is the
ambient bus that ties the imperative jQuery code, the React islands under
Tools/, and the embed API together. Anything that
needs to know which layers exist, which are toggled on, what filters are applied,
or which feature is active reads L_. The layers sub-object is normalized:
layers: {
data: {}, // uuid -> layer config
dataFlat: [], // ordered list
layer: {}, // uuid -> live engine layer object
on: {}, // uuid -> visible bool
opacity: {},
filters: {},
nameToUUID: {},
refreshIntervals: {},
}
L_.onceLoaded(cb) is how late-arriving code (tools, components) defers work
until the initial mission load finishes.
Map_, Globe_, Viewer_
The three viewports are independent modules that share L_ but otherwise know
little about each other:
Basics/Map_/Map_.jsis the 2D map. Historically Leaflet-only; now an engine-agnostic facade (see below).Basics/Globe_/Globe_.jsis the 3D viewport. It delegates toGlobeRenderer.js(a Cesium/THREE-based lithosphere renderer) and is driven from the sameL_.viewand tile-map resource as the 2D map.Basics/Viewer_/Viewer_.jsis the third "image viewer" pane — Leaflet-on-image for raster imagery, a THREE-based Photosphere, ModelViewer, and PDFViewer for 3D/document content attached to features.
The map engine abstraction
A 2024–25 refactor moved behind a swappable engine interface in
Basics/MapEngines/.
IMapEngine (IMapEngine.ts) defines an imperative facade — setView,
fitBounds, addLayer, on, queryRenderedFeatures, etc. — that two adapters
implement: LeafletAdapter (the historical Leaflet 1.x map) and DeckGLAdapter
(deck.gl with a MapLibre/Mapbox basemap). MapEngineRegistry.ts is a small
registry that owns adapter classes and the active instance. Map_.init reads
L_.configData.msv.mapEngine, asks the registry for that engine, and assigns it
to Map_.engine. Map_.map still points at the native L.Map for
backwards-compatible callers, with a thin shim layer for deck.gl:
mapEngineRegistry.register(MAP_ENGINE.LEAFLET, LeafletAdapter)
mapEngineRegistry.register(MAP_ENGINE.DECKGL, DeckGLAdapter)
const engine = mapEngineRegistry.createEngine(engineType)
this.engine = engine
this.map = engine.getNativeMap() ?? {}
ENGINE_LAYER_SUPPORT in types/engine.ts declares which LayerTypes each
engine can render; engineSupportsLayer() is consulted by layer construction to
skip incompatible layers. A scattering of if (Map_.engine.engineType !== LEAFLET) return early-exits inside Map_.js mark the methods that haven't been ported
to the deck.gl path yet — the migration is in flight.
Panel layout
The three viewports live inside a horizontal split managed by
Basics/UserInterface_/.
UserInterface_.js selects UserInterfaceMobile_ or UserInterfaceDefault_ at
load based on user agent. The default UI tracks pxIsViewer / pxIsMap /
pxIsGlobe pixel widths and exposes getPanelPercents() /
setPanelPercents(viewer, map, globe) (must sum to 100) which most other code —
the splitter drag handlers, QueryURL, the "open globe" buttons — calls to
resize panes. Opening the Globe pane for the first time syncs its center to the
2D map.
A newer typed panel system lives at Basics/PanelManager_/types/ (priority-based
layout with iconified/focused/expanded states for left/right/top/bottom panels).
This is a forward-looking spec that the tools layer is migrating
toward; the runtime panel layout is still the legacy three-pane split.
ToolController_, ComponentController_, TimeControl_
ToolController_.init(L_.tools) builds the tool sidebar from the mission's
configured tool list and lazy-loads each tool module from
pre/tools.js
(the build-time glob over Tools/ plus plugin dirs). It owns activeTool,
opens/closes the tool panel, and dispatches keyboard shortcuts. See
mapping tools for the per-tool shape.
ComponentController_ is the smaller sibling for non-tool plugins — analytics,
keybindings, background services. It runs once after fina(), iterates
L_.configData.components, and calls each enabled component's init(vars) with
errors caught individually so one bad component cannot brick the page.
TimeControl_ (under Basics/TimeControl_/) implements MMGIS's global time
window. When config.time.enabled is true it stands up the bottom time bar
(TimeUI), filters layers by their per-layer time settings, and registers
time:getCurrent/time:set providers on the mmgisAPI bus.
Formulae_
Basics/Formulae_/Formulae_.js
is F_ — the dumping ground for shared math: planet-radius math, lat/lng
distance and bearing helpers, GeoJSON normalization, file/path utilities,
azimuth/elevation calculations. Imported almost everywhere; touch with care.
The 2D viewport facade. Historically Leaflet-only, now an engine-agnostic surface over
LeafletAdapter and DeckGLAdapter. Map_.map still points at the live Leaflet map
for backwards-compatible callers. See Core runtime.
Self-contained tool modules (Draw, Measure, Layers, Identifier, …) loaded by the ToolController, plus the plugin-drop convention used to add new ones.
Related
- Frontend (Essence) — Mapping toolsSelf-contained tool modules (Draw, Measure, Layers, Identifier, …) loaded by the ToolController, plus the plugin-drop convention used to add new ones.
- Frontend (Essence) — Ancillary UI and chromeThe non-map UI surface — login, search, context menus, modals, scale bar, coordinate readout, help, query-by-URL, and the landing page.
- Frontend (Essence) — mmgisAPI (embed/extension surface)The public, stable JavaScript API exposed to embedders and plugin authors so they can drive MMGIS from outside.
- Backend (API server) — Feature modules under API/BackendThe repeating shape every backend feature follows, and a tour of the modules that matter (Datasets, Geodatasets, Draw, Config, Stac, Webhooks, Shortener, etc.).