Mechanical reformat — no logic changes. 398 files changed, 19125 insertions(+), 16457 deletions(-). Prettier 3.8.4 with .prettierrc (singleQuote:true, semi:true, tabWidth:2, trailingComma:all, printWidth:100). Isolated per D-13-08 for reviewability.
159 lines
9.0 KiB
Markdown
159 lines
9.0 KiB
Markdown
---
|
||
phase: 04-shared-lists-live-sync
|
||
plan: '01'
|
||
subsystem: pwa-routing, db-schema, test-harness
|
||
tags: [react-router, bottom-tab-bar, lists-surface, drizzle-migration, wave-0-red-stubs]
|
||
dependency_graph:
|
||
requires: []
|
||
provides:
|
||
- BrowserRouter shell with /calendar, /lists, /lists/:listId routes
|
||
- BottomTabBar + AppNav desktop Lists link
|
||
- ListsIndex empty surface
|
||
- lists/list_items/list_shares Drizzle tables (migrated)
|
||
- API Vitest test harness (setup.ts + vitest.config setupFiles)
|
||
- Wave-0 RED stub test files (4 files, 12+44 todo items)
|
||
affects:
|
||
- apps/pwa/src/App.tsx (router wrapping)
|
||
- apps/pwa/src/components/AppNav.tsx (desktop nav links)
|
||
- apps/pwa/src/components/CalendarShell.test.tsx (MemoryRouter fix)
|
||
- apps/api/src/db/schema.ts (new tables)
|
||
tech_stack:
|
||
added:
|
||
- react-router@7.17.0 (declarative BrowserRouter mode)
|
||
- '@dnd-kit/core (installed, used in later plans)'
|
||
- '@dnd-kit/sortable (installed, used in later plans)'
|
||
- fractional-indexing (PWA + API)
|
||
patterns:
|
||
- NavLink with isActive style callback (BottomTabBar + AppNav desktop)
|
||
- TanStack Query for list data fetching (ListsIndex)
|
||
- Zustand UI-only store (listsStore: no server data)
|
||
- drizzle-kit generate+migrate (NOT push) for DDL
|
||
- it.todo() Wave-0 stub pattern (RED stubs safe to import)
|
||
key_files:
|
||
created:
|
||
- apps/pwa/src/App.tsx (rewritten — BrowserRouter shell)
|
||
- apps/pwa/src/components/BottomTabBar.tsx
|
||
- apps/pwa/src/routes/ListsIndex.tsx
|
||
- apps/pwa/src/routes/ListDetail.tsx (placeholder stub)
|
||
- apps/pwa/src/store/listsStore.ts
|
||
- apps/pwa/src/api/listsClient.ts (fetchLists + List/ListItem types)
|
||
- apps/api/test/setup.ts
|
||
- apps/api/tests/routes/lists.test.ts
|
||
- apps/api/tests/lib/listEmitter.test.ts
|
||
- apps/pwa/src/hooks/useListSSE.test.ts
|
||
- apps/pwa/src/routes/ListDetail.test.tsx
|
||
- apps/api/src/db/migrations/0002_lists_schema.sql
|
||
modified:
|
||
- apps/pwa/src/components/AppNav.tsx (added NavLink imports + desktop Lists nav link)
|
||
- apps/pwa/src/components/CalendarShell.test.tsx (MemoryRouter wrapper)
|
||
- apps/api/src/db/schema.ts (lists, listShares, listItems tables appended)
|
||
- apps/api/vitest.config.ts (setupFiles → apps/api/test/setup.ts)
|
||
- apps/pwa/package.json (react-router, @dnd-kit/core, @dnd-kit/sortable, fractional-indexing)
|
||
- apps/api/package.json (fractional-indexing)
|
||
decisions:
|
||
- 'D-17 satisfied: react-router@7 declarative BrowserRouter (no data router/loaders)'
|
||
- 'D-16 satisfied: BottomTabBar with Calendar + Lists NavLinks at /calendar and /lists'
|
||
- 'generate+migrate enforced: 0002_lists_schema.sql is additive (CREATE TABLE only, no DROP)'
|
||
- 'ioredis NOT added (fan-out is in-memory EventEmitter per D-04, Plan 02)'
|
||
- 'Wave-0 RED stubs use it.todo() to be safe-to-import without implementations'
|
||
- 'CalendarShell.test.tsx wrapped in MemoryRouter after AppNav gained NavLink (Rule 1 fix)'
|
||
metrics:
|
||
duration: '~65 minutes (continuation agent, prior executor completed Tasks 1-2)'
|
||
completed: '2026-06-09'
|
||
task_count: 4
|
||
file_count: 17
|
||
---
|
||
|
||
# Phase 4 Plan 1: Foundation Shell Summary
|
||
|
||
**One-liner:** React-router BrowserRouter shell + BottomTabBar + empty Lists surface; three list tables migrated to MariaDB; Wave-0 RED test stubs in place.
|
||
|
||
## Tasks Completed
|
||
|
||
| Task | Name | Commit | Files |
|
||
| ---- | ------------------------------------------------------------------ | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||
| 1 | Package legitimacy gate (human-verify) | — (checkpoint, prior run) | — |
|
||
| 2 | Install new deps + scaffold API test harness with Wave-0 RED stubs | 39d4ec8 | package.json ×2, setup.ts, vitest.config.ts, 4 test files |
|
||
| 3 | Add list tables to schema + generate+migrate [BLOCKING] | 2f25b15 | schema.ts, 0002_lists_schema.sql, drizzle journal |
|
||
| 4 | Add react-router + BottomTabBar + empty ListsIndex shell | c0088ed | App.tsx, BottomTabBar.tsx, ListsIndex.tsx, ListDetail.tsx, listsStore.ts, listsClient.ts, AppNav.tsx, CalendarShell.test.tsx |
|
||
|
||
## Deviations from Plan
|
||
|
||
### Auto-fixed Issues
|
||
|
||
**1. [Rule 1 - Bug] Wave-0 RED test stubs missing vitest imports**
|
||
|
||
- **Found during:** Task 4 verification
|
||
- **Issue:** `apps/pwa/src/hooks/useListSSE.test.ts` and `apps/pwa/src/routes/ListDetail.test.tsx` used bare `describe`/`it` without importing from `vitest`. TypeScript raised TS2582 errors; the files would not run in the test harness.
|
||
- **Fix:** Added `import { describe, it } from 'vitest'` to both files following the same pattern as `apps/pwa/src/api/client.test.ts`.
|
||
- **Files modified:** `apps/pwa/src/hooks/useListSSE.test.ts`, `apps/pwa/src/routes/ListDetail.test.tsx`
|
||
- **Commit:** c0088ed
|
||
|
||
**2. [Rule 1 - Bug] CalendarShell.test.tsx broke after AppNav gained NavLink**
|
||
|
||
- **Found during:** Task 4 verification (CalendarShell test run)
|
||
- **Issue:** Adding NavLink to AppNav's DesktopNav required a Router context. The existing `CalendarShell.test.tsx` rendered `<CalendarShell />` directly without any Router wrapper, causing all 6 tests to fail with `useLocation() may be used only in the context of a <Router> component`.
|
||
- **Fix:** Added `import { MemoryRouter } from 'react-router'` and wrapped `renderWithClient`'s render call in `<MemoryRouter initialEntries={['/calendar']}>`. All 6 tests pass again.
|
||
- **Files modified:** `apps/pwa/src/components/CalendarShell.test.tsx`
|
||
- **Commit:** c0088ed
|
||
|
||
## Verification Results
|
||
|
||
### TypeScript
|
||
|
||
- `pnpm --filter @familysync/api typecheck` — PASS
|
||
- `pnpm --filter @familysync/pwa exec tsc --noEmit` — PASS
|
||
|
||
### Tests
|
||
|
||
- API Wave-0 stubs: 108 passed, 44 todo (RED stubs, as expected)
|
||
- PWA Wave-0 stubs (`useListSSE.test.ts`, `ListDetail.test.tsx`): 12 todo (as expected)
|
||
- `CalendarShell.test.tsx`: 6 passed (regression guard green)
|
||
|
||
### Migration
|
||
|
||
- `0002_lists_schema.sql` is additive: CREATE TABLE only for `lists`, `list_shares`, `list_items`
|
||
- No DROP/TRUNCATE of pre-existing tables
|
||
- `db:migrate` applied via `pnpm --filter @familysync/api db:migrate`
|
||
|
||
### Playwright Browser Check (per CLAUDE.md convention)
|
||
|
||
Navigated to `http://localhost:5173/lists` (DEV_AUTH_BYPASS active, DB not running locally):
|
||
|
||
- "Lists" heading rendered (`<h1>Lists</h1>`)
|
||
- "New list" button present (placeholder FAB)
|
||
- BottomTabBar visible with Calendar (`/calendar`) and Lists (`/lists`) NavLinks
|
||
- Loading state shown ("Loading lists…") — expected; `/api/lists` returns 404 until Plan 04-02 mounts the route
|
||
- No unexpected errors (favicon.ico 404 and `/api/lists` 404 are both expected at this stage)
|
||
|
||
### vite.config.ts navigateFallback
|
||
|
||
Verified: `navigateFallbackDenylist` only excludes `/^\/callback/`, `/^\/api\//`, `/^\/health/`. The `/lists/*` paths are NOT in the denylist — SPA deep-links to `/lists/:listId` will be served by the SW correctly.
|
||
|
||
## Known Stubs
|
||
|
||
| File | Stub | Reason |
|
||
| ---------------------------------------- | ----------------------------------------------------------------- | ------------------------------------------------- |
|
||
| `apps/pwa/src/routes/ListDetail.tsx` | Full list detail UI (placeholder renders "List view coming soon") | Plan 04-04 implements items, SSE, drag-to-reorder |
|
||
| `apps/pwa/src/routes/ListsIndex.tsx` FAB | `onClick` is a no-op | Plan 04-03 wires `CreateListSheet` |
|
||
| `apps/pwa/src/api/listsClient.ts` | Only `fetchLists` exists; no create/delete/item CRUD | Plans 04-02/04-03 expand |
|
||
|
||
These stubs intentionally leave the surface navigable but empty — subsequent plans fill in the data and interaction layer.
|
||
|
||
## Threat Surface Scan
|
||
|
||
No new trust boundaries introduced. `listsClient.ts` makes `GET /api/lists` calls (no credentials beyond what existing `client.ts` establishes — same `credentials: 'include'` pattern). T-04-SC (react-router legitimacy) was satisfied by Task 1 human gate.
|
||
|
||
## Self-Check: PASSED
|
||
|
||
- `apps/pwa/src/App.tsx` — FOUND
|
||
- `apps/pwa/src/components/BottomTabBar.tsx` — FOUND
|
||
- `apps/pwa/src/routes/ListsIndex.tsx` — FOUND
|
||
- `apps/pwa/src/routes/ListDetail.tsx` — FOUND
|
||
- `apps/pwa/src/store/listsStore.ts` — FOUND
|
||
- `apps/pwa/src/api/listsClient.ts` — FOUND
|
||
- `apps/api/src/db/migrations/0002_lists_schema.sql` — FOUND (committed in 2f25b15)
|
||
- Commit 39d4ec8 — FOUND
|
||
- Commit 2f25b15 — FOUND
|
||
- Commit c0088ed — FOUND
|