`chriskwan/whiteboard` and the Beautiful Simplicity of Peer-to-Peer Drawing

A tiny no-build canvas app shows how far you can get with WebRTC, a shared peer ID, and a deliberate refusal to build a server.

6 to 7 min read · chriskwan/whiteboard

Two laptop screens sit on separate desks, linked by a thin hand-drawn thread that passes through a floating peer ID card and lands on a shared canvas of dots. An empty pedestal sits off to the side, showing the missing server that the app refuses to depend on. The image explains that the collaboration model itself is the story, not the whiteboard surface.
The app’s real subject is the connection between browsers. The whiteboard is just the visible proof that the link exists.
Key Takeaways

The most interesting thing about `chriskwan/whiteboard` is not the canvas. It is the decision to treat the server as optional and see how much collaboration you can still get from two browsers, a shared peer ID, and a very small amount of JavaScript.

The server is the feature

This repo makes a quiet but radical claim: if two browsers can find each other, they can collaborate without a central room in the middle. The whiteboard is just the visible layer. The real product is the connection model underneath it.

That is why the project feels bigger than it is. It compresses WebRTC, PeerJS, and the Canvas API into a demo you can hold in your head at once. The absence of a backend is not a limitation here. It is the point.

A mouse pointer drops discrete black squares onto a canvas on the left, and the same squares reappear on a remote screen on the right after moving through a chain of peer nodes. The scene explains why the app uses points instead of paths, showing how simple payloads are easier to synchronize across browsers.
The app draws with points, not strokes. That keeps the data tiny and the sync model legible.

What the app actually ships

The codebase is tiny by design. There is an `index.html` entry point, one JavaScript file, and a README. No build system, no bundler, no framework. That puts the architecture in plain sight.

<canvas id="drawingArea" width="800" height="500"></canvas>
<input id="peerId" />
<input id="friendId" />
<div id="peerList"></div>

A single dot moves through the whole system. That is the project’s strongest teaching tool.

In practical terms, the app does three things well. It renders dots on a canvas, it sends those dots over a PeerJS data channel, and it exposes connection state in the UI so the invisible handshake does not stay invisible for long.

The drawing model is intentionally dumb

The core rendering choice is `fillRect`, not path drawing. Every mouse move becomes a small square. That sounds crude, but it is exactly why the sync story works.

function drawPoint(point, color) {
  context.fillStyle = color;
  context.fillRect(point.x, point.y, 5, 5);
}

function sendPointToPeers(point, color) {
  peer.connections.forEach(function(conn) {
    conn.send({ point: point, color: color });
  });
}

Points are stateless. They do not need a stroke history, a replay buffer, or a path reconstruction algorithm. If a packet is late, you miss one square, not an entire curve. The cost is visual elegance. The benefit is that every message stays tiny and easy to reason about.

How two browsers find each other

PeerJS acts as the abstraction layer over WebRTC. Instead of making readers wade through the signaling boilerplate, the repo lets them work with a peer ID, an invite link, and a connection list. Discovery is simplified, not invented from scratch.

StepWhat this repo doesWhat a production system usually adds
IdentityA peer ID and a shareable invite linkAccounts, auth, access control, and recovery
TransportPeerJS over WebRTC data channelsServers, fallbacks, retries, and observability
StateSmall point payloadsStroke models, conflict handling, presence, and persistence
UIA direct canvas plus simple connection panelsTooling, layers, undo, export, and permissions

That table is the whole story in miniature. The repo trims away everything that is not required to get a remote point from one browser into another browser. What remains is a surprisingly clear handshake.

The surprising part: it starts to look like a mesh

The most interesting line in the code is not about drawing. It is the logic that shares known connections back out to new peers. That hints at transitive discovery, where peers can find peers through peers instead of waiting for a central coordinator to tell them where to go.

That is a small idea with a big feel. It pushes the repo from a simple two-user demo toward something that resembles a decentralized social graph, even if only in prototype form.


A 2015-style time capsule, for better and worse

The repo also carries its era on its sleeve. It relies on raw hosted dependencies, uses a hardcoded PeerJS API key, and reflects the old no-build habit of wiring a demo together with whatever was easiest to reach from the browser.

That gives it a kind of historical honesty. It is clean enough to learn from, but brittle enough to remind you how much frontend infrastructure has changed. The code is small. The dependencies are the part that aged.

TraitThenNow
Dependency deliveryDirect script includes from hosted URLsPackage managers, pinning, and build pipelines
Collaboration modelPeer-to-peer demo logicPersistent sync, auth, and offline recovery
MaintainabilityReadable but fragileHeavier, but more resilient

How it compares to modern whiteboard systems

Against modern tools like tldraw or CRDT-backed editors, `chriskwan/whiteboard` loses on nearly every production metric and wins on clarity. It is not trying to be a platform. It is trying to make a network idea legible.

Dimension`chriskwan/whiteboard`Modern collaborative whiteboards
Connection modelDirect P2P invites through PeerJSServer-mediated sync, auth, and presence
Drawing modelDiscrete points rendered as squaresStrokes, shapes, objects, and transforms
GoalShow the collaboration stack clearlySupport teams at scale
TradeoffSimple and portableRobust and extensible

That comparison is unfair in one sense and useful in another. Production systems solve the hard parts the demo avoids. This repo makes the hard parts visible.

Why this tiny repo still matters

`chriskwan/whiteboard` is useful because it turns collaboration infrastructure into something you can inspect line by line. It shows that browser-to-browser drawing is less mysterious than it looks, provided you are willing to simplify the drawing model and accept the network as the main character.

That is the lasting lesson. Some repos are valuable because they ship features. Others are valuable because they make a system readable. This one does the second thing very well.