Replace Alpine frontend with Next.js Claude Activity Dashboard (#7)

Rebuild the bundled web UI as a Next.js (React + TypeScript) static export
implementing the Claude Activity Dashboard design: a left-nav "Control Center"
hub over Runs, Repositories, Agents, Approvals, Git Servers, Activity, and
Shared, styled with the Leeworks design-system tokens (flat, dark, border-led).

The dashboard is a pure client of the existing API (same contract as curl):
the browser prompts for the token once, stores it in localStorage, attaches it
to every call, and renders all API values as React text so agent-authored
strings stay inert. Control actions enqueue a command and poll it to a terminal
state, matching the worker model.

The build output is committed to src/handler/api/static/ so the wheel ships it
and FastAPI serves it same-origin. app.py now mounts the export at "/" after the
API routers (a non-shadowing fallback: unmatched paths 404, no SPA rewrite).
UI-serving tests updated for the export; frontend source lives in frontend/.


Claude-Session: https://claude.ai/code/session_01ATgVWRjFzG8nHEnwgZpJWD

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Wyatt
2026-07-10 14:34:43 -04:00
committed by GitHub
parent 6668d14c34
commit 7399315185
45 changed files with 3763 additions and 1223 deletions
+25
View File
@@ -337,6 +337,29 @@ covered. The seams — `control.tmux`, `control.forge`, `control.gitops`, `hooks
and `control.spawn.resume` — are the mock points that stand in for live
`claude`/`tmux`/`mise`/`forge`/`git`, and the drop-in points for wiring them up for real.
### Frontend
The dashboard (`frontend/`) is a **Next.js** app (React + TypeScript) that builds to a
**static export** — the `Claude Activity` Control Center: a left-nav hub over Runs,
Repositories, Agents, Approvals, Git Servers, Activity, and Shared. It is a pure client of
the API (same contract as `curl`): the browser prompts for the token once, stores it in
`localStorage`, and attaches it to every call. All API values render as React text
(never `dangerouslySetInnerHTML`) so agent-authored strings can't inject markup.
The build output is committed to `src/handler/api/static/` so the Python wheel ships it and
FastAPI serves it same-origin — there is no separate frontend server and no node step in the
Docker image. Rebuild after changing the UI:
```bash
cd frontend
npm install
npm run build # static export → frontend/out/
npm run export # build, then sync frontend/out/ → src/handler/api/static/
```
`npm run dev` runs the UI against a live API on another origin — set
`NEXT_PUBLIC_API_BASE=http://127.0.0.1:8000` and enable `CORS_ORIGINS` on the API.
## Project layout
```
@@ -348,6 +371,8 @@ src/handler/
# forge/gitops seams, credentials, skills_gen, CI poller
hooks/ # Stop/SessionEnd, PreToolUse gate (push + approval), Notification
migrations/ # Alembic env + versions
api/static/ # built Next.js export (generated — see frontend/)
frontend/ # Next.js dashboard source (builds to api/static/)
tests/ # DB, API, hook, and control tests (SQLite)
docs/PLAN.md # full design + phased roadmap (the original plan of action)
```