"Inguru" means "around / nearby" in Basque.
Inguru is a mobile-first progressive web app that shows you what's happening around you, right now, during a local festival. Built for the Fêtes de Bayonne, it's fully generic and can host any festival with just three JSON files.
- 🗺️ OpenStreetMap — 100% free, zero API key required
▶️ 2-line smart markers — short event name + live countdown (in 42min/in 2h30/Mon. at 8:30pm/dd/MM at HH:mm)- 🔴 Animated LIVE dot on currently running events
- 🚫 Past events auto-hidden — only present and future events appear on the map
- 📍 Floating locate button (FAB) — bottom-right, re-centers on your position, requests permission if needed
- 💬 Liquid Glass popup on marker tap:
- Mobile: slides up from the bottom, max 50% screen height, internal scroll
- Desktop: centered on screen, min 25vw width, internal scroll
- Shows: title, time range, status badge, live countdown, tags, description, walking distance, today's schedule
- 🗺️ Go there button → opens Google Maps link from
venues.json - 💬 Tell my friends button → Web Share API (WhatsApp, SMS…) with a pre-filled message and nav link
- 🌐 Trilingual FR / ES / EU — language picker in the header, all translations inline (no network fetch)
- 🎨 Per-festival dual-color theme — primary/secondary colors injected as CSS variables from
data/index.json - 🎪 Festival switcher — dropdown with color-coded cards, status badges, and automatic map flyTo on selection
- 📴 Installable PWA with offline cache via Service Worker
git clone https://github.com/YOUR_USER/inguru.git
cd inguru
python3 -m http.server 8080Open http://localhost:8080. Always use the same origin to avoid Service Worker conflicts.
⚠️ Geolocation requires HTTPS orlocalhost. GitHub Pages provides HTTPS automatically.
- DevTools → Application → Service Workers → Unregister all
- Application → Storage → Clear site data
- Reload
inguru/
├── index.html # Single-page app entry point
├── manifest.json # PWA manifest
├── sw.js # Service Worker (offline cache)
│
├── assets/
│ ├── css/main.css # Liquid Glass design system, mobile-first
│ └── js/
│ ├── app.js # Bootstrap, festival picker, popup, FAB, i18n
│ ├── map.js # Leaflet map, 2-line markers, smooth zoom
│ ├── events.js # Data loading and event filtering
│ ├── time.js # Status logic, countdowns (ISO 8601)
│ ├── i18n.js # FR/ES/EU translations inline — zero fetch
│ └── utils.js # Haversine, formatting, Maps links
│
└── data/
├── index.json # List of all festivals
└── festivals/
├── bayonne-2026/
│ ├── festival.json
│ ├── venues.json # Venues with GPS coords + "go" Maps link
│ └── events.json # Schedule with ISO timestamps + shortName
└── _template/ # Empty template to add a new festival
- Copy
data/festivals/_template/→data/festivals/MY-FESTIVAL-YEAR/ - Fill in the three JSON files (see formats below)
- Add an entry to
data/index.json
The active festival is selected automatically based on today's date.
{
"festivals": [
{
"id": "bayonne-2026",
"name": { "fr": "Fêtes de Bayonne", "es": "Fiestas de Bayona", "eu": "Baionako Festak" },
"city": "Bayonne",
"dates": { "start": "2026-07-29", "end": "2026-08-02" },
"center": { "lat": 43.4929, "lng": -1.4748 },
"theme": { "primary": "#e63012", "secondary": "#ffffff" },
"emoji": "🐄"
}
]
}[
{
"id": "place-liberte",
"name": { "fr": "Place de la Liberté", "es": "Plaza de la Libertad", "eu": "Askatasun Plaza" },
"coords": { "lat": 43.4927, "lng": -1.4743 },
"type": "place",
"address": "Place de la Liberté, Bayonne",
"go": "https://maps.app.goo.gl/XXXXXXX"
}
]
go— Google Maps URL for the venue, used by the "Go there" button and the share message.
[
{
"id": "evt-001",
"city_id": "bayonne-2026",
"venueId": "place-liberte",
"shortName": "Opening ceremony",
"startTimestamp": "2026-07-29T18:00:00+02:00",
"endTimestamp": "2026-07-29T19:30:00+02:00",
"title": {
"fr": "Ouverture officielle – Lâcher de vaches",
"es": "Apertura oficial – Suelta de vacas",
"eu": "Irekiera ofiziala – Behiak askatzea"
},
"description": {
"fr": "La vache landaise fait son entrée…",
"es": "La vaca landesa hace su entrada…",
"eu": "Landako behia hasten du…"
},
"tags": ["gratuit", "tradition"]
}
]
shortName— display name on the map bubble, max 18 characters.
startTimestamp/endTimestamp— ISO 8601 with timezone offset (e.g.+02:00for French summer time).
Settings→Pages→ Source:GitHub Actions- Push to
main→ auto-deploy via.github/workflows/deploy.yml - Live at:
https://YOUR_USER.github.io/inguru/
| Layer | Solution | Cost |
|---|---|---|
| Map | Leaflet.js + OpenStreetMap | Free |
| Distance | Haversine formula (as the crow flies) | Free |
| Navigation | Google Maps / Apple Maps deep link | Free |
| Hosting | GitHub Pages | Free |
| Data | Static JSON files | Free |
| Geolocation | navigator.geolocation Web API |
Free |
| Translations | Inline in i18n.js |
Free |
Total infrastructure cost: €0
| Context | Event popup | Notes |
|---|---|---|
| Mobile portrait | Slides up, bottom half of screen, internal scroll | FAB 📍 fixed bottom-right |
| Mobile landscape | Same, max 50vh | Compact header |
| Tablet / Desktop | Centered, min 25vw, internal scroll, no arrow | 4–5 column festival grid |
v1 — current
- Leaflet map with live 2-line countdown markers
- Liquid Glass popup (mobile bottom sheet / desktop centered)
- Go there + Tell my friends (Web Share API)
- Locate FAB with permission request
- FR / ES / EU inline i18n
- Per-festival dual-color theming
- PWA + offline cache
- Auto-hide past events
v2
- Filters by type, free/paid
- Favorites (localStorage)
- Real walking directions via OSRM (free, open source)
- Push notifications ("starts in 15 min")
v3
- Auto-scraping of official festival schedules
- Lightweight backend for real-time updates
- Community error reporting
MIT — free to use, modify, and redistribute.