# Hördle Eine Web-App inspiriert von Heardle, bei der Nutzer täglich einen Song anhand kurzer Audio-Schnipsel erraten müssen. ## Features - **Tägliches Rätsel:** Jeden Tag ein neuer Song für alle Nutzer. - **Inkrementelle Hinweise:** Startet mit 2 Sekunden, dann 4s, 7s, 11s, 16s, 30s, bis 60s (7 Versuche). - **Admin Dashboard:** - Upload von MP3-Dateien. - Automatische Extraktion von ID3-Tags (Titel, Interpret). - Bearbeitung von Metadaten. - Sortierbare Song-Bibliothek (Titel, Interpret, Hinzugefügt am). - Play/Pause-Funktion zum Vorhören in der Bibliothek. - **Cover Art:** - Automatische Extraktion von Cover-Bildern aus MP3-Dateien. - Anzeige des Covers nach Spielende (Sieg/Niederlage). - Automatische Migration bestehender Songs. - **Teilen-Funktion:** Ergebnisse können als Emoji-Grid geteilt werden. - **PWA Support:** Installierbar als App auf Desktop und Mobilgeräten (Manifest & Icons). - **Persistenz:** Spielstatus wird lokal im Browser gespeichert. - **Benachrichtigungen:** Integration mit Gotify für Push-Nachrichten bei Spielabschluss. - **Genre-Management:** - Erstellen und Verwalten von Musik-Genres. - Manuelle Zuweisung von Genres zu Songs. - KI-gestützte automatische Kategorisierung mit OpenRouter (Claude 3.5 Haiku). - Genre-spezifische tägliche Rätsel. ## Tech Stack - **Framework:** Next.js 16 (App Router) - **Styling:** Vanilla CSS - **Datenbank:** SQLite (via Prisma ORM) - **Deployment:** Docker & Docker Compose ## Lokale Entwicklung 1. Abhängigkeiten installieren: ```bash npm install ``` 2. Datenbank initialisieren: ```bash npx prisma generate npx prisma db push ``` 3. **Optional: Cover-Bilder migrieren:** Falls MP3-Dateien ohne Cover in der Datenbank sind: ```bash node scripts/migrate-covers.mjs ``` 4. Entwicklungsserver starten: ```bash npm run dev ``` Die App läuft unter `http://localhost:3000`. ## Deployment mit Docker Das Projekt ist für den Betrieb mit Docker optimiert. 1. **Vorbereitung:** Kopiere die Beispiel-Konfiguration: ```bash cp docker-compose.example.yml docker-compose.yml ``` Passe die Umgebungsvariablen in der `docker-compose.yml` an: - `ADMIN_PASSWORD`: Admin-Passwort als Bcrypt-Hash. Erstelle den Hash mit: `node scripts/hash-password.js ` Standard (admin123): `$2b$10$SHOt9G1qUNIvHoWre7499.eEtp5PtOII0daOQGNV.dhDEuPmOUdsq` - `TZ`: Zeitzone für täglichen Puzzle-Wechsel (Standard: `Europe/Berlin`) - `GOTIFY_URL`: URL deines Gotify Servers (z.B. `https://gotify.example.com`) - `GOTIFY_APP_TOKEN`: App Token für Gotify (z.B. `A...`) - `OPENROUTER_API_KEY`: API-Key für OpenRouter (für KI-Kategorisierung, optional) 2. **Starten:** ```bash docker compose up --build -d ``` Die App ist unter `http://localhost:3010` erreichbar (Port in `docker-compose.yml` konfiguriert). 3. **Daten-Persistenz:** - Die SQLite-Datenbank wird im Ordner `./data` gespeichert. - Hochgeladene Songs und Cover liegen in `./public/uploads`. - Beide Ordner werden als Docker Volumes eingebunden, sodass Daten auch bei Container-Neustarts erhalten bleiben. - Beim Start des Containers wird automatisch ein Migrations-Skript ausgeführt, das fehlende Cover-Bilder aus den MP3s extrahiert. 4. **Admin-Zugang:** - URL: `/admin` - Standard-Passwort: `admin123` (Bitte in `docker-compose.yml` ändern! Muss als Hash hinterlegt werden.) ## Nginx-Konfiguration (für Reverse Proxy) Wenn du Nginx als Reverse Proxy verwendest, benötigst du spezielle Einstellungen für Audio-Streaming: ```nginx server { listen 80; server_name your-domain.com; # Erhöhe Upload-Limit client_max_body_size 50M; location / { proxy_pass http://localhost:3010; proxy_http_version 1.1; # Wichtig für Audio-Streaming: Range Requests weiterleiten proxy_set_header Range $http_range; proxy_set_header If-Range $http_if_range; proxy_no_cache $http_range $http_if_range; # Standard Proxy Headers proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } ``` Eine vollständige Beispiel-Konfiguration findest du in `nginx.conf.example`. ## Troubleshooting ### Audio-Dateien lassen sich nicht abspielen (in Produktion mit Nginx) **Problem:** MP3-Dateien funktionieren lokal, aber nicht hinter Nginx. **Lösung:** 1. Stelle sicher, dass Nginx Range Requests unterstützt (siehe Nginx-Konfiguration oben) 2. Prüfe die Nginx-Logs: `sudo tail -f /var/log/nginx/error.log` 3. Teste direkt ohne Nginx: `http://localhost:3010/uploads/dateiname.mp3` 4. Überprüfe die Response-Headers im Browser (Developer Tools → Network) **Wichtige Nginx-Einstellungen:** - `proxy_set_header Range $http_range;` - Leitet Range Requests weiter - `proxy_buffering off;` - Deaktiviert Buffering für große Dateien - `client_max_body_size 50M;` - Erlaubt große Uploads ## Lizenz MIT