Are you an LLM? You can read better optimized documentation at /app/navigation.md for this page in Markdown format
Navigation
The app uses Expo Router for file-based navigation with route groups.
Route Structure
app/
├── _layout.tsx # Root layout
├── (auth)/
│ ├── _layout.tsx # Auth stack
│ ├── welcome.tsx # Landing screen
│ ├── create-account.tsx
│ ├── check-email.tsx
│ ├── device-selection.tsx
│ ├── genres.tsx
│ ├── goal.tsx
│ └── success.tsx
└── (tabs)/
├── _layout.tsx # Tab navigator
├── index.tsx # Home tab
├── discover.tsx # Discover tab
├── create.tsx # Create tab
├── clubs.tsx # Clubs tab
└── profile.tsx # Profile tabAuth Flow
The onboarding flow progresses through these screens:
welcome- App introductioncreate-account- Email inputcheck-email- Magic link sentdevice-selection- Reading device preferencesgenres- Genre selectiongoal- Reading goal settingsuccess- Welcome to the app
Programmatic Navigation
typescript
import { router } from "expo-router"
// Navigate to next onboarding step
router.push("/check-email")
// Replace (no back button)
router.replace("/success")
// Navigate to authenticated area
router.replace("/(tabs)")Tab Navigation
Five-tab bottom navigation:
| Tab | Screen | Icon |
|---|---|---|
| Home | index.tsx | House |
| Discover | discover.tsx | Search |
| Create | create.tsx | Plus |
| Clubs | clubs.tsx | Users |
| Profile | profile.tsx | User |
Tab Configuration
typescript
// app/(tabs)/_layout.tsx
<Tabs>
<Tabs.Screen
name="index"
options={{
title: "Home",
tabBarIcon: ({ color }) => <Home color={color} />,
}}
/>
{/* ... other tabs */}
</Tabs>Deep Linking
The app supports deep links via the logbook:// scheme:
typescript
// Handle magic link verification
logbook://verify?token=xxx
// Navigate to specific book
logbook://books/123Configuration
Deep linking is configured in app.json:
json
{
"expo": {
"scheme": "logbook",
"ios": {
"associatedDomains": ["applinks:logbook.so"]
}
}
}Protected Routes
Routes are protected by the AuthGate in _layout.tsx:
typescript
const { isAuthenticated, isLoading } = useAuthStore()
if (isLoading) {
return <SplashScreen />
}
// Redirect based on auth state
useEffect(() => {
if (!isAuthenticated) {
router.replace("/(auth)/welcome")
}
}, [isAuthenticated])