← Selected work

Local-first software / Personal project

SyncLabKeep editing. Reconnect. Converge.

An offline-capable collaborative editor with a TypeScript CRDT, an encrypted persistent outbox, and an ordered ASP.NET Core WebSocket relay.

C#ASP.NET CoreReactTypeScriptAES-GCM
200randomized convergence trials
250Kreplica-operation observations
5replicas in each stress trial

01 / The problem

Why I built it

Real-time editors cannot assume an always-on, ordered connection. A child insert may arrive before its parent, a delete before its target, and a reconnect may replay an operation the peer already applied.

02 / My contribution

What I engineered

I built the collaborative editor and its operation-based CRDT integration, offline replay path, and encrypted transport. I repaired out-of-order and duplicate handling, then added checks for convergence and relay ordering.

03 / Interactive demonstration

See the behavior, not just the claim.

Two independent CRDT replicas. Disconnect delivery, make edits, and replay the pending operations.

SyncLab / replica labActual CRDT · simulated delivery
Connected · 0 queued operations

Replica A

Build together.

Replica B

Build together.

Disconnect delivery, append a different edit in each replica, then reconnect. Documents match.

Runs the repository’s RGA-style CRDT. Reconnect delivers pending operations out of order and twice; it does not copy one pane over the other. No server, encryption, or persistence in this isolated demo. Limited to 600 edit operations; reset to start again.

04 / Architecture

Follow the data.

  1. 01React editor
  2. 02RGA-style CRDT
  3. 03AES-GCM + persisted outbox
  4. 04Ordered WebSocket relay
  5. 05Peer decrypts + applies

Operation identity instead of arrival-order assumptions

Each operation carries a unique ID. Applied and pending IDs prevent duplicate delivery from duplicating edits. Missing dependencies are queued and replayed when their prerequisite arrives.

An offline outbox instead of disabling editing

Local operations apply optimistically while the encrypted outbox retains unconfirmed work for reconnect. The full app can replay events after refresh; the embedded demo isolates the CRDT mechanism.

Ciphertext relay instead of server-readable documents

The room key is carried in the URL fragment, which is not sent in HTTP or WebSocket requests. The relay handles ciphertext and ordering, while clients decrypt. Room IDs, timing, and sender metadata are still visible to the relay.

Explicit ordering on the relay

Bounded fragmented-message assembly, per-socket send serialization, per-room broadcast ordering, and monotonic sequence numbers address failures that a simple broadcast loop can miss.

05 / Verification

Results you can inspect.

The Python stress model uses 200 trials, 250 operations per trial, five replicas, 20% temporary loss, and 10% duplicate delivery. A shuffled anti-entropy pass then delivers the operations and checks identical materialized state. TypeScript regression tests separately exercise implementation edge cases.

Measurement context

250,000 means 200 × 250 × 5 replica-operation observations. It is not 250,000 independent trials or a benchmark of network latency. The stress model and the TypeScript implementation are complementary checks, not the same executable.

The browser demonstration below uses the repository’s TypeScript CRDT with in-memory simulated delivery. It does not run the ASP.NET relay, encryption, or persistent outbox, and it is not a full-stack integration test.

Evidence pinned to repository revision 0b657aff3f07. Recorded results are from the linked project evidence, not new benchmark runs for this website.

06 / Engineering boundaries

What I would harden next

The relay keeps room history in memory, membership is unauthenticated, and the client retains only its latest 5,000 events. Production use would need durable room storage, authorization, key rotation, and compaction.

07 / Next iteration

Where it goes from here

A useful next stage is authenticated membership and durable room history, followed by a small collaboration pilot. The priority is preserving the offline and convergence properties as those boundaries change.

Eesher Janda / Software engineering

Let’s build something useful.

Seeking software engineering internships and co-ops.