crabidy/cbd-web
Test User 435af91d9c Add a Leptos web client served by the server
crabidy-server now serves a browser client with the same functionality
as the TUI at its own address, behind the default-on web-ui feature.

The new cbd-web crate is a client-side Leptos/WASM app talking gRPC-web
(tonic-web-wasm-client) over the same crabidy-core client and proto the
TUI uses, so parity is structural: library browsing, search terms,
marks, bookmarks/captures with live progress and confirmed deletion,
the full queue and playback controls, and the update stream with
reconnect. Keys mirror the TUI; every key also has a clickable control.
Styling is hand-written modern CSS with a single crab orange-red accent
and light/dark themes.

The server wraps its existing gRPC service in tonic-web and composes one
axum router (auth layer -> grpc-web -> service, web bundle as fallback);
axum::serve replaces tonic transport, and native gRPC (h2c) still works.
The bundle is embedded via include_dir behind a build.rs that falls back
to a placeholder so a plain cargo build needs no wasm toolchain. To make
crabidy-core build for wasm, tonic is codegen-only there (transport
generation disabled) and native config loading is target-gated.

devenv gains the wasm toolchain and build-web/serve-web scripts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 22:43:06 +02:00
..
src Add a Leptos web client served by the server 2026-07-21 22:43:06 +02:00
.gitignore Add a Leptos web client served by the server 2026-07-21 22:43:06 +02:00
Cargo.toml Add a Leptos web client served by the server 2026-07-21 22:43:06 +02:00
README.md Add a Leptos web client served by the server 2026-07-21 22:43:06 +02:00
Trunk.toml Add a Leptos web client served by the server 2026-07-21 22:43:06 +02:00
index.html Add a Leptos web client served by the server 2026-07-21 22:43:06 +02:00
style.css Add a Leptos web client served by the server 2026-07-21 22:43:06 +02:00

README.md

cbd-web — the browser client

A Leptos client-side WASM app with the same functionality as cbd-tui, served by crabidy-server itself. See architecture/web-client.md for the design.

How it works

  • Transport: gRPC-web (tonic-web-wasm-client) over the same generated client and proto types the TUI uses (crabidy-core). No second API surface — feature parity is structural. The server wraps its existing gRPC service in tonic-web, so the browser and the TUI hit identical /crabidy.v1.CrabidyService/… paths, and the role auth layer (architecture/roles-auth.md) gates both.
  • Serving: the built bundle (cbd-web/dist) is embedded into crabidy-server at compile time behind the default-on web-ui feature and served as the fallback route on port 50051. gRPC and static assets share one origin, so there is no CORS story.
  • Local-first: pure client-side rendering, every asset in the bundle (no CDN, no external fonts), library listings cached in memory like the TUI, credentials and theme in localStorage, and the update stream reconnects with backoff when the server disappears. There is no CRDT layer — this is a remote control for one live server state, not an offline-editing app (a deliberate departure from the web_client_example_workspace template that informed the toolchain).

Functionality

Everything the TUI does: browse the library (j/k/h/l, click), marks, create/rename/delete nodes (%/e/d, with the capture-delete y/N confirmation), bookmark and capture (w/W, with live progress lines and skipped-track marking), the full queue and playback controls, volume, shuffle/repeat, and a ? help overlay listing the keys. Keys mirror the TUI; every key also has a clickable control. A light/dark theme follows the OS and can be toggled (persisted). The accent color is the crab orange-red.

When the server requires credentials, a login form collects the role (owner / queue-owner / queue-appender) and password; they are stored in localStorage and sent as the gRPC-web authorization header on every request.

Building

The WASM toolchain (trunk, wasm-bindgen, the wasm32-unknown-unknown target) is provided by devenv. From the repo root:

devenv shell -- build-web        # release bundle → cbd-web/dist
cargo build -p crabidy-server    # embeds cbd-web/dist

build-web clears RUSTFLAGS first: the native toolchain sets the mold linker, which rust-lld (the wasm linker) cannot parse.

Building crabidy-server without a cbd-web/dist present is fine — it embeds a placeholder page telling you to run build-web. Build the server --no-default-features to drop the web client (and the tonic-web layer) entirely.

Dev loop

Run a server, then a live-reloading trunk server that proxies gRPC-web to it:

cargo run -p crabidy-server      # or `cbd`
devenv shell -- serve-web        # trunk serve on http://127.0.0.1:8080

Trunk.toml proxies /crabidy.v1.CrabidyService to 127.0.0.1:50051, so the app behaves as if served from the server.

Tests

The DOM-free logic (pane/selection state machines, the keymap, capture progress formatting) lives in src/state.rs and src/keymap.rs and is unit-tested on the native target:

cargo test -p cbd-web

Components in src/app.rs stay thin over that logic. The server-side serving and the gRPC-web + auth routing are tested in crabidy-server (src/web.rs, tests/web_server.rs).