Mobile Onboarding Flow
Location: apps/mobile/src/app/(onboarding)/
The onboarding flow guides a new user from invite code entry through to the main feed. It consists of 5 screens rendered in a protected (onboarding) stack.
Screens
| Screen | File | Description |
|---|---|---|
| Welcome | _layout.tsx (entry) | App landing + "Enter invite code" CTA |
| AI Reflection | ai-reflect.tsx | 5-question reflection to seed interests |
| Interests L1 | interests-1.tsx | Pick top-level interest categories |
| Interests L2/L3 | interests-2.tsx | Drill into sub-interests |
| Interests confirm | interests-3.tsx | Review and set depth + expertise |
Flow Diagram
Welcome Screen
└─ Enter invite code → POST /identity/invite-codes/reserve
└─ Register form → POST /identity/register
└─ AI Reflection (ai-reflect.tsx)
├─ Letter-rain topic selector
├─ 5 questions answered
└─ POST /ai/sessions/:id/map-interests
└─ Accept suggestions → POST /ai/sessions/:id/apply-suggestions
└─ interests-1.tsx (L1 category picker)
└─ interests-2.tsx (L2 drill-down)
└─ interests-3.tsx (review + depth set)
└─ Profile setup (firstName, avatar)
└─ Main feed (tabs)Invite Code Step
- User opens app → sees welcome screen.
- Enters a
REG-XXXXXXcode and generates acandidateSessionId(UUID v4). POST /identity/invite-codes/reserve { code, candidateSessionId }→ returns{ inviteCodeId, reservedUntil }.- Code is reserved for 30 minutes.
- User fills registration form (email, password, name, DOB, country, city).
POST /identity/register { inviteCodeId, email, password, input }→{ userId, accessToken, refreshToken }.- Tokens stored in MMKV via
apps/mobile/src/lib/storage.ts.
AI Reflection Screen (ai-reflect.tsx)
See AI Reflection for full animation details.
- User picks a topic from interest chips or types their own.
POST /ai/sessions { topic }→ starts session.- 5 turns of question-answer.
POST /ai/sessions/:id/complete.POST /ai/sessions/:id/map-interests→ receives suggestions.- User accepts/declines each suggestion.
POST /ai/sessions/:id/apply-suggestions { ids }→ seeds UserInterest rows.- Navigate → interests-1.tsx.
interests-1.tsx (L1 Category Picker)
- Loads L1 interests from
GET /interests/catalog?level=1. - Displays as a scrollable grid of chips with accent color from
interest.accentColor. - User selects at least 3 interests.
- Stores selection in local state, navigates to interests-2.tsx.
interests-2.tsx (L2 Drill-Down)
- For each selected L1 interest, loads children
GET /interests/catalog?parentId=<id>. - Accordion-style expansion with sub-interest chips.
- User can select multiple L2 and L3 interests within each L1 parent.
- Navigates to interests-3.tsx.
interests-3.tsx (Review + Depth)
- Lists all selected interests (L1 + L2 + L3).
- For each: depth slider (1..5) and expertise slider (1..5).
- "Confirm" →
POST /interests/me/bulkwith all interest selections. - Emits
interests.user_selected→ seeds reputation +5 per L1 interest. - Navigate to profile setup → main feed.
State Management
- Registration form state: local
useState(not persisted across app restarts). - Invite code + JWT tokens: MMKV via
lib/storage.ts. - TanStack Query mutations for all API calls.
- Navigation:
expo-router(file-system routing, stack navigation).