Architecture

Toboggan is organized as a Rust workspace with multiple crates:

Toboggan architecture diagram

CrateRole
toboggan-coreCore types & no_std logic
toboggan-serverAxum WebSocket server (talk state owner)
toboggan-cliMarkdown → TOML conversion
toboggan-clientShared WebSocket client library
toboggan-tuiTerminal UI (Ratatui)
toboggan-webWeb frontend (TypeScript + WASM)
toboggan-desktopDesktop app (Iced + wgpu, separate workspace)
toboggan-mobileiOS bindings (UniFFI)
toboggan-statsPresentation statistics
toboggan-esp32ESP32 embedded client

Key design decisions

  • toboggan-core is no_std compatible, usable from embedded devices
  • Server owns the talk state and broadcasts changes to all clients
  • Clients are stateless — they display what the server sends
  • Protocol is WebSocket for real-time, REST for batch operations
  • Desktop is a separate workspace to reduce build RAM usage

Protocol

The WebSocket protocol uses JSON messages:

// Server → Client
{ "type": "state", "state": { "current": 0, "total": 10 } }
{ "type": "slide", "index": 0, "content": { "title": "...", "body": "..." } }

// Client → Server
{ "type": "command", "command": "NextSlide" }
{ "type": "ping" }

// Server → Client
{ "type": "pong" }
{ "type": "error", "message": "..." }