diff --git a/README.md b/README.md index 9832e16..e35af89 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,55 @@ Das Projekt ist für den Betrieb mit Docker optimiert. - URL: `/admin` - Standard-Passwort: `admin123` (Bitte in `docker-compose.yml` ändern!) +## 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 diff --git a/app/api/daily/route.ts b/app/api/daily/route.ts index 85affeb..0c62d09 100644 --- a/app/api/daily/route.ts +++ b/app/api/daily/route.ts @@ -1,18 +1,12 @@ import { NextResponse } from 'next/server'; import { PrismaClient } from '@prisma/client'; +import { getTodayISOString } from '@/lib/dateUtils'; const prisma = new PrismaClient(); export async function GET() { try { - // Use timezone from environment variable (default: Europe/Berlin) - const timezone = process.env.TZ || 'Europe/Berlin'; - const today = new Date().toLocaleDateString('en-CA', { - timeZone: timezone, - year: 'numeric', - month: '2-digit', - day: '2-digit' - }); // Format: "2025-11-21" + const today = getTodayISOString(); let dailyPuzzle = await prisma.dailyPuzzle.findUnique({ where: { date: today }, diff --git a/app/page.tsx b/app/page.tsx index f930c14..75daf04 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,4 +1,5 @@ import Game from '@/components/Game'; +import { getTodayISOString } from '@/lib/dateUtils'; export const dynamic = 'force-dynamic'; @@ -14,7 +15,7 @@ if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma; async function getDailyPuzzle() { try { - const today = new Date().toISOString().split('T')[0]; + const today = getTodayISOString(); console.log(`[getDailyPuzzle] Checking puzzle for date: ${today}`); let dailyPuzzle = await prisma.dailyPuzzle.findUnique({ diff --git a/lib/dateUtils.ts b/lib/dateUtils.ts new file mode 100644 index 0000000..639b417 --- /dev/null +++ b/lib/dateUtils.ts @@ -0,0 +1,8 @@ +export function getTodayISOString(timezone = process.env.TZ || 'Europe/Berlin'): string { + return new Date().toLocaleDateString('en-CA', { + timeZone: timezone, + year: 'numeric', + month: '2-digit', + day: '2-digit' + }); +} diff --git a/lib/gameState.ts b/lib/gameState.ts index 0489286..90f9690 100644 --- a/lib/gameState.ts +++ b/lib/gameState.ts @@ -1,6 +1,7 @@ 'use client'; import { useState, useEffect } from 'react'; +import { getTodayISOString } from './dateUtils'; export interface GameState { date: string; @@ -31,7 +32,7 @@ export function useGameState() { useEffect(() => { // Load game state const stored = localStorage.getItem(STORAGE_KEY); - const today = new Date().toISOString().split('T')[0]; + const today = getTodayISOString(); if (stored) { const parsed: GameState = JSON.parse(stored); diff --git a/next.config.ts b/next.config.ts index a0043f5..8e3c525 100644 --- a/next.config.ts +++ b/next.config.ts @@ -9,6 +9,9 @@ const nextConfig: NextConfig = { bodySizeLimit: '50mb', }, }, + env: { + TZ: process.env.TZ || 'Europe/Berlin', + }, async headers() { return [ {