Reported by the customer in cismet/wupp#4198: on the live geoportal the locator does nothing. The button turns orange on click and that is the end of it.
Symptom
Tapping the locator flips the icon to orange, no position marker appears, the map does not recentre, and the browser never even asks for the geolocation permission.
Cause
apps/geoportal/src/app/components/GeoportalMap/controls/MapWrapper.tsx fills its topleft order 30 control slot with RoutedMapLocateControl. That component drives the leaflet map through TopicMapContext.routedMapRef.
Live runs maplibre. useLibreMapEnabled() returns !flags.featureFlagLeafletMap, whose default is false (91da566ad, 2026-08-11; live since a404b4ab9, 2026-08-24), so GeoportalMap renders LibreGeoportalMap and no TopicMapComponent ever mounts.
With no leaflet map, routedMapRef stays null, L.control.locate(...) is never constructed, and the click only flips isLocationActive. The loading flag lives inside the effect guarded by that missing instance, so the icon skips the spinner and goes straight to text-orange-500. Exactly what Stefan describes.
Evidence
Measured in the browser on the geoportal dev server, geolocation API calls counted by wrapping navigator.geolocation:
| mode |
click result |
| maplibre (live default) |
icon orange, geolocation calls [], 0 markers, no move |
ff=leaflet |
icon orange, watchPosition called, 1 marker, map recentred |
Why no maplibre locator was in place
LibreMapLocateControl and useLibreMapLocateControl do exist. They were added in 21eb2e1ee (2025-12-11) and wired into CarmaMap only. geoportal switches off every CarmaMap-internal control on purpose, because it hosts its own ControlLayout in MapWrapper where the locator needs its stacking order, the showLocatorButton redux gate and the oblique gate. So the order 30 slot simply never got a maplibre counterpart when the engine switched.
The libre control has also never actually rendered anywhere else: every other consumer that leaves it enabled is desktop (belis-desktop, playgrounds), and the component returns null on desktop user agents. Its first real execution surfaced two further defects, see below.
Defects found on first execution of the libre control
map.addSource throws Error: Style is not done loading. from inside the geolocation success callback, which aborts the callback before the map.flyTo that follows it. Drawing the accuracy circle costs the user the recentring. geoportal reapplies its style on every layer change, so this is not a rare window.
- Two markers per activation:
updateLocationMarker creates the marker inside import("maplibre-gl").then(...), and a second position update arriving before that import resolves sees markerRef.current still null.
- A style swap drops the accuracy source and layer, and nothing puts them back.
- The control's own
flyTo trips its hasMapMoved state, so it reports "user panned away" (blue) right after locating.
Scope
geoportal only. belis-desktop and the playgrounds go through CarmaMap's own branch, and the topicmaps are still on leaflet.
Not part of this
The locator is mobile-only on both gates (isMobile in MapWrapper, isDesktop inside the control), so no desktop check can ever see it. A ff=locator flag is added so it can be looked at from a developer machine.
Reported by the customer in cismet/wupp#4198: on the live geoportal the locator does nothing. The button turns orange on click and that is the end of it.
Symptom
Tapping the locator flips the icon to orange, no position marker appears, the map does not recentre, and the browser never even asks for the geolocation permission.
Cause
apps/geoportal/src/app/components/GeoportalMap/controls/MapWrapper.tsxfills itstopleft order 30control slot withRoutedMapLocateControl. That component drives the leaflet map throughTopicMapContext.routedMapRef.Live runs maplibre.
useLibreMapEnabled()returns!flags.featureFlagLeafletMap, whose default isfalse(91da566ad, 2026-08-11; live sincea404b4ab9, 2026-08-24), soGeoportalMaprendersLibreGeoportalMapand noTopicMapComponentever mounts.With no leaflet map,
routedMapRefstays null,L.control.locate(...)is never constructed, and the click only flipsisLocationActive. The loading flag lives inside the effect guarded by that missing instance, so the icon skips the spinner and goes straight totext-orange-500. Exactly what Stefan describes.Evidence
Measured in the browser on the geoportal dev server, geolocation API calls counted by wrapping
navigator.geolocation:[], 0 markers, no moveff=leafletwatchPositioncalled, 1 marker, map recentredWhy no maplibre locator was in place
LibreMapLocateControlanduseLibreMapLocateControldo exist. They were added in21eb2e1ee(2025-12-11) and wired intoCarmaMaponly. geoportal switches off every CarmaMap-internal control on purpose, because it hosts its ownControlLayoutinMapWrapperwhere the locator needs its stacking order, theshowLocatorButtonredux gate and the oblique gate. So theorder 30slot simply never got a maplibre counterpart when the engine switched.The libre control has also never actually rendered anywhere else: every other consumer that leaves it enabled is desktop (belis-desktop, playgrounds), and the component returns
nullon desktop user agents. Its first real execution surfaced two further defects, see below.Defects found on first execution of the libre control
map.addSourcethrowsError: Style is not done loading.from inside the geolocation success callback, which aborts the callback before themap.flyTothat follows it. Drawing the accuracy circle costs the user the recentring. geoportal reapplies its style on every layer change, so this is not a rare window.updateLocationMarkercreates the marker insideimport("maplibre-gl").then(...), and a second position update arriving before that import resolves seesmarkerRef.currentstill null.flyTotrips itshasMapMovedstate, so it reports "user panned away" (blue) right after locating.Scope
geoportal only. belis-desktop and the playgrounds go through
CarmaMap's own branch, and the topicmaps are still on leaflet.Not part of this
The locator is mobile-only on both gates (
isMobilein MapWrapper,isDesktopinside the control), so no desktop check can ever see it. Aff=locatorflag is added so it can be looked at from a developer machine.