LiveBoard
Ein kollaboratives Kanban-Board in Echtzeit mit Präsenzanzeige, optimistischer UI, versionsbasierter Konfliktbehandlung und Redis zur Skalierung über mehrere Instanzen.
- Art
- Nebenprojekt
- Tech-Stack
- NestJS
- Socket.IO
- React
- Redis
Das Problem
Ein gemeinsames Board ist nur nützlich, wenn alle dasselbe sehen. In einer Demo ist das einfach, in der Praxis nicht: Zwei Leute bearbeiten dieselbe Karte, eine Verbindung bricht ab, oder Nutzer landen auf verschiedenen Server-Instanzen. Nichts davon soll die Oberfläche flackern lassen oder still eine Änderung verschlucken.
Was es macht
LiveBoard ist ein Kanban-Board, auf dem Änderungen sofort bei allen ankommen. Karten lassen sich anlegen, bearbeiten, verschieben und löschen. Avatare, Live-Cursor und eine Tipp-Anzeige zeigen, wer gerade da ist, und ein Aktivitätsprotokoll hält jede Änderung fest. Jedes Board ist ein eigener WebSocket-Raum mit Zugriffskontrolle.
Änderungen greifen in der Oberfläche sofort und werden zurückgerollt, wenn der Server sie ablehnt. Nach einem Verbindungsabbruch holt der Client die verpassten Events nach.
Eine Karte verschieben
- Der Client verschiebt die Karte, aktualisiert die Oberfläche optimistisch und sendet
card:movemit derversionder Karte. - Das Gateway prüft das JWT, die Board-Mitgliedschaft und die
version. - Die Änderung wird in einer Transaktion in PostgreSQL gespeichert und die
versionum eins erhöht. - Der Server sendet
card:movedan den Board-Raum und über Redis an die anderen Instanzen. - War die Version veraltet, bekommt der Absender
card:rejectedund synchronisiert neu.
- BrowserSocket.IO-Clients
- NestJS-Gatewaysmehrere Instanzen
- RedisPub/Sub-Adapter
- PostgreSQLPrisma
Entscheidungen
Jede Karte hat eine Versionsnummer. Statt „Last Write Wins“ lehnt der Server Updates auf Basis einer alten Version ab. So überschreibt niemand still die Änderung eines Teammitglieds.
Der Login läuft über REST, das JWT wird beim Verbindungsaufbau des Sockets geprüft. Danach ist jede Verbindung auf die Boards beschränkt, zu denen der Nutzer gehört.
Der Redis-Adapter war von Anfang an dabei. Mit docker compose up --scale api=2 lässt sich zeigen, dass Clients auf verschiedenen Instanzen synchron bleiben. Cursor-Events werden gedrosselt, damit die Präsenzanzeige flüssig bleibt, ohne die Verbindung zu überlasten.