Expo Router Overview
Sovran uses Expo Router for navigation, which provides file-based routing similar to Next.js. Routes are defined by the file structure in theapp/ directory.
Navigation Hierarchy
The app follows a three-level navigation structure:Root Layout
app/_layout.tsx:1-334 Key responsibilities:- Initialize provider hierarchy (see Architecture Overview)
- Configure Stack navigator with modal presentations
- Handle theme changes via React
keyprop - Manage profile switching by remounting inner providers
Drawer Layout
app/(drawer)/_layout.tsx:1-454 The drawer provides the main app navigation with a custom drawer content component. Features:- Profile switcher at the top (switch between multiple wallets)
- User avatar and QR code (tap to view profile)
- Menu items: Feed, Wallet, Payments, Settings
- 82% screen width (max 320px)
- Slide animation with 60% black overlay
Tab Layout
app/(drawer)/(tabs)/_layout.tsx:1-166 The tabs use conditional rendering based on device capabilities:iOS 26+ with Liquid Glass
app/(drawer)/(tabs)/_layout.tsx:38-98 UsesExpo55NativeTabs for native iOS tab bar with blur effects.
Android & iOS (below version 26)
app/(drawer)/(tabs)/_layout.tsx:102-164 Fallback to standardTabs with BlurView background.
Tab structure:
- Feed (
feed/) - Social feed and stories (house icon) - Payments (
payments/) - Contacts and messages (arrow.up.arrow.down icon) - Wallet (
index/) - Balances and transactions (wallet.bifold icon) - Explore (
explore/) - AI chat, maps, pending ecash (paperplane icon)
The wallet tab is at
index/ (not wallet/) for backward compatibility with deep links.Route Groups
Expo Router uses parentheses() for route groups that don’t appear in URLs:
Flow-Based Groups
These groups represent multi-step user flows:Special Layouts
Each route group has a_layout.tsx that configures:
- Presentation style (modal, formSheet, card)
- Header options (title, background, blur)
- Gesture handling
- Animation settings
Navigation Patterns
Type-Safe Navigation
Deep Linking
app.json configures deep link schemes:useDeeplink hook:
Modal Presentations
app/_layout.tsx:216-220 Modal screens are configured inconfig/modalScreens.ts:
Route Parameters
Access route parameters usinguseLocalSearchParams:
Payment Flow Routing
The payment flows use intelligent routing based on available data: hooks/coco/useProcessPaymentString.ts:216-331 Payment request routing logic:
This minimizes user friction by skipping screens when data is already available.
Screen Transitions
Sovran uses hero transitions for seamless animations between screens:Best Practices
Keep screens thin
Keep screens thin
Screens in
app/ should be orchestration-only. Move business logic to hooks/, data fetching to stores/, and UI to components/blocks/.Use replace for form flows
Use replace for form flows
When navigating from a form screen to another form screen, use
router.replace() to avoid stack buildup:Validate params early
Validate params early
Route parameters are always strings or undefined. Validate and parse them at the top of the component:
Related Documentation
State Management
Learn how Zustand stores integrate with navigation
Cashu Integration
See how payment flows interact with Coco manager