112 lines
5.4 KiB
Markdown
112 lines
5.4 KiB
Markdown
# React Dashboard Migration
|
|
|
|
## Outcome
|
|
|
|
The inline dashboard has been replaced by a typed, accessible React application.
|
|
Express remains the authenticated API, SSE, private-media, and production
|
|
static-asset host.
|
|
|
|
## Current status
|
|
|
|
The current routes are Overview, Conversations (including route-addressable
|
|
detail), Media, Performance, Operations, and validated Settings and Access.
|
|
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` requires that build and
|
|
fails startup with an actionable error if it is absent. The legacy HTML has
|
|
been removed. Root pages, assets, APIs, SSE, and private media share the same
|
|
timing-safe dashboard authentication boundary.
|
|
|
|
## 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` | Validated runtime configuration and Reddit access state |
|
|
|
|
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.
|
|
|
|
All slices now run from the React application; the migration phases above are
|
|
retained as implementation history.
|
|
|
|
## 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. The server serves only generated React
|
|
assets plus authenticated private content.
|
|
|
|
## Cutover evidence
|
|
|
|
Cutover verification covers API and SSE authentication, private media access,
|
|
SSE recovery, responsive navigation, frontend type-check/build, backend build,
|
|
the complete Vitest suite, and browser smoke journeys.
|