From 786a283f3165d19af1be75d69dad5b3ae2535d4f Mon Sep 17 00:00:00 2001 From: vince Date: Sat, 20 Jun 2026 05:17:28 +0200 Subject: [PATCH] docs: specify turbo component library migration --- ...26-06-20-turbo-component-library-design.md | 186 ++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 docs/superpowers/specs/2026-06-20-turbo-component-library-design.md diff --git a/docs/superpowers/specs/2026-06-20-turbo-component-library-design.md b/docs/superpowers/specs/2026-06-20-turbo-component-library-design.md new file mode 100644 index 0000000..ba0fefc --- /dev/null +++ b/docs/superpowers/specs/2026-06-20-turbo-component-library-design.md @@ -0,0 +1,186 @@ +# Turbo Component Library Migration Design + +## Context + +The current Dimension Lab website is a single Bun/Vite React package. It owns +the browser app, Bun production server, dashboard model, persistence, datasource +adapters, reusable UI components, Storybook, Playwright checks, and container +deployment from one `package.json`. + +The UI components are already mostly generic and content-free under +`src/lib/ui`, but they are not reusable by another project because they live +inside the app package, depend on app path aliases, and share the app build, +test, and Storybook configuration. One file in that area, +`src/lib/ui/model-renderer.ts`, imports the Dimension Lab dashboard model and +therefore is an app adapter, not reusable component-library code. + +The migration goal is to turn the repository into a Turborepo workspace where +the Dimension Lab website consumes a separate reusable React component package. + +## Target Repository Shape + +Use one application workspace and one component-library workspace: + +```text +. +├── apps/ +│ └── web/ +│ ├── src/ +│ ├── tests/ +│ ├── drizzle/ +│ ├── Containerfile +│ └── package.json +├── packages/ +│ └── ui/ +│ ├── src/ +│ ├── .storybook/ +│ ├── package.json +│ └── tsconfig.json +├── package.json +├── turbo.json +├── tsconfig.base.json +└── bun.lock +``` + +The root package is private and contains only workspace orchestration: +workspaces, Turbo scripts, shared dev dependencies where useful, and the lock +file. Runtime dependencies belong to the workspace that imports them. + +## Package Ownership + +`packages/ui` is a compiled React library named `@dimensionlab/ui`. + +It owns: + +- Reusable React components currently under `src/lib/ui/components`. +- UI CSS tokens and component styles. +- Theme helpers currently under `src/lib/ui/theme.ts`. +- Generic UI prop/data types currently under `src/lib/ui/types.ts`. +- Generic formatting helpers currently under `src/lib/ui/format.ts`. +- Generic Storybook stories and story fixtures. +- UI render tests, boundary tests, and Storybook inventory tests. + +It must not import from the website app, the dashboard model, server modules, +database modules, datasource modules, or deployment files. + +The library publishes explicit package exports: + +- `@dimensionlab/ui` for component and type exports. +- `@dimensionlab/ui/styles.css` for the combined token/component CSS entry. +- Optional explicit subpath exports for future direct imports where useful. + +The compiled output goes to `packages/ui/dist` and includes JavaScript, +declaration files, and copied CSS. The package stays private for now but is +structured so it can later be published or moved into another Dimension Lab repo +without taking the website runtime with it. + +`apps/web` owns: + +- The Vite React browser app. +- The Bun production server and API routes. +- Dashboard model, fixtures, schema, validation, and model migrations. +- Drizzle/SQLite persistence and checked-in SQL migrations. +- Datasource adapters and runtime dashboard loading. +- Agent dashboard configuration endpoint. +- The `dashboardDocumentToUiDashboard` adapter that maps the app model to UI + package props. +- Playwright e2e tests and deployment container. + +## Why A Compiled Package + +The component package should be compiled rather than a just-in-time source +package. This is slightly more setup, but it better fits reuse outside the +current app because consumers can import stable JavaScript and declarations +instead of relying on their bundler to transpile this repo's TypeScript source. +It also gives Turbo a cacheable `@dimensionlab/ui#build` task. + +## Build And Task Graph + +Root scripts delegate through Turbo: + +- `bun run dev` runs the web dev server and any required dependency tasks. +- `bun run build` runs package builds in dependency order. +- `bun run check` runs TypeScript checks for all workspaces. +- `bun run test:unit` runs Vitest unit tests for all workspaces. +- `bun run build-storybook` builds Storybook from `packages/ui`. +- `bun run test:e2e` runs the web app Playwright suite. +- `bun run test:qa` is the full release gate. + +`turbo.json` defines `build`, `check`, `test:unit`, `build-storybook`, +`test:e2e`, and `test:qa` tasks. Build outputs include `dist/**`, +`storybook-static/**`, and `build/**` as appropriate. + +The web app depends on `@dimensionlab/ui` using Bun workspace syntax. The web +Vite config aliases `$lib` to `apps/web/src/lib`; the UI package should not use +that app alias. + +## Storybook + +Storybook moves with the component package. It should load +`@dimensionlab/ui/styles.css`, use React Vite Storybook, and keep the existing +generic story inventory. Environment-specific Dimension Lab labels, hostnames, +links, fallback values, and datasource names remain forbidden in package UI +source and stories. + +The repository should no longer have a root Storybook tied to the web app. + +## Deployment + +The deployed website remains the same service from the outside: + +- Production command remains `bun build/index.js` inside the runtime image. +- The container still exposes port `3000` and mounts `/data`. +- Runtime environment variables and database behavior remain unchanged. + +The `Containerfile` moves to `apps/web/Containerfile` or remains root with +updated workspace-aware copy/build steps. The chosen layout must preserve the +existing Podman service contract used by `dimensionlab-website.service`. + +## Testing Strategy + +The migration must add or update tests that prove the new boundaries: + +- The root package is a Bun workspace with `apps/*` and `packages/*`. +- The web app imports UI from `@dimensionlab/ui`, not from local copied + component files. +- `packages/ui` does not import from `apps/web`, `$lib/server`, `$lib/model`, + or any website runtime module. +- `dashboardDocumentToUiDashboard` lives in `apps/web` and is tested there. +- Storybook inventory is evaluated against `packages/ui`. +- The full QA gate still covers typecheck, unit tests, app build, Storybook + build, and Playwright desktop/mobile checks. + +## Completion Criteria + +The migration is complete only when current evidence proves all of these: + +- Root `package.json` is a private workspace root with Turbo scripts. +- `turbo.json` exists and models the workspace task graph. +- The web application lives under `apps/web`. +- The reusable React component library lives under `packages/ui`. +- `packages/ui/package.json` is named `@dimensionlab/ui` and has compiled + exports for code, types, and CSS. +- The web app depends on `@dimensionlab/ui` through the workspace. +- Reusable components and Storybook have been removed from the web app package. +- App-specific model/server/database/datasource code has not moved into + `packages/ui`. +- `dashboardDocumentToUiDashboard` is outside the UI package. +- `bun run check` passes from the root. +- `bun run test:unit` passes from the root. +- `bun run build` passes from the root. +- `bun run build-storybook` passes from the root. +- `bun run test:e2e` passes from the root. +- The production container can still be built and run with the same service + contract. + +## Migration Approach + +Implement this on branch `codex/turbo-component-library` in focused commits: + +1. Add the workspace/Turbo scaffolding and boundary tests. +2. Move UI code and Storybook to `packages/ui`. +3. Move the app runtime into `apps/web` and wire it to `@dimensionlab/ui`. +4. Move the model-to-UI adapter into the web app. +5. Update build, test, Playwright, Storybook, README, and container paths. +6. Run the full QA gate, push a ready PR, perform independent review, resolve + blockers, merge to `main`, and deploy only when checks and review are clean.