feat(web): Add Cloudflare Workers geolocation fallback

Add a minimal cfgeo Cloudflare Worker that returns coarse location
from Cloudflare's edge geolocation data. Use it as a fast default
location on load, preferring browser geolocation or an explicit
search/URL selection whenever those are available.
This commit is contained in:
abdus committed 2026-10-08 21:11:07 +02:00
1 parent e295a997a1
commit dc25633f61
5 files changed
+84 -5

No files matched your search

+45 -5
View File
@@ -1,3 +1,6 @@
const CFGEO_ENDPOINT = "https://cfgeo.abdusco.workers.dev/";
const CFGEO_TIMEOUT_MS = 2000;
const app = () => ({
futureTimes: [],
selectedLocation: Alpine.$persist(null),
@@ -34,13 +37,30 @@ const app = () => ({
}, 500);
if (!urlCoords) {
try {
const coords = await getUserLocation();
await this.selectNearestLocation(coords.latitude, coords.longitude, {updateURL: true});
} catch (_error) {
// Ignore geolocation errors and rely on manual search.
await this.resolveDefaultLocation();
}
},
async resolveDefaultLocation() {
let browserResolved = false;
const geoPromise = getUserLocation()
.then((coords) => {
browserResolved = true;
return coords;
})
.catch(() => null);
if (!this.selectedLocation) {
const cfCoords = await withTimeout(getCFGeoLocation(), CFGEO_TIMEOUT_MS);
if (cfCoords && !browserResolved) {
await this.selectNearestLocation(cfCoords.latitude, cfCoords.longitude, {updateURL: false});
}
}
const geoCoords = await geoPromise;
if (geoCoords) {
await this.selectNearestLocation(geoCoords.latitude, geoCoords.longitude, {updateURL: true});
}
},
onHash() {
@@ -396,6 +416,26 @@ function getUserLocation() {
});
}
async function getCFGeoLocation() {
if (!CFGEO_ENDPOINT) {
return null;
}
const data = await fetchJSON(CFGEO_ENDPOINT);
if (typeof data.latitude !== "number" || typeof data.longitude !== "number") {
return null;
}
return {latitude: data.latitude, longitude: data.longitude};
}
function withTimeout(promise, ms) {
return Promise.race([
promise,
new Promise((resolve) => setTimeout(() => resolve(null), ms))
]).catch(() => null);
}
function normalizeLanguageTag(tag) {
return String(tag).toLowerCase().split("-")[0];
}