Your agent and you — same vault, right access
@@ -424,67 +489,75 @@
svg.appendChild(label);
}
+ const POPS = [
+ {name:"Washington D.C.", region:"us-east-1", lat:37.5, lon:-77.5},
+ {name:"San Francisco", region:"us-west-1", lat:37.8, lon:-122.4},
+ {name:"Montréal", region:"ca-central-1", lat:45.5, lon:-73.6},
+ {name:"Mexico City", region:"mx-central-1", lat:19.4, lon:-99.1},
+ {name:"Bogotá", region:"sa-bogota", lat:4.7, lon:-74.1},
+ {name:"São Paulo", region:"sa-east-1", lat:-23.6, lon:-46.6},
+ {name:"Santiago", region:"sa-west-1", lat:-33.4, lon:-70.6},
+ {name:"London", region:"eu-west-2", lat:51.5, lon:-0.1},
+ {name:"Zürich", region:"eu-central-2", lat:47.4, lon:8.5},
+ {name:"Madrid", region:"eu-south-2", lat:40.4, lon:-3.7},
+ {name:"Stockholm", region:"eu-north-1", lat:59.3, lon:18.1},
+ {name:"Istanbul", region:"tr-west-1", lat:41.0, lon:28.9},
+ {name:"Dubai", region:"me-central-1", lat:25.2, lon:55.3},
+ {name:"Lagos", region:"af-west-1", lat:6.5, lon:3.4},
+ {name:"Nairobi", region:"af-east-1", lat:-1.3, lon:36.8},
+ {name:"Cape Town", region:"af-south-1", lat:-33.9, lon:18.4},
+ {name:"Mumbai", region:"ap-south-1", lat:19.1, lon:72.9},
+ {name:"Singapore", region:"ap-southeast-1", lat:1.3, lon:103.8},
+ {name:"Sydney", region:"ap-southeast-2", lat:-33.9, lon:151.2},
+ {name:"Tokyo", region:"ap-northeast-1", lat:35.7, lon:139.7},
+ {name:"Seoul", region:"ap-northeast-2", lat:37.6, lon:126.9},
+ {name:"Hong Kong", region:"ap-east-1", lat:22.3, lon:114.2},
+ ];
+
+ function findClosestPop(lat, lon) {
+ return POPS.reduce((best, p) => {
+ const d = (lat-p.lat)**2 + (lon-p.lon)**2;
+ const bd = (lat-best.lat)**2 + (lon-best.lon)**2;
+ return d < bd ? p : best;
+ });
+ }
+
function handleGeoData(d) {
if (!d.latitude || !d.longitude) return;
addVisitorDot(d.latitude, d.longitude, d.city || 'You');
- const grid = document.getElementById('dc-grid');
- if (!grid) return;
-
- // Build visitor card
- const flag = d.country_code ? d.country_code.toUpperCase().split('').map(c =>
- String.fromCodePoint(c.charCodeAt(0) + 127397)).join('') : '📍';
- const city = d.city || 'You';
- const country = d.country_name || '';
- const region = d.region || '';
-
- const card = document.createElement('div');
- card.className = 'rounded-xl p-4 text-center card-hover';
- card.setAttribute('data-lon', d.longitude);
- card.style.cssText = 'background:#1f0a0a;border:1px solid rgba(239,68,68,0.35);flex:1;min-width:0';
- card.innerHTML = `
-
${flag}
-
${city}
-
${country}
-
${region}
-
- You are here
-
`;
-
- // Insert at correct longitude position
- const cards = [...grid.children];
- const insertBefore = cards.find(c => parseFloat(c.getAttribute('data-lon')) > d.longitude);
- if (insertBefore) grid.insertBefore(card, insertBefore);
- else grid.appendChild(card);
-
-
+ const closest = findClosestPop(d.latitude, d.longitude);
+ const nameEl = document.getElementById('closest-name');
+ const subEl = document.getElementById('closest-sub');
+ const buyEl = document.getElementById('closest-buy');
+ if (nameEl) nameEl.textContent = closest.name;
+ if (subEl) subEl.textContent = d.city ? `~${d.city}` : 'Your region';
+ if (buyEl) buyEl.href = `/signup?region=${closest.region}`;
}
- fetch('/geo')
- .then(r => r.json())
- .then(d => {
- if (d.latitude) {
- handleGeoData(d);
- } else if (d.private && navigator.geolocation) {
- navigator.geolocation.getCurrentPosition(pos => {
- const lat = pos.coords.latitude, lon = pos.coords.longitude;
- // Reverse geocode via open-meteo's free geocoding isn't ideal;
- // use bigdatacloud free reverse geocode — no key, no signup
- fetch(`/geo?lat=${lat}&lon=${lon}`)
- .then(r => r.json())
- .then(g => handleGeoData({
- latitude: lat, longitude: lon,
- city: g.city || 'You',
- region: g.region || '',
- country_name: g.country_name || '',
- country_code: g.country_code || ''
- }))
- .catch(() => handleGeoData({ latitude: lat, longitude: lon,
- city: 'You', region: '', country_name: '', country_code: '' }));
- }, () => {});
- }
- })
- .catch(() => {});
+ // Ask browser geolocation first (accurate, triggers permission prompt)
+ // Fall back to server-side IP lookup if denied or unavailable
+ function tryIPGeo() {
+ fetch('/geo')
+ .then(r => r.json())
+ .then(d => { if (d.latitude) handleGeoData(d); })
+ .catch(() => {});
+ }
+
+ if (navigator.geolocation) {
+ navigator.geolocation.getCurrentPosition(
+ pos => {
+ handleGeoData({
+ latitude: pos.coords.latitude,
+ longitude: pos.coords.longitude,
+ city: '', region: '', country_name: '', country_code: ''
+ });
+ },
+ () => tryIPGeo() // denied — fall back to IP
+ );
+ } else {
+ tryIPGeo();
+ }
})();