apps/mobile/app. apps/mobile/src/stacks/main.tsx declares the root stack, while apps/mobile/app/_layout.tsx mounts providers, deep-link handling, AccessGate, and that stack.
Route groups
The tab bar exposes home, AI tools, activity, and profile. The AI tools tab links directly to
/(modal)/ai-chat. The insights file exists but its tab has href: null.
Route constants
Import app route constants from the app-local path:ROUTES currently defines public setup/auth routes, unlock, developer routes, onboarding routes, home/AI tools/activity, and modal routes. STACKS defines root screen names used by MainStack.
AccessGate order
AccessGate reads useSegments(), usePathname(), auth state, per-user security setup, app-local onboarding state, and security lock state. After auth finishes loading, it evaluates these gates in order:
- An unauthenticated user may remain on public
welcome,sign-in,sign-up, orforgot-password, in(dev), or in(unlock). Other routes redirect toROUTES.WELCOME. - An authenticated user without verified email redirects to
ROUTES.VERIFY_EMAIL. - A verified user without a PIN redirects to
ROUTES.SETUP_PIN. - A user who has not completed biometric setup redirects to
ROUTES.SETUP_BIOMETRICS. Skipping biometrics still marks setup complete. - An incomplete welcome step redirects to
ROUTES.ONBOARDING_WELCOME. - An incomplete push explanation redirects to
ROUTES.ONBOARDING_PERMISSIONS. - An incomplete system permission prompt redirects to
ROUTES.NOTIFICATION_PERMISSION_MODAL. - Completed users are moved out of onboarding or the permission modal to
ROUTES.HOME. - A lockable, locked session redirects to
ROUTES.UNLOCK. - Unknown authenticated locations redirect to
ROUTES.HOME; app, modal, dev, onboarding, unlock, and root locations are recognized.
flags.enableAppLock, authentication, a user ID, completed PIN setup, and a route outside public, onboarding, and unlock groups. Foreground and background delays come from amisiConfig.security.
flags.enableOnboarding is not consulted by the current gate. The three app-local onboarding completion values always participate.
Email-verification deep links
AuthDeepLinkHandler subscribes to React Native Linking URL events and calls Linking.getInitialURL() for cold starts. It accepts only URLs whose query has mode=verifyEmail and a non-empty oobCode.
It then calls applyActionCode(oobCode) and reloadUser(). A verified session navigates with router.replace('/'); otherwise it navigates to ROUTES.VERIFY_EMAIL. Parsing and application failures do not navigate.
Firebase email links are configured in apps/mobile/app/_layout.tsx from EXPO_PUBLIC_FIREBASE_EMAIL_CONTINUE_URL and optional EXPO_PUBLIC_FIREBASE_AUTH_LINK_DOMAIN.
Lock and route restoration
useAppLockManager calls lockUserSession(userId, pathname) after foreground inactivity or a long-enough background interval. The store persists the pathname as that user’s pending unlock route.
AccessGate also writes the current pathname before replacing a locked route with ROUTES.UNLOCK. The unlock screen calls unlockUserSession(userId) after a valid six-digit PIN or successful biometrics. On the next gate pass, AccessGate restores lockState.pendingRoute, consumes the persisted route, and falls back to ROUTES.HOME when no route exists.
The root GestureHandlerRootView calls notifyAppInteraction on every touch start so active touches reset the foreground inactivity timer.