File-Based Routing
Route file conventions and naming patterns.
Routes are defined by creating files in your src/_routes/ directory. The file path determines the URL path.
File Naming Conventions
Basic Routes
| File | URL Path |
|---|---|
index.tsx | / |
about.tsx | /about |
settings.tsx | /settings |
users/index.tsx | /users |
users/profile.tsx | /users/profile |
Dynamic Routes
Use brackets for dynamic segments:
| File | URL Path | Example |
|---|---|---|
[id].tsx | /:id | /123 |
users/[userId].tsx | /users/:userId | /users/abc |
posts/[postId]/comments.tsx | /posts/:postId/comments | /posts/5/comments |
Optional Parameters
Use double brackets for optional segments:
| File | URL Path | Matches |
|---|---|---|
[[id]].tsx | /:id? | / or /123 |
users/[[tab]].tsx | /users/:tab? | /users or /users/settings |
Catch-All Routes
Use spread syntax for catch-all segments:
| File | URL Path | Matches |
|---|---|---|
[...slug].tsx | /* | /a, /a/b, /a/b/c |
docs/[...path].tsx | /docs/* | /docs/intro, /docs/api/hooks |
Special Files
Layout Files (_layout.tsx)
Define navigator configuration for a directory:
// src/_routes/_layout.tsx
import { defineLayout } from "@teardown/navigation";
export default defineLayout({
type: "stack",
screenOptions: {
headerShown: true,
},
});Screen Files
All other .tsx files define screens:
// src/_routes/settings.tsx
import { defineScreen } from "@teardown/navigation";
function SettingsScreen() {
return <View><Text>Settings</Text></View>;
}
export default defineScreen({
component: SettingsScreen,
options: { title: "Settings" },
});Route Groups
Use parentheses to group routes without affecting the URL:
src/_routes/
├── (auth)/
│ ├── _layout.tsx # Auth-specific layout
│ ├── login.tsx # /login
│ └── register.tsx # /register
├── (main)/
│ ├── _layout.tsx # Main app layout (tabs)
│ ├── home.tsx # /home
│ └── profile.tsx # /profile
└── _layout.tsx # Root layoutRoute groups are useful for:
- Applying different layouts to different sections
- Organizing related routes together
- Keeping the URL structure clean
Directory Structure Examples
Simple App
src/_routes/
├── _layout.tsx # Stack navigator
├── index.tsx # /
├── about.tsx # /about
└── settings.tsx # /settingsApp with Nested Routes
src/_routes/
├── _layout.tsx # Root stack
├── index.tsx # /
├── users/
│ ├── _layout.tsx # Users stack
│ ├── index.tsx # /users
│ └── [userId].tsx # /users/:userId
└── settings/
├── index.tsx # /settings
├── account.tsx # /settings/account
└── notifications.tsx # /settings/notificationsApp with Tabs
src/_routes/
├── _layout.tsx # Root stack
├── (tabs)/
│ ├── _layout.tsx # Tab navigator
│ ├── home.tsx # /home (tab)
│ ├── search.tsx # /search (tab)
│ └── profile.tsx # /profile (tab)
└── settings.tsx # /settings (modal)Defining Screens
Basic Screen
import { defineScreen } from "@teardown/navigation";
import { View, Text } from "react-native";
function MyScreen() {
return (
<View>
<Text>Hello World</Text>
</View>
);
}
export default defineScreen({
component: MyScreen,
});Screen with Options
import { defineScreen } from "@teardown/navigation";
export default defineScreen({
component: ProfileScreen,
options: {
title: "Profile",
headerShown: true,
presentation: "modal",
},
});Screen with Dynamic Options
import { defineScreen } from "@teardown/navigation";
export default defineScreen({
component: UserScreen,
options: ({ route }) => ({
title: `User ${route.params?.userId}`,
}),
});Screen with Event Listeners
import { defineScreen } from "@teardown/navigation";
export default defineScreen({
component: FormScreen,
options: { title: "Edit" },
listeners: {
beforeRemove: (e) => {
// Prevent leaving if form is dirty
if (formIsDirty) {
e.preventDefault();
// Show confirmation dialog
}
},
},
});Auto-Generated Templates
When autoTemplate is enabled (default), creating a new file automatically populates it with a template:
// Auto-generated when you create src/_routes/new-page.tsx
import { View, Text, StyleSheet } from "react-native";
import { defineScreen } from "@teardown/navigation";
function NewPageScreen() {
return (
<View style={styles.container}>
<Text>New Page</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
});
export default defineScreen({
component: NewPageScreen,
options: {
title: "New Page",
},
});Next Steps
- Type-Safe Navigation - Navigate with full type safety
- Layouts - Configure Stack, Tab, and Drawer navigators