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_idinapp_metadata - Public-Tournament-Route filtert auf Tenant
- Table-Routen: Hardcoded
DEFAULT_TENANT_IDdurch 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.
