Piattaforma web AI per la valorizzazione turistica di Gioiosa Marea, costa tirrenica messinese. Powered by TTATTÀ GO.
Tutte le versioni e gli aggiornamenti rilasciati in produzione.
/esplora/guida-turistica): mappa Leaflet con tutti i POI numerati, filtri per categoria, sheet detail mobile swipe-up + desktop panel fisso, zoom auto al click, versione stampabile PDFmedia="print" trick — eliminato blocco render da ~800ms su mobilemarked.min.js caricato con defer — non blocca più il render sulla homepageisolation: isolate su tutti i container Leaflet — z-index interni Leaflet (fino a 1000) confinati nel proprio stacking context, bottom nav e overlay non più bucati dalla mappa/mangia/:slug, /dormi/:slug, ecc.open_now? real-timePiattaforma web Rails che funge da guida turistica AI per Gioiosa Marea. Gli utenti accedono tramite QR code — nessuna installazione richiesta. I dati di luoghi, eventi, esperienze e vendor sono sincronizzati automaticamente dalla piattaforma TTATTÀ GO.
Ogni punto del paese ha il suo QR code. L'utente inquadra e accede istantaneamente all'app senza installare nulla. Installabile come PWA da browser.
Web App + PWAMappa Leaflet con tutti i POI numerati, filtrabili per categoria. Sheet detail con foto, orari, indicazioni. Stampabile come PDF in 3 sezioni geografiche.
Leaflet.jsChat con Claude Haiku che conosce tutti i luoghi, il meteo attuale, gli orari e la storia del territorio. Input testuale e vocale (Whisper). Streaming real-time.
Claude + WhisperDurata, interessi, tipo di gruppo → Claude genera un itinerario su misura verificando orari apertura, meteo e preferenze. Output con mappa Leaflet integrata.
AI PersonalizedSolidQueue jobs sincronizzano automaticamente eventi, esperienze, vendor e luoghi dalla piattaforma madre. Fallback graceful se API non raggiungibile.
SolidQueue + APIGeolocalizzazione browser con calcolo distanza Haversine. Ordina e filtra luoghi, vendor ed esperienze per prossimità rispetto alla posizione corrente dell'utente.
Geolocation APIOgni componente scelto per leggerezza, velocità di sviluppo e minima dipendenza da servizi esterni.
| Layer | Tecnologia |
|---|---|
| Framework | Ruby on Rails 8.1.2 |
| Linguaggio | Ruby 3.4.7 |
| Database | SQLite3 via Active Record (3 DB separati: main, cache, queue) |
| Frontend | Hotwire (Turbo Drive + Turbo Streams + Stimulus) + Tailwind CSS |
| Asset pipeline | Propshaft + Importmap (no Webpack/bundler) |
| Mappe | Leaflet.js 1.9.4 + leaflet.markercluster via CDN |
| AI — Chat & Itinerario | Claude Haiku 4.5 (claude-haiku-4-5-20251001) via ruby_llm gem |
| AI — Voce | OpenAI Whisper API (trascrizione audio → testo) |
| Streaming | ActionCable + Turbo::StreamsChannel broadcast |
| Job Queue | Solid Queue (integrato in Puma, SQLite-backed) |
| Cache | Solid Cache (SQLite-backed, configurato in config/cache.yml) |
| Meteo | Open-Meteo API — gratuita, no API key, coordinate fisse Gioiosa Marea |
| Dati esterni | TTATTÀ GO REST API — sync eventi/esperienze/vendor/luoghi |
| Markdown rendering | marked.js 9 via CDN (con defer — non blocca render) |
| Deploy | VPS Linux — server dedicato configurato ad hoc, Puma + Nginx reverse proxy |
| Static files cache | public_file_server.headers → Cache-Control: public, max-age=31536000 |
I contenuti (eventi, esperienze, vendor, luoghi) vengono sincronizzati dalla piattaforma TTATTÀ GO tramite la sua REST API. Ogni sync service è idempotente e gestisce gracefully i fallback.
TtattaApi.events(place_slug: "gioiosa-marea")
TtattaApi ritorna nil (timeout, errore di rete, API down), il sync service aggiunge un entry in result.errors e interrompe senza crashare. I dati esistenti rimangono intatti. Il job viene loggato su stdout per monitoring.
SQLite3 con Active Record. Schema evoluto da 3 a 9+ tabelle con l'aggiunta di vendor, eventi, esperienze e sincronizzazione API.
hours_json — chiavi giorno (mon–sun), array di slot [apertura, chiusura]:
Routing completo dell'applicazione. Tutte le URL sono SEO-friendly con slug leggibili.
| Metodo | Path | Descrizione |
|---|---|---|
| GET | / | Homepage con preview dinamica di tutti i contenuti |
| GET | /esplora | Mappa Leaflet + griglia luoghi con filtri categoria |
| GET | /esplora/:slug | Dettaglio luogo con gallery, mappa, orari, indicazioni |
| GET | /esplora/guida-turistica | Guida turistica interattiva — mappa POI + list + sheet detail + print |
| GET | /eventi | Griglia eventi con badge stato, filtro attivi/passati |
| GET | /eventi/:slug | Dettaglio evento con mappa e link prenotazione |
| GET | /esperienze | Griglia esperienze con badge difficulty, price, season |
| GET | /esperienze/:slug | Dettaglio esperienza con link prenotazione TTATTÀ GO |
| GET | /mangia / /mangia/:slug | Vendor food — ristoranti, bar, locali |
| GET | /dormi / /dormi/:slug | Vendor sleep — hotel, agriturismi, B&B |
| GET | /benessere / /benessere/:slug | Vendor wellness — lidi, spa, centri benessere |
| GET | /produttori / /produttori/:slug | Vendor producers — artigiani, tipicità |
| GET | /vita-notturna / /vita-notturna/:slug | Vendor nightlife — discoteche, locali serali |
| GET | /servizi-turistici / /servizi-turistici/:slug | Vendor tourism — guide, noleggi, servizi |
| GET | /assistente | UI chat AI con input testuale e vocale (Whisper) |
| POST | /assistente | Invia messaggio → avvia ChatStreamJob |
| POST | /assistente/voice | Upload audio → Whisper → risposta AI |
| DEL | /assistente | Reset conversazione |
| GET | /itinerario | Form generatore + widget meteo |
| POST | /itinerario | Avvia ItineraryStreamJob |
| GET | /up | Health check ping (monitoraggio server) |
| GET | /manifest | Web App Manifest JSON per PWA |
| GET | /docs | Questa documentazione (static HTML) |
Chat, itinerario e voce: architettura streaming basata su ActionCable + SolidQueue.
OpenAI::Client.audio.transcribe()
ChatStreamJob.perform_later(chat_id)
ItineraryStreamJob.perform_later(params)
Ogni pagina ha dati strutturati schema.org specifici per il tipo di contenuto. Copertura completa per Google Search e Google Maps.
StructuredDataHelper in Ruby come JSON-LD e iniettati nell'<head> via content_for :structured_data. Nessun JavaScript necessario — markup statico nell'HTML.
L'app è installabile come PWA su iOS e Android direttamente dal browser, senza App Store.
Ottimizzazioni applicate per migliorare PageSpeed Insights mobile (target: score > 90 su tutte le metriche).
Integrazione Open-Meteo — completamente gratuita, nessuna API key richiesta.
Server VPS Linux dedicato, configurato ad hoc. Puma come application server, Nginx come reverse proxy. Deploy via SSH con git pull e restart.
File principali dell'applicazione organizzati per layer.