diff --git a/Dockerfile b/Dockerfile index 40db75c..69ec51e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -63,8 +63,7 @@ ENV PORT 3000 ENV HOSTNAME "0.0.0.0" # Start command: migrate DB and start server -# Note: In production, migrations should ideally be run in a separate step or init container, -# but for simplicity with SQLite we can run push here or assume the volume has the DB. -# We'll use a custom start script or just run server, assuming user handles migration or we use prisma db push on start. -# Let's use a simple entrypoint script to ensure DB exists. -CMD ["node", "server.js"] +COPY --from=builder --chown=nextjs:nodejs /app/scripts/docker-entrypoint.sh ./scripts/docker-entrypoint.sh +RUN chmod +x ./scripts/docker-entrypoint.sh + +CMD ["./scripts/docker-entrypoint.sh"] diff --git a/package.json b/package.json index ec4cf24..fbf7469 100644 --- a/package.json +++ b/package.json @@ -5,13 +5,14 @@ "scripts": { "dev": "next dev", "build": "next build", - "start": "next start", + "start": "prisma migrate deploy && next start", "lint": "eslint" }, "dependencies": { "@prisma/client": "^6.19.0", "music-metadata": "^11.10.2", "next": "16.0.3", + "prisma": "^6.19.0", "react": "19.2.0", "react-dom": "19.2.0" }, @@ -22,7 +23,6 @@ "babel-plugin-react-compiler": "1.0.0", "eslint": "^9", "eslint-config-next": "16.0.3", - "prisma": "^6.19.0", "typescript": "^5" } -} +} \ No newline at end of file diff --git a/scripts/docker-entrypoint.sh b/scripts/docker-entrypoint.sh new file mode 100755 index 0000000..e2855e4 --- /dev/null +++ b/scripts/docker-entrypoint.sh @@ -0,0 +1,12 @@ +#!/bin/sh +set -e + +echo "Starting deployment..." + +# Run migrations +echo "Running database migrations..." +npx prisma migrate deploy + +# Start the application +echo "Starting application..." +exec node server.js diff --git a/walkthrough.md b/walkthrough.md index 1027832..3fb232c 100644 --- a/walkthrough.md +++ b/walkthrough.md @@ -1,41 +1,55 @@ -# Hördle - Walkthrough +# Genre/Tag System Implementation Walkthrough -Die Hördle Webapp ist nun einsatzbereit. Hier ist eine Anleitung, wie du sie nutzt und verwaltest. +## Overview +Implemented a comprehensive Genre/Tag system for Hördle, allowing songs to be categorized and users to play genre-specific daily puzzles. -## Starten der App +## Changes -1. Öffne ein Terminal im Projektverzeichnis: `/home/markus/hördle` -2. Starte den Entwicklungsserver: - ```bash - npm run dev - ``` -3. Öffne `http://localhost:3000` im Browser. +### Database +- **New Model**: `Genre` (id, name, songs, dailyPuzzles). +- **Updated Model**: `Song` (added M-N relation to `Genre`). +- **Updated Model**: `DailyPuzzle` (added optional `genreId`, updated unique constraint to `[date, genreId]`). -## Admin-Bereich (Songs hochladen) +### Backend API +- **`app/api/genres/route.ts`**: New endpoints for GET (list) and POST (create) and DELETE genres. +- **`app/api/songs/route.ts`**: Updated to handle genre assignment (POST/PUT) and retrieval (GET). +- **`app/api/daily/route.ts`**: Updated to support `?genre=` query parameter. +- **`lib/dailyPuzzle.ts`**: Shared logic for fetching/creating daily puzzles (Global or Genre-specific). -1. Gehe zu `http://localhost:3000/admin` -2. Logge dich ein. Das Standard-Passwort ist `admin123` (kann in `.env` geändert werden). -3. **Upload**: Wähle eine MP3-Datei aus. Titel und Interpret werden automatisch aus den ID3-Tags ausgelesen, falls du die Felder leer lässt. -4. **Bibliothek**: Unter dem Upload-Formular siehst du eine Tabelle aller verfügbaren Songs. +### Frontend (Admin) +- **Genre Management**: Create and delete genres. +- **Song Assignment**: Assign genres during upload and edit. +- **Post-Upload Workflow**: Prompt to assign genres immediately after upload. +- **Song List**: Display assigned genres in the table. -## Spielablauf +### Frontend (User) +- **Genre Selection**: Links on the main page to switch between Global and Genre-specific games. +- **Game Logic**: Refactored to support independent game states per genre (localStorage keys: `hoerdle_game_state_`). +- **Dynamic Route**: `app/[genre]/page.tsx` for genre-specific URLs. +- **Sharing**: Share text now includes the genre name. -- Das Spiel wählt jeden Tag (um Mitternacht) automatisch einen neuen Song aus der Datenbank. -- Wenn noch kein Song für den heutigen Tag festgelegt wurde, wird beim ersten Aufruf der Seite zufällig einer ausgewählt. -- Der Spieler hat 6 Versuche. -- Der Fortschritt wird im LocalStorage des Browsers gespeichert. +### Deployment +- **Auto-Migration**: Added `scripts/docker-entrypoint.sh` to run `prisma migrate deploy` on startup. +- **Dockerfile**: Updated to use the entrypoint script. +- **Dependencies**: Moved `prisma` to `dependencies` in `package.json`. -## Technologien +## Verification Results -- **Framework**: Next.js 14 (App Router) -- **Datenbank**: SQLite (via Prisma) -- **Styling**: Vanilla CSS (in `app/globals.css`) -- **State**: React Hooks + LocalStorage +### Automated Build +- `npm run build` passed successfully. +- `npx prisma generate` passed. -## Wichtige Dateien - -- `app/page.tsx`: Hauptseite des Spiels. -- `components/Game.tsx`: Die Spiellogik. -- `components/AudioPlayer.tsx`: Der Audio-Player mit Segment-Logik. -- `app/api/daily/route.ts`: API für das tägliche Rätsel. -- `prisma/schema.prisma`: Datenbank-Schema. +### Manual Verification Steps (Recommended) +1. **Admin Dashboard**: + * Go to `/admin`. + * Create a new genre (e.g., "Rock"). + * Upload a song and assign "Rock" to it. + * Edit an existing song and assign "Rock". +2. **User Interface**: + * Go to `/`. Verify "Global" game works. + * Click "Rock". Verify URL changes to `/Rock`. + * Play the "Rock" game. Verify it picks a song tagged with "Rock". + * Verify stats are separate for Global and Rock. +3. **Deployment**: + * Deploy to Docker. + * Verify migrations run automatically on startup.