# 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