Zurück DOKUMENTATION
📄 OpenAPI YAML

Lauschfreunde — Dokumentation

Technische Referenz zum kooperativen Hör-Abenteuerspiel: Architektur, Spielablauf, QR-System, Sprachsynthese-Pipeline, PDF-Generierung und API.

Architektur-Übersicht

Lauschfreunde ist eine React-Single-Page-Application, die das Spiel und den Admin-Bereich in einem gemeinsamen Bundle ausliefert. Sie kommuniziert über eine REST-Schnittstelle mit dem Nexus-Backend — einer Node.js-Anwendung auf Basis von Express, mit eingebetteter SQLite-Datenbank und JWT-basierter Authentifizierung. Als Progressive Web App läuft das Frontend nach dem ersten Laden auch ohne Internetverbindung.

Spiel- und Admin-Bereich teilen sich eine einzige React-Codebasis (der Admin-Bereich liegt unter dem Pfad /admin). Frontend und Backend sind klar entkoppelt — das Frontend lässt sich dadurch unabhängig ausliefern.
Browser / PWA — installierbar, offline-fähig Game-Flow Admin / Editor Service Worker (Cache) REST · JWT (Bearer) WebSocket (Socket.io) Nexus-API (Node.js) Express · JWT-Auth · Multer Boxen · Adventures · Cards · Uploads cddevapps.com/api/nexus/lauschfreunde Datenhaltung & Infra SQLite (better-sqlite3) Datei-Storage (Audio/Bild/PDF) nginx Reverse Proxy · PM2 ElevenLabs TTS (extern)

Frontend-Stack

KomponenteTechnologieVersion
FrameworkReact19.x
Build-ToolVite8.x
CSSTailwindCSS4.x
RoutingReact Router7.x
QR-Scannerhtml5-qrcode + jsQR (Fallback)2.x / 1.x
Audio-PlayerHowler.js2.x
PWA / Offlinevite-plugin-pwa (Workbox)1.x
PDF-GenerierungjsPDF + qrcode4.x / 1.x
Bild-Analysenode-vibrant (Farbpaletten)3.x

Backend-Stack (Nexus)

Das Nexus-Backend ist eine schlanke Node.js-Anwendung auf einem einzelnen Server — ohne externe Datenbank-Abhängigkeit.

KomponenteTechnologieVersion
Sprache & RuntimeJavaScript / Node.js≥ 18
Web-FrameworkExpress4.21
Echtzeit-KommunikationSocket.io (WebSocket)4.7
DatenbankSQLite via better-sqlite3 (eingebettet)11.x
Authentifizierungjsonwebtoken (JWT, 30 Tage gültig)
Datei-Uploadsmulter (multipart/form-data)
Schutzexpress-rate-limit · cors
SprachsyntheseElevenLabs API (eleven_multilingual_v2)v1
Process-ManagerPM2
Reverse Proxynginx (leitet /api/nexus/ und /socket.io/ an Port 3001)

Dateistruktur

Das Frontend ist nach Feature-Bereichen gegliedert: getrennte Verzeichnisse für pages/game/ und pages/admin/, eigene Hooks bündeln die Spiel-Logik, und lib/ kapselt die API-Aufrufe und externen Anbindungen.

📁 lauschfreunde-app/ React SPA (Vite)
📁 src/
📁 pages/game/ Home, BoxDetail, Scan, Assign, StrandSort, Solution, Finale, Celebration
📁 pages/admin/ Dashboard, BoxEdit, AdventureEdit, QRExport, Login
📁 hooks/ useGameState · useAudio · useQRScanner · useBoxData · useDemoMode
📁 components/ ui/ · game/ · decorative/
📁 lib/ api.js · elevenlabs.js · qr.js · generateMaterialPdf.js · generateCertificatePdf.js
📁 utils/ constants.js
📁 public/ PWA-Assets, Icons, Manifest
📁 landing/ Diese Seite (statisch)
📄 api-spec.yaml OpenAPI 3.0

Spielablauf

Ein typisches Abenteuer durchläuft die folgenden Phasen:

Box wählen HomePage → BoxDetailPage Abenteuer wählen + Schwierigkeit setzen Leicht (zuordnen) · Fortgeschritten (zuordnen + sortieren) → AdventureIntroPage QR-Code scannen html5-qrcode · jsQR-Fallback Audio abspielen Howler.js · Charakter-Stimme Lauschfreund zuordnen AssignPage noch Karten? → ja 12 Karten zugeordnet Reihenfolge sortieren (optional) Nur in Stufe „Fortgeschritten" → StrandSortPage Holzfiguren platzieren SolutionPage prüft Lösung Richtig ✓ Finale-Audio · Feier · Urkunde Falsch ✗ Hinweis · erneut versuchen

Zustands-Übersicht

Der Spielzustand wird über Custom Hooks (vor allem useGameState) verwaltet. Die wichtigsten Zustände im Spielverlauf:

ZustandBeschreibung
idleStartseite, noch kein Spiel aktiv
selectingBox oder Abenteuer wird ausgewählt
scanningQR-Scanner ist aktiv und wartet auf eine Karte
listeningAudio-Schnipsel wird abgespielt
assigningKarte wird einem Lauschfreund zugeordnet
sortingKarten werden in die richtige Reihenfolge gebracht (nur fortgeschrittene Stufe)
solvingHolzfiguren werden auf die Lösungstafel gestellt
completeAbenteuer erfolgreich abgeschlossen

QR-System

Payload-Format

Jeder QR-Code enthält einen kompakten Identifikator nach folgendem Schema:

lauschfreunde:<box-slug>:<adventure-slug>:<card-slug>

Der Server liefert über GET /cards/resolve?qr=... die zugehörige Karte samt Audio-URL und Charakter-Zuordnung zurück.

Das Präfix lauschfreunde: dient als Marker. Codes ohne dieses Präfix werden vom Scanner ignoriert.

Zwei Scanner parallel

Die App nutzt zwei Scanner-Bibliotheken nebeneinander, um auf möglichst vielen Geräten zuverlässig zu funktionieren:

ScannerStärkeRolle
html5-qrcodeNutzt direkt die Kamera-API des Browsers, schnellPrimär
jsQRCanvas-basiert, größere Kompatibilität auf älteren GerätenFallback

TTS-Pipeline

Übersicht

Audio lässt sich direkt aus dem Admin-Editor per ElevenLabs erzeugen. Das Ergebnis wird als MP3 im Storage abgelegt und über eine URL mit der jeweiligen Karte oder dem Abenteuer verknüpft. Für produktive Aufnahmen können alternativ fertige MP3-Dateien hochgeladen werden.

1. Admin-Editor Text + Charakter-Voice-ID 2. POST /admin/tts Bearer Token, JSON-Payload ElevenLabs API eleven_multilingual_v2 MP3 44.1k/128 3. Im Storage ablegen + URL erhalten files/audio/<box>/<adventure>/<card>.mp3 4. URL an Karte / Adventure speichern PUT /admin/cards/:id · PUT /admin/adventures/:id

Stimmen-Konfiguration

Jeder Charakter bekommt eine eigene Stimme. Die jeweilige Voice-ID wird pro Charakter in der Datenbank hinterlegt und beim Generieren mitgeschickt.

ParameterWertBeschreibung
model_ideleven_multilingual_v2Mehrsprachiges Modell mit guter deutscher Aussprache
stability0.5Natürliche Variation
similarity_boost0.75Stimmkonsistenz
output_formatmp3_44100_128Hohe Qualität für Kinder-Audio

PDF-Generierung (optional — nur für selbst angelegte Editor-Inhalte)

Spielkarten

Für Welten, die im Editor selbst angelegt wurden, erzeugt das Admin-Panel druckfertige A4-PDFs mit den Karten, QR-Codes und Schnittmarken. Bei einem Verlagsprodukt entfällt das — die Box wird mit fertig produziertem Material ausgeliefert.

A4 — 6 Karten pro Bogen, Schnittmarken Bild Titel Bild Titel Bild Titel Bild Titel Bild Titel Bild Titel
Hochgeladene Bildvorlagen werden automatisch auf die Kartengröße skaliert. Empfohlenes Quellformat: 1240×1748 px (A5 hoch), PNG oder JPG.

Urkunden

Nach Abschluss eines Abenteuers können die Kinder eine Urkunde als PDF herunterladen. Sie nennt das gelöste Abenteuer, das Datum und trägt ein Siegel mit Lauschfreunde-Branding.

API Endpoints

Übersicht

Die Nexus REST-API ist in zwei Bereiche aufgeteilt: öffentliche Game-Endpoints (kein Auth) und Admin-Endpoints (Bearer Token). Alle Antworten kommen im Envelope { data: ... }; Fehler als { error: "..." }.

BereichPräfixAuth
Game/boxes · /cards/resolve · /crossover-bonusKeine
Auth/auth/loginLogin
Admin Content/admin/boxes · /admin/characters · /admin/adventures · /admin/cardsBearer
Uploads/admin/upload/audio · /admin/upload/image · /admin/upload/pdfBearer
TTS/admin/tts/*Bearer

Basis-URL in Produktion: https://cddevapps.com/api/nexus/lauschfreunde

Authentifizierung

Admin-Login über E-Mail + Passwort. Antwort enthält den Bearer Token, der im Frontend in localStorage liegt und bei jedem Admin-Request mitgeschickt wird.

POST /auth/login
Content-Type: application/json

{
  "email": "admin@example.com",
  "password": "***"
}

Response: { "data": { "token": "eyJhbG...", "user": { ... } } }
Alle /admin/*-Endpoints erfordern Authorization: Bearer <token>. Die App speichert den Token unter dem Key lf_admin_token.

Spiel-Routen (öffentlich)

MethodePfadBeschreibung
GET/boxesAlle verfügbaren Boxen auflisten
GET/boxes/:slugVollständige Box-Daten inkl. Charakteren, Abenteuern und Karten
GET/cards/resolve?qr=...QR-Code auflösen und die zugehörige Karte samt Audio-URL zurückgeben
GET/crossover-bonusCrossover-Bonus zwischen zwei Boxen abfragen

Admin: Inhalte verwalten (Bearer Token)

MethodePfadBeschreibung
POST/admin/boxesBox anlegen
PUT/admin/boxes/:idBox bearbeiten
DELETE/admin/boxes/:idBox löschen
POST/admin/boxes/:id/charactersCharakter zu einer Box hinzufügen
PUT/admin/characters/:idCharakter bearbeiten (inkl. Voice-ID)
DELETE/admin/characters/:idCharakter löschen
POST/admin/boxes/:id/adventuresAbenteuer zu einer Box hinzufügen
PUT/admin/adventures/:idAbenteuer bearbeiten (inkl. asset_pdf_url)
POST/admin/adventures/:advId/cardsKarte zu einem Abenteuer hinzufügen
PUT/admin/cards/:idKarte bearbeiten
PUT/admin/adventures/:id/solution-placementsFelder der Lösungstafel konfigurieren
PUT/admin/adventures/:id/special-soundsSpezial-Sounds (Sticker-Trigger) konfigurieren

Admin: Uploads und Sprachsynthese (Bearer Token)

MethodePfadBeschreibung
POST/admin/upload/audioMP3-Datei hochladen (max. 10 MB)
POST/admin/upload/imagePNG- oder JPG-Bild hochladen
POST/admin/upload/pdfPDF-Datei hochladen, etwa für Spielmaterial (max. 10 MB)
POST/admin/tts/previewVorschau einer Sprachausgabe erzeugen, ohne sie zu speichern
POST/admin/tts/generate-and-saveSprachausgabe erzeugen, speichern und der Karte zuweisen
POST/admin/tts/sound-effectSound-Effekt per ElevenLabs erzeugen
GET/admin/tts/usageAktuelles ElevenLabs-Kontingent und Verbrauch abfragen
Datei-Uploads laufen als multipart/form-data mit den Feldern file und path. Der Browser setzt dabei die Boundary selbst — der Client darf keinen Content-Type explizit setzen.