SURVEY RECORD R-002
CollabBoard is a real-time collaborative whiteboard built end-to-end in Rust. Seven crates in a Cargo workspace share types, validation logic, and wire protocol definitions with zero duplication across client and server boundaries. There is no JavaScript runtime anywhere in the stack.
The client is a Leptos 0.8 application that renders on the server via SSR, then hydrates in the browser as a WebAssembly binary. The canvas engine is a from-scratch 2D drawing system with its own hit-testing, input state machine, and rendering pipeline. Its core has zero browser dependencies — the full test suite (250+ tests) runs under cargo test without a browser. A thin WASM wrapper forwards DOM events in and calls render() out.
All client-server communication flows through a single WebSocket carrying binary protobuf frames. Each frame has a syscall prefix — board:*, object:*, cursor:*, chat:*, ai:* — and the server routes it to a handler function. Handlers never touch the socket directly: they return an Outcome enum (Broadcast, Reply, or ReplyStream) and a single dispatch layer decides who receives what.
Persistence runs at two speeds. Object mutations collect in a dirty set and flush to PostgreSQL every 100ms. The frame log uses a separate batched writer at 5ms intervals for audit-grade event capture. Ephemeral frames (cursors, presence heartbeats) never hit the database.
AI integration supports both Anthropic (Claude) and OpenAI-compatible backends. The server runs a multi-round tool-call loop with 9 tools that read board state, create and modify objects, and respond to natural language instructions. Tool calls route through the same syscall dispatch as user actions, so AI mutations broadcast to all connected clients in real time.
Authentication supports GitHub OAuth and email access codes with single-use WebSocket tickets. Board sharing uses 6-character invite codes with member ACLs. The whole system deploys as a single Docker image on Railway, with migrations running automatically on startup.
Axum HTTP server, WebSocket hub, and persistence layer. Handler functions return an Outcome enum and a single dispatch layer decides routing. Two-speed persistence with object dirty flush and frame log queue.
Leptos 0.8 application that renders on the server (SSR) and hydrates in the browser as a WASM binary. Pure Rust, no TypeScript, no JS framework. Eight RwSignal contexts for state management.
From-scratch 2D whiteboard engine. Compiles to native Rust for testing, compiles to WASM for the browser. Zero browser dependencies in the core. Seven gesture states, nine shape kinds, full hit testing.
Shared crate defining the Frame type and encode/decode functions. Binary protobuf via Prost 0.13. Status lifecycle: Request → Item* → Done | Error | Cancel.
Shared trace and event primitives for the observability UI. Syscall prefix-to-display mapping, trace filtering, frame-to-session grouping, waterfall timing, aggregate metrics.
End-to-end performance tests over real HTTP and WebSocket connections. Round-trip latency, board complexity scaling, and 25-user concurrent load scenarios.
Clap-based CLI for board management and debugging. REST board CRUD, WebSocket JSONL object streaming, and a stress generator with spiral pattern mode for load testing.
The entire stack is Rust. The server is Axum with SQLx for database access. The frontend is Leptos — server-side rendered, then hydrated in the browser as WASM. No JavaScript runtime anywhere.
Auth supports GitHub OAuth and email access codes with single-use WebSocket tickets. AI features work with either Anthropic (Claude) or OpenAI-compatible backends. Deployed on Railway with Docker, migrations run automatically on startup.
"No JavaScript runtime anywhere in the stack. Server, frontend, canvas engine, wire protocol — one language, one type system, shared crates between client and server."
"Binary wire format for WebSocket frames. Compact, typed, with a recursive serde_json::Value to prost_types::Value conversion for flexible data payloads."
"Handlers return an Outcome — Broadcast, Reply, ReplyStream — and dispatch decides routing. Keeps handlers pure and testable. They never touch the socket directly."
"Object dirty flush at 100ms, frame log queue with batched writer at 5ms. Each path tuned to its traffic pattern. Ephemeral frames never hit the database."
"EngineCore has zero web-sys dependencies. The full test suite runs in cargo test without a browser. The WASM wrapper just forwards DOM events and calls render()."
FIELD LOG R-003
EXPEDITION LOG R-005