diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..b1682148
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+frontend/prebuilt/** -diff
diff --git a/frontend/prebuilt/assets/BotCodeEditor-BD2FOJ4s.js b/frontend/prebuilt/assets/BotCodeEditor-BzmXJa-U.js
similarity index 99%
rename from frontend/prebuilt/assets/BotCodeEditor-BD2FOJ4s.js
rename to frontend/prebuilt/assets/BotCodeEditor-BzmXJa-U.js
index be010762..82b29951 100644
Binary files a/frontend/prebuilt/assets/BotCodeEditor-BD2FOJ4s.js and b/frontend/prebuilt/assets/BotCodeEditor-BzmXJa-U.js differ
diff --git a/frontend/prebuilt/assets/BotCodeEditor-BD2FOJ4s.js.map b/frontend/prebuilt/assets/BotCodeEditor-BzmXJa-U.js.map
similarity index 99%
rename from frontend/prebuilt/assets/BotCodeEditor-BD2FOJ4s.js.map
rename to frontend/prebuilt/assets/BotCodeEditor-BzmXJa-U.js.map
index 74f86138..e7769f85 100644
Binary files a/frontend/prebuilt/assets/BotCodeEditor-BD2FOJ4s.js.map and b/frontend/prebuilt/assets/BotCodeEditor-BzmXJa-U.js.map differ
diff --git a/frontend/prebuilt/assets/CrackerPanel-DSLlik3_.js b/frontend/prebuilt/assets/CrackerPanel-C3rwFxw9.js
similarity index 99%
rename from frontend/prebuilt/assets/CrackerPanel-DSLlik3_.js
rename to frontend/prebuilt/assets/CrackerPanel-C3rwFxw9.js
index cc959c59..8683859a 100644
Binary files a/frontend/prebuilt/assets/CrackerPanel-DSLlik3_.js and b/frontend/prebuilt/assets/CrackerPanel-C3rwFxw9.js differ
diff --git a/frontend/prebuilt/assets/CrackerPanel-DSLlik3_.js.map b/frontend/prebuilt/assets/CrackerPanel-C3rwFxw9.js.map
similarity index 99%
rename from frontend/prebuilt/assets/CrackerPanel-DSLlik3_.js.map
rename to frontend/prebuilt/assets/CrackerPanel-C3rwFxw9.js.map
index 3a2863cb..5809b54e 100644
Binary files a/frontend/prebuilt/assets/CrackerPanel-DSLlik3_.js.map and b/frontend/prebuilt/assets/CrackerPanel-C3rwFxw9.js.map differ
diff --git a/frontend/prebuilt/assets/MapView-7UG06zXw.js b/frontend/prebuilt/assets/MapView-7UG06zXw.js
deleted file mode 100644
index ff0d3986..00000000
Binary files a/frontend/prebuilt/assets/MapView-7UG06zXw.js and /dev/null differ
diff --git a/frontend/prebuilt/assets/MapView-7UG06zXw.js.map b/frontend/prebuilt/assets/MapView-7UG06zXw.js.map
deleted file mode 100644
index f729e3de..00000000
Binary files a/frontend/prebuilt/assets/MapView-7UG06zXw.js.map and /dev/null differ
diff --git a/frontend/prebuilt/assets/MapView-BW3wM0G8.js b/frontend/prebuilt/assets/MapView-BW3wM0G8.js
new file mode 100644
index 00000000..63a189f6
Binary files /dev/null and b/frontend/prebuilt/assets/MapView-BW3wM0G8.js differ
diff --git a/frontend/prebuilt/assets/MapView-BW3wM0G8.js.map b/frontend/prebuilt/assets/MapView-BW3wM0G8.js.map
new file mode 100644
index 00000000..d30a1962
Binary files /dev/null and b/frontend/prebuilt/assets/MapView-BW3wM0G8.js.map differ
diff --git a/frontend/prebuilt/assets/NeighborsMiniMap-C3Ju-R0X.js b/frontend/prebuilt/assets/NeighborsMiniMap-BfUArOef.js
similarity index 85%
rename from frontend/prebuilt/assets/NeighborsMiniMap-C3Ju-R0X.js
rename to frontend/prebuilt/assets/NeighborsMiniMap-BfUArOef.js
index f26f3325..9e9190a6 100644
Binary files a/frontend/prebuilt/assets/NeighborsMiniMap-C3Ju-R0X.js and b/frontend/prebuilt/assets/NeighborsMiniMap-BfUArOef.js differ
diff --git a/frontend/prebuilt/assets/NeighborsMiniMap-C3Ju-R0X.js.map b/frontend/prebuilt/assets/NeighborsMiniMap-BfUArOef.js.map
similarity index 97%
rename from frontend/prebuilt/assets/NeighborsMiniMap-C3Ju-R0X.js.map
rename to frontend/prebuilt/assets/NeighborsMiniMap-BfUArOef.js.map
index 8dbf1329..faf7323e 100644
Binary files a/frontend/prebuilt/assets/NeighborsMiniMap-C3Ju-R0X.js.map and b/frontend/prebuilt/assets/NeighborsMiniMap-BfUArOef.js.map differ
diff --git a/frontend/prebuilt/assets/PathRouteMap-DdylhAp-.js b/frontend/prebuilt/assets/PathRouteMap-Cg3mrjz1.js
similarity index 95%
rename from frontend/prebuilt/assets/PathRouteMap-DdylhAp-.js
rename to frontend/prebuilt/assets/PathRouteMap-Cg3mrjz1.js
index c57417ad..83429567 100644
Binary files a/frontend/prebuilt/assets/PathRouteMap-DdylhAp-.js and b/frontend/prebuilt/assets/PathRouteMap-Cg3mrjz1.js differ
diff --git a/frontend/prebuilt/assets/PathRouteMap-DdylhAp-.js.map b/frontend/prebuilt/assets/PathRouteMap-Cg3mrjz1.js.map
similarity index 99%
rename from frontend/prebuilt/assets/PathRouteMap-DdylhAp-.js.map
rename to frontend/prebuilt/assets/PathRouteMap-Cg3mrjz1.js.map
index bb5e2d94..5183fa66 100644
Binary files a/frontend/prebuilt/assets/PathRouteMap-DdylhAp-.js.map and b/frontend/prebuilt/assets/PathRouteMap-Cg3mrjz1.js.map differ
diff --git a/frontend/prebuilt/assets/Popup-CqM5D37r.js b/frontend/prebuilt/assets/Popup-DkSClDwo.js
similarity index 81%
rename from frontend/prebuilt/assets/Popup-CqM5D37r.js
rename to frontend/prebuilt/assets/Popup-DkSClDwo.js
index 977a2429..7f83aec8 100644
Binary files a/frontend/prebuilt/assets/Popup-CqM5D37r.js and b/frontend/prebuilt/assets/Popup-DkSClDwo.js differ
diff --git a/frontend/prebuilt/assets/Popup-CqM5D37r.js.map b/frontend/prebuilt/assets/Popup-DkSClDwo.js.map
similarity index 97%
rename from frontend/prebuilt/assets/Popup-CqM5D37r.js.map
rename to frontend/prebuilt/assets/Popup-DkSClDwo.js.map
index bd61344c..39a7a948 100644
Binary files a/frontend/prebuilt/assets/Popup-CqM5D37r.js.map and b/frontend/prebuilt/assets/Popup-DkSClDwo.js.map differ
diff --git a/frontend/prebuilt/assets/RepeaterDashboard-DrFtUyWd.js b/frontend/prebuilt/assets/RepeaterDashboard-DjXZo1ON.js
similarity index 98%
rename from frontend/prebuilt/assets/RepeaterDashboard-DrFtUyWd.js
rename to frontend/prebuilt/assets/RepeaterDashboard-DjXZo1ON.js
index 7d57d958..2d737dbb 100644
Binary files a/frontend/prebuilt/assets/RepeaterDashboard-DrFtUyWd.js and b/frontend/prebuilt/assets/RepeaterDashboard-DjXZo1ON.js differ
diff --git a/frontend/prebuilt/assets/RepeaterDashboard-DrFtUyWd.js.map b/frontend/prebuilt/assets/RepeaterDashboard-DjXZo1ON.js.map
similarity index 99%
rename from frontend/prebuilt/assets/RepeaterDashboard-DrFtUyWd.js.map
rename to frontend/prebuilt/assets/RepeaterDashboard-DjXZo1ON.js.map
index c974c9a2..1b8123a5 100644
Binary files a/frontend/prebuilt/assets/RepeaterDashboard-DrFtUyWd.js.map and b/frontend/prebuilt/assets/RepeaterDashboard-DjXZo1ON.js.map differ
diff --git a/frontend/prebuilt/assets/SearchView-CqEz3JCz.js b/frontend/prebuilt/assets/SearchView-Dvalyr5p.js
similarity index 97%
rename from frontend/prebuilt/assets/SearchView-CqEz3JCz.js
rename to frontend/prebuilt/assets/SearchView-Dvalyr5p.js
index 6b559262..3641060f 100644
Binary files a/frontend/prebuilt/assets/SearchView-CqEz3JCz.js and b/frontend/prebuilt/assets/SearchView-Dvalyr5p.js differ
diff --git a/frontend/prebuilt/assets/SearchView-CqEz3JCz.js.map b/frontend/prebuilt/assets/SearchView-Dvalyr5p.js.map
similarity index 99%
rename from frontend/prebuilt/assets/SearchView-CqEz3JCz.js.map
rename to frontend/prebuilt/assets/SearchView-Dvalyr5p.js.map
index 9dcbef74..04848382 100644
Binary files a/frontend/prebuilt/assets/SearchView-CqEz3JCz.js.map and b/frontend/prebuilt/assets/SearchView-Dvalyr5p.js.map differ
diff --git a/frontend/prebuilt/assets/SettingsModal-GFXFFaeS.js b/frontend/prebuilt/assets/SettingsModal-DgO2ZLSb.js
similarity index 99%
rename from frontend/prebuilt/assets/SettingsModal-GFXFFaeS.js
rename to frontend/prebuilt/assets/SettingsModal-DgO2ZLSb.js
index 23cbe618..d9f5087c 100644
Binary files a/frontend/prebuilt/assets/SettingsModal-GFXFFaeS.js and b/frontend/prebuilt/assets/SettingsModal-DgO2ZLSb.js differ
diff --git a/frontend/prebuilt/assets/SettingsModal-GFXFFaeS.js.map b/frontend/prebuilt/assets/SettingsModal-DgO2ZLSb.js.map
similarity index 99%
rename from frontend/prebuilt/assets/SettingsModal-GFXFFaeS.js.map
rename to frontend/prebuilt/assets/SettingsModal-DgO2ZLSb.js.map
index 3edb2b98..6c0d981b 100644
Binary files a/frontend/prebuilt/assets/SettingsModal-GFXFFaeS.js.map and b/frontend/prebuilt/assets/SettingsModal-DgO2ZLSb.js.map differ
diff --git a/frontend/prebuilt/assets/VisualizerView-BswMOFbt.js b/frontend/prebuilt/assets/VisualizerView-DlcD_Fhk.js
similarity index 99%
rename from frontend/prebuilt/assets/VisualizerView-BswMOFbt.js
rename to frontend/prebuilt/assets/VisualizerView-DlcD_Fhk.js
index 59d04215..1bb9a6c9 100644
Binary files a/frontend/prebuilt/assets/VisualizerView-BswMOFbt.js and b/frontend/prebuilt/assets/VisualizerView-DlcD_Fhk.js differ
diff --git a/frontend/prebuilt/assets/VisualizerView-BswMOFbt.js.map b/frontend/prebuilt/assets/VisualizerView-DlcD_Fhk.js.map
similarity index 99%
rename from frontend/prebuilt/assets/VisualizerView-BswMOFbt.js.map
rename to frontend/prebuilt/assets/VisualizerView-DlcD_Fhk.js.map
index 98d4b193..6a0f1350 100644
Binary files a/frontend/prebuilt/assets/VisualizerView-BswMOFbt.js.map and b/frontend/prebuilt/assets/VisualizerView-DlcD_Fhk.js.map differ
diff --git a/frontend/prebuilt/assets/hooks-Bk-tBmjl.js b/frontend/prebuilt/assets/hooks-Bk-tBmjl.js
deleted file mode 100644
index f74ff367..00000000
Binary files a/frontend/prebuilt/assets/hooks-Bk-tBmjl.js and /dev/null differ
diff --git a/frontend/prebuilt/assets/hooks-DfhmuKzA.js b/frontend/prebuilt/assets/hooks-DfhmuKzA.js
new file mode 100644
index 00000000..1865f7e6
Binary files /dev/null and b/frontend/prebuilt/assets/hooks-DfhmuKzA.js differ
diff --git a/frontend/prebuilt/assets/hooks-Bk-tBmjl.js.map b/frontend/prebuilt/assets/hooks-DfhmuKzA.js.map
similarity index 90%
rename from frontend/prebuilt/assets/hooks-Bk-tBmjl.js.map
rename to frontend/prebuilt/assets/hooks-DfhmuKzA.js.map
index d73cfcef..3912044c 100644
Binary files a/frontend/prebuilt/assets/hooks-Bk-tBmjl.js.map and b/frontend/prebuilt/assets/hooks-DfhmuKzA.js.map differ
diff --git a/frontend/prebuilt/assets/index-DSM_ctlA.js b/frontend/prebuilt/assets/index-DhrMLy6_.js
similarity index 99%
rename from frontend/prebuilt/assets/index-DSM_ctlA.js
rename to frontend/prebuilt/assets/index-DhrMLy6_.js
index a924b4c6..d45ab6c8 100644
Binary files a/frontend/prebuilt/assets/index-DSM_ctlA.js and b/frontend/prebuilt/assets/index-DhrMLy6_.js differ
diff --git a/frontend/prebuilt/assets/index-DSM_ctlA.js.map b/frontend/prebuilt/assets/index-DhrMLy6_.js.map
similarity index 99%
rename from frontend/prebuilt/assets/index-DSM_ctlA.js.map
rename to frontend/prebuilt/assets/index-DhrMLy6_.js.map
index 0ef131e9..6aa688be 100644
Binary files a/frontend/prebuilt/assets/index-DSM_ctlA.js.map and b/frontend/prebuilt/assets/index-DhrMLy6_.js.map differ
diff --git a/frontend/prebuilt/assets/leaflet-Bn7rjtY9.js b/frontend/prebuilt/assets/leaflet-lJm4twjh.js
similarity index 99%
rename from frontend/prebuilt/assets/leaflet-Bn7rjtY9.js
rename to frontend/prebuilt/assets/leaflet-lJm4twjh.js
index f429b49e..79c9787f 100644
Binary files a/frontend/prebuilt/assets/leaflet-Bn7rjtY9.js and b/frontend/prebuilt/assets/leaflet-lJm4twjh.js differ
diff --git a/frontend/prebuilt/assets/leaflet-Bn7rjtY9.js.map b/frontend/prebuilt/assets/leaflet-lJm4twjh.js.map
similarity index 99%
rename from frontend/prebuilt/assets/leaflet-Bn7rjtY9.js.map
rename to frontend/prebuilt/assets/leaflet-lJm4twjh.js.map
index 8305ed17..c1fc0099 100644
Binary files a/frontend/prebuilt/assets/leaflet-Bn7rjtY9.js.map and b/frontend/prebuilt/assets/leaflet-lJm4twjh.js.map differ
diff --git a/frontend/prebuilt/assets/separator-B1Gufat6.js b/frontend/prebuilt/assets/separator-DS1eMu86.js
similarity index 89%
rename from frontend/prebuilt/assets/separator-B1Gufat6.js
rename to frontend/prebuilt/assets/separator-DS1eMu86.js
index 97eb89e0..d91b37d3 100644
Binary files a/frontend/prebuilt/assets/separator-B1Gufat6.js and b/frontend/prebuilt/assets/separator-DS1eMu86.js differ
diff --git a/frontend/prebuilt/assets/separator-B1Gufat6.js.map b/frontend/prebuilt/assets/separator-DS1eMu86.js.map
similarity index 98%
rename from frontend/prebuilt/assets/separator-B1Gufat6.js.map
rename to frontend/prebuilt/assets/separator-DS1eMu86.js.map
index 98672d69..cdcb6a47 100644
Binary files a/frontend/prebuilt/assets/separator-B1Gufat6.js.map and b/frontend/prebuilt/assets/separator-DS1eMu86.js.map differ
diff --git a/frontend/prebuilt/index.html b/frontend/prebuilt/index.html
index 090e9270..2f9460f7 100644
Binary files a/frontend/prebuilt/index.html and b/frontend/prebuilt/index.html differ
diff --git a/frontend/src/components/MapView.tsx b/frontend/src/components/MapView.tsx
index 84105d88..71065947 100644
--- a/frontend/src/components/MapView.tsx
+++ b/frontend/src/components/MapView.tsx
@@ -104,7 +104,7 @@ function MapBoundsHandler({
}
export function MapView({ contacts, focusedKey }: MapViewProps) {
- const sevenDaysAgo = Date.now() / 1000 - 7 * 24 * 60 * 60;
+ const [sevenDaysAgo] = useState(() => Date.now() / 1000 - 7 * 24 * 60 * 60);
// Filter to contacts with GPS coordinates, heard within the last 7 days.
// Always include the focused contact so "view on map" links work for older nodes.
diff --git a/frontend/src/test/mapView.test.tsx b/frontend/src/test/mapView.test.tsx
index 88a7e6b4..effd7664 100644
--- a/frontend/src/test/mapView.test.tsx
+++ b/frontend/src/test/mapView.test.tsx
@@ -52,4 +52,43 @@ describe('MapView', () => {
).toBeInTheDocument();
expect(screen.getByText('Last heard: Never heard by this server')).toBeInTheDocument();
});
+
+ it('keeps the 7-day cutoff stable for the lifetime of the mounted map', () => {
+ vi.useFakeTimers();
+ try {
+ vi.setSystemTime(new Date('2026-03-15T12:00:00Z'));
+
+ const contact: Contact = {
+ public_key: 'bb'.repeat(32),
+ name: 'Almost Stale',
+ type: 1,
+ flags: 0,
+ last_path: null,
+ last_path_len: -1,
+ out_path_hash_mode: -1,
+ route_override_path: null,
+ route_override_len: null,
+ route_override_hash_mode: null,
+ last_advert: null,
+ lat: 41,
+ lon: -73,
+ last_seen: Math.floor(Date.now() / 1000) - 7 * 24 * 60 * 60 + 60,
+ on_radio: false,
+ last_contacted: null,
+ last_read_at: null,
+ first_seen: null,
+ };
+
+ const { rerender } = render();
+
+ expect(screen.getByText(/showing 1 contact heard in the last 7 days/i)).toBeInTheDocument();
+
+ vi.advanceTimersByTime(2 * 60 * 1000);
+ rerender();
+
+ expect(screen.getByText(/showing 1 contact heard in the last 7 days/i)).toBeInTheDocument();
+ } finally {
+ vi.useRealTimers();
+ }
+ });
});