Backend · 2026

markdown-live

Real-time collaborative Markdown preview over a from-scratch RFC 6455 WebSocket

Complete · source available

Overview

  • What: a real-time Markdown previewer: type in one tab, the Markdown is rendered on the server and pushed to every tab watching the document.
  • Hardest problem: implementing the WebSocket protocol from scratch against RFC 6455 with no ws dependency.
  • How it is validated: 63 tests, including the RFC’s own byte vectors and end-to-end tests over real TCP sockets.

The only runtime dependency is markdown-it, kept deliberately because a safe Markdown renderer is a separate problem.

Architecture

 browser tab --WebSocket (RFC 6455, hand-written)--> server
   handshake, frame encode / streaming decode, masking, fragmentation, ping/pong, close
                                  |
                        topic pub/sub hub (retained last value)
                                  |
              throttled render pipeline (conflation queue) --> markdown-it
                                  |
                      pushed to every tab on the document
fig. 01 — markdown-live architecture

Highlights

  • ws/frame.ts streaming decoder handles frames delivered one byte at a time, non-minimal length encodings, reserved bits, oversized/fragmented control frames and close-code validation.
  • Topic pub/sub hub with a retained last value, a throttled render pipeline with a conflation queue, and a static file server with a path-traversal guard.
  • --trace prints every frame in both directions (direction, fin, mask, length), the fastest way to watch the protocol work.
  • 63 tests: RFC 6455 section 1.3 accept-value example, section 5.7 byte vectors, HTML escaping and javascript: URL rejection, and end-to-end tests over real TCP sockets (multi-tab fan-out, late joiners, presence, an unmasked client frame refused with code 1002).

What I learned

A streaming decoder has to survive frames arriving one byte at a time, and the only way to be sure was to test exactly that. The RFC’s own examples made good test vectors.

Limits

Deliberately unimplemented and documented: permessage-deflate, TLS, subprotocol negotiation, Autobahn conformance, auth and persistence.