The app hook
Register the map with one line in test and development builds; nothing is imported and nothing ships.
const map = new maplibregl.Map({ ... });(window.__geowright_maps ??= {}).main = map;// that's it; nothing is imported, nothing shipsKeep that line out of production builds (if (import.meta.env.MODE !== 'production'), or your bundler's equivalent):
it makes the map instance reachable by every script on the page (SECURITY.md).
In TypeScript, add /// <reference types="geowright/app" /> to a .d.ts file your app's tsconfig includes (a Vite
app has src/vite-env.d.ts) and the line compiles as written, without (window as any). It is types only: nothing ships.
With a wrapper the map instance arrives in a callback — still one line (all three verified in wild/apps/):
<Map onLoad={e => ((window.__geowright_maps ??= {}).main = e.target)} … />// react-map-gl<MapLibre onload={(e) => ((window.__geowright_maps ??= {}).main = e.target)} … />// svelte-maplibre-gl<mgl-map @map:load="e => ((e.map.getContainer().ownerDocument.defaultView.__geowright_maps ??= {}).main = e.map)" … />// ^ vue-maplibre-gl: a Vue template cannot see `window`; in <script setup> the plain line worksWrappers fire that callback on MapLibre's load, which needs every declared source: if a data request fails, the map is never registered.
The in-page adapter is injected by Playwright at test time. (Auto-discovery is not possible for bundled ESM apps — tests/discovery.spec.ts proves it.)
If the map is never found or never becomes idle, see Troubleshooting.