Tachimetro, limite di velocità dal map-matching, avviso autovelox, GPS live. Nessun build step: sono file statici, si deployano così come sono.
npm run deploy
# equivale a: npx wrangler pages deploy . --project-name lanzarote-pwaAl primo lancio wrangler apre il browser per l'accesso a Cloudflare e crea il progetto.
Al termine stampa l'URL: https://lanzarote-pwa.pages.dev.
Su Cloudflare Dashboard → Workers & Pages → Create → Pages → Connect to Git:
| Campo | Valore |
|---|---|
| Repository | questo repo |
| Framework preset | None |
| Build command | (vuoto) |
| Build output directory | / |
Ogni push sul branch di produzione ridistribuisce il sito.
- Apri l'URL
https://…pages.devcon Chrome (Android) o Safari (iOS). - Menu → Aggiungi a schermata Home. Si apre a schermo intero, senza barra del browser.
- Tocca 📍 GPS e concedi il permesso di posizione. Il pallino in alto diventa verde.
- Senza muoverti, tocca ▶︎ Demo: percorre la LZ-2 e mostra tachimetro, cartello del limite e avviso autovelox.
Perché serve il deploy https: il GPS (geolocation) e il service worker sono
bloccati dai browser su file://. Solo https:// o localhost li abilitano.
Prova in locale prima di pubblicare:
npm run dev # http://localhost:8788- iOS: Impostazioni → Privacy → Localizzazione → Safari → Mentre usi l'app, e "Posizione esatta" attiva.
- Android: tieni premuta l'icona dell'app → Autorizzazioni → Posizione → Consenti sempre, precisione attiva.
- La velocità resta
–finché il telefono non si muove davvero:coords.speedènullda fermo. - Se l'app è installata e non prende posizione, disinstallala e reinstallala dopo aver concesso il permesso nel browser.
Non serve fare niente: l'app rileva il service worker nuovo, lo attiva e ricarica una volta sola.
L'app non contatta nessun server dopo il primo caricamento. Niente tile server, niente PMTiles, niente R2: Lanzarote è un'isola piccola e la sua rete stradale sta in un GeoJSON che il browser tiene in cache.
| File | Contenuto | Peso | Compresso |
|---|---|---|---|
data/basemap.geojson |
8813 strade, 217 tratti di costa, 10 centri abitati | 1,6 MB | ~200 KB |
data/speed_limits.geojson |
2106 tratti con maxspeed reale |
359 KB | ~44 KB |
data/speed_cameras.geojson |
16 autovelox OSM | 2 KB | 0,4 KB |
vendor/maplibre-gl.js |
motore mappa, servito in locale | 803 KB | ~220 KB |
Cloudflare Pages comprime in gzip/brotli: il primo caricamento costa meno di 1 MB. Da lì in poi il service worker serve tutto dalla cache, anche in modalità aereo.
La mappa è disegnata da MapLibre direttamente dal GeoJSON, con quattro livelli (costa, strade minori, secondarie, primarie). Le etichette dei paesi sono marker HTML e non glyph: i font glyph sarebbero un'altra dipendenza di rete.
I dati in data/ sono un'estrazione OSM del bbox di Lanzarote
(28.83,-13.90,29.27,-13.40). Per rigenerarli servono le query Overpass in
tools/:
tools/grab_osm.sh # scarica gli estratti (quadrante per quadrante)
python3 tools/build_data.py tools/osm dataOverpass rifiuta le query troppo grandi: lo script divide l'isola in quadranti e riprova con backoff. Rigenera i dati ogni tanto — i limiti cambiano.
⚠️ Gli avvisi non sostituiscono i cartelli sulla strada. La copertura OSM dimaxspeedè buona sulle arterie (LZ-1/2/3) e lacunosa sulle secondarie: dove il dato manca, l'app non mostra nulla invece di indovinare. Il database degli autovelox è parziale per costruzione. In Spagna gli avvisi sugli autovelox fissi sono ammessi, quelli sui controlli mobili no.
La sola distanza non basta: con i dati OSM reali, a 120 m da una statale ci sono vicoli da 20 km/h, e il cartello sbagliato compariva in autostrada (difetto trovato in test). Il map-matching usa tre criteri:
- distanza dal segmento, entro 45 m;
- direzione di marcia — un segmento a 90° dalla traiettoria paga 90 m di penalità, quindi perde contro la strada su cui stai davvero viaggiando;
- isteresi — il cartello cambia solo dopo due letture concordi, così un fix GPS sporco non lo fa lampeggiare.
La direzione arriva da coords.heading se il telefono la fornisce, altrimenti è
calcolata dagli ultimi due fix (scartando spostamenti sotto i 4 m, che sono rumore).
index.html app completa (UI + mappa + logica GPS/limiti/autovelox)
sw.js service worker: cache offline
manifest.webmanifest installabilità PWA
_headers regole di cache per Cloudflare Pages
vendor/maplibre-gl.{js,css} motore mappa, servito in locale
data/basemap.geojson strade, costa e paesi — la mappa offline
data/speed_limits.geojson limiti di velocità OSM
data/speed_cameras.geojson autovelox OSM
tools/ script di rigenerazione dei dati
icon-*.png icone app
Test eseguito con la rete staccata dopo il primo caricamento:
- la mappa si disegna: 9040 feature, isola intera, nomi dei paesi, 16 autovelox
- demo lungo la LZ-1: tachimetro 90 km/h e cartello del limite stabile a 90 per tutta la corsa (25 campioni consecutivi, nessuna oscillazione)
- service worker in controllo della pagina, tutti gli asset serviti dalla cache
- zero errori JS e zero richieste di rete
Da verificare sul telefono: permesso GPS reale, precisione in movimento, installazione dalla schermata Home.