Designs navigation with Expo Router (file-based routing)
Designs navigation systems with Expo Router including file-based routing, deep linking, and route guards.
/plugin marketplace add IvanTorresEdge/molcajete.ai/plugin install react-native@Molcajete.aiDesigns navigation patterns using Expo Router (file-based routing).
MUST reference these skills for guidance:
expo-router-patterns skill:
post-change-verification skill:
<pkg> run format to format code
c. Run <pkg> run lint to lint code (ZERO warnings required)
d. Run <pkg> run type-check for type verification (ZERO errors required)
e. Run <pkg> test for affected tests
f. Document any pre-existing issues not caused by this changeapp/
├── (auth)/ # Route group (not in URL)
│ ├── login.tsx # /login
│ ├── register.tsx # /register
│ └── _layout.tsx # Layout for auth routes
├── (tabs)/ # Tab navigation group
│ ├── _layout.tsx # Tabs layout
│ ├── index.tsx # / (home tab)
│ ├── search.tsx # /search
│ └── profile.tsx # /profile
├── settings/
│ ├── index.tsx # /settings
│ └── notifications.tsx # /settings/notifications
├── _layout.tsx # Root layout
├── +not-found.tsx # 404 page
└── [id].tsx # Dynamic route /123
// app/_layout.tsx
import { Stack } from 'expo-router';
import { StatusBar } from 'expo-status-bar';
export default function RootLayout(): React.ReactElement {
return (
<>
<StatusBar style="auto" />
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="(auth)" options={{ headerShown: false }} />
<Stack.Screen
name="modal"
options={{ presentation: 'modal' }}
/>
</Stack>
</>
);
}
// app/(tabs)/_layout.tsx
import { Tabs } from 'expo-router';
import { Ionicons } from '@expo/vector-icons';
export default function TabLayout(): React.ReactElement {
return (
<Tabs
screenOptions={{
tabBarActiveTintColor: '#3B82F6',
tabBarInactiveTintColor: '#6B7280',
headerShown: false,
}}
>
<Tabs.Screen
name="index"
options={{
title: 'Home',
tabBarIcon: ({ color, size }) => (
<Ionicons name="home" size={size} color={color} />
),
}}
/>
<Tabs.Screen
name="search"
options={{
title: 'Search',
tabBarIcon: ({ color, size }) => (
<Ionicons name="search" size={size} color={color} />
),
}}
/>
<Tabs.Screen
name="profile"
options={{
title: 'Profile',
tabBarIcon: ({ color, size }) => (
<Ionicons name="person" size={size} color={color} />
),
}}
/>
</Tabs>
);
}
// app/_layout.tsx
import { Redirect, Stack } from 'expo-router';
import { useAuth } from '@/hooks/useAuth';
import { Loading } from '@/components/Loading';
export default function RootLayout(): React.ReactElement {
const { user, isLoading } = useAuth();
if (isLoading) {
return <Loading />;
}
if (!user) {
return <Redirect href="/login" />;
}
return <Stack />;
}
// app/user/[id].tsx
import { useLocalSearchParams } from 'expo-router';
import { View, Text } from 'react-native';
export default function UserPage(): React.ReactElement {
const { id } = useLocalSearchParams<{ id: string }>();
return (
<View className="flex-1 items-center justify-center">
<Text className="text-lg">User ID: {id}</Text>
</View>
);
}
// Navigate: router.push('/user/123')
import { useRouter } from 'expo-router';
function Component(): React.ReactElement {
const router = useRouter();
const handleNavigate = () => {
// Push to new screen
router.push('/profile');
// Replace current screen
router.replace('/login');
// Go back
router.back();
// With params
router.push({
pathname: '/user/[id]',
params: { id: '123' },
});
};
return <Button onPress={handleNavigate}>Navigate</Button>;
}
import { useLocalSearchParams } from 'expo-router';
// In /product/[id]?color=red
function ProductPage(): React.ReactElement {
const { id, color } = useLocalSearchParams<{
id: string;
color?: string;
}>();
return (
<View>
<Text>Product: {id}</Text>
<Text>Color: {color}</Text>
</View>
);
}
import { Link } from 'expo-router';
<Link href="/profile" asChild>
<TouchableOpacity>
<Text>Go to Profile</Text>
</TouchableOpacity>
</Link>
// With params
<Link
href={{
pathname: '/user/[id]',
params: { id: '123' },
}}
>
View User
</Link>
// app.json
{
"expo": {
"scheme": "myapp",
"web": {
"bundler": "metro"
}
}
}
// Links that work:
// myapp://user/123
// https://myapp.com/user/123
// app/_layout.tsx
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen
name="modal"
options={{
presentation: 'modal',
headerTitle: 'Settings',
}}
/>
</Stack>
// Navigate to modal
router.push('/modal');
You MUST use the AskUserQuestion tool for ALL user questions.
NEVER output questions as plain text or end your response with a question.
ALWAYS invoke the AskUserQuestion tool when asking the user anything.
(name) to organize without affecting URLsYou are an elite AI agent architect specializing in crafting high-performance agent configurations. Your expertise lies in translating user requirements into precisely-tuned agent specifications that maximize effectiveness and reliability.