TT-ControlTurniersystem

TT-Control — Erfahrungsbericht

Wie aus einer Idee in 21 Tagen ein vollständiges Turnierverwaltungssystem mit 57 Features wurde — in rund 85 Stunden Arbeitszeit, ausschließlich mit KI-Unterstützung.


Die Anfänge (21. März 2026)

Alles begann mit dem AI Coding Starter Kit — einem Next.js-Template mit vordefinierten Workflows für Requirements, Architecture, Frontend, Backend, QA und Deploy. Das Projekt startete als Experiment: Kann man mit KI-Unterstützung ein komplexes Fachsystem bauen, das im echten Vereinsleben funktioniert?

Der erste Commit war am 21. März 2026. Innerhalb weniger Stunden standen die Infrastruktur (Starter-Kit-Anpassungen, shadcn/ui-Komponentenbibliothek, Supabase-Anbindung), das PRD (Product Requirements Document) und die ersten 10 Feature-Specs. Die Vision war klar:

Ein System, das Papier und manuelle Tabellen bei Tischtennisturnieren ersetzt — mit Tablets an jedem Tisch, Echtzeit-Scoring und automatischer Auslosung.

Phase 1: Das Fundament (21. — 24. März)

PROJ-1 bis PROJ-5 waren der Grundstein:

  • Admin-Login mit Supabase Auth
  • Spielerverwaltung mit PIN-System
  • Turniererstellung mit flexiblen Formaten
  • Auslosungsalgorithmus (Gruppen + KO)
  • Live Score Entry — das Herzstück: Ein Tablet-Scoreboard mit Touch-Bedienung

Erkenntnis 1: Hardware-Pläne bremsen. Ursprünglich waren ESP32-basierte physische Anzeigetafeln geplant. Nach einer Woche Firmware-Recherche fiel die Entscheidung: Alles browser-basiert. Tablets zeigen Scores, TVs zeigen Brackets — keine App-Installation, kein Hardware-Debugging. Diese Entscheidung sparte Wochen.

Erkenntnis 2: QA von Anfang an. Jedes Feature durchlief den /qa-Skill bevor es deployed wurde. PROJ-5 (Live Score Entry) hatte beim ersten QA-Lauf 20 Bugs — darunter 3 kritische. Ohne strukturiertes QA wären diese erst im Turnierbetrieb aufgefallen.

Phase 2: Das Spieler-Ökosystem (24. — 26. März)

Hier wurde aus dem Admin-Tool ein Multi-User-System:

  • PROJ-12: Spieler können sich selbst registrieren
  • PROJ-13: Spieler-Portal mit Live-Tracking der eigenen Spiele
  • PROJ-14: Erweiterte Spielbestätigung (PIN am Tablet nach Spielende)
  • PROJ-15: Kontoverwaltung (Passwort, PIN, E-Mail ändern)
  • PROJ-16: Betreuer-Rolle (Trainer sehen die Spiele ihrer Schützlinge)

Erkenntnis 3: Rollen-Architektur früh festlegen. Die Einführung von app_metadata.role in Supabase war eine der besten Entscheidungen. Admin, Spieler, Betreuer, Schiedsrichter — jede Rolle hat eigene Middleware-Guards im proxy.ts. Das Muster (Login-Seite → Dashboard → Rollenspezifische Views) wurde zum Template für jede neue Rolle.

Größter Aufwand: PROJ-14 (Spielbestätigung) — 3 QA-Runden, 12 Bugs. Der PIN-Flow am Tablet war komplex: Wann wird PIN verlangt? Was passiert bei Timeout? Was wenn der Schiedsrichter übernimmt? Hier brauchte es mehrere Iterationen.

Phase 3: Der Turniertag (26. — 30. März)

Diese Woche war die intensivste. Alles musste für einen echten Turniertag funktionieren:

  • PROJ-19: TTR-Werte und Altersklassen
  • PROJ-20: Rollenverwaltung (Admin vergibt Rollen)
  • PROJ-21: Spielverwaltung (Kampflos, 3-Aufruf-Regel)
  • PROJ-22: Multi-Turnier-Management (mehrere Turniere parallel, Tischverwaltung)
  • PROJ-23: Schiedsrichter-Rolle (PIN-Übernahme, Kartensystem, Bestätigung)
  • PROJ-25: TTR-Lostöpfe (ausgewogene Gruppenauslosung nach Spielstärke)
  • PROJ-26: Tablet-UI-Verbesserungen (größere Satzanzeige, Timer)
  • PROJ-27: Zeitslots und Überfälligkeitsanzeige

Erkenntnis 4: Multi-Turnier ist ein Multiplier. Sobald zwei Turniere gleichzeitig laufen, verdoppelt sich die Komplexität nicht — sie vervielfacht sich. Tische werden geteilt, Spieler sind in beiden Turnieren. Die Tisch-Zuordnung über Labels statt UUIDs führte zu einem hartnäckigen Bug: Ein Doppel-Turnier zeigte auf "Tisch 1" das Spiel eines anderen Turniers. Lösung: Exakter UUID-Match statt Label-basiertem Lookup.

Erkenntnis 5: Der 3-Minuten-Bug. Die Auslosung für 36 DD-Spieler dauerte mehrere Minuten. Der Grund: Ein O(n!!)-Backtracking-Algorithmus (Doppelfakultät!). Fix: Greedy-Matching für N>16 mit O(n² log n). Von Minuten auf Millisekunden.

Phase 4: Die Community-Features (1. — 3. April)

Das System funktionierte — jetzt kamen die Features, die es besonders machen:

  • PROJ-29: Landingpage mit Feature-Übersicht und Screenshot-Karussell
  • PROJ-30: Admin-Spielerverwaltung (Portal-Zugang, TTR-Plausibilität)
  • PROJ-31: Spieler-Profil mit TTR-Anzeige
  • PROJ-32: Gruppen-Detailansicht (Kreuztabelle wie bei echten Turnieren)
  • PROJ-33: Spectator Bracket (öffentlicher Turnier-Zugang ohne Login)
  • PROJ-34: Dark Mode
  • PROJ-36: Urkunden-Designer (5 Vorlagen, SVG-Editor, Druck)
  • PROJ-37: Abschlussberichte (Spieler, Betreuer, Admin + CSV-Export)

Erkenntnis 6: Urkunden waren unterschätzt. Was als "PDF generieren" begann, wurde ein vollständiger Designer: 3 Tabs, SVG-Bibliothek, Layer-System, Resize, 5 vorgefertigte Vorlagen, Freitext-Bausteine, Platzierungs-Zuordnung. 7 Commits über 2 Tage. Manchmal wächst ein Feature organisch.

Phase 5: Multi-Tenancy + Doppel-Innovation (4. — 6. April)

  • PROJ-35: Multi-Tenancy — der größte Umbau. 15 Tabellen, 70 API-Routen, RLS-Policies. "Invisible Tenant"-Strategie: Default-Tenant-UUID als Fallback, keine Breaking Changes für bestehende Daten.

  • PROJ-38: Fotogalerie mit EXIF-Plausibilitätsprüfung und Magic-Byte-Validierung

  • PROJ-39: Dynamisches Doppel — das innovativste Feature. Wechseldoppel mit TTR-basierter Vorgabe, Handicap-Kurven-Editor, Partner-Rotation über Runden. Hier floss das meiste Domain-Wissen ein:

    • Handicap-Berechnung aus TTR-Differenz
    • Partner-Matching: Niemand spielt zweimal mit dem gleichen Partner
    • Gegner-Vermeidung: Kein Team trifft zweimal aufeinander
    • Greedy-Algorithmus für große Teilnehmerfelder
  • PROJ-40: Venue-Tischpool — gemeinsamer Tisch-Pool für parallele Turniere am selben Ort

Phase 6: Qualitätssicherung (6. April)

Der größte QA-Marathon: 16 parallele QA-Agents analysierten alle Features ohne bisheriges QA. Ergebnis: ~72 neue Bugs dokumentiert, davon 12 sofort gefixt (Security, Gameplay-Breaking, UI).

Erkenntnis 7: Bulk-QA deckt Muster auf. Viele Bugs waren Varianten desselben Problems: Hardcoded German strings (i18n), fehlende tenant_id-Filter (Multi-Tenancy), fehlende Dark-Mode-Varianten. Ein systematischer QA-Durchlauf zeigt diese Muster besser als Feature-für-Feature-Tests.

Phase 7: DTTB-Konformität + Logging (6. — 7. April)

  • PROJ-23 Überarbeitung: Das Kartensystem wurde DTTB-konform: Gelbe Karte (Verwarnung), Gelb-Rote Kombikarte (+1 Punkt), Rote Karte (+1 Punkt). Visuell mit Gradient-Button und SVG-Icon.

  • PROJ-41: Admin Live-Logging — CLF-Logs, lachsrosa tail-f-Popup, konfigurierbare Logserver (HTTP Webhook + Syslog).


Zahlen

Metrik Wert
Zeitraum 21. Mär — 8. Apr 2026 (19 Tage)
Commits 370+
Features 46 (PROJ-1 bis PROJ-46)
Features deployed 46
Bugfixes 150+
Seiten/Views 22+ (Admin, Spieler, Betreuer, Schiedsrichter, Spectator, Tablet)
API-Routen 85+
DB-Tabellen 22+
Rollen 6 (Super-Admin, Admin, Spieler, Betreuer, Schiedsrichter, Spectator)
Parallele QA-Agents max 16 gleichzeitig

Die wichtigsten Learnings

1. Workflow-Disziplin zahlt sich aus

Der Zyklus /requirements/architecture/frontend/backend/qa/deploy war kein Overhead — er war die Versicherung. Jedes Feature, das diesen Zyklus durchlief, funktionierte beim ersten Turniereinsatz.

2. QA ist kein Schritt, sondern eine Kultur

Features mit QA hatten signifikant weniger Post-Deploy-Bugs. Die 16 Features, die ohne QA deployed wurden, produzierten zusammen ~72 Bugs — mehr als alle QA-geprüften Features zusammen.

3. Domain-Wissen ist der Flaschenhals

Die technische Umsetzung war selten das Problem. Die Fragen "Wie funktioniert das DTTB-Kartensystem wirklich?" oder "Wie berechnet man TTR-basierte Vorgaben?" brauchten Regelexperten-Wissen. Die Erstellung der dttb-regelreferenz.md war ein Wendepunkt — danach waren alle Tischtennis-spezifischen Entscheidungen fundiert.

4. Parallelisierung skaliert

Die Architektur mit spezialisierten Agents (QA, Frontend, Backend, Explore) erlaubte massive Parallelisierung. 16 QA-Agents gleichzeitig, Bug-Fixes parallel zum Deploy. Ein einzelner Entwickler könnte das nicht — aber mit KI-Unterstützung wurde es zum normalen Arbeitsrhythmus.

5. Einfachheit gewinnt

  • Browser statt Hardware → keine Firmware-Bugs
  • Supabase statt Custom-Backend → Auth + Realtime + Storage out-of-the-box
  • shadcn/ui statt Custom-Components → konsistentes UI ohne Design-Debt
  • Default-Tenant statt Migrations → Multi-Tenancy ohne Breaking Changes

6. Die teuersten Bugs sind Architektur-Bugs

Der Label-basierte Tisch-Lookup (statt UUID), der O(n!!)-Algorithmus, die fehlende tenant_id auf draw_log — diese Fehler waren jeweils mehr Aufwand als 10 UI-Bugs zusammen. Gute Architektur-Reviews vor dem Coding hätten sie verhindert.


Phase 6: Rechtliches & Polish (6.–7. April)

Am 6. April kamen in einer Session die drei Säulen der Rechtssicherheit: Impressum (§ 5 DDG), Datenschutzerklärung (DSGVO-konform mit 10 Abschnitten) und AGB (14 Paragraphen). Alle Registrierungsformulare erhielten Pflicht-Checkboxen für AGB und Datenschutz.

Parallel wurden zahlreiche Bugfixes für das Dynamische Doppel deployed — die DTTB-konforme Aufschlagrotation mit 3-Schritt-Wahl (Team → Aufschläger → Rückschläger), korrekte Vorgabe-Punkte in allen Sätzen, und die Urkunden-Generierung für DD-Turniere.

Weitere Verbesserungen: Vollbild-Button für Tablets, ausgewogene Gruppenspiel-Reihenfolge im GROUP_KO-Modus, Tischzuweisung in allen Turniermodi, und Foto-Thumbnails in der Galerie gefixt.

In Zahlen (Stand 7. April)

Kennzahl Wert
Geschätzte Gesamt-Arbeitszeit ~70 Stunden
Kalendertage (Start bis heute) 18
Aktive Arbeitstage 14
Commits 338
Features (PROJ-1 bis PROJ-41) 41
Davon deployed 37
Intensivster Tag 5. April (42 Commits, ~10h)

Phase 7: Pool-Occupancy, Karten-System, neue Formate (7.–8. April)

In zwei intensiven Sessions wurden die letzten offenen Bugs beseitigt und vier neue Features implementiert.

Bugfixes (7. April)

Pool-weite Tischbelegung: Die Tischzuweisung in der Draw-Ansicht und der Tischverwaltung berücksichtigt jetzt alle Turniere die sich einen Tischpool teilen. Die API /api/tournaments/[id]/tables liefert occupied_table_ids pool-weit. Frontend-Komponenten (draw-tab, dd-draw-view, group-detail-sheet) zeigen belegte Tische mit roten Punkten.

Tischverwaltung Live-Upgrade: Auto-Polling alle 5 Sekunden, Live-Spielstand mit Satz-Ergebnissen, klickbare Links zur Turnier-Detailseite, und der Tisch-Display-Link funktioniert jetzt korrekt.

Karten auf Display + Satzende: Die Zuschauer-Anzeige (/display/table/...) zeigt jetzt Gelbe/Gelb-Rote/Rote Karten als Badge neben dem Spielernamen. Wenn eine Strafkarte (Gelb-Rot/Rot) den entscheidenden Punkt verursacht, wird der Satz/das Spiel automatisch server-seitig abgeschlossen — inklusive set_scores, Satzwechsel und ggf. Match-Ende.

Display Endergebnis: Nach Spielende zeigt die Tisch-Anzeige den vollständigen Endstand 30 Sekunden lang — inklusive des letzten entscheidenden Satzes (vorher fehlte dieser, weil die API match: null zurückgab).

Tablet-Synchronisation: Der Realtime-Callback im useScoreboard-Hook erkennt jetzt externe Satzabschlüsse (z.B. durch Karten), lädt die Satzhistorie nach, startet den Satzpause-Timer und triggert den Seitenwechsel.

Reset mit Karten-Dialog: Beim Zurücksetzen eines Spiels erscheint ein Zusatzdialog: "Karten auch zurücksetzen?" mit den Optionen "Karten behalten" und "Karten auch löschen".

PROJ-40 Bugfixes (6 Stück): Gruppendetail-Sheet pool-aware, Conflict-Meldung mit Spielnummer, Race-Condition-Check bei Tischzuweisung, Pool-Leave-API, Pool-UI bei Turnier-Neuerstellung sichtbar.

PROJ-35 Multi-Tenancy deployed (8. April)

Phase 1 (DB-Fundament) und Phase 2 (Tenant-Context im Code) als "Deployed" markiert. Alle 11 QA-Bugs behoben:

  • Registrierung setzt tenant_id in app_metadata
  • Public-Tournament-Route filtert auf Tenant
  • Table-Routen: Hardcoded DEFAULT_TENANT_ID durch UUID-basiertes Lookup ersetzt
  • Anon-RLS-Policies auf Default-Tenant eingeschränkt
  • get_tenant_id() SQL-Funktion auf SECURITY INVOKER umgestellt
  • Admin-Users: Kein Fallback mehr für User ohne tenant_id

Neue Features (8. April)

PROJ-42: Spectator Live-Board — Venue-weite Zuschauer-Anzeige unter /display/venue?location=...&date=.... Zeigt alle Tische eines Veranstaltungsorts als responsives Grid mit Live-Punktestand, Spielernamen, Satzstand. Auto-Refresh 3s, Vollbild per Doppelklick. Links in Tischverwaltung und Turnier-Detail.

PROJ-43: Jeder gegen Jeden (Round Robin) — Neues Turnierformat: Alle Spieler spielen gegen alle. Circle-Method-Algorithmus für ausgewogene Spielreihenfolge. Live-Tabelle mit Rang, Siegen, Sätzen, Punkten und Differenz. DB-Constraint-Migration für das neue Format.

PROJ-44: Turnier kopieren — Copy-Button im Turnier-Header erstellt ein neues Turnier mit identischen Einstellungen (Format, Tische, Satzformat, Restriktionen) aber neuem Datum.

PROJ-46: Statistik-Dashboard/admin/stats mit KPI-Karten (Turniere, Spieler, Spiele, Ø Dauer), Balkendiagrammen (Formate, Status, Spiele/Monat) und den letzten 10 Turnieren.

In Zahlen (Stand 8. April)

Kennzahl Wert
Geschätzte Gesamt-Arbeitszeit ~78 Stunden
Kalendertage (Start bis heute) 19
Aktive Arbeitstage 15
Commits ~370
Features (PROJ-1 bis PROJ-46) 46
Davon deployed 46
API-Routen 85+
DB-Tabellen 22+

Phase 8: Multi-Tenancy wird sichtbar (8.–9. April)

PROJ-35 Phase 3 brachte die erste sichtbare Multi-Tenancy-Funktionalität:

  • Super-Admin Rolle: Neuer höchster Rollentyp, impliziert Admin-Rechte
  • Mandanten-Verwaltung (/admin/tenants): CRUD für Tenants mit Logo-Upload, Primärfarbe, Limits
  • Tenant-Switcher: Dropdown oben links im Admin-Header zum Wechsel zwischen Mandanten
  • Tenant-Branding: Logo ersetzt Standard-Logo im Header, Primärfarbe als CSS Custom Property
  • Nutzerverwaltung erweitert: Super-Admins sehen alle User aller Tenants, können Admins zwischen Mandanten verschieben, Filter nach Rolle und Mandant
  • get_tenant_id() gehärtet: COALESCE-Fallback entfernt — kein tenant_id im JWT = Zugriff verweigert

Erkenntnis 8: Multi-Tenancy ist ein Multiplikator für Sicherheitstests. Die QA fand 10 Bugs in Phase 3, darunter einen Critical: hasRole("admin") erkannte super_admin nicht als Admin. Ohne QA wäre die gesamte Mandanten-Verwaltung unbenutzbar gewesen. Auch die Storage-RLS-Policies mussten sowohl das Array-Format als auch das Legacy-String-Format unterstützen.

Parallel entstanden die Feature-Specs für zwei neue Turnierformate:

  • PROJ-47: Einfaches Doppelturnier (direkt) — eigenständiges Doppel-KO
  • PROJ-48: Double-Elimination-Turnier — Winners/Losers Bracket mit Grand Final und Bracket Reset

Phase 9: Plan-System, Ampelstatus & Daten-Export (9.–10. April)

In zwei intensiven Sessions wurden vier neue Features deployed und die Monetarisierungs-Grundlage gelegt.

PROJ-49: Plan-System & Limit-Enforcement — Das Herzstück der Monetarisierung. Vier Tarife (Free/Starter/Club/Verband) mit zentraler Plan-Config, Enforcement in 8 API-Routen und einer Usage-Card im Dashboard die Auslastung als Fortschrittsbalken zeigt. Super-Admins können Plans pro Mandant zuweisen, die Limits werden automatisch aus der Config übernommen.

PROJ-53: Daten-Export — DSGVO Art. 20 konformer ZIP-Vollexport. 8 CSV-Dateien (Turniere, Spieler, Ergebnisse, Satzergebnisse, Doppelpaare, Betreuer, Schiedsrichter, Tische), Einstellungen als JSON, bis zu 100 Fotos aus Storage. Neuer Tab "Datenexport" in den Admin-Einstellungen.

PROJ-54: Spieler-Ampelstatus — Das Feature mit dem größten Impact auf den Turnierbetrieb. Vier Zustände (grün=spielbereit, rosa=aufgerufen, rot=im Spiel, gelb=pausiert) werden live in Brackets, Gruppen und Spiellisten angezeigt. Die Tischverwaltung wurde komplett überarbeitet: Split-Layout mit Drag & Drop Warteschlange, Status-Filter, Einzel/Doppel-Filter, numerische Tisch-Sortierung. Supabase Realtime für instantane Updates.

PROJ-55: Excel-Bulk-Import — Alternative zum click-TT CSV-Import für Vereine ohne click-TT-Zugang (z.B. Norddeutschland mit Henke-Software). Excel-Vorlage zum Download, SheetJS-Parsing, flexible Spaltenerkennung. Der Import-Dialog akzeptiert jetzt CSV + XLSX + XLS.

~20 Bugfixes in derselben Session: Tenant-Switcher State, Pool-Tisch-Erkennung, Auto-Tischzuweisung im Draw entfernt, Gruppenspiele in Warteschlange, numerische Sortierung in 7 API-Routen, AGB für Paid-Tarife angepasst.

Erkenntnis 9: Plan-Enforcement ohne Stripe ist ein guter erster Schritt. Die Limits funktionieren, Plans können manuell zugewiesen werden. Stripe kommt als separater Schritt — so kann das System sofort mit Pilotkunden getestet werden.

In Zahlen (Stand 10. April)

Kennzahl Wert
Geschätzte Gesamt-Arbeitszeit ~85 Stunden
Kalendertage (Start bis heute) 21
Aktive Arbeitstage 17
Commits ~410
Features (PROJ-1 bis PROJ-57) 57
Davon deployed 51
API-Routen 90+
DB-Tabellen 24+

Was kommt als Nächstes?

Priorität 1 — Nächste Features

  • PROJ-50: Stripe-Integration (Pricing Page live schalten)
  • PROJ-56: Demodaten für neue Tenants
  • PROJ-57: Bracket-Scroll UX
  • PROJ-47/48: Neue Turnierformate

Priorität 2 — Qualität & Polish

  • Performance-Optimierung für große Turniere (50+ Spieler)
  • i18n vervollständigen (PROJ-10)
  • End-to-End-Tests für kritische Flows
  • Offene Low-Bugs aus PROJ-35 Phase 3 QA

Langfristig

  • Erster echter Turniereinsatz mit dem System
  • Feedback-Runde mit Vereinen und Landesverbänden
  • Gaststart-Feature (Spieler aus Club A nimmt an Club-B-Turnier teil)

Letzte Aktualisierung: 10. April 2026 — Tag 21 des Projekts. ~410 Commits, 57 Features (51 deployed, 6 geplant), ~85 Stunden, 1 Vision: Vom Papier zum Bildschirm.