# 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 ORIGINAL SOURCE: PROJECT CONTEXT: - React 19 + TypeScript + Vite + Tailwind CSS - PocketBase backend at pb (import from '../lib/pocketbase') - Types defined in ../types.ts — see - Uses lucide-react for icons - Existing pages for reference: Dashboard.tsx, QuoteGenerator.tsx FEATURES TO IMPLEMENT: 1. Feature with specific behavior 2. ... POCKETBASE COLLECTIONS: - '' collection with fields: 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 `` 4. **Lazy loading**: use `React.lazy()` + `` 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 `` in ``. - **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 `` and other context providers ABOVE `` in App.tsx.