Notes of a collaborative webapp
XERUS - Unmet Needs of a WorldCongress
Creation of a real-time collaborative client-server gamification application. One of the requirements is “accessibility”, so a browser-based app was a given.
Objectives and the TechStack
A simple Client-Server Architecture, collaborative Application. NestJS and socketio on the Server and React Client. Websockets for Real-Time-Sharing and in the future a Database to persist Data and User-Auth.
Explorations + Decisions
It is a private mono repository and server and client is handled via yarn workspaces.
Some History
I’ve also considered WASM/emscripten or building an app with PlayCanvas, Unreal engine or OF, maybe for my next multiplayer side project.
Client
I tried not to blindly choose any mainstream libraries, but React with Typescript is a solid choice for reasons (VS code/language server supports autocomplete on types, which is really helpful to get things done reliably). A frontend router (location[5] or wouter) and native websockets and state management (Zustand).
While there are many possibilities with 3D in CSS, I didn’t want to miss the opportunity to use WebGL and the recently (React 16) introduced Reconciliation alogrithm “React-Fiber”, which is based on a somewhat overused Linked List, but seems to work great with R3F (React-Three-Fiber), which allows to use React’s scheduling capabilities with ThreeJS [6].
- [5] React Location
- [6] R3F
Server
A small Typescript NestJS Server with SocketIO as WebSocket Gateway and express as HTTP Backend. First I tried the Ws-library, but then I switched to SocketIO.
Collaborative Data
The standard solutions are OT (Operational Transform) or CRDT (convergent or commutative replicated data type).
- OT: Operations are sent over the wire and concurrent operations are transformed once they are received.
- CvRDTs (convergent replicated data types): State based. Its full local state is sent and is merged with the state of a copy (or optimized, Delta Mutations).
- CmRDTs (commutative replicated data types) operation based, for example only “+b” is transmitted and applied locally (a+b has the same result as b+a and is therfore commutative).
While evaluating industry standards, I came up with a simple solution that works purposefully for an MVP: Broadcast the full state to all clients. This pragmatic approach is of course only a crutch to be able to test a proof of concept on students of the actual target of the application.
- [8] Treedoc
- [9] Replicated Data Types (Marek_Alexey_Burckhardt)
- [10] A Conflict-Free Replicated JSON Datatype
- [11] YJS
- [12] NotesUtils Notes
- [13] automerge
Releases
Release | Value | Status |
---|---|---|
enphi v0.1 | very basic Collab | DONE |
v0.2 | Persistence, DB? | WIP |
The repository was private and deployed from github to digitalocean and used a terminated mongodb-cluster: https://github.com/pce/worldcongress