9.4 KiB
9.4 KiB
Session Handoff: oysqn.app Initial Setup
Date: 2026-03-25 Session Duration: ~1 hour Session Focus: Create new project oysqn.app — scaffold, schema extraction, icon copy, role-based menu Context Usage at Handoff: Medium
What Was Accomplished
- Created project directory
/home/ptoal/Dev/mobile-projects/oysqn.app/and scaffolded full Nuxt 4 + Ionic Vue + PrimeVue + Supabase stack → all files listed in Files table below - Installed dependencies via
yarn install --ignore-engines(Node 20 compat issue withrollup-plugin-visualizer@7.0.1requiring Node >=22) →yarn.lockcreated,.yarnrcset with--ignore-engines true - Extracted schema from bab-app stores and translated Appwrite model → Supabase SQL →
supabase/schema.sql - Populated full TypeScript types →
app/types/supabase.ts - Rebuilt auth store with Supabase equivalents: magic link, OTP,
hasRequiredRole(),fetchMember(),getUserNameById()→app/stores/auth.ts - Updated
app/app.vuewith role-based IonMenu (3 visibility tiers) - Copied all icons and brand assets from bab-app →
public/icons/,public/ - Renamed composable
useToast→useIonToastto avoid conflict with PrimeVue's auto-importeduseToast→app/composables/useIonToast.ts yarn typecheckpasses with 0 errors
Exact State of Work in Progress
- Supabase project NOT created —
.envis empty placeholder; schema SQL exists but has not been run app/stores/boat.tsusesas anycast for supabase client — placeholder until real types wired viasupabase gen types- Auth store uses
as anycast for same reason — will resolve oncesupabase gen typesoutput replacesapp/types/supabase.ts - No pages beyond skeleton
index.vue,login.vue,auth/callback.vue— all page content is TODO - No
app/stores/interval.ts,app/stores/intervalTemplate.ts,app/stores/reservation.ts,app/stores/reference.tsyet — to be built - Scheduling refactor deferred — new resource picker + booking flow design not started
Decisions Made This Session
- USE
IonRouterOutletinapp.vueinstead of<NuxtPage>BECAUSE user decision — enables Ionic page transitions and lifecycle hooks — STATUS: confirmed - USE Supabase INSTEAD OF Appwrite BECAUSE user decision — new project rewrite — STATUS: confirmed
- USE
mode: 'md'in IonicVue plugin BECAUSE consistent cross-platform appearance for PWA — STATUS: confirmed - USE
@nuxtjs/supabasemodule BECAUSE handles SSR-safe client creation anduseSupabaseUser()composable automatically — STATUS: confirmed - NO
@ionic/vue-routerBECAUSE Nuxt manages the router;IonRouterOutletfrom@ionic/vueworks with standard Vue Router — STATUS: confirmed - USE magic link + OTP only (no password auth) BECAUSE carried forward from bab-app confirmed auth model — STATUS: confirmed
- USE
rolecolumn onmemberstable INSTEAD OF Appwrite Teams BECAUSE Supabase native pattern; simpler RLS — STATUS: confirmed - USE
handle_new_user()trigger BECAUSE auto-createsmembersrow on first sign-in without extra client code — STATUS: provisional (not yet tested) - USE
as anycast onuseSupabaseClient()in stores FOR NOW BECAUSE@nuxtjs/supabasedoesn't propagate generic Database type through PostgREST column-select type inference; will resolve aftersupabase gen types— STATUS: provisional - SAME IonMenu for all roles with conditional sections BECAUSE user decision — STATUS: confirmed
- USE
.yarnrcwith--ignore-engines trueBECAUSE Node 20 installed,rollup-plugin-visualizerrequires Node >=22 — STATUS: confirmed
Key Numbers Generated or Discovered This Session
- 6 tables in schema:
boats,members,interval_templates,intervals,reservations,reference_docs - 3 menu visibility tiers: all-authenticated / isBoatswain (admin+boatswain) / isAdmin only
- 0 TypeScript errors (
yarn typecheckclean) - 31 icon/asset files copied from bab-app to
public/icons/ - 1 trigger in schema:
handle_new_user()onauth.usersinsert
Conditional Logic Established
- IF
member.roleis in['admin', 'boatswain']THENisBoatswainis true → shows "Manage Schedule" menu item - IF
member.roleis'admin'THENisAdminis true → shows "Users" + "Manage Boats" menu items - IF
authStore.userchanges to non-null THENfetchMember()is called → populatesmemberref → menu items become visible - IF
certinmembers.certificationsmatches entry inboats.required_certsTHEN user may book that boat — ASSUMED (not yet enforced in code, logic carried from bab-app) - IF
interval.boat_idmatchesboats.idTHEN interval appears in that boat's resource column in FullCalendar (scheduling refactor — deferred)
Files Created or Modified
| File Path | Action | Description |
|---|---|---|
package.json |
Created | Nuxt 4 + @ionic/vue + primevue + @nuxtjs/supabase + @pinia/nuxt + @vite-pwa/nuxt |
nuxt.config.ts |
Created | Nuxt config: SSR=false, PrimeVue OYS theme (#027be3), PWA manifest, Ionic CSS |
tsconfig.json |
Created | Extends .nuxt/tsconfig.json |
.gitignore |
Created | Standard Nuxt gitignore |
.env.example |
Created | SUPABASE_URL + SUPABASE_KEY placeholders |
.yarnrc |
Created | --ignore-engines true for Node 20 compat |
yarn.lock |
Created | Resolved dependency lockfile |
supabase/schema.sql |
Created | Full Supabase schema: 6 tables, RLS policies, handle_new_user trigger |
app/app.vue |
Created | IonApp + IonMenu (role-based) + IonRouterOutlet; fetchMember on mount/user-watch |
app/plugins/ionic.client.ts |
Created | IonicVue plugin, mode: 'md' |
app/middleware/auth.ts |
Created | Global Supabase auth guard via useSupabaseUser() |
app/stores/auth.ts |
Created | Full auth store: role, isAdmin, isBoatswain, fetchMember, sendMagicLink, sendOtp, verifyOtp, getUserNameById, signOut, updateName |
app/stores/boat.ts |
Created | Skeleton boat store with placeholder types |
app/types/supabase.ts |
Created | Full Database type: 6 tables + MemberRole, ReservationStatus, Defect, TimeTuple |
app/composables/useIonToast.ts |
Created | Ionic toastController wrapper (renamed from useToast to avoid PrimeVue conflict) |
app/pages/index.vue |
Created | Skeleton home page (IonPage shell) |
app/pages/login.vue |
Created | Skeleton login page |
app/pages/auth/callback.vue |
Created | Supabase auth callback page |
CLAUDE.md |
Created | Project-specific instructions for new stack |
docs/planning/personas.md |
Created | Copied from bab-app |
docs/context/archive-rules.md |
Created | Copied from bab-app |
docs/context/processing-protocol.md |
Created | Copied from bab-app |
docs/context/subagent-rules.md |
Created | Copied from bab-app |
templates/claude-templates.md |
Created | Copied from bab-app |
public/icons/ |
Created | 31 icon/asset files copied from bab-app |
public/favicon.ico |
Created | Copied from bab-app |
public/oysqn_logo.png |
Created | Copied from bab-app |
public/oysqn_logo_only.png |
Created | Copied from bab-app |
public/oys_lighthouse.jpg |
Created | Copied from bab-app |
What the NEXT Session Should Do
- First: Create Supabase project at supabase.com; copy URL + anon key to
.env - Then: Run schema: paste
supabase/schema.sqlinto Supabase SQL editor and execute - Then: Run
npx supabase gen types typescript --project-id YOUR_ID > app/types/supabase.tsto replace placeholder types and removeas anycasts - Then: Implement
app/pages/login.vue— OTP flow: email input → sendOtp() → token input → verifyOtp() → redirect to/ - Then: Implement
app/pages/auth/callback.vue— handle magic link redirect (Supabase sets session from URL hash) - Then: Run
yarn devand verify IonRouterOutlet renders, menu appears, auth redirect fires - Then: Build remaining stores:
reservation.ts,interval.ts,intervalTemplate.ts,reference.ts
Open Questions Requiring User Input
- Supabase project ID — needed before types, schema, and
.envcan be configured - Scheduling refactor design — should new resource picker and booking flow be designed before or after auth + boat pages are implemented?
- Should
members.roleever be set to something other than'member'automatically, or is role assignment always manual (admin sets it)?
Assumptions That Need Validation
- ASSUMED:
handle_new_user()trigger correctly fires on Supabase magic link / OTP first sign-in — validate by creating a test user and checkingmemberstable - ASSUMED:
IonRouterOutletinapp.vueworks without<NuxtLayout>wrapper in Nuxt 4 — validate atyarn dev - ASSUMED:
useSupabaseUser()watcher inapp.vuefires after OTP verification completes — validate in auth flow test - ASSUMED: cert matching logic (
members.certificationsvsboats.required_certs) carried forward as string array comparison — validate against domain rules indocs/planning/
What NOT to Re-Read
docs/archive/handoffs/handoff-2026-03-25-project-scaffold.md— superseded by this handoff- bab-app stores — schema extraction complete; source of truth is now
supabase/schema.sql+app/types/supabase.ts
Files to Load Next Session
supabase/schema.sql— if modifying schema before running itapp/stores/auth.ts— when implementing login pageapp/pages/login.vue— primary implementation targetapp/types/supabase.ts— after regenerating from real Supabase project