From ef9715c5a6a75807abf9c9a91960ff65768f273f Mon Sep 17 00:00:00 2001 From: vince Date: Fri, 19 Jun 2026 23:21:09 +0200 Subject: [PATCH] docs: define react runtime migration --- ...26-06-19-react-runtime-migration-design.md | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 docs/superpowers/specs/2026-06-19-react-runtime-migration-design.md diff --git a/docs/superpowers/specs/2026-06-19-react-runtime-migration-design.md b/docs/superpowers/specs/2026-06-19-react-runtime-migration-design.md new file mode 100644 index 0000000..10af83a --- /dev/null +++ b/docs/superpowers/specs/2026-06-19-react-runtime-migration-design.md @@ -0,0 +1,163 @@ +# React Runtime Migration Design + +## Context + +The current Dimension Lab website is a SvelteKit application. It uses Bun, +Vite, Svelte 5, SvelteKit server routes, Svelte Storybook stories, and +Svelte SSR component tests. The app has one dashboard route, one agent +configuration API route, reusable Svelte UI components, typed dashboard model +data, Drizzle-backed SQLite persistence, datasource resolution, Playwright +desktop/mobile checks, and a Bun-based container runtime. + +The migration goal is to make the project React-based so dashboard UI +components can be reused outside the current app. A partial React island inside +SvelteKit would leave the app split across two component systems, so the target +state is a React runtime and React component library. + +## Target Architecture + +Use Vite React for the browser app and a small Bun HTTP server for production +runtime. This keeps the existing Bun SQLite persistence model and avoids adding +a heavier React framework where the current route/API surface is small. + +The migrated app will have these boundaries: + +- `src/main.tsx` mounts the React application in the browser. +- `src/App.tsx` owns dashboard loading, refresh timing, document-to-UI mapping, + and non-ready dashboard states. +- `src/server/index.ts` serves the Vite build output in production and exposes + JSON API routes. +- `src/server/routes/dashboard.ts` loads the dashboard runtime and resolves live + datasources unless `DISABLE_LIVE_DATASOURCES=1`. +- `src/server/routes/agent-dashboard.ts` delegates POST requests to the existing + `handleAgentDashboardRequest` function. +- `src/lib/model/**`, `src/lib/server/db/**`, `src/lib/server/dashboard.ts`, + `src/lib/server/datasources/**`, and `src/lib/server/agent-config/**` remain + TypeScript business logic with minimal import-path updates. +- `src/lib/ui/components/*.tsx` contains the reusable React component library. +- `src/lib/ui/stories/*.stories.tsx` contains React Storybook stories. + +## Component Migration + +Every current Svelte UI component will be ported to React with typed props: + +- Badge +- Button +- CornerBracketFrame +- DashboardFrame +- DashboardHeader +- DiagonalStripeField +- FooterCell +- FooterStatusCell +- GridFrame +- IconButton +- IconGlyph +- LineChart +- ModuleCard +- Panel +- ProgressMeter +- ScanlineField +- Separator +- ServiceGroupPanel +- ServicePanel +- ServiceRow +- SignalTrace +- Sparkline +- StatusBadge +- StatusStrip +- SystemState +- TelemetryCard +- TelemetryGrid +- TelemetryStrip +- WeatherModule + +The visual design, CSS custom property tokens, accessibility attributes, +data-model identifiers, severity attributes, focusable links, reduced-motion +behavior, and screenshot-tested dashboard layout must stay equivalent to the +current Svelte implementation. + +CSS will remain in `src/lib/ui/tokens.css` and component-specific CSS files. +React components should import their own CSS modules or regular CSS files in a +consistent local pattern. Shared UI types and `dashboardDocumentToUiDashboard` +remain framework-agnostic TypeScript. + +## Runtime And API Behavior + +The React app will fetch `GET /api/dashboard` on page load. When the runtime +state is ready, the response includes the dashboard document and metadata. When +the runtime state is empty, loading, or invalid, the React app renders the same +state shell that the Svelte page currently renders. + +Ready dashboard documents use `metadata.refreshIntervalSeconds` to schedule a +refresh. The React implementation will clear old timers when the dashboard +state changes and on unmount. + +The existing agent configuration endpoint remains available at +`POST /api/agent/dashboard`. The request validation, token authorization, +preview, publish, rollback, JSON patch behavior, and persistence behavior remain +owned by `src/lib/server/agent-config/index.ts`. + +## Build, Storybook, And Deployment + +`package.json` will move from Svelte/SvelteKit dependencies to React tooling: + +- Runtime dependencies include `@vitejs/plugin-react`, `react`, `react-dom`, + `@iconify/react`, and existing non-Svelte libraries that still apply. +- Storybook moves from `@storybook/sveltekit` and Svelte CSF to + `@storybook/react-vite`. +- `svelte.config.js`, `src/app.html`, `src/routes/**`, and `.svelte` files are + removed after equivalent React/server files exist. + +The production build still creates `build/index.js` as the Bun server entry so +the current container command remains: + +```sh +DATABASE_URL=file:/data/dimensionlab.sqlite HOST=0.0.0.0 PORT=3000 bun build/index.js +``` + +The `Containerfile` continues to install with Bun, build with Bun, copy the +client/server build output plus `drizzle/`, and run the Bun server. + +## Testing Strategy + +The migration is verified with equivalent or stronger tests: + +- TypeScript check covers React TSX, server modules, and shared model code. +- Current model, validation, database, datasource, and agent-config unit tests + remain in place. +- Svelte SSR component tests become React `react-dom/server` tests. +- Page rendering tests become React app/server response tests. +- Storybook boundary tests are updated to require React story files and continue + preventing Dimension Lab-specific content in reusable presentation stories. +- Playwright desktop/mobile tests continue to run against the production Bun + server and the built React app. +- The full QA gate remains `bun run test:qa`. + +## Completion Criteria + +The migration is complete only when current evidence proves all of these: + +- There are no `.svelte` app, component, route, or story files left. +- `package.json` has no Svelte, SvelteKit, or Svelte Storybook dependencies. +- `bun run check` passes. +- `bun run test:unit` passes. +- `bun run build` produces the React client build and Bun server entry. +- `bun run build-storybook` passes with React stories. +- `bun run test:e2e` passes on desktop and mobile. +- The dashboard renders from the same validated dashboard model data. +- `POST /api/agent/dashboard` still exercises the existing agent config logic. +- The production container still runs with `bun build/index.js`. + +## Migration Approach + +The work should be implemented in focused commits on `codex/react-migration`: + +1. Establish React/Vite/Bun server scaffolding and tests while keeping the + current Svelte code available for reference. +2. Port reusable UI components to React and update render tests. +3. Port the dashboard app route and refresh behavior to React. +4. Port Storybook stories and presentation boundary tests to React. +5. Remove SvelteKit runtime files and dependencies. +6. Update build, e2e, README, and container behavior. +7. Run the full QA gate, push the branch, open a ready PR, perform independent + review, fix blockers, and merge only after checks and review pass.