# Session Handoff: Nuxt Migration — Phases 3–5 Complete **Date:** 2026-03-19 **Session Focus:** Auth, all stores, all pages, all layouts, all components **Context at Handoff:** High — recommend fresh session for Phase 6+ ## What Was Accomplished 1. Phase 3 — Auth (stores/auth.ts, middleware, callback page, plugin) 2. Phase 4 — All 7 non-task stores 3. Phase 5 — All pages, layouts, and non-task components ## Exact State of bab-app-nuxt ### Layouts - `app/layouts/default.vue` — MainLayout port; reads `route.meta.title` for header title - `app/layouts/admin.vue` — AdminLayout port; tabs updated to `/admin/user` and `/admin/boat` - `app/app.vue` — Updated to `` ### Pages (all created) | Nuxt Path | Old Path | Notes | |-----------|----------|-------| | `pages/index.vue` | `IndexPage.vue` | Uses `useNavLinks()` composable | | `pages/login.vue` | `LoginPage.vue` | `layout: false`; magic link `onMounted` removed (→ `auth/callback.vue`) | | `pages/auth/callback.vue` | (new) | Handles `?userId=&secret=` from magic link | | `pages/boat.vue` | `BoatPage.vue` | | | `pages/profile.vue` | `ProfilePage.vue` | | | `pages/certification.vue` | `CertificationPage.vue` | | | `pages/checklist.vue` | `ChecklistPage.vue` | | | `pages/schedule.vue` | `SchedulePageView.vue` | Parent wrapper; `` | | `pages/schedule/index.vue` | `ScheduleIndexPage.vue` | | | `pages/schedule/book.vue` | `BoatReservationPage.vue` | | | `pages/schedule/view.vue` | `BoatScheduleView.vue` | | | `pages/schedule/list.vue` | `ListReservationsPage.vue` | | | `pages/schedule/edit/[id].vue` | `ModifyBoatReservation.vue` | | | `pages/schedule/manage.vue` | `ManageCalendar.vue` | `requiredRoles: ['Schedule Admins']` | | `pages/reference.vue` | `ReferencePage.vue` | Parent wrapper | | `pages/reference/index.vue` | `ReferenceIndexPage.vue` | | | `pages/reference/reference/[id]/view.vue` | `ReferenceItemPage.vue` | Double `reference` path preserved from old routes | | `pages/admin/user.vue` | `UserAdminPage.vue` | `layout: 'admin'`, `requiredRoles: ['admin']` | | `pages/admin/boat.vue` | `BoatAdminPage.vue` | `layout: 'admin'`, `requiredRoles: ['admin']` | | `pages/signup.vue` | `SignupPage.vue` | **STUB** — password auth removed; shows "contact admin" | | `pages/pwreset.vue` | `ResetPassword.vue` | **STUB** — password auth removed | | `pages/terms-of-service.vue` | `TermsOfServicePage.vue` | `layout: false` | | `pages/privacy-policy.vue` | `PrivacyPolicyPage.vue` | `layout: false` | | `pages/[...slug].vue` | `ErrorNotFound.vue` | Catch-all 404 | ### Components (all created under `app/components/`) - `boat/BoatComponent.vue` — stub - `boat/BoatPickerComponent.vue` - `boat/BoatPreviewComponent.vue` - `CertificationComponent.vue` - `ReferencePreviewComponent.vue` - `BoatReservationComponent.vue` - `ResourceScheduleViewerComponent.vue` — abandoned/retained for reference - `scheduling/NavigationBar.vue` - `scheduling/ReservationCardComponent.vue` — named route updated to `/schedule/edit/${id}` - `scheduling/BoatSelection.vue` — empty stub - `scheduling/IntervalTemplateComponent.vue` - `scheduling/boat/BoatScheduleTableComponent.vue` - `scheduling/boat/CalendarHeaderComponent.vue` - `LeftDrawer.vue` — uses `useNavLinks()` composable; logout via `authStore.logout()` - `BottomNavComponent.vue` ### Utils added - `app/utils/navlinks.ts` — `useNavLinks()` composable (replaces module-level `enabledLinks`) - `app/utils/version.ts` — `APP_VERSION = '0.0.0'` - `app/assets/` — All assets copied from old project ### Skipped (task feature parked) - `task/TaskEditPage.vue`, `task/TaskPage.vue`, `admin/TaskAdminPage.vue` - `task/TaskEditComponent.vue`, `task/TaskListComponent.vue`, `task/TaskCardComponent.vue`, `task/TaskTableComponent.vue` - `NewPasswordComponent.vue` (password auth removed) ## Key Decisions Made This Session - **ToolbarComponent dropped** — layout `default.vue` handles title via `route.meta.title`. Pages use `definePageMeta({ title: '...' })` instead. - **Public pages pattern** — `definePageMeta({ public: true, layout: false })` for all auth-less full-layout pages - **Magic link redirect** — `/auth/callback` (not `/login`) — matches Phase 3 decision - **signup.vue / pwreset.vue as stubs** — password auth removed; stubs show redirect message. CONFIRMED. - **navlinks.ts → composable** — original had module-level `useAuthStore()` which would break in Nuxt; converted to `useNavLinks()` composable - **Nuxt named routes not used** — all navigation uses explicit paths (`/schedule/edit/${id}` not `{ name: 'edit-reservation' }`) to avoid Nuxt route name collisions ## Open Questions - [ ] **OPEN**: `task`/`taskTags`/`skillTags` collections — will they ever be created in `bab_prod`? - [x] **RESOLVED**: `signup.vue` — admin-only invite is permanent. `signup.vue` stub is the final state; self-service registration will not be built. ## What NEXT Session Should Do 1. **Phase 6 — Build & Test** - Run `yarn dev` in `bab-app-nuxt/` — verify dev server starts clean - Navigate to `/login` — verify page renders - Test login flow (magic link or OTP) - Navigate through key pages post-login - Fix any TypeScript or import errors that surface 2. **Phase 7 — nuxt.config.ts QCalendar registration** - `@quasar/quasar-ui-qcalendar` is imported directly in components — verify this works in Nuxt (no plugin registration needed if imported directly) - If calendar components don't render, add CSS import to `nuxt.config.ts` 3. **Phase 8 — Deploy** (if Phase 6 passes) - `yarn generate` → verify `.output/public/` built correctly - Update Ansible deploy playbook if needed (path may differ from old `dist/`) ## Files to Load Next Session - `bab-app-nuxt/nuxt.config.ts` — check QCalendar CSS import, verify PWA config - `bab-app-nuxt/package.json` — verify no missing deps - Any error output from `yarn dev` ## What NOT to Re-Read - All files in `bab-app-nuxt/app/` — just created; content known - All files in `bab-app/src/` — fully migrated; do not re-read