Live · seit 2026
Website und Vereinssoftware des Schachklubs Sulzfeld
Mein Schachverein hatte eine veraltete Website und organisierte alles über Chats und private Postfächer. Ich habe ihm eine Website mit Redaktionssystem, Mitgliederbereich und Spieltag-Planung gebaut und betreibe sie.
Problem
Die Website meines Vereins war veraltet und nur von einer Person zu pflegen. Ligaergebnisse tippte jemand von Hand ab, Rundmails gingen aus privaten Postfächern raus, Aufstellungen wurden in Chatgruppen zusammengesucht. Viel Arbeit für Ehrenamtliche, und nichts davon war für Besucher sichtbar.
Meine Rolle
Ich habe die Lösung allein konzipiert, entwickelt und in Betrieb genommen, und ich betreibe sie bis heute.
Fallstudie
Meine Lösung
Ich wollte, dass die Vereinsarbeit dort passiert, wo die Daten liegen: ein Redaktionssystem für den Vorstand, ein Mitgliederbereich für Einreichungen und ein Import, der alles holt, was andere Systeme ohnehin schon wissen.
- Ergebnisse, Wertungszahlen und Spiellokale importiere ich jede Nacht aus nuLiga und vom Schachbund
- Partieformulare werden per Foto zu PGN: eine KI transkribiert, Stockfish prüft, offene Züge entscheidet ein Mensch
- Mitglieder reichen Artikel, Spielberichte und Rundmails ein, der Vorstand gibt sie frei
- Die Spieltag-Planung schlägt Aufstellungen vor und sammelt Verfügbarkeiten und Fahrgemeinschaften
Umsetzung
Ich habe die Seite mit Angular und Server-Side-Rendering gebaut, damit sie schnell lädt und gefunden wird, dazu eine ASP.NET-Core-API auf PostgreSQL und einen eigenen Node-Worker für den Import. Weil die Software Mitgliederdaten verarbeitet, habe ich die Rechte von Anfang an verschlossen gestartet: Jeder Endpunkt verlangt einen Admin, Mitglieder- und Gastbereiche öffne ich gezielt.
SkSulzfeld.Api/Program.csbuilder.Services.AddAuthorization(options =>
{
var adminOnly = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.RequireRole(nameof(UserRole.Admin))
.Build();
options.DefaultPolicy = adminOnly;
options.FallbackPolicy = adminOnly;
options.AddPolicy(AuthorizationPolicies.MemberArea, policy => policy
.RequireAuthenticatedUser()
.RequireRole(nameof(UserRole.Admin), nameof(UserRole.Member)));
});Betrieb
Ich deploye per GitHub Actions mit einem Datenbank-Dump vor jedem Rollout, teste vorher auf einem Staging in meinem Homelab und sichere jede Nacht verschlüsselt außer Haus. Einmal im Monat spielt ein automatischer Restore-Drill die Sicherung zur Probe ein. Das Repository ist privat, weil es Mitgliederdaten verarbeitet.
Entscheidungen
- Alles ist zu, bis ich es öffne
- Ich habe mich gegen eine feine Rollenmatrix entschieden: Ohne Freigabe braucht jeder Endpunkt einen Admin, und ein Test friert die öffentliche Oberfläche ein. Ein vergessenes Attribut sperrt aus, statt etwas offenzulegen.
- Ich kopiere keine personenbezogenen Daten
- Mitgliederdaten schreiben keine Revisionen, und Rundmail-Protokolle verweisen auf das Mitglied, statt die Adresse zu kopieren. So lebt niemand nach dem Austritt im Verlauf weiter; einen Änderungsverlauf gibt es dafür nicht.
- Niemand bekommt eine Rundmail doppelt
- Ich beanspruche jeden Empfänger vor dem Versand in einer einzigen Datenbank-Anweisung. Zwei parallele Anfragen können so niemanden doppelt anschreiben. Stirbt der Prozess genau dazwischen, bleibt ein Empfänger als versendet stehen.
Ergebnis
Seit September 2026 ist die Seite live. Der Vorstand pflegt Inhalte selbst, Mitglieder können Berichte über den Mitgliederbereich einreichen, Ergebnisse und Wertungszahlen kommen jede Nacht von allein. Dahinter stehen 26 Fachbereiche mit rund 1.400 Backend- und 2.000 Frontend-Tests.