120 lines
5.9 KiB
Markdown
120 lines
5.9 KiB
Markdown
# React Dashboard Migration
|
|
|
|
## Outcome
|
|
|
|
Replace the inline dashboard in `public/index.html` with a typed, accessible React
|
|
application without disrupting the bot worker or its Express API. At cutover,
|
|
Express will remain the authenticated API, SSE, private-media, and static-asset
|
|
host.
|
|
|
|
## Current status
|
|
|
|
The React application and production build are present. The current routes are
|
|
Overview, Conversations (including route-addressable detail), Media,
|
|
Performance, Operations, and a Settings placeholder. Shared HTTP and realtime
|
|
schemas live in `packages/api-contracts`, and `/api/events/stream` supplies the
|
|
typed SSE transport.
|
|
|
|
`npm run build` compiles the server and writes the Vite application to
|
|
`apps/dashboard/dist`. `src/web/dashboard-assets.ts` can select that build and
|
|
fall back to `public/index.html`, but the checked-in Express server has not yet
|
|
completed that authenticated static-hosting cutover. Until it does, the legacy
|
|
page remains the served fallback and the dashboard must not be exposed to an
|
|
untrusted network.
|
|
|
|
The migration is complete only when the legacy dashboard can be removed without
|
|
losing a documented capability and the full test, type-check, production-build,
|
|
browser-acceptance, authentication, private-media, and reconnect gates pass.
|
|
|
|
## Architecture
|
|
|
|
- `apps/dashboard`: React, TypeScript, Vite, React Router, and TanStack Query.
|
|
- `packages/api-contracts`: shared Zod schemas for HTTP and realtime transport.
|
|
- `src/web`: existing Express host, gradually adapted to the shared contracts.
|
|
- Backend service and database types stay private to the backend. Transport
|
|
contracts must not expose database rows as an accidental public API.
|
|
- Server state lives in TanStack Query. Route, filter, and selection state lives
|
|
in URLs. Local component state is reserved for ephemeral presentation state.
|
|
- Do not add a global client-state library until a demonstrated cross-feature
|
|
state requirement cannot be met by those boundaries.
|
|
|
|
## Navigation
|
|
|
|
The application shell provides a responsive sidebar or drawer with these routes:
|
|
|
|
| Route | Responsibility |
|
|
| --- | --- |
|
|
| `/` | Health, metrics, timers, limits, and important recent activity |
|
|
| `/conversations` | Searchable conversation inbox |
|
|
| `/conversations/:id` | Conversation history, context, suggestions, and sending |
|
|
| `/media` | Private blurred-by-default gallery and sync controls |
|
|
| `/performance` | Trends, strategies, subreddits, and successful examples |
|
|
| `/operations` | Domain activity, background jobs, and diagnostics |
|
|
| `/settings` | Placeholder for runtime and access settings |
|
|
|
|
Overview surfaces bot state, dry-run state, cooldowns, timers, and the guarded
|
|
start/stop control. Operations owns connection health, sync state, activity,
|
|
and the bounded technical console.
|
|
|
|
## Realtime model
|
|
|
|
HTTP snapshots are authoritative. A typed SSE event stream updates or invalidates
|
|
the relevant query cache. Every event has an ID, type, occurrence timestamp, and
|
|
validated payload. The stream supports bounded replay and `Last-Event-ID` resume.
|
|
Relevant events invalidate TanStack Query keys so the next HTTP read remains
|
|
authoritative. Connection loss marks cached state stale while `EventSource`
|
|
reconnects.
|
|
|
|
Required event families are bot status, message sent or failed, conversation
|
|
updated, reply received, sync lifecycle and progress, rate-limit state, Reddit
|
|
session state, and technical logs.
|
|
|
|
Important domain events appear in a readable activity timeline. Raw logs remain
|
|
in Operations. Toasts are reserved for user-triggered outcomes requiring timely
|
|
feedback. Realtime disconnection never blanks cached content; it marks it stale
|
|
and falls back to visibility-aware polling where necessary.
|
|
|
|
## Feature slices
|
|
|
|
1. Capture and validate existing HTTP contracts and critical legacy journeys.
|
|
2. Add the frontend build, application shell, authentication handling, routing,
|
|
error boundaries, design tokens, query client, and test harness.
|
|
3. Deliver Overview as the first production vertical slice.
|
|
4. Add the typed realtime event core, SSE transport, reconnection, and query
|
|
invalidation.
|
|
5. Migrate Conversations, including explicit suggestion and send mutations.
|
|
6. Migrate Media, preserving authentication and blur-by-default privacy.
|
|
7. Migrate Performance with sample sizes and low-confidence warnings.
|
|
8. Migrate Operations, access/login, and route-backed validated Settings.
|
|
9. Run feature parity and security audits, switch Express to the Vite output,
|
|
remove the legacy HTML, and update operator and deployment documentation.
|
|
|
|
Each slice must be usable independently and must not require a flag-day rewrite.
|
|
The legacy dashboard remains available until replacement behavior is proven.
|
|
|
|
## Engineering gates
|
|
|
|
- New behavior follows red-green-refactor with Vitest.
|
|
- Component tests use Testing Library and test observable behavior.
|
|
- HTTP tests use a controlled boundary such as MSW rather than mocking `fetch`
|
|
throughout feature tests.
|
|
- Contract tests prove representative current responses parse and malformed
|
|
payloads fail.
|
|
- Realtime tests cover ordering, replay, duplicate handling, reconnection, and
|
|
cache repair.
|
|
- Browser tests cover authentication, start/stop, conversation inspection,
|
|
sending confirmation, sync, settings persistence, and private media.
|
|
- Interactive controls are keyboard accessible and restore focus after dialogs.
|
|
- No production frontend or backend code uses `any` or `console.log`.
|
|
- Mutations display the confirmed server outcome and do not rely on optimistic
|
|
success for operational controls.
|
|
- Production builds are deterministic. Serving only generated frontend assets
|
|
plus authenticated private content remains a cutover gate.
|
|
|
|
## Cutover evidence
|
|
|
|
Before deleting `public/index.html`, record evidence for every legacy capability,
|
|
all API and SSE authentication paths, private media access, container restart and
|
|
SSE recovery, responsive navigation, frontend type-check/build, backend build,
|
|
the complete Vitest suite, and the critical Playwright journeys.
|