# Architecture ## Shape ``` ┌ Browser ─────────────────────────────────────────────────┐ │ console/ — React + Vite, six pages on one shared frame │ └───────────────┬──────────────────────────────────────────┘ │ GET /api/state · WS /ws/ui (whole snapshot) │ POST/PATCH/DELETE /api/… (commands) ┌ caspar-avd ───┴──────────────────────────────────────────┐ │ api.rs HTTP + WebSocket, serves the built console │ │ bridge.rs supervised connection, snapshot, command log │ │ show.rs canvas · screens · cues · pads → AMCP │ └──┬──────────────────┬───────────────────┬────────────────┘ │ AMCP/TCP 5250 │ OSC/UDP │ HTTP 8000 │ │ (ephemeral port) │ ┌──┴──────────────────┴───┐ ┌────┴──────────┐ │ CasparCG Server 2.5 │ │ media-scanner │ └─────────────────────────┘ └───────────────┘ ``` Four crates: | Crate | Responsibility | |---|---| | `amcp` | Protocol codec and async client. Knows nothing about shows. | | `casparosc` | OSC decoding and the telemetry state tree. | | `scanner` | media-scanner HTTP client. | | `showd` | The daemon: bridge, show model, API. Binary `caspar-avd`. | The split is deliberate: `amcp` and `casparosc` are reusable by anything that needs to talk to CasparCG, and neither depends on the show model. If the show layer turns out to be wrong, the protocol work survives it. ## The snapshot contract One type, `Snapshot`, is the entire read interface. The console renders it and holds no authoritative state of its own. ```rust struct Snapshot { health: Health, // connecting | connected | down — of CasparCG server: ServerInfo, // host, port, version, paths, OSC port in use channels: Vec, // live, from OSC media: Vec, // from media-scanner templates: Vec