# ÖBB Planner — Implementation Checklist > Phase 2 complete. Moving to Phase 3. --- **Checkbox key** - `[ ]` pending (required) — blocks the next phase until both ✅ and ✔️ are `[x]` - `[x]` done - `[~]` optional or deferred — never blocks phase advancement; check `[x]` if completed, leave `[~]` to skip --- ## Phase 1 — Scaffold Next.js Project (~30 min) | # | Item | ✅ | ✔️ | |---|---|----|-| | 1 | Initialize Next.js with App Router, TypeScript, Tailwind CSS | [x] | [x] | | 2 | Set up `tsconfig.json` with strict mode | [x] | [x] | | 3 | Create `.env.example` with `PORT`, `HAFAS_URL`, `NOMINATIM_URL`, `OSRM_URL` | [x] | [x] | | 4 | Configure `next.config.ts` (rewrites if needed) _(optional — only required if URL rewrites are actually needed)_ | [~] | [~] | | 5 | Configure `vitest.config.ts` _(deferred — must be done before Phase 7 begins, but not required to complete Phase 1)_ | [x] | [~] | | 6 | Set up `postcss.config.mjs` | [x] | [x] | --- ## Phase 2 — Types + Library Layer (~2 hours) | # | Item | ✅ | ✔️ | |---|---|----|-| | 7 | Define TypeScript types in `src/types/index.ts` | [x] | [x] | | 8 | Port `lib/hafas-client.ts` — HAFAS API client functions with proper types | [x] | [x] | | 9 | Port `lib/calendar-utils.ts` — `extractEvents` + `cleanLocation` | [x] | [x] | | 10 | Port `lib/countdown-utils.ts`, `lib/formatting.ts`, `lib/constants.ts`, `lib/demo.ts` | [x] | [x] | | 11 | Create `lib/geocoding-client.ts` — Nominatim client (NEW) | [x] | [x] | | 12 | Create `lib/bike-routing-client.ts` — OSRM client (NEW) | [x] | [x] | --- ## Phase 3 — API Routes (~45 min) | # | Item | ✅ | ✔️ | |---|---|----|-| | 13 | `src/app/api/hafas/route.ts` — POST handler, same logic as Express | [x] | [x] | | 14 | `src/app/api/calendar/route.ts` — GET handler for remote ICS | [x] | [x] | | 15 | `src/app/api/calendar/parse/route.ts` — POST handler for ICS body | [x] | [x] | | 16 | `src/app/api/geocode/route.ts` — GET handler for Nominatim (NEW) | [x] | [x] | | 17 | `src/app/api/bike-route/route.ts` — GET handler for OSRM (NEW) | [x] | [x] | | 18 | `src/app/api/health/route.ts` — health check | [x] | [x] | --- ## Phase 4 — Custom Hooks (~2.5 hours) | # | Item | ✅ | ✔️ | |---|---|----|-| | 19 | `useServerHealth.ts` — polls `/api/health` every 30s | [x] | [x] | | 20 | `useClock.ts` — interval that updates `now` every 10s | [x] | [x] | | 21 | `useGeolocation.ts` — wraps `navigator.geolocation` | [x] | [x] | | 22 | `useOriginStation.ts` — finds nearest station from geolocation | [x] | [x] | | 23 | `useJourneys.ts` — the complex `fetchAll` logic, per-event journey fetching | [x] | [x] | | 24 | `useBikeRoute.ts` — fetches bicycle route for an event (NEW) | [x] | [x] | | 25 | `useCalendar.ts` — URL/file import with merge logic | [x] | [x] | | 26 | `useEventsStore.ts` — shared events state via Context (NEW) | [x] | [x] | --- ## Phase 5 — UI Components (~3.5 hours) | # | Item | ✅ | ✔️ | |---|---|----|-| | 27 | `ui/Chip.tsx` — small badge component | [x] | [x] | | 28 | `ui/Button.tsx` — styled button | [x] | [x] | | 29 | `ui/LoadingSpinner.tsx` — loading indicator | [x] | [x] | | 30 | `event/LeaveByBadge.tsx` — countdown badge | [x] | [x] | | 31 | `event/JourneyList.tsx` — departure rows | [x] | [x] | | 32 | `event/TrainSection.tsx` — train data in event card | [x] | [x] | | 33 | `event/BikeSection.tsx` — bicycle data in event card (NEW) | [x] | [x] | | 34 | `event/EventCard.tsx` — composes train + bike sections | [x] | [x] | | 35 | `calendar/UrlTab.tsx` | [x] | [x] | | 36 | `calendar/FileTab.tsx` | [x] | [x] | | 37 | `calendar/CalendarPanel.tsx` | [x] | [x] | | 38 | `add-event/AddEventModal.tsx` | [x] | [x] | | 39 | `layout/Header.tsx` | [x] | [x] | | 40 | `layout/Navbar.tsx` (NEW) | [x] | [x] | --- ## Phase 6 — Calendar Page (~1 hour) | # | Item | ✅ | ✔️ | |---|---|----|-| | 41 | `calendar/CalendarView.tsx` — month grid component (NEW) | [x] | [x] | | 42 | `calendar/DayEvents.tsx` — events for a selected day (NEW) | [x] | [x] | | 43 | `app/calendar/page.tsx` — calendar route (NEW) | [x] | [x] | --- ## Phase 7 — Tests (~2 hours) | # | Item | ✅ | ✔️ | |---|---|----|-| | 44 | Migrate `server/__tests__/*.test.js` → `src/app/api/__tests__/*.test.ts` | [ ] | [ ] | | 45 | Add unit tests for `calendar-utils.ts`, `countdown-utils.ts` in `src/lib/__tests__/` | [ ] | [ ] | | 46 | Add API tests for `geocode` and `bike-route` in `src/app/api/__tests__/` (NEW) | [ ] | [ ] | | 47 | Add component smoke tests with `@testing-library/react` _(optional — valuable but not on the critical path; skip if setup cost outweighs benefit at the time)_ | [~] | [~] | --- ## Phase 8 — Cleanup (~30 min) | # | Item | ✅ | ✔️ | |---|---|----|-| | 48 | Delete old `server/` directory | [ ] | [ ] | | 49 | Delete old `oebb-planner-app/` directory | [ ] | [ ] | | 50 | Delete `oebb-planner.jsx` | [ ] | [ ] | | 51 | Update `README.md` with new architecture and instructions | [ ] | [ ] | | 52 | Final integration test | [ ] | [ ] | --- **✅ Implemented** — Code exists and is in the repo. **✔️ Reviewed** — Code has been reviewed for correctness against the plan. `[ ]` pending required · `[x]` done · `[~]` optional/deferred (never blocks phase advancement)