Case · Go backend
Pixel Wall: a shared canvas
A shared 256x256 canvas in the spirit of r/place: 16 colors, a cooldown per session and IP, an own WebSocket layer on the stdlib (RFC 6455) with a binary protocol (4 bits per pixel), a snapshot plus deltas, a snapshot with a journal and recovery, a timelapse, zoom and pan, a minimap, PNG export and admin tools. A side project.
- Go
- stdlib only
- WebSocket
- Canvas 2D
- Vanilla JS
- embed
- Binary protocol
- Snapshot + journal
- Docker
- GitHub Actions
01 · How it looks
Screenshots


02 · About
What it is and why
Pixel Wall is a shared pixel canvas in the spirit of r/place: 256x256, 16 colors, one pixel every few seconds per session. Changes appear for everyone at once over WebSocket, and the history is kept and replayed as a timelapse. A side project.
Go standard library only, with no dependencies or CGO; the WebSocket layer per RFC 6455 is written by hand (taken from the realtime-rooms project), and the vanilla JS and canvas client is embedded through embed. Demo mode has a prepared artwork and a few bots, all of them honestly marked.
Limitations
Everything lives in one process on one disk and does not scale out. Cooldowns, sessions and rate limits are in memory and reset on restart (bans persist).
A session is an identifier in localStorage: whoever clears the storage gets a new one. It protects against simple bots, not against a targeted attack from many IPs; behind a shared NAT the per-IP limit is shared by everyone.
The journal is written without an fsync per pixel, with an fsync every 30 seconds: on a power loss the last seconds can be lost. The client needs DecompressionStream (Chrome 103+, Safari 16.4+, Firefox 113+).
There are no automated browser tests in the repository; the interface was checked by hand in Edge. The -race tests run only in CI, and the Docker image has not been built.
What is inside
- An own WebSocket and binary protocol: a client sends a pixel in 6 bytes and the server broadcasts deltas every 50 ms; a new client gets a compressed snapshot and then only deltas
- Consistency: a snapshot carries seq, a delta carries firstSeq, the client reconnects on a gap, and a slow client with an overflowing queue is disconnected
- Storage at 4 bits per pixel (256x256 = 32 KiB), a snapshot on disk (crc32, fsync, rename) plus a change journal
- Crash recovery: the snapshot, then journal records with a larger seq, with a torn tail truncated; a corrupt snapshot is rebuilt from the journal
- A server-side cooldown per session and per IP (a sliding window), signed sessions, rate limits on HTTP and WebSocket, Origin checks, and limits on message sizes and connections
- A timelapse over the journal: the old color stored in each record lets the client roll history back with no base snapshot; speeds 1x, 4x, 16x
- Zoom and pan (wheel, pinch, drag, keyboard), a minimap, an online counter, PNG export and ?embed=1
- A token-protected admin: clear an area, ban a session or IP, view recent placements; a load test with 300 clients and no missed deltas
03 · How to run
Run it locally
git clone <repository on request> pixel-wall
cd pixel-wall
SEED_DEMO=1 ADMIN_TOKEN=secret go run ./cmd/server # http://localhost:8103, admin at /?admin04 · Code
The repository is private
The source lives in a private repository. I will grant access on request: write to me and I will send an invitation.
Request the code