From aab42610efca8f938ac094d36719a8fe432e41ef Mon Sep 17 00:00:00 2001 From: Emi Griffith Date: Sat, 18 Jul 2026 00:48:17 -0700 Subject: [PATCH] Fix the hero's "Use my location" doing nothing (#179) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The button was dead on plain HTTP and failed silently everywhere. Browsers only expose geolocation on secure origins, but `navigator.geolocation` still EXISTS on http:// — getCurrentPosition just fails with a permission error ("Only secure origins are allowed"). The guard was `if (!navigator.geolocation) return;`, which passes on http://, so the call went ahead, errored, and landed in an empty error callback. Nothing happened at all. `make lan-run` serves plain HTTP on 0.0.0.0:8137 so phones can reach it, so the button could never work in the normal dev-and-phone workflow, and gave no hint why. It would have worked on thermograph.org, which is HTTPS. - Gate on `window.isSecureContext`, not just the API's presence. Where the browser will refuse, hide the locate button and promote "Pick on the map" to primary rather than offering a control that cannot work. - Report failures: a declined prompt, a timeout, and an unavailable fix each get their own message in an aria-live slot. A silent failure is indistinguishable from a broken button, which is exactly how this went unnoticed. - Show a "Locating…" state while the fix is pending; it can take seconds. To exercise geolocation against the LAN dev server, serve it over TLS: `make lan-run TLS=1` (self-signed cert into certs/). Verified by driving the button in a real browser across all three cases: insecure origin (button hidden, map promoted), permission granted (hero re-points at the located place), permission denied (message shown, button restored). --- templates/home.html.j2 | 3 +++ tests/test_homepage.py | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/templates/home.html.j2 b/templates/home.html.j2 index b42018e..68d73cb 100644 --- a/templates/home.html.j2 +++ b/templates/home.html.j2 @@ -62,9 +62,12 @@ {% endif %}
+ {# app.js hides the locate button outside a secure context, where the + browser refuses geolocation and it could only ever fail. #}
+

See your week ↓

diff --git a/tests/test_homepage.py b/tests/test_homepage.py index 30e07ff..ec60713 100644 --- a/tests/test_homepage.py +++ b/tests/test_homepage.py @@ -124,6 +124,16 @@ def test_homepage_is_complete_without_js(client, no_feed): assert 'p class="site-name"' in html +def test_hero_locate_has_a_status_slot(client, no_feed): + """The locate button needs somewhere to report a declined prompt or a + timeout. Without it the control fails silently, which is how it shipped + broken: navigator.geolocation exists on plain http:// but always errors.""" + html = client.get(f"{B}/").text + assert 'id="hero-locate"' in html + assert 'id="hero-locate-msg"' in html + assert 'aria-live="polite"' in html + + def test_city_chips_all_resolve(client, no_feed): """Every homepage chip must be a real, routable city — a stale slug would render an empty chip list and leak a 404 link."""