Skip to the solution
HardFrontend13 min read

Build a Collaborative Kanban Board with Yjs (CRDT)

565 views

The problem

Question presented to candidate: "Our Kanban board is used by several people at once, sometimes on flaky connections. Two people can move or rename the same card while one of them is offline. Build a board where every copy ends up identical once they reconnect, without a server deciding who wins. You may mention Yjs, but show me you understand what it does."

Requirements:

  • Two replicas of the board on one page (standing in for two tabs), each with an Online toggle; edits sync through a simulated network with latency.
  • Add, move (buttons and drag and drop), rename and delete cards on either replica, including while offline.
  • Edits made while partitioned are queued and delivered on reconnect.
  • After concurrent edits and a reconnect, both boards are identical, with a deterministic, explainable winner for each conflict.
  • Show how the same board would be modelled with Yjs.

What a strong answer should cover:

  • What a CRDT is and why it converges without a central lock: merge is commutative, associative and idempotent.
  • A concrete design: per-field last-writer-wins registers with Lamport timestamps and a replica id tie-break; deletes as tombstones.
  • Ordering cards without renumbering: fractional positions between neighbours, a deterministic tie-break, and their precision limit.
  • Binding an external store to the UI framework (subscribe, version counter, useSyncExternalStore or equivalent).
  • Which conflicts LWW resolves badly (concurrent text edits) and how Yjs differs: Y.Map, Y.Array, Y.Text, state vectors and updates, providers such as y-websocket.
  • How convergence is tested: replaying shuffled and duplicated operations.

Clarifying questions expected:

  • "Is there a server at all, or peer to peer? Do we need offline persistence?"
  • "When two people move the same card, is any consistent winner acceptable, or must the later move win by wall clock?"
  • "Do card titles need character-level merging, or is whole-title last-writer-wins acceptable?"

Code / implementation expected: Yes. A working two-replica board with a small hand-written CRDT and a convergence demonstration; Yjs as a sketch.

  • React
  • Kanban
  • Yjs
  • CRDT
  • Collaboration

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

13 min read ยท 10 sections

React solution

Every file of the working solution. Open it in the playground to run and change it.

ReactComplete solution
import { useState } from "react";
import { createNetwork } from "./src/utils/crdt";
import ReplicaBoard from "./src/components/ReplicaBoard";

export default function App() {
  // Two replicas in one page, standing in for two browser tabs.
  const [net] = useState(() => createNetwork(300));
  const [online, setOnline] = useState({ A: true, B: true });

  function toggle(id) {
    const value = !online[id];
    setOnline((o) => ({ ...o, [id]: value }));
    net.setOnline(id, value);
  }

  return (
    <main className="app">
      <h1>Collaborative board</h1>
      <p className="hint">
        Two replicas sync through a simulated network (300 ms latency). Take one
        offline, edit both, then reconnect.
      </p>
      <div className="replicas">
        <ReplicaBoard
          replica={net.a}
          name="Tab A"
          online={online.A}
          onToggle={() => toggle("A")}
        />
        <ReplicaBoard
          replica={net.b}
          name="Tab B"
          online={online.B}
          onToggle={() => toggle("B")}
        />
      </div>
    </main>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 92 of 107 in Machine coding

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

Up nextHard

Build a Data Table with Virtualized Rows, Sorting & Filtering

Continue