# Plan — web client From `architecture/web-client.md` and `quality/web-client.md`. ## Toolchain & skeleton (done during api-design) - [x] devenv: trunk, wasm-bindgen-cli, binaryen, wasm32 target; `build-web`/`serve-web` scripts (RUSTFLAGS cleared for rust-lld). - [x] crabidy-core on wasm: tonic codegen-only (workspace tonic default-features=false, members re-enable), `build_transport(false)`, native-only config gated. Verify: `cargo check -p crabidy-core --target wasm32-unknown-unknown`. - [x] cbd-web crate: Trunk.toml (+ dev proxy), index.html, style.css skeleton, `state.rs` (pane logic ports + tests), `keymap.rs` (TUI bindings port + tests), `rpc.rs` (gRPC-web client + basic auth header), app shell. Verify: wasm check + native tests + `trunk build --release`. - [x] crabidy-server: `web-ui` feature (default on), build.rs staging (dist or placeholder), `web.rs` static fallback (+tests), serve() on one axum router: auth → grpc-web → service, assets public. Verify: check with/without feature, tests. ## Implementation - [x] **Stream task**: connect `GetUpdateStream` on startup, apply updates to signals (queue, mods, play state, volume, mute, position, capture board), reconnect with capped backoff + `connected` signal. Gate: parity/stream. - [x] **Library pane**: listing from `LibraryPane` state, click = select, double-click/`l` = dive, breadcrumb/`h` = ascend, marks, capability badges (`%`/`[e]`/`[d]` equivalents), skipped red. Library cache honoring `is_cacheable`. Gate: parity/semantics. - [x] **Queue pane**: track list with current highlight + resolving indicator, select/play/remove/clear/save, insert-here from library selection. Gate: parity. - [x] **Transport bar**: play/pause, prev/next, restart, stop-aware play state, volume slider + mute, shuffle/repeat toggles, progress gauge from `TrackPosition`. Gate: parity. - [x] **Dialogs**: name input (create/rename/save-queue/capture with slow-warning label), capture-delete y/N (red), help overlay (`?`), login form on `UNAUTHENTICATED` (localStorage-backed). All modal: keys bypass the keymap. Gate: parity + security. - [x] **Keyboard wiring**: global keydown listener → `keymap::lookup` → actions; input elements exempt (typing in dialogs). Gate: parity. - [x] **Capture progress lines**: board fed by stream, rendered at the library pane bottom, errors red, linger semantics from state.rs. Gate: parity. - [x] **CSS**: full styling — layout grid, pane focus ring, selection bar, accent `--accent` (crab orange-red) with color-mix derivations, light/dark via light-dark() + persisted toggle, phone breakpoint. Gate: styling. - [x] **README + docs**: cbd-web/README.md (build, dev loop, config), root README (web UI section, feature flag, build-web), update architecture doc if the implementation deviates. Gate: build. - [x] **Verification**: full workspace tests + clippy (native and wasm) + fmt + markdownlint; live smoke test: server with bundle → browser fetch of `/`, gRPC-web call, TUI gRPC call, auth denial over gRPC-web. Tick `quality/web-client.md`; write `plan/summary.md` section; commit.