Skip to main content

What it is

@nika-js/onlymap-native is the official React Native adapter for OnlyMap JS. It packages the complete web runtime — every layer type, data format, live transport, and validation rule — inside a secure WebView served from a loopback-only host, and gives you <OmMap> and <OmLayer> components that speak the same vocabulary as the web library. The adapter owns the JSON bridge, the app lifecycle (background suspend, foreground resume), and WebView renderer recovery. It is not a native MapLibre renderer and not the web @nika-js/onlymap/react adapter: it is the OnlyMap runtime itself, hosted natively. A 20-fixture parity gate keeps the React Native surface byte-identical to the web React adapter at the intermediate-representation level.

Support matrix

Install the package and follow the setup in its bundled llms.txt (local networking permission, cleartext-for-loopback exception, and the Metro config extension for the packaged host assets):

The rules that differ from web

  • Accessors are expression strings, never functions. getPosition="[$lon, $lat]" crosses the JSON bridge; getPosition={(d) => ...} cannot and is rejected.
  • Props are camelCase JSX, not the web manifest’s kebab-case attributes.
  • Everything crossing the bridge is finite plain JSON. Bulk data stays out of the bridge: pass URLs (the full web format matrix works unchanged from a URL inside the packaged host — GeoJSON, CSV, KML, GPX, FlatGeobuf, GeoArrow including zstd, GeoParquet, Shapefile, range-requested COG), WebSocket source="upsert" streams with streamKey, or refresh polling.
  • Native UI lives beside the map, driven by the imperative handle and useOmMapWatch; the web’s <om-widget>/<om-overlay> elements have no native components yet.
  • emit() runs core-backed actions (fly-to, zoom-in, zoom-out, zoom-to-feature, registered custom actions) exactly as on the web MapController. DOM-manifest actions (toggle-layer, filter-layer, overlay/tooltip/story actions, set-basemap) deliberately warn and do nothing natively — express those through React props and state.

The imperative handle

A ref (or useOmMap() in descendants) exposes the MapController surface, all Promise-returning: flyTo, flyToBounds, zoomBy, setView, getViewState, project, getSelection, emit, snapshot, stats, data, dataInViewport, irSnapshot, reload, and injectPick. injectPick is the consumer testing surface: a synthetic selection travels the same code path as a real tap and reaches your per-layer onClick/onHover, so interaction handling is testable in CI without a device. reload() deliberately rebuilds the WebView renderer and replays canonical state; repeated calls are harmless.

Lifecycle, verified on hardware

The adapter suspends rendering and live transports when the app backgrounds and restores them on foreground; WebView renderer loss replays configuration, the complete layer document, settled camera, and watches. These are tested claims, not intentions: the acceptance suite runs on an iOS simulator and an Android emulator in CI on every change, and on physical hardware the full flow suite is green — including a five-minute background against a live WebSocket feed (current data within seconds of returning), airplane-mode network loss with structured errors and unattended recovery, and bridge round-trip latency measured at ~8.5 ms median on a mid-range Android phone.

Reference

  • The package ships llms.txt (the complete agent-facing authoring reference) and an installable agent skill — both inside the npm tarball.
  • Repository, examples, and acceptance evidence: github.com/NikaGeospatial/onlymap-native
  • Licensing: commercial keys support app-scoped apps claims for packaged applications — see Licensing & Telemetry.