diff --git a/README.md b/README.md index d361d95..32130dc 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ Kalender nie. - 📨 **Buchungsanfragen** annehmen/ablehnen; angenommene Zeiten werden belegt und verhindern Doppelbuchungen - ⚙️ Buchungsregeln: Zeitfenster, Slot-Raster (10–60 Min), Dauern, Wochentage, Horizont (1–120 Tage), Zeitzone - 🧊 **Liquid-Glass-UI** mit **Dark-/Light-Mode**: Umschalter (Auto / Dunkel / Hell) auf jeder Seite, automatische Systemerkennung (`prefers-color-scheme`) inkl. Live-Wechsel, Auswahl wird pro Browser gespeichert +- 📱 **Voll mobilfähig**: responsive Layouts ab ~320 px, 44px-Touch-Targets, kein iOS-Fokus-Zoom (16px-Inputs), Safe-Area-Unterstützung (Notch), `dvh`-Höhen, `touch-action` ohne Doppeltipp-Zoom +- 📲 **PWA**: installierbar (Android/Desktop: „App installieren“, iOS: „Zum Home-Bildschirm“), Manifest mit Maskable-Icons, App-Shortcuts; Service Worker cached die App-Shell → Startseite funktioniert offline (API-Aufrufe brauchen natürlich Netz) - 🔒 Provider-Tokens werden **AES-256-GCM-verschlüsselt** in der SQLite-DB gespeichert ## Tech Stack @@ -58,6 +60,13 @@ go run ./cmd/server Der Go-Server liefert dann das Frontend (`dist/`) **und** die API über einen Port. +### PWA-Hinweise + +- Der Service Worker wird nur im Production-Build registriert (`npm run build` + Auslieferung über `STATIC_DIR`), nicht im Vite-Dev-Modus. +- Die Cache-Version des Service Workers wird pro Build automatisch neu gesetzt (Build-Zeitstempel) — nach einem Deploy holen Clients die neue Version und alte Caches werden geräumt. +- `/api/*` wird niemals gecached; offline funktioniert die App-Shell (Startseite/Navigation), Kalender- und Buchungsdaten benötigen eine Verbindung. +- Icons liegen als SVG-Quellen in `frontend/public/icons/` und werden per `rsvg-convert` zu PNGs konvertiert (Neuerzeugung: siehe Skript unten im Abschnitt „Tests“). + ## Kalender-Anbindung einrichten ### Google @@ -130,3 +139,13 @@ frontend/ ```bash cd backend && go test ./... # ICS-Parser, Dauer-Handling, Interval-Clamping ``` + +PWA-Icons neu erzeugen (benötigt `rsvg-convert`): + +```bash +cd frontend/public/icons +rsvg-convert -w 192 -h 192 -o icon-192.png icon.svg +rsvg-convert -w 512 -h 512 -o icon-512.png icon.svg +rsvg-convert -w 512 -h 512 -o icon-maskable-512.png icon-maskable.svg +rsvg-convert -w 180 -h 180 -o apple-touch-icon.png apple-touch-icon.svg +``` diff --git a/backend/internal/httpapi/server.go b/backend/internal/httpapi/server.go index b884008..da9287d 100644 --- a/backend/internal/httpapi/server.go +++ b/backend/internal/httpapi/server.go @@ -78,6 +78,9 @@ func (s *Server) Router() http.Handler { static := s.Cfg.StaticDir r.Get("/*", func(w http.ResponseWriter, req *http.Request) { p := filepath.Join(static, filepath.Clean(req.URL.Path)) + if strings.HasSuffix(p, ".webmanifest") { + w.Header().Set("Content-Type", "application/manifest+json") + } if st, err := os.Stat(p); err == nil && !st.IsDir() { http.ServeFile(w, req, p) return diff --git a/frontend/index.html b/frontend/index.html index 6be70bb..ae46ef2 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -3,8 +3,14 @@ - + + + + + + +