# Mass Port via Delegation

Pattern used on 2026-06-26 to port 6 pages from vanilla JS v1 to React v2 in one session.

## Approach: Parallel Fan-Out

1. **Infrastructure first** — update types, routes, navigation yourself (quick edits, no delegation needed)
2. **Dispatch all pages in parallel** — 2 batches of 3 `delegate_task` calls
3. **Each subagent gets**: target file path, original source file paths, project context (types, existing patterns, PB collections), feature checklist
4. **Subagents write the complete .tsx file** — no partial work, no test cycle (speed over perfect TDD for bulk codegen)

## Batch Structure

```
Wave 1 (dispatch together): Customers, RepairOrders, Appointments
Wave 2 (dispatch together): FinancialDashboard, Invoices, Settings
```

## Per-Task Context Template

```
TASK: Build <file path>

ORIGINAL SOURCE: <v1 file paths with sizes>

PROJECT CONTEXT:
- React 19 + TypeScript + Vite + Tailwind CSS
- PocketBase backend at pb (import from '../lib/pocketbase')
- Types defined in ../types.ts — see <interfaces>
- Uses lucide-react for icons
- Existing pages for reference: Dashboard.tsx, QuoteGenerator.tsx

FEATURES TO IMPLEMENT:
1. Feature with specific behavior
2. ...

POCKETBASE COLLECTIONS:
- '<name>' collection with fields: <schema>

CODE PATTERNS TO FOLLOW:
- Import pb from '../lib/pocketbase'
- LoadingSpinner for loading state
- Error state with retry button
- Empty state with create CTA
- Modals for create/edit
- Tailwind dark mode patterns
```

## Post-Dispatch

1. **Build**: `npx vite build`
2. **Fix import errors** — subagents may use wrong paths or import components that need providers (e.g. `useToast` needs `ToastProvider` wrapper)
3. **Add ToastProvider** — lazy-loaded pages that use `useToast` crash silently if `ToastProvider` isn't wrapping `<Routes>`
4. **Lazy loading**: use `React.lazy()` + `<Suspense>` to isolate page errors and enable code splitting
5. **PB collections**: subagents can't create collections without admin access. Create missing ones or handle gracefully with error states.

## Pitfalls

- **`useToast` crash**: New pages using toast without `ToastProvider` → white screen with no error message. Always wrap `<Routes>` in `<ToastProvider>`.
- **Broken sort field**: Legacy PocketBase collections may lack `created`/`updated` system fields. Dashboard `sort=-created` returns 400. Patch built JS to use `sort=-id`.
- **Double `/api` prefix**: PocketBase SDK's `buildURL` adds `/api/` to the path. Proxy must NOT blindly prepend another `/api/`.
- **Refreshed browser snapshots**: After navigation, refs change. Always re-snapshot before clicking nav links.
- **Missing onClick handlers**: Subagents frequently create buttons with text but no `onClick` — verify every button in generated code has an attached handler.
- **AI function signature mismatches**: Subagents may write UI code calling AI functions with different signatures than the actual `ai.ts` module. Always cross-check the `handleAiWrite`/`handleGeneratePriorities`/`handleAiSuggest` call signatures against the exports in `src/lib/ai.ts`.
- **Wrong PB collection names**: Original v1 code uses underscore names (`repair_orders`) but the PocketBase instance uses camelCase (`repairOrders`). Subagents copy the v1 name verbatim → query fails. Always verify collection names against the actual PB instance before dispatching.
- **Lazy-loaded pages and providers**: Pages wrapped in `React.lazy()` don't get providers from parent context if the provider is mounted after the lazy boundary. Mount `<ToastProvider>` and other context providers ABOVE `<Suspense>` in App.tsx.
