Redesigned flow: lightPrimary backgrounds, social-first auth, combined Welcome+Role, deepBlue for posters, terracotta for contractors.
Step 1 — Welcome + Role Selection (Combined)
V2: Welcome + Role = 1 screen. Poster CTA = deepBlue (per Bible). Logo at 96px (hero).
WelcomeRoleScreen — Sets userRole in Clerk metadata via useMutation(api.users.setRole).
useAuth().isSignedIn → skip to tabs. CTA text & color change on selection.
V2: Contractor CTA = terracotta (btn-secondary). Role colors swap correctly.
WelcomeRoleScreen — Alternate state.
useMutation(api.users.setRole) → route to sign-up
Step 2 — Carousel (Optional Guided Path)
V2: lightPrimary bg. Icons = ic-A (deepBlue outline). CTA = btn-primary. Skip = midGray.
OnboardingCarousel — 3 swipeable slides, horizontal pager.
PagerView with dot indicators
OnboardingCarousel — Slide 2.
OnboardingCarousel — Final slide. CTA = "Get Started".
onComplete() → navigate to Sign Up
Step 3 — Account Creation (Social First)
V2: Social above email. CTA = btn-primary (deepBlue). Checkbox = deepBlue. Focus = deepBlue. Logo = 52px (medium).
SignUpScreen — Clerk signUp.create() with email strategy.
useSignUp() from @clerk/clerk-expo
V2: CTA = btn-primary. OTP cells = deepBlue. Verify = primary + disabled (opacity 0.4). Timer = deepBlue.
PhoneVerificationScreen — Clerk phone_code strategy.
signUp.prepareVerification({ strategy: "phone_code" })
Step 4 — Sign In & Recovery
V2: Social above email. CTA = btn-primary. Logo = 52px (medium).
SignInScreen — Clerk signIn.create() with email or phone.
useSignIn() → setActive({ session })
V2: Hero = ic-E (white fill + deepBlue border). CTA = btn-primary. Back arrow = deepBlue.
ForgotPasswordScreen — Clerk password_reset flow.
signIn.create({ strategy: "reset_password_email_code" })
V2: CTA = btn-primary. ic-H (success) for checkmark.
ForgotPasswordScreen — Success state after email sent.
Linking.openURL("mailto:") for "Open Email App"
Step 5 — Email Verification
V2: Top-aligned (not centered). Email in highlight card. Clear instruction text. Hero = ic-E. CTA = deepBlue. Header bar added for navigation.
EmailVerificationScreen — Shown after email signup.
signUp.prepareVerification({ strategy: "email_code" })
V2: CTA = btn-primary. ic-H (success).
EmailVerificationScreen — Deep link callback confirms email.
signUp.attemptVerification() → setActive() → profile setup
Step 6 — Poster Profile Setup
V2: Card sections group related fields. "How did you hear" removed (covered by Acquisition Source Picker). deepBlue header + CTA. Focus = deepBlue. lightPrimary body.
PosterProfileSetup — Google Places autocomplete for address.
useMutation(api.users.posters.updateProfile) + api.users.posterProperties.create
Step 7 — Contractor Profile Setup
Contractor = terracotta throughout (header, CTA, chips, focus, tags). Per Bible.
ContractorProfileSetup — Multi-select chips for service categories.
useMutation(api.users.contractors.updateProfile) + serviceArea array
Step 8 — Enhanced Auth & Acquisition
V2: Google = btn-outline (deepBlue border). CTA = btn-primary.
SignInScreen — Google OAuth via Clerk. Falls back to email/password. Deep-linked from magic link invitations.
useSignIn() → oauth_google strategy → setActive({ session })
V2: Selection = deepBlue border (card.selected). CTA = btn-primary. Icons = deepBlue.
AcquisitionSourcePicker — Tracks acquisition source for growth analytics. 11 options mapped to marketing channels.
useMutation(api.users.updateAcquisitionSource) → acquisitionSource field
V2: Social above form. Homeowner tab = deepBlue fill. CTA = btn-primary.
SignUpScreen — Role-aware tab selector. Tab choice sets intendedSetupRole for post-auth routing.
useSignUp() → unsafeMetadata.intendedSetupRole = "poster" | "contractor"
useSignUp() — Handles email/phone registration with ClerkuseSignIn() — Email or phone login, social OAuth (Google, Apple)useAuth() — Session state, isSignedIn, userIduseUser() — Current user profile from Clerkemail_code, phone_code, oauth_google, oauth_apple, reset_password_email_codeexp:// scheme for email verification callbackspublicMetadata.role via users.setRoleposterUsers + posterProfile + posterPropertiescontractorUsers + contractorProfile#growth_feed alertonboardingProgress: { userId, role, step, completedSteps[] }useOnboarding() hook for step navposterUsers — clerkId, email, name, phoneposterProfile — avatar, preferences, referralSourceposterProperties — address, propertyType, lat/lngcontractorUsers — clerkId, email, name, phonecontractorProfile — businessName, license, categories, serviceAreauseAuth() — Clerk session state, isSignedIn, isLoadeduseOnboarding() — Steps completed, current step, next() / back()useWarmup() — Preloads user data after auth for instant navigationuseDeepLinking() — Handles email verification callback URLs(auth)/welcome-role → (auth)/onboarding (optional carousel)(auth)/sign-up → (auth)/verify-email → (auth)/profile-setup(auth)/sign-in → (auth)/forgot-password(poster)/ or (contractor)/ tab navigatorisSignedIn ? tabs : auth via Expo Router layout