Home
Portfolio
Bit
Brush
Multiplayer pixel canvas
under the hood
scroll to explore
▿
Browser
REST Controller
@RestController
WebSocket
STOMP broker
Services
Pixel · Banking
Postgres
Architecture
Painted locally first for instant feedback, then persisted and broadcast server-side
Full canvas state delivered on first subscribe. Late joiners won't miss a pixel
Anonymous multiplayer via client-generated UUID; no sign-up required
Cloudflare Turnstile blocks bots without interrupting painters
placement log: pixel (12, 7)
placed
2:01 pm
placed
2:03 pm
×
erased
2:05 pm
placed
2:08 pm
← now
MAX(placed_at) → derives current state
Append-only canvas
Every pixel placement appended to the log. Full audit trail
Current state derived via MAX(placed_at): last writer wins
Eraser writes palette index 0, erasing without destroying history
Full history enables stats, author tracking, and future canvas replay
+1
Earn
Every 3 seconds
Max 25 banked
Connected only
↔
−1
Spend
Per pixel placed
Atomic deduction
Partial batch OK
Thread-safe banking
ConcurrentHashMap.compute() - atomic balance check-and-deduct, no locks
Immutable BankState record eliminates partial-mutation bugs
Drag-painting with low balance: partial batch placed, not rejected outright
Per-user balance pushed via WebSocket. Bank bar always in sync