|
| 1 | +# 2026-04-05 Preact Router Reliability Plan |
| 2 | + |
| 3 | +## Summary |
| 4 | +Upgrade the SPA from a transient single-view flow to a route-driven, recoverable tool experience. |
| 5 | +Scope is frontend-only in this pass. Delivery is one broad pass, split into bounded workstreams with strict reviewer `accept` gates before merge. |
| 6 | + |
| 7 | +## Decisions Locked |
| 8 | +- Output: agent-ready execution packet. |
| 9 | +- Scope shape: single large pass. |
| 10 | +- Boundary: frontend-only (no backend/OpenAPI changes). |
| 11 | +- Route model: three routes. |
| 12 | +- Priority: reliability mechanics first (no polish stream). |
| 13 | +- Review gate: strict `accept` only. |
| 14 | + |
| 15 | +## Route Contract (Target) |
| 16 | +- `/create` |
| 17 | +- `/token` |
| 18 | +- `/result/:feedToken` |
| 19 | +- Preserve `?url=` prefill support for create flow bootstrap. |
| 20 | + |
| 21 | +## Workstream A: Router + Navigation Skeleton |
| 22 | +Goal: replace implicit internal screen switching with explicit route transitions. |
| 23 | + |
| 24 | +In scope: |
| 25 | +- Add Preact router integration in app root. |
| 26 | +- Migrate create/token/result transitions to route transitions. |
| 27 | +- Ensure browser back/forward/reload behavior is deterministic. |
| 28 | + |
| 29 | +Out of scope: |
| 30 | +- Backend API changes. |
| 31 | +- Visual redesign. |
| 32 | + |
| 33 | +Primary files: |
| 34 | +- `frontend/src/main.tsx` |
| 35 | +- `frontend/src/components/App.tsx` |
| 36 | + |
| 37 | +Acceptance criteria: |
| 38 | +- Direct navigation to each route renders correct state. |
| 39 | +- Back/forward does not break task continuity. |
| 40 | +- Reload keeps user on intended state frame. |
| 41 | + |
| 42 | +## Workstream B: Durable Session and Recovery |
| 43 | +Goal: make flow recoverable after refresh without server-side persistence. |
| 44 | + |
| 45 | +In scope: |
| 46 | +- Persist local draft state (url, strategy). |
| 47 | +- Persist latest successful result snapshot keyed by `feed_token`. |
| 48 | +- Hydrate route state from local snapshot on load. |
| 49 | +- Resolve unused auth hook surface (`useAuth`) explicitly (retain with rationale or retire). |
| 50 | + |
| 51 | +Out of scope: |
| 52 | +- Server-side history/status endpoints. |
| 53 | + |
| 54 | +Primary files: |
| 55 | +- `frontend/src/hooks/useFeedConversion.ts` |
| 56 | +- `frontend/src/hooks/useAccessToken.ts` |
| 57 | +- new local session helper module(s) |
| 58 | + |
| 59 | +Acceptance criteria: |
| 60 | +- Refresh on `/result/:feedToken` restores result view from local snapshot. |
| 61 | +- Refresh on `/create` restores draft input and selected strategy. |
| 62 | +- No stale error banners shown unless still applicable. |
| 63 | + |
| 64 | +## Workstream C: Reliability State Machine and Error Taxonomy |
| 65 | +Goal: convert ad-hoc boolean/error handling into explicit operational states. |
| 66 | + |
| 67 | +In scope: |
| 68 | +- Introduce explicit state machine: |
| 69 | + - `idle`, `validating`, `submitting`, `token_required`, `warming`, `ready`, `failed` |
| 70 | +- Classify errors into actionable categories: |
| 71 | + - `auth`, `input`, `readiness`, `network`, `server` |
| 72 | +- Enforce one canonical primary action per state. |
| 73 | + |
| 74 | +Out of scope: |
| 75 | +- New endpoint design. |
| 76 | + |
| 77 | +Primary files: |
| 78 | +- `frontend/src/components/AppPanels.tsx` |
| 79 | +- `frontend/src/components/ResultDisplay.tsx` |
| 80 | + |
| 81 | +Acceptance criteria: |
| 82 | +- Every failure state has one clear primary recovery action. |
| 83 | +- Token rejection flow is deterministic and route-safe. |
| 84 | +- Strategy fallback/retry behavior is explicit and test-covered. |
| 85 | + |
| 86 | +## Workstream D: Test Expansion for State Parity and Durability |
| 87 | +Goal: lock behavior with tests so reliability regressions are caught. |
| 88 | + |
| 89 | +In scope: |
| 90 | +- Add tests for deep links and direct route loads. |
| 91 | +- Add tests for refresh/back-forward across create/token/result. |
| 92 | +- Add parity assertions for affected states (guest/token/result). |
| 93 | +- Add uniqueness checks: one canonical primary action per state. |
| 94 | + |
| 95 | +Primary files: |
| 96 | +- `frontend/src/__tests__/App.test.tsx` |
| 97 | +- `frontend/src/__tests__/App.contract.test.tsx` |
| 98 | +- `frontend/e2e/smoke.spec.ts` |
| 99 | + |
| 100 | +Acceptance criteria: |
| 101 | +- Route and recovery regressions fail tests. |
| 102 | +- E2E smoke validates primary user journey with parity checks. |
| 103 | + |
| 104 | +## Verification Requirements |
| 105 | +Required per workstream: |
| 106 | +- `make ready` |
| 107 | +- Relevant frontend tests (`pnpm run test:ci`) |
| 108 | +- E2E smoke (`pnpm run test:e2e`) where route/state behavior changes |
| 109 | + |
| 110 | +Required manual smoke: |
| 111 | +- Run app in Dev Container (`make dev`) |
| 112 | +- Validate in chrome-devtools at `http://127.0.0.1:4001/` |
| 113 | +- Check create/token/result states for: |
| 114 | + - state parity |
| 115 | + - one primary action per outcome |
| 116 | + - proper focus behavior on transitions |
| 117 | + |
| 118 | +## Agent Workflow (Execution + Review) |
| 119 | +Execution order: |
| 120 | +1. Start A and B in parallel. |
| 121 | +2. Land C after A/B route/session primitives are stable. |
| 122 | +3. Finalize D with comprehensive assertions after A/B/C complete. |
| 123 | + |
| 124 | +Review policy: |
| 125 | +- Separate reviewer pass per workstream. |
| 126 | +- Reviewer output must include: |
| 127 | + 1. findings first (severity ordered, file/line) |
| 128 | + 2. residual risks |
| 129 | + 3. verdict (`accept` or `needs fix`) |
| 130 | +- Merge only when verdict is `accept` and required checks are green. |
| 131 | + |
| 132 | +## Implementation Prompt Template (for each agent) |
| 133 | +Read: |
| 134 | +- `/Users/gil/versioned/html2rss/html2rss-web/AGENTS.md` |
| 135 | +- `/Users/gil/versioned/html2rss/html2rss-web/docs/design-system.md` |
| 136 | +- this plan file (`docs/20260405-preact-router.md`) |
| 137 | + |
| 138 | +Task: |
| 139 | +Deliver only assigned workstream. |
| 140 | + |
| 141 | +Constraints: |
| 142 | +- Frontend-only. |
| 143 | +- Preserve design-system grammar. |
| 144 | +- No cross-workstream scope drift. |
| 145 | + |
| 146 | +Required outputs: |
| 147 | +1. Implement slice. |
| 148 | +2. Report changed files and acceptance criteria status. |
| 149 | +3. Report blockers/risk notes. |
| 150 | + |
| 151 | +Required verification: |
| 152 | +- `make ready` |
| 153 | +- relevant frontend tests |
| 154 | +- manual state checks in chrome-devtools at `http://127.0.0.1:4001/` |
| 155 | + |
| 156 | +## Reviewer Prompt Template |
| 157 | +Review assigned workstream for production readiness. |
| 158 | + |
| 159 | +Focus: |
| 160 | +- behavioral regressions |
| 161 | +- routing/state durability |
| 162 | +- action uniqueness per state |
| 163 | +- missing tests and edge cases |
| 164 | + |
| 165 | +Output: |
| 166 | +1. findings (severity ordered, file/line) |
| 167 | +2. residual risks |
| 168 | +3. verdict: `accept` or `needs fix` |
0 commit comments