87 lines
3.4 KiB
Markdown
87 lines
3.4 KiB
Markdown
# cbd-web — the browser client
|
|
|
|
A [Leptos](https://leptos.dev) 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:
|
|
|
|
```sh
|
|
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:
|
|
|
|
```sh
|
|
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:
|
|
|
|
```sh
|
|
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`).
|