This repository has been archived on 2026-10-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
maestro/web
naps62-yolo 3aedd7a0a5
ci / rust (push) Failing after 5m3s
feat(maestro): live directory autocomplete in spawn form (NAP-329)
Adds api.listDir + a reusable dirAutocomplete widget (live dropdown,
Tab/Enter completion, /-drill-in, per-(daemon,dir) cache) wired onto the
cwd and worktree base-repo fields, with matching dropdown styling.
2026-06-15 21:20:36 +00:00
..

maestro-web

Browser UI for Maestro. Connects to the registry HTTP/WS API for the catalog and to individual daemons (via direct WebSocket) for terminal I/O.

Framework choice: vanilla TypeScript

No frontend framework. The UI is small enough that the cost of pulling in Preact / Solid / Leptos doesn't pay back. xterm.js does all the heavy rendering; everything else is a session tree and a spawn form, both trivial in plain DOM.

This decision is non-architectural — swap in a framework later without touching the registry or daemon if needed.

Layout

src/
  main.ts        # entry point, hash-route dispatch
  api.ts         # registry HTTP API client
  events.ts      # `/api/events` WebSocket subscriber
  catalog.ts     # session tree view (groups by metadata.label)
  attach.ts      # xterm.js + daemon WS attach view
  spawn.ts       # spawn-session modal
  theme.ts       # dark/light theme toggle + persistence
  types.ts       # mirror of `maestro-protocol` JSON shapes
  styles.css     # design-system tokens + component styles
  mock.ts        # DEV-only review fixture (see Design)

Design

The visual system (OKLCH token palette, monospace-first typography, dark+light theming, motion, components) is documented in ../DESIGN.md; the tokens live in the :root block of src/styles.css. Strategic intent (register, brand, principles) is in ../PRODUCT.md. Theme follows the OS by default and can be pinned via the header toggle (persisted in localStorage).

mock.ts is a DEV-only fixture (stripped from production builds): visit the dev server with ?mock to seed a representative catalog without a running registry, ?mock&spawn to open the spawn modal, and ?theme=light|dark to pin a theme.

Routing is hash-based:

  • #/ → catalog
  • #/attach/<session-id> → terminal

This keeps the registry's static handler dumb (no SPA fallback needed). Concurrent attaches: open the same #/attach/<id> URL in another tab.

Dev

pnpm install
pnpm dev      # http://localhost:5173, proxies /api → http://127.0.0.1:8080
pnpm build    # → dist/, embedded into the registry binary at cargo build time

The Vite dev server proxies /api and the events WebSocket to a maestro-registry. Default is http://127.0.0.1:8080; point it elsewhere by exporting MAESTRO_REGISTRY before pnpm dev:

MAESTRO_REGISTRY=https://maestro-registry.example.com pnpm dev
# Daemon-facing URL also works — `wss://...` is rewritten to `https://...`
# and a trailing `/daemon` is stripped.
MAESTRO_REGISTRY=wss://maestro-registry.example.com/daemon pnpm dev

Direct daemon WS connections (for attach) bypass the proxy and use the URL returned by GET /api/sessions/:id/connect-info.

Production

pnpm build writes the bundle to web/dist/. The Rust registry crate embeds that directory via rust-embed at compile time and serves it from /. See crates/maestro-registry/src/web_assets.rs.