Installable, offline-capable Progressive Web App that acts as a visitor companion for multi-day events – line-up, timetable, personal schedule, map, news and push notifications in one app, without an app store.
Core principle: fully static. At runtime the app is purely static (any web space will do); all content comes from versioned JSON files. Data is fetched at build time from selectable sources (manual / Joomla / WordPress) and normalized to a single schema. Reference project: ROCK IM DORF Festival (demo.festivadget.com).
Looking for a crew/staff app to go with it? CrewCare is our companion product for festival crews (shift plans, check-in, invites, push, and more). It is offered as a hosted SaaS solution on request and includes a hosted Festivadget instance.
| Home | Timetable | Line-up |
|---|---|---|
![]() |
![]() |
![]() |
| Map | News feed | More |
|---|---|---|
![]() |
![]() |
![]() |
No build machine, no command line, no technical knowledge required. If you can upload files to a web space, you can run Festivadget:
- Download the latest release package (
festivadget-vX.Y.Z.zip) from the releases page. - Upload its contents via FTP into the webroot of a (sub)domain on any PHP web space (shared hosting is fine).
- Open
https://your-domain/install/in the browser. The wizard checks every requirement, asks for a CMS admin password (plus optional MySQL for web push – the VAPID keys are generated automatically) and sets everything up. It is deliberately foolproof: unsupported setups are caught with a clear message before anything is written. - Delete the
install/folder (one click on the final page) – done. App at/, CMS at/push/cms/.
The package ships with a fictional sample festival ("Gadget Festival") – replace the content right in the CMS. Updates are one click in the CMS "Update" tab; your content is never touched. Details: docs/INSTALL.md.
- Home dashboard: "Now / up next" programme block, news feed preview, sponsor branding, push opt-in.
- Line-up & artist pages: filter by day, detail pages with image, text and slots.
- Timetable: stage grid with time axis plus list view, stages can be hidden.
- My plan: mark favourites, personal schedule, overlap warnings, export as a calendar file (.ics).
- Offline map: Leaflet with preloaded tiles, POIs with freely definable categories and icons.
- News feed: editorial news (scheduled / pinned / expiring), automatic "on stage now" items generated from the programme, optional live news via Telegram.
- Web push (optional): lock-screen notifications including per-category opt-in for visitors – the backend is a set of lightweight PHP files on the same shared web space, no dedicated server required.
- Weather (optional): forecast with a selectable provider.
- Global search across artists, programme, info pages and POIs.
- Info pages, sponsors, tickets: freely editable info pages (Markdown), sponsor grid, ticket shop embedding.
- Full PWA: installable (with built-in Android/iOS hints), offline-capable, automatic updates, content refresh in production without an app rebuild (~2 min).
- Dark/light theme and a selectable app language: 32 visitor languages (de, en, fr, es, it, nl, cs, pl, pt, fi, hu, sk, hr, da, sv, uk, ro, sl, tr, pt-BR, zh-CN, ja-JP, ko-KR, sq, af, el, hi, id, is, nb, ru, th). Content (info pages, news, day labels, POIs, …) can be maintained per language with an English/German fallback.
- Anonymous statistics (optional): page views without user tracking, evaluated in the CMS.
- Mini CMS (optional, PHP): news editor with scheduling & push, POI/category management, statistics, weather configuration – usable from the orga team's phone; interface in four languages (de/en/fr/es, switchable under Settings).
Static PWA + optional PHP backend for push/CMS – deliberately without a permanently running application server:
content/*.json + slots.csv ─┐
Joomla/WordPress REST ──────┼─► scripts/import-from-source.ts ─► public/data/*.json
┘ │
scripts/build-data.ts ────┴─► version.json (hashes)
React (TanStack Query) ◄── fetch /data/*.json ◄── version.json (2-min poll, targeted invalidation)
- App: Vite · React 18 · TypeScript · TailwindCSS · react-router-dom · TanStack Query · Zustand · idb-keyval · Luxon · Leaflet · vite-plugin-pwa · react-i18next · lucide-react · react-markdown.
- Data pipeline: source adapters (manual/Joomla/WordPress) → normalization +
validation →
public/data/*.json+version.jsonwith content hashes. Clients pollversion.jsonevery 2 minutes and re-fetch only changed files. - Web push backend (optional): PHP endpoints + MySQL + cron under
push/on the same shared-hosting web space; VAPID key pair, the public key is embedded into the client build. Details:docs/PUSH.md. - CMS (optional): PHP interface under
push/cms/(news, POIs, statistics, weather; UI in de/en/fr/es). Details:docs/ADMIN.md.
Deep dives: IMPLEMENTATION.md (concept),
docs/DATEN.md (content sources),
docs/TELEGRAM.md (live news). All docs are also
available in German, French and Spanish (language links at the top of each file).
Only needed for development or custom builds – to simply run Festivadget,
use the installation package
above. Maintainers build release packages with tools/build-release.ps1.
Requirements: Node.js ≥ 20 and pnpm (corepack enable is enough).
pnpm install
# Generate content data (sample data lives under content/)
pnpm run import # sources → public/data/*.json (default: everything "manual")
pnpm run build:data # validation + version.json (hashes)
pnpm run dev # dev server (Vite)More commands:
pnpm run typecheck # TypeScript check
pnpm run build # production build into dist/
pnpm run preview # serve the built dist/ locally
pnpm run gen-icons # generate PWA PNG icons from public/icons/*.svg (sharp)All content is data, not code. Which domain comes from which source is controlled by
content-sources.config.ts – per domain manual
(JSON files under content/), joomla or wordpress:
| File | Content |
|---|---|
festival.json |
name, dates, location, home texts, map bounds |
artists.json |
line-up (name, image, text, links) |
stages.json / slots.csv |
stages + programme (timetable) |
info.json |
info pages (Markdown) |
news.json |
editorial news |
pois.json / poi-categories.json |
map points + categories |
sponsors.json |
sponsor grid |
Guide including CMS integration and replacing the sample data:
docs/DATEN.md.
Copy the template: cp .env.example .env
| Variable | Purpose | Visibility |
|---|---|---|
JOOMLA_API_TOKEN |
Joomla API token (build-time import) | secret – Node script only |
WP_USER, WP_APP_PW |
WordPress application password (build-time import) | secret |
VITE_VAPID_PUBLIC_KEY |
public VAPID key for web push (optional fallback – fetched at runtime from /push/vapid.php) |
public (client build) |
Security rule: only variables prefixed with VITE_ end up in browser code.
Never prefix secrets (private VAPID key, CMS tokens) with VITE_.
- Colors/fonts: CSS variables in
src/styles/index.css(dark and light theme), token structure inpackages/tokens. - Logo & icons:
public/icons/(SVG sources,pnpm run gen-iconsproduces the PWA PNGs), header logo and background artwork underpublic/. - Copy: app texts for all 32 visitor languages under
src/i18n/(one JSON per language; the admin/CMS UI stays de/en/fr/es).
pnpm run import && pnpm run build:data && pnpm run build- Upload
dist/to your web space (HTTPS required, SPA fallback + cache headers via.htaccess– seeIMPLEMENTATION.md§15). - Content updates in production: upload only the changed
data/*.json+version.json– clients pick them up within ~2 minutes, no app rebuild needed.
Windows convenience: deploy-data.bat builds and uploads via
FTPS (credentials once in deploy.env.bat from the template, gitignored) – without
arguments only content data, with full the complete app, with push the PHP
backend.
Setting up VAPID, MySQL and cron on shared hosting: docs/PUSH.md.
The push toggle appears in the app under More as soon as a VAPID key is
available (fetched at runtime from /push/vapid.php; VITE_VAPID_PUBLIC_KEY
is an optional build-time fallback). Telegram live news:
docs/TELEGRAM.md.
Code under the GNU AGPLv3: free to use, modify and self-host; if you run a modified version as a network service, you must publish your changes under the same license. Content, logos, maps and trademarks of the reference project are excluded.





