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
Miguel PalhasandClaude Opus 5 80af2e6816 feat(maestro): one pane, one tab on mobile
Below 860px the layout no longer grows a second navigation surface. The
pane pill strip is gone, the tab bar stays collapsed however many tabs
exist, and opening or spawning takes over the current pane instead of
splitting beside it or opening a tab. The sidebar drawer is the only way
to move between sessions.

The tree itself is untouched, so a desktop-built layout comes back when
the window widens again.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-31 22:14:42 +01:00
..

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.