3.6 KiB
3.6 KiB
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
- Infrastructure first — update types, routes, navigation yourself (quick edits, no delegation needed)
- Dispatch all pages in parallel — 2 batches of 3
delegate_taskcalls - Each subagent gets: target file path, original source file paths, project context (types, existing patterns, PB collections), feature checklist
- 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
- Build:
npx vite build - Fix import errors — subagents may use wrong paths or import components that need providers (e.g.
useToastneedsToastProviderwrapper) - Add ToastProvider — lazy-loaded pages that use
useToastcrash silently ifToastProviderisn't wrapping<Routes> - Lazy loading: use
React.lazy()+<Suspense>to isolate page errors and enable code splitting - PB collections: subagents can't create collections without admin access. Create missing ones or handle gracefully with error states.
Pitfalls
useToastcrash: New pages using toast withoutToastProvider→ white screen with no error message. Always wrap<Routes>in<ToastProvider>.- Broken sort field: Legacy PocketBase collections may lack
created/updatedsystem fields. Dashboardsort=-createdreturns 400. Patch built JS to usesort=-id. - Double
/apiprefix: PocketBase SDK'sbuildURLadds/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.tsmodule. Always cross-check thehandleAiWrite/handleGeneratePriorities/handleAiSuggestcall signatures against the exports insrc/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.