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/README.md
T
Miguel Palhas 5c3f9cab9f feat(maestro): replace spawn modal with draft panes (#62)
The draft pane covers every field the modal had; the modal was a second
code path for the same job. The header Spawn button, sidebar empty state,
welcome button, and ?mock&spawn now open a draft pane via
MultiView.openDraft — reusing an empty focused pane, else splitting it.
"Spawn similar" seeds a draft with the session's cwd + command.

Modal-only CSS (backdrop, sheet/dialog chrome, keyframes) is deleted;
.modal-body form styling folds into .spawn-form, which also picks up the
select styling the worktree branch picker was borrowing from the modal.
2026-08-23 22:36:48 +01:00

2.7 KiB

maestro-web

Browser UI for Maestro. Talks to a single local daemon over its /api/* HTTP/WS surface — session catalog, spawn/kill, and 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 daemon if needed.

Layout

src/
  main.ts        # entry point, hash-route dispatch
  api.ts         # daemon HTTP API client
  events.ts      # `/api/events` WebSocket subscriber
   catalog.ts     # session tree view (groups by working directory)
   attach.ts      # xterm.js + attach WS view
   multiview.ts   # tabs + split panes; draft panes host the spawn form
   spawnForm.ts   # shared spawn form (preset tiles, project picker, worktree)
  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 daemon, ?mock&spawn to open a draft pane, and ?theme=light|dark to pin a theme.

Routing is hash-based:

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

This keeps the 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:7070
pnpm build    # → dist/, embedded into the maestro-web binary at cargo build time

The Vite dev server proxies /api and the WebSockets to a local daemon. Default is http://127.0.0.1:7070; point it elsewhere by exporting MAESTRO_DAEMON_URL before pnpm dev:

MAESTRO_DAEMON_URL=http://laptop.lan:7070 pnpm dev

Production

pnpm build writes the bundle to web/dist/. The maestro-web crate embeds that directory at compile time and serves it from /, reverse-proxying /api/* to the daemon. See crates/maestro-web/src/static_bundle.rs.