docs(03-01): complete frontend scaffold plan — Vite+React+ClickHouse design system

This commit is contained in:
Mikkel Georgsen 2026-04-10 06:17:42 +00:00
parent d38f93dd67
commit f151b96f88

View file

@ -0,0 +1,182 @@
---
phase: 03-dashboard-intake-ui
plan: "01"
subsystem: ui
tags: [react, typescript, vite, tailwind, shadcn, tanstack-router, tanstack-query, zustand, clickhouse-design]
# Dependency graph
requires: []
provides:
- Vite 5 + React 18 + TypeScript 5 SPA scaffold in web/
- ClickHouse design tokens as Tailwind CSS custom colors (volt, forest, canvas, charcoal, near-black)
- TanStack Router v1 route tree with placeholder routes for /, /item/$id, /intake, /scan
- TanStack Query v5 QueryClientProvider wired in App.tsx
- Zustand uiStore with viewMode, scannerActive, intakeStep
- shadcn/ui Button, Card, Badge components with ClickHouse variants
- npm run build produces web/dist/ ready for Go go:embed
- Vite dev proxy: /api -> http://localhost:8080
affects: [03-02, 03-03, 03-04, 03-05]
# Tech tracking
tech-stack:
added:
- vite@5.3.x
- react@18.3.x
- typescript@5.5.x
- tailwindcss@3.4.x
- "@tanstack/react-router@1.48.x"
- "@tanstack/react-query@5.51.x"
- "@tanstack/router-devtools@1.48.x"
- zustand@4.5.x
- class-variance-authority@0.7.x
- clsx@2.1.x
- tailwind-merge@2.5.x
- lucide-react@0.417.x
- react-dropzone@14.2.x
- react-hot-toast@2.4.x
- "@radix-ui/react-slot@1.1.x"
- "@zxing/browser@0.1.5"
- "@types/node@25.x (devDep)"
- "@typescript-eslint v8 (devDep)"
patterns:
- ClickHouse design tokens as Tailwind extend.colors (not CSS vars)
- shadcn/ui components hand-written (not CLI-generated) with ClickHouse variants
- TanStack Router code-based route tree (not file-based)
- QueryClient singleton exported from lib/queryClient.ts
- Zustand store in src/store/ui.ts — UI state only, not server data
key-files:
created:
- web/package.json
- web/vite.config.ts
- web/tsconfig.json
- web/tsconfig.app.json
- web/tsconfig.node.json
- web/postcss.config.cjs
- web/tailwind.config.ts
- web/index.html
- web/components.json
- web/src/styles/globals.css
- web/src/lib/utils.ts
- web/src/lib/queryClient.ts
- web/src/store/ui.ts
- web/src/router.tsx
- web/src/App.tsx
- web/src/main.tsx
- web/src/components/ui/button.tsx
- web/src/components/ui/card.tsx
- web/src/components/ui/badge.tsx
modified:
- Makefile (added frontend, dev-frontend targets)
- .gitignore (added web/node_modules, web/dist/assets, *.tsbuildinfo, bin/, hwlab)
- web/dist/index.html (replaced stub with Vite-built SPA shell)
key-decisions:
- "Used @typescript-eslint v8 (not v7) for ESLint v9 compatibility — v7 requires ESLint v8"
- "Added @types/node devDep for path/__dirname in vite.config.ts"
- "ClickHouse tokens as Tailwind extend.colors (not CSS variables) — simpler, no shadcn cssVariables conflict"
- "shadcn/ui components hand-written with ClickHouse-specific variants rather than CLI-generated defaults"
- "TanStack Router code-based route tree chosen over file-based — appropriate for this project scale"
patterns-established:
- "ClickHouse design: volt (#faff69) accent, canvas (#000000) bg, near-black (#141414) surfaces, charcoal/80 borders"
- "cn() utility from clsx+tailwind-merge for all component className merging"
- "Button variants: default(neon), forest(green), secondary(dark), outline(ghost), destructive, ghost, link"
- "All routes are placeholder stubs — replaced by feature plans 03-02 through 03-05"
requirements-completed: [UI-06]
# Metrics
duration: 25min
completed: 2026-04-10
---
# Phase 3 Plan 01: Frontend Scaffold Summary
**Vite 5 + React 18 + TypeScript 5 SPA with ClickHouse design tokens (volt/canvas/forest/charcoal), TanStack Router v1, TanStack Query v5, Zustand, and shadcn/ui Button/Card/Badge components**
## Performance
- **Duration:** ~25 min
- **Started:** 2026-04-10T06:10:00Z
- **Completed:** 2026-04-10T06:35:00Z
- **Tasks:** 2
- **Files modified:** 21
## Accomplishments
- Full Vite 5 + React 18 + TypeScript 5 + Tailwind 3 project scaffolded in `web/`
- ClickHouse design system tokens applied as Tailwind custom colors — `volt`, `canvas`, `near-black`, `forest`, `charcoal`, `hover-gray`, etc.
- TanStack Router v1 route tree with placeholder pages for `/`, `/item/$id`, `/intake`, `/scan`
- shadcn/ui Button (7 variants), Card, Badge components written with ClickHouse-specific styling
- `npm run build` produces `web/dist/` that Go's `go:embed` picks up unchanged
## Task Commits
1. **Tasks 1+2: Scaffold + wire React app** - `d38f93d` (feat)
**Plan metadata:** (pending docs commit)
## Files Created/Modified
- `web/package.json` - npm manifest with all deps pinned
- `web/vite.config.ts` - Vite 5 config with /api proxy to :8080 and @ alias
- `web/tailwind.config.ts` - ClickHouse design tokens as Tailwind colors/fonts
- `web/src/styles/globals.css` - Tailwind directives + CSS custom properties
- `web/src/router.tsx` - TanStack Router v1 code-based route tree
- `web/src/App.tsx` - QueryClientProvider + RouterProvider + Toaster shell
- `web/src/main.tsx` - React 18 entry point
- `web/src/store/ui.ts` - Zustand uiStore (viewMode, scannerActive, intakeStep)
- `web/src/lib/queryClient.ts` - QueryClient singleton (30s stale, no window refetch)
- `web/src/lib/utils.ts` - cn() helper (clsx + tailwind-merge)
- `web/src/components/ui/button.tsx` - Button with neon/forest/secondary/outline/ghost/link variants
- `web/src/components/ui/card.tsx` - Card, CardHeader, CardTitle, CardContent, CardFooter
- `web/src/components/ui/badge.tsx` - Badge with indexed/draft/needs_research/researched/complete/destructive variants
- `web/components.json` - shadcn/ui CLI config
- `Makefile` - Added `frontend` and `dev-frontend` targets
- `.gitignore` - Added node_modules, dist/assets, tsbuildinfo, bin/, hwlab binary
## Decisions Made
- `@typescript-eslint` bumped to v8 (from plan's v7) because ESLint v9 requires v8+
- `@types/node` added as devDep for `path` module and `__dirname` in `vite.config.ts`
- Design tokens applied directly as Tailwind `extend.colors` rather than CSS variables — avoids shadcn `cssVariables` mode complexity while keeping full Tailwind utility access
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 1 - Bug] Updated @typescript-eslint to v8 for ESLint v9 compatibility**
- **Found during:** Task 1 (npm install)
- **Issue:** Plan specified `@typescript-eslint` v7, which requires `eslint@^8`. Installed `eslint@^9` resolved to v9.39.4, causing peer conflict
- **Fix:** Bumped `@typescript-eslint/eslint-plugin` and `@typescript-eslint/parser` from `^7.15.0` to `^8.0.0`
- **Files modified:** `web/package.json`
- **Verification:** `npm install` succeeded without peer conflicts
- **Committed in:** d38f93d
**2. [Rule 3 - Blocking] Added @types/node and vite/client types to fix TypeScript build**
- **Found during:** Task 1 verify (`npm run build`)
- **Issue:** `vite.config.ts` failed — `path` module not found, `__dirname` not defined. `router.tsx` failed — `import.meta.env` not typed
- **Fix:** Added `@types/node` devDep; added `"types": ["node"]` to `tsconfig.node.json`; added `"types": ["vite/client"]` to `tsconfig.app.json`
- **Files modified:** `web/package.json`, `web/tsconfig.node.json`, `web/tsconfig.app.json`
- **Verification:** `npm run build` exits 0, produces `dist/index.html` + `dist/assets/*.js`
- **Committed in:** d38f93d
---
**Total deviations:** 2 auto-fixed (1 dependency version conflict, 1 missing TypeScript types)
**Impact on plan:** Both auto-fixes were necessary for build to succeed. No scope creep.
## Issues Encountered
None beyond the two auto-fixed TypeScript/npm issues above.
## User Setup Required
None - no external service configuration required.
## Next Phase Readiness
- Frontend scaffold is complete and buildable — `npm run build` exits 0
- Go binary still compiles (`go build ./...` passes) — embed path unchanged
- Plan 03-02 can begin immediately: replace placeholder route components with real Dashboard and Item Detail views
- TanStack Query is wired; just needs `useQuery` hooks pointing at `/api/inventory` endpoints
- Zustand `useUIStore` is importable for `viewMode` toggle in dashboard
---
*Phase: 03-dashboard-intake-ui*
*Completed: 2026-04-10*