diff --git a/src/components/FirstRunChecklist.tsx b/src/components/FirstRunChecklist.tsx
index c7a4de6..f4bf170 100644
--- a/src/components/FirstRunChecklist.tsx
+++ b/src/components/FirstRunChecklist.tsx
@@ -87,6 +87,11 @@ export function FirstRunChecklist() {
{t('mapUi.firstRunWallet')}
+
+
+
);
diff --git a/src/components/SpotMap.tsx b/src/components/SpotMap.tsx
index 935cfe1..2f98f4e 100644
--- a/src/components/SpotMap.tsx
+++ b/src/components/SpotMap.tsx
@@ -548,7 +548,7 @@ interface SpotMapProps {
onSpotClick?: (spot: SkateSpot) => void;
selectedSpot?: SkateSpot | null;
onMapClick?: (lat: number, lng: number) => void;
- onMapMove?: (center: { lat: number; lon: number }) => void;
+ onMapMove?: (center: { lat: number; lon: number; zoom?: number }) => void;
enableClickToAdd?: boolean;
className?: string;
weatherEnabled?: boolean;
@@ -977,7 +977,7 @@ export function SpotMap({
// Add moveend handler for BTC Map updates
map.on('moveend', () => {
const center = map.getCenter();
- onMapMoveRef.current?.({ lat: center.lat, lon: center.lng });
+ onMapMoveRef.current?.({ lat: center.lat, lon: center.lng, zoom: map.getZoom() });
});
mapInstanceRef.current = map;
@@ -1029,7 +1029,7 @@ export function SpotMap({
map.whenReady(() => {
// Trigger initial map move event
const center = map.getCenter();
- onMapMoveRef.current?.({ lat: center.lat, lon: center.lng });
+ onMapMoveRef.current?.({ lat: center.lat, lon: center.lng, zoom: map.getZoom() });
});
}, 100);
diff --git a/src/pages/MapPage.tsx b/src/pages/MapPage.tsx
index 3f43a01..f76faa7 100644
--- a/src/pages/MapPage.tsx
+++ b/src/pages/MapPage.tsx
@@ -678,6 +678,27 @@ export default function MapPage() {
// of the default world view. Resolved once at mount — a fresh fix or a manual
// pan supersedes it. Makes the map feel "already yours" the moment it opens.
const [initialView] = useState(() => {
+ // Restore the last map view first; a brand-new device falls back to the
+ // cached location, then to the world view.
+ try {
+ const raw = localStorage.getItem('skatespots:map-view');
+ const saved = raw ? JSON.parse(raw) as { lat?: unknown; lon?: unknown; zoom?: unknown } : null;
+ if (
+ saved &&
+ typeof saved.lat === 'number' && Number.isFinite(saved.lat) &&
+ typeof saved.lon === 'number' && Number.isFinite(saved.lon) &&
+ typeof saved.zoom === 'number' && Number.isFinite(saved.zoom)
+ ) {
+ return {
+ center: [saved.lat, saved.lon] as [number, number],
+ zoom: Math.min(18, Math.max(1, saved.zoom)),
+ lat: saved.lat,
+ lon: saved.lon,
+ };
+ }
+ } catch {
+ // fall through to the location/world default
+ }
const cached = getLastLocation();
return cached
? { center: [cached.lat, cached.lng] as [number, number], zoom: 12, lat: cached.lat, lon: cached.lng }
@@ -692,6 +713,14 @@ export default function MapPage() {
lat: initialView.lat,
lon: initialView.lon,
});
+ const handleMapMove = (center: { lat: number; lon: number; zoom?: number }) => {
+ setMapCenter({ lat: center.lat, lon: center.lon });
+ try {
+ localStorage.setItem('skatespots:map-view', JSON.stringify(center));
+ } catch {
+ // storage unavailable — map still works
+ }
+ };
// Near Me fly-to state
const [flyTo, setFlyTo] = useState<{ lat: number; lng: number; zoom?: number } | null>(null);
@@ -1751,7 +1780,7 @@ export default function MapPage() {
selectedSpot={selectedSpot}
onSpotClick={setSelectedSpot}
onMapClick={handleMapClick}
- onMapMove={setMapCenter}
+ onMapMove={handleMapMove}
enableClickToAdd={!!user}
className="h-full ss-map-floating-toolbar"
weatherEnabled={weatherEnabled}