A WeWeb custom component for personal location selection with privacy controls and reverse geocoding.
- ✅ Browser Geolocation: Auto-request user's location with permission dialog
- ✅ Manual Location Marking: Click on map to set location manually
- ✅ Reverse Geocoding: Convert coordinates to human-readable addresses
- ✅ Privacy Mode: Fuzzy location with random offset within radius
- ✅ Privacy Circle Visualization: Show privacy radius on map
- ✅ Multiple Map Types: OSM, Satellite, Terrain, Dark, Light themes
- Install dependencies:
cd /home/plato/Projects/simple-geolocation-map
npm install- Serve locally:
npm run serve --port=3000- Add component in WeWeb editor (Developer > Custom Elements > http://localhost:3000)
- Request User Location: Auto-request browser geolocation on load
- Show User Location Marker: Display marker at detected location
- Center Map on User Location: Auto-center map when location granted
- Allow Click to Mark: Users can click map to manually set location
- Enable Privacy Mode: Hide exact location, show randomized position
- Privacy Radius (km): Radius for location obfuscation (0.1-50km)
- Privacy Radius (miles): Same in miles (0.1-31 miles)
- Privacy Unit: Choose between kilometers or miles
- Enable Reverse Geocoding: Lookup address for selected locations
- Geocoding Rate Limit (ms): Delay between requests (min 1000ms)
- Initial Latitude/Longitude: Starting map center
- Initial Zoom Level: Starting zoom (1-18)
- Map Type: OSM, Satellite, Terrain, Dark, Light
- Map Height: CSS height value
- Map Border Radius: Corner rounding
- User Marker Color: Color for geolocation marker
- Marked Location Color: Color for manually placed marker
- Privacy Circle Color: Color for privacy radius circle
| Variable | Type | Description |
|---|---|---|
userLocation |
Object | { lat, lng, timestamp } - Auto-detected location |
clickedLocation |
Object | { lat, lng, timestamp } - Manually marked location |
geocodedAddress |
Object | Address details with continent, country, state, city, postcode, road |
isPrivacyActive |
Boolean | Whether privacy mode is currently enabled |
currentZoom |
Number | Current map zoom level |
| Event | When Fired | Data |
|---|---|---|
location-granted |
User grants location permission | { position: { lat, lng } } |
location-denied |
User denies location permission | {} |
location-marked |
User clicks map to mark location | { position: { lat, lng } } |
user-location-click |
User clicks geolocation marker | { position: { lat, lng } } |
marked-location-click |
User clicks marked location marker | { position: { lat, lng } } |
location-geocoded |
Generic location geocoded | { geocoded, coordinates } |
user-location-geocoded |
User location geocoded | { geocoded, coordinates } |
marked-location-geocoded |
Marked location geocoded | { geocoded, coordinates } |
privacy-toggled |
Privacy mode changed | { enabled: boolean } |
map-ready |
Map initialized | {} |
1. Add "Simple Geolocation Map" component
2. Enable "Request User Location": ON
3. Enable "Allow Click to Mark": ON
4. Enable "Reverse Geocoding": ON
1. Add component
2. Enable "Privacy Mode": ON
3. Set "Privacy Radius": 5 km
4. Bind [Component].userLocation to Supabase user profile
5. Users see fuzzy location, you store exact coordinates
ON [Map].location-granted:
- Save [Map].userLocation to Supabase
- Save [Map].geocodedAddress.address to user profile
ON [Map].marked-location-geocoded:
- Display [Map].geocodedAddress.displayName in text
- Enable "Save Location" button
{
displayName: "123 Main St, Springfield, IL 62701, USA",
address: {
continent: "North America",
country: "United States",
countryCode: "us",
state: "Illinois",
city: "Springfield",
postcode: "62701",
road: "Main Street",
houseNumber: "123"
},
raw: { /* Full Nominatim response */ }
}For WeWeb hosting environments, recommended CSP headers:
Content-Security-Policy:
default-src 'self';
script-src 'self' https://cdnjs.cloudflare.com;
style-src 'self' 'unsafe-inline';
img-src 'self' https: data:;
font-src 'self';
connect-src 'self'
https://nominatim.openstreetmap.org
https://tile.openstreetmap.org
https://server.arcgisonline.com
https://tile.opentopomap.org
https://basemaps.cartocdn.com;
frame-ancestors 'none';
base-uri 'self';
form-action 'self';
All external API calls (Nominatim, tile servers) include proper CORS handling:
credentials: 'omit'- no credentials sent- User-Agent header included (Nominatim requirement)
- Timeouts enforced (5 seconds for geocoding)
- Errors logged with request ID for debugging
- Coordinates: Validated within bounds (lat: -90 to 90, lng: -180 to 180)
- Colors: Sanitized hex colors and named color whitelist
- API Responses: Nominatim responses validated against schema
- XSS Protection: All marker styling via CSS variables, no HTML interpolation
- Always request location permission first: Enable "Request User Location" only after explaining why
- Respect privacy: Use Privacy Mode when sharing location publicly
- Rate limit geocoding: Keep "Geocoding Rate Limit" >= 1000ms (OpenStreetMap policy)
- Fallback to manual: Always enable "Allow Click to Mark" as fallback
- Validate coordinates: Check lat/lng are within valid ranges before saving
- Enable HTTPS: Required for geolocation (except localhost)
- Set CSP headers: Configure Content Security Policy for production
| Browser | Version | Support | Notes |
|---|---|---|---|
| Chrome | 54+ | ✅ Full | All features |
| Firefox | 55+ | ✅ Full | All features |
| Safari | 12.1+ | ✅ Full | All features |
| Edge | 15+ | ✅ Full | Chromium-based |
| IE 11 | - | ❌ Not Supported | Missing ResizeObserver, AbortController |
| iOS Safari | 12.2+ | ✅ Full | Requires HTTPS |
| Chrome Android | 54+ | ✅ Full | All features |
Required:
- ResizeObserver API (responsive map sizing)
- AbortController API (request cancellation)
- Fetch API (Nominatim geocoding)
- Geolocation API (browser location)
- ES2015+ support (const, arrow functions, async/await)
Note: Requires HTTPS for geolocation (except localhost)
Location permission denied:
- User must manually enable in browser settings
- Enable "Allow Click to Mark" as fallback
Geocoding not working:
- Check "Geocoding Rate Limit" >= 1000ms
- Verify internet connection
- OpenStreetMap Nominatim has usage limits
Map not displaying:
- Check internet connection (tile servers)
- Verify map height is set
- Check browser console for errors
MIT