diff --git a/.changeset/osm-weather-map-referrer.md b/.changeset/osm-weather-map-referrer.md
new file mode 100644
index 00000000..2848edd9
--- /dev/null
+++ b/.changeset/osm-weather-map-referrer.md
@@ -0,0 +1,5 @@
+---
+"ftw": patch
+---
+
+The weather location map loads again. OpenStreetMap's volunteer tiles now require a Referer, and the box was sending none.
diff --git a/web/index.html b/web/index.html
index 986fb937..2aa33e5f 100644
--- a/web/index.html
+++ b/web/index.html
@@ -938,7 +938,7 @@
Price bars (top of the chart)
-
+
diff --git a/web/leaflet-vendor.test.mjs b/web/leaflet-vendor.test.mjs
index bf84d81b..ab29ad2d 100644
--- a/web/leaflet-vendor.test.mjs
+++ b/web/leaflet-vendor.test.mjs
@@ -14,6 +14,13 @@ test('weather map loads Leaflet from the vendored copy, not unpkg', () => {
assert.match(weather, /\/vendor\/leaflet\/leaflet\.css/);
});
+test('weather map sends a Referer on OSM tiles so volunteer servers do not 403', () => {
+ assert.match(weather, /tile\.openstreetmap\.org/);
+ assert.match(weather, /referrerPolicy:\s*"strict-origin-when-cross-origin"/);
+ const leaflet = readFileSync(join(vendor, 'leaflet.js'), 'utf8');
+ assert.match(leaflet, /typeof this\.options\.referrerPolicy/);
+});
+
test('vendored Leaflet 1.9.4 files are present', () => {
for (const rel of [
'leaflet.js',
diff --git a/web/settings/tabs/weather.js b/web/settings/tabs/weather.js
index 4e0ea11c..9ba3a871 100644
--- a/web/settings/tabs/weather.js
+++ b/web/settings/tabs/weather.js
@@ -120,9 +120,13 @@
if (window._weatherMap) { try { window._weatherMap.remove(); } catch (e) {} window._weatherMap = null; }
var map = L.map(container, { zoomControl: true }).setView([lat, lon], 11);
window._weatherMap = map;
+ // OSM volunteer tiles 403 when the page sends no Referer. The box
+ // sends Referrer-Policy: no-referrer on every response, so Leaflet
+ // must opt these images back in. Origin only; the path stays private.
L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
maxZoom: 18,
attribution: "© OpenStreetMap",
+ referrerPolicy: "strict-origin-when-cross-origin",
}).addTo(map);
var marker = L.marker([lat, lon], { draggable: true }).addTo(map);
function setCoord(la, lo) {