Files
hoerdle/README.md

162 lines
5.6 KiB
Markdown

# 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 <dein-passwort>`
**Wichtig:** In `docker-compose.yml` müssen alle `$` Zeichen im Hash verdoppelt werden (`$$`), damit sie nicht als Variablen interpretiert werden!
Beispiel: `$$2b$$10$$...`
- `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
### Admin Login schlägt fehl (Docker)
**Problem:** "Wrong password" trotz korrekt generiertem Hash.
**Ursache:** Docker Compose interpretiert `$` Zeichen im Hash als Variablen.
**Lösung:**
In der `docker-compose.yml` müssen alle `$` Zeichen im Hash verdoppelt werden (`$$`).
Falsch: `$2b$10$...`
Richtig: `$$2b$$10$$...`
Das Skript `node scripts/hash-password.js <pw>` gibt nun auch direkt den passenden String für Docker Compose aus.
## Lizenz
MIT