# Router 101

## Core concepts of file-based routing in Expo Router

Learn the ground rules of Expo Router and how it relates to the rest of your code.

Before diving into how to construct your app's navigation tree with Expo Router, let's first understand the core concepts that make up the foundation of file-based routing in Expo Router, and how an Expo Router project might differ in structure from other React Native projects.
## The rules of Expo Router
### 1. All screens/pages are files inside of app directory
All navigation routes in your app are defined by the files and sub-directories inside the **app** directory. Every file inside the **app** directory has a default export that defines a distinct page in your app (except for the special **\_layout** files).
Accordingly, directories inside **app** define groups of related screens together as stacks, tabs, or in other arrangements.
### 2. All pages have a URL
All pages have a URL path that matches the file's location in the **app** directory, which can be used to navigate to that page in the address bar on the web, or as an app-specific deep link in a native mobile app. This is what is meant by Expo Router supporting "universal deep-linking". All pages in your app can be navigated to with a URL, regardless of the platform.
### 3. First index.tsx is the initial route
With Expo Router, you do not define an initial route or first screen in code. Rather, when you open your app, Expo Router will look for the first **index.tsx** file matching the `/` URL. This could be an **app/index.tsx** file, but it doesn't have to be. If the user should start by default in a deeper part of your navigation tree, you can use a [route group](/router/basics/notation/#parentheses) (a directory where the name is surrounded in parenthesis), and that will not count as part of the URL. If you want your first screen to be a group of tabs, you might put all of the tab pages inside the **app/(tabs)** directory and define the default tab as **index.tsx**. With this arrangement, the `/` URL will take the user directly to **app/(tabs)/index.tsx** file.
### 4. Root \_layout.tsx replaces App.jsx/tsx
Every project should have a **\_layout.tsx** file directly inside the **app** directory. This file is rendered before any other route in your app and is where you would put the initialization code that may have previously gone inside an **App.jsx** file, such as loading fonts or interacting with the splash screen.
### 5. Non-navigation components live outside of app directory
In Expo Router, the **app** directory is exclusively for defining your app's routes. Other parts of your app, like components, hooks, utilities, and so on, should be placed in other top-level directories. If you put a non-route inside of the **app** directory, Expo Router will attempt to treat it like a route.
Alternatively, you can create a [top-level **src** directory](/router/reference/src-directory/) and put your routes inside the **src/app** directory, with non-route components going in folders like **src/components**, **src/utils**, and so on. This is the only other directory structure that Expo Router will recognize.
### 6. It's still React Navigation under the hood
While this may sound quite a bit different from React Navigation, Expo Router is actually built on top of React Navigation. You can think of Expo Router as an Expo CLI optimization that translates your file structure into React Navigation components that you previously defined in your own code.
This also means that you can often refer to React Navigation documentation for how to style or configure navigation, as the default stack and tab navigators use the exact same options.
## The rules of Expo Router applied
Let's apply these foundational rules of Expo Router to quickly identify key elements of the following project file structure:
```
âââ app/
â   âââ index.tsx
â   âââ home.tsx
â   âââ _layout.tsx
â   âââ profile/
â       âââ friends.tsx
âââ components/
    âââ TextField.tsx
    âââ Toolbar.tsx
```
- **app/index.tsx** is the initial route, and will appear first when you open the app or navigate to your web app's root URL.
- **app/home.tsx** is a page with the route `/home`, so you can navigate to it with a URL like `yourapp.com/home` in the browser, or `myapp://home` in a native app.
- **app/\_layout.tsx** is the root layout. Any initialization code you may have previously put in **App.jsx** should go here.
- **app/profile/friends.tsx** is a page with the route `/profile/friends`.
- **TextField.tsx** and **Toolbar.tsx** are not in the **app** directory, so they will not be considered pages. They will not have a URL, and they cannot be the target of a navigation action. However, they can be used as components in the pages inside of the **app** directory.


## Expo Router notation

Learn how to use special filenames and notation to expressively define your app's navigation tree within your project's file structure.

When you look inside the **app** directory in a typical Expo Router project, you'll see a lot more than some simple file and directory names. What do the parentheses and brackets mean? Let's learn the significance of file-based routing notation and how it allows you to define complex navigation patterns.
## Types of route notation
### Simple names/no notation
```
âââ app/
    âââ home.tsx
    âââ feed/
        âââ favorites.tsx
```
Regular file and directory names without any notation signify _static routes_. Their URL matches exactly as they appear in your file tree. So, a file named **favorites.tsx** inside the **feed** directory will have a URL of `/feed/favorites`.
### Square brackets
```
âââ app/
    âââ [userName].tsx
    âââ products/
        âââ [productId]/
            âââ index.tsx
```
If you see square brackets in a file or directory name, you are looking at a _dynamic route_. The name of the route includes a parameter that can be used when rendering the page. The parameter could be either in a directory name or a file name. For example, a file named **[userName].tsx** will match `/evanbacon`, `/expo`, or another username. Then, you can access that parameter with the `useLocalSearchParams` hook inside the page, using that to load the data for that specific user.
### Parentheses
```
âââ app/
    âââ (tabs)/
        âââ index.tsx
        âââ settings.tsx
```
A directory with its name surrounded in parentheses indicates a _route group_. These directories are useful for grouping routes together without affecting the URL. For example, a file named **app/(tabs)/settings.tsx** will have `/settings` for its URL, even though it is not directly in the **app** directory.
Route groups can be useful for simple organization purposes, but often become more important for defining complex relationships between routes.
### index.tsx files
```
âââ app/
    âââ (tabs)/
    â   âââ index.tsx
    âââ profile/
        âââ index.tsx
```
Just like on the web, an **index.tsx** file indicates the default route for a directory. For example, a file named **profile/index.tsx** will match `/profile`. A file named **(tabs)/index.tsx** will match `/`, effectively becoming the default route for your entire app.
### \_layout.tsx files
```
âââ app/
    âââ _layout.tsx
    âââ (tabs)/
    â   âââ _layout.tsx
    âââ feed/
        âââ _layout.tsx
```
**\_layout.tsx** files are special files that are not pages themselves but define how groups of routes inside a directory relate to each other. If a directory of routes is arranged as a stack or tabs, the layout route is where you would define that relationship by using a stack navigator or tab navigator component.
Layout routes are rendered before the actual page routes inside their directory. This means that the **\_layout.tsx** directly inside the **app** directory is rendered before anything else in the app, and is where you would put the initialization code that may have previously gone inside an **App.jsx** file.
### Plus sign
```
âââ app/
    âââ +not-found.tsx
    âââ +html.tsx
    âââ +native-intent.tsx
    âââ +middleware.ts
```
Routes that include a `+` have special significance to Expo Router, and are used for specific purposes. A few examples:
- [`+not-found`](/router/error-handling/#unmatched-routes), which catches any requests that don't match a route in your app.
- [`+html`](/router/web/static-rendering/#root-html) is used to customize the HTML boilerplate used by your app on web.
- [`+native-intent`](/router/advanced/native-intent/) is used to handle deep links into your app that don't match a specific route, such as links generated by third-party services.
- [`+middleware`](/router/web/middleware/) is used to run code before a route is rendered, allowing you to perform tasks like authentication or redirection for every request.
## Route notation applied
Consider the following project file structure to identify the different types of routes represented:
```
âââ app/
    âââ (tabs)/
    â   âââ _layout.tsx
    â   âââ index.tsx
    â   âââ feed.tsx
    â   âââ profile.tsx
    âââ _layout.tsx
    âââ users/
    â   âââ [userId].tsx
    âââ +not-found.tsx
    âââ about.tsx
```
- **app/about.tsx** is a static route that matches `/about`.
- **app/users/[userId].tsx** is a dynamic route that matches `/users/123`, `/users/456`, and so on.
- **app/(tabs)** is a route group. It will not factor into the URL, so `/feed` will match **app/(tabs)/feed.tsx**.
- **app/(tabs)/index.tsx** is the default route for the **(tabs)** directory, so it will be the initially-focused tab, and will match the `/` URL.
- **app/(tabs)/\_layout.tsx** is a layout file defining how the three pages inside **app/(tabs)/** relate to each other. If you use a tab navigator component inside of this file, then those screens will be arranged as tabs.
- **app/\_layout.tsx** is the root layout file, and is rendered before any other route in the app.
- **+not-found.tsx** is a special route that will be displayed if the user navigates to a route that doesn't exist in your app.


## Navigation layouts in Expo Router

Learn how to construct different relationships between pages by using directories and layout files.

<VideoBoxLink
  videoId="Yh6Qlg2CYwQ"
  title="Introduction to Expo Router Layout Files"
  description="What are layout files, how to navigate between screens, and block access using redirects."
  className="mb-6"
/>
Each directory within the **app** directory (including **app** itself) can define a layout in the form of a **\_layout.tsx** file inside that directory. This file defines how all the pages within that directory are arranged. This is where you would define a stack navigator, tab navigator, drawer navigator, or any other layout that you want to use for the pages in that directory. The layout file exports a default component that is rendered before whatever page you are navigating to within that directory.
Let's look at a few common layout scenarios.
## Root layout
Virtually every app will have a **\_layout.tsx** file directly inside the **app** directory. This is the root layout and represents the entry point for your navigation. In addition to describing the top-level navigator for your app, this file is where you would put initialization code that may have previously gone inside an **App.jsx** file, such as loading fonts, interacting with the splash screen, or adding context providers.
Here's an example root layout:
```tsx app/_layout.tsx
import { useFonts } from 'expo-font';
import { Stack } from 'expo-router';
import * as SplashScreen from 'expo-splash-screen';
import { useEffect } from 'react';
SplashScreen.preventAutoHideAsync();
export default function RootLayout() {
  const [loaded] = useFonts({
    SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
  });
  useEffect(() => {
    if (loaded) {
      SplashScreen.hide();
    }
  }, [loaded]);
  if (!loaded) {
    return null;
  }
  return <Stack />;
}
```
The above example shows the splash screen initially and then renders a stack navigator once the fonts are loaded, which will cause your app to proceed to the initial route.
## Stacks
You can implement a stack navigator in your root layout, as shown above, or in any other layout file inside a directory. Let's suppose you have a file structure with a stack inside of a directory:
```
âââ app/
    âââ products/
        âââ _layout.tsx
        âââ index.tsx
        âââ [productId].tsx
        âââ accessories/
            âââ index.tsx
```
If you want everything inside of the **app/products** directory to be arranged in a stack relationship, inside the **\_layout.tsx** file, return a `Stack` component:
```tsx app/products/_layout.tsx
import { Stack } from 'expo-router';
export default function StackLayout() {
  return <Stack />;
}
```
When you navigate to `/products`, it will first go to the default route, which is **products/index.tsx**. If you navigate to `/products/123`, then that page will be pushed onto the stack. By default, the stack will render a back button in the header that will pop the current page off the stack, returning the user to the previous page. Even when a page isn't visible, if it is still pushed onto the stack, it is still being rendered.
The `Stack` component implements [React Navigation's native stack](https://reactnavigation.org/docs/native-stack-navigator/) and can use the same screen options. However, you do not have to define the pages specifically inside the navigator. The files inside the directory will be automatically treated as eligible routes in the stack. However, if you want to define screen options, you can add a `Stack.Screen` component inside the `Stack` component. The `name` prop should match the route name, but you do not need to supply a `component` prop; Expo Router will map this automatically:
```tsx app/products/_layout.tsx
import { Stack } from 'expo-router';
export default function StackLayout() {
  return (
    <Stack>
      <Stack.Screen name="[productId]" options={{ headerShown: false }} />
    </Stack>
  );
}
```
While it is possible to nest navigators, be sure to only do so when it is truly needed. In the above example, if you want to push **products/accessories/index.tsx** onto the stack, it's not necessary to have an additional **\_layout.tsx** in the **accessories** directory with a `Stack` navigator. That would define another stack inside the first one. It is fine to add directories that only affect the URL, otherwise, use the same navigator as the parent directory.
## Tabs
Much like a stack, you can implement a tab navigator in your layout file, and all the routes directly inside that directory will be treated as tabs. Consider the following file structure:
```
âââ app/
    âââ (tabs)/
        âââ _layout.tsx
        âââ index.tsx
        âââ feed.tsx
        âââ profile.tsx
```
In the **\_layout.tsx** file, return a `Tabs` component:
```tsx app/(tabs)/_layout.tsx
import { Tabs } from 'expo-router';
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
export default function TabLayout() {
  return (
    <Tabs>
      <Tabs.Screen
        name="index"
        options={{
          title: 'Home',
          tabBarIcon: ({ color }) => <MaterialIcons size={28} name="house.fill" color={color} />,
        }}
      />
      <!-- Add more tabs here -->
    </Tabs>
  );
}
```
This will cause the **index.tsx**, **feed.tsx**, and **profile.tsx** files to appear together in the same bottom tabs navigator. This `Tabs` component uses [React Navigation's native bottom tabs](https://reactnavigation.org/docs/bottom-tab-navigator/) and supports the same options.
In the case of `Tabs`, you will likely want to define the tabs in the navigator, as this influences the order in which tabs appear, the title, and the icon inside the tab. The index route will be the default selected tab.
## Slot
In some cases, you may want a layout without a navigator. This is helpful for adding a header or footer around the current route, or for displaying a modal over any route inside a directory. In this case, you can use the `Slot` component, which serves as a placeholder for the current child route.
Consider the following file structure:
```
âââ app/
    âââ social/
        âââ _layout.tsx
        âââ index.tsx
        âââ feed.tsx
        âââ profile.tsx
```
For example, you may want to wrap any route inside the **social** directory with a header and footer, but you want navigating between the pages to simply replace the current page rather than pushing new pages onto a stack, which can then later be popped off with a "back" navigation action. In the **\_layout.tsx** file, return a `Slot` component surrounded by your header and footer:
```tsx app/social/_layout.tsx
import { Slot } from 'expo-router';
export default function Layout() {
  return (
    <>
      <Header />
      <Slot />
      <Footer />
    </>
  );
}
```
## Other layouts
These are just a few examples of common layouts to give you an idea of how it works. There's much more you can do with layout:
- Implement a [Drawer navigator](/router/advanced/drawer)
- Replace the default tabs with [fully customized tabs](/router/advanced/custom-tabs)
- Use a [modal](/router/advanced/modals) to display a page with transparency, such that the parent navigator is still visible underneath
- [Adapt any navigator that is compatible with React Navigation](/versions/latest/sdk/router/#withlayoutcontextnav-processor), including top tabs, bottom sheets, and more


## Navigating between pages in Expo Router

Learn the different ways to link to and navigate to pages in Expo Router.

Once you have a few pages in your app and their layouts setup, it's time to start navigating between them. Navigation in Expo Router works a lot like React Navigation, but with all pages having a URL by default, we can create links and use these URLs to move about our app using familiar web patterns.
## Native navigation basics with `useRouter`
Like in React Navigation, you can call a function from an `onPress` handler to navigate to another page. In Expo Router, you can use the `useRouter` hook to access navigation functions:
```tsx
import { useRouter } from 'expo-router';
import { Button } from 'react-native';
export default function Home() {
  const router = useRouter();
  return <Button title="Go to About" onPress={() => router.navigate('/about')} />;
}
```
Expo Router apps default to stack navigation, where navigating to a new route pushes a screen onto a stack, and backing out of that route pops it off the stack. Usually, you would want to use the `router.navigate` function. This will either push a new page onto the stack or unwind to an existing route on the stack. However, you can also call `router.push` to explicitly push a new page onto the stack, `router.back` to go back to the previous page, or `router.replace` to replace the current page on the stack.
With Expo Router, you refer to pages by their URL, or their position relative to the **app** directory. Check out the following file structure and how you would navigate to each page:
```
âââ app/
    âââ index.tsx  # router.navigate("/")
    âââ about.tsx  # router.navigate("/about")
    âââ profile/
        âââ index.tsx  # router.navigate("/profile")
        âââ friends.tsx  # router.navigate("/profile/friends")
```
## Links and buttons
The typical way to link to a page in Expo Router is to use links like web apps. Expo Router has a `Link` component for navigating between pages, where the `href` is the same route you would use in `router.navigate`:
```tsx app/index.tsx
import { View } from 'react-native';
import { Link } from 'expo-router';
export default function Page() {
  return (
    <View>
      <Link href="/about">About</Link>
    </View>
  );
}
```
By default, Links can only wrap `Text` components. You can use `Pressable` or other components that support `onPress` and `onClick` props inside a link with the `asChild` prop:
```tsx
import { Pressable, Text } from 'react-native';
import { Link } from 'expo-router';
export default function Page() {
  return (
    <Link href="/other" asChild>
      <Pressable>
        <Text>Home</Text>
      </Pressable>
    </Link>
  );
}
```
## Relative routes
You don't always have to use the absolute path to a route. Using paths that start with `./` (for the current directory) or `../` (for the parent directory) will navigate relative to the current route.
A relative URL is a URL prefix with `./`, such as `./article`, or `./article/`. Relative URLs are resolved relative to the current rendered screen.
```tsx
<Link href="./article">Go to article</Link>
```
```ts
router.navigate('./article');
```
## Dynamic routes and URL parameters
<VideoBoxLink
  videoId="izZv6a99Roo"
  time={350}
  title="Using dynamic routes with Expo Router"
  description="Learn how to make a segment of a route dynamic."
  className="mb-6"
/>
Dynamic routes can be linked to with their full URL, or by passing a `params` object.
Consider the following file structure:
```
âââ app/
    âââ user/
        âââ [id].tsx
```
Each of these links will navigate to the same page:
```tsx app/index.tsx
import { Link, router } from 'expo-router';
import { View, Pressable, Text } from 'react-native';
export default function Page() {
  return (
    <View>
      <Link
        href="/user/bacon">
        View user (id inline)
      </Link>
      <Link
        href={{
          pathname: '/user/[id]',
          params: { id: 'bacon' }
        }}
      >
        View user (id in params in href)
      </Link>
      <Pressable
        onPress={() =>
          router.navigate({
            pathname: '/user/[id]',
            params: { id: 'bacon' }
          })
        }
      >
        <Text>View user (imperative)</Text>
      </Pressable>
    </View>
  );
}
```
> **info** Some parameters are reserved for internal use by Expo Router and React Navigation. You can find them in the [Using URL parameters guide](/router/reference/url-parameters/#reserved-parameters).
### Passing query parameters
You can specify query parameters in the link URL itself, or as additional parameters in the `params` object. Any parameters that don't match the name of the dynamic route variable are equivalent to query parameters.
```tsx
<Link href="/users?limit=20">View users</Link>
<Link
  href={{
    pathname: '/users',
    params: { limit: 20 }
  }}>
  View users
</Link>
```
### Using dynamic route variables and query parameters in the destination page
All variables in the link URL are accessible to the receiving page via the `useLocalSearchParams` hook. This hook returns an object with all the URL parameters, including those passed as `params`.
For example, if you have a link like this:
```tsx
<Link href="/users?limit=20">View users</Link>
```
Then you can read the parameters on the other end like this:
```tsx
import { useLocalSearchParams } from 'expo-router';
import { View, Text } from 'react-native';
export default function Users() {
  const { id, limit } = useLocalSearchParams();
  return (
    <View>
      <Text>User ID: {id}</Text>
      <Text>Limit: {limit}</Text>
    </View>
  );
}
```
### Updating query parameters without navigating
Query parameters can be updated without navigating to a new page. This can be done with a `Link` that uses the same URL as the current page, but with updated query parameters, or imperatively.
```tsx
<Link href="/users?limit=50">View more users</Link>
<Pressable onPress={() => router.setParams({ limit: 50 })}>
  <Text>View more users</Text>
</Pressable>
```
## Redirects
You can immediately redirect to another route from a page or layout with the `Redirect` component. This functions like the `replace` imperative navigation function. A redirect will navigate to the new route without rendering the current page.
```tsx
import { Redirect } from 'expo-router';
export default function Page() {
  return <Redirect href="/about" />;
}
```
## Prefetching
The `prefetch` prop on a `<Link />` component enables prefetching of the target screen when the component is rendered. This allows for faster navigation by preparing the screen in advance.
```tsx
import { Link } from 'expo-router';
export default function Page() {
  return <Link href="/about" prefetch />;
}
```
When `prefetch` is set, Expo Router will attempt to render the target screen off-screen. The exact behavior depends on the type of navigator used:
- **Expo Router Navigators**: Render the target screen off-screen to enable preloading.
- **Custom Navigators**: May implement prefetching differently or not support it at all.
When a screen is preloaded in a stack navigator, it will have a few limitations:
- It cannot use the imperative `router` API.
- It cannot update options with `useNavigation().setOptions()`
- It cannot listen to events from the navigator (for example focus, tabPress, and so on).
The navigation object will be updated once you navigate to the screen. So if you have an event listener in a useEffect hook, and have a dependency on navigation, it will add any listeners when the screen is navigated to:
```tsx
const navigation = useNavigation();
useEffect(() => {
  const unsubscribe = navigation.addListener('tabPress', () => {
    // do something
  });
  return () => {
    unsubscribe();
  };
}, [navigation]);
```
Similarly, for dispatching actions or updating options, you can check if the screen is focused before doing so:
```tsx
const navigation = useNavigation();
if (navigation.isFocused()) {
  navigation.setOptions({ title: 'Updated title' });
}
```
For more information, refer to the [React Navigation preload docs](https://reactnavigation.org/docs/navigation-object/#preload)
## Deep links
Deep linking is when a URL opens a specific page in your app. Expo Router supports deep linking by default, so you can link to any page in your app with a URL from outside of your app, as you would inside your app with `Link`. This is especially useful for sharing links to specific pages in your app.
On web, deep linking is as simple as navigating to that specific URL in your web browser. On mobile, you define a `scheme` in your [app config](/workflow/configuration/) file, and this becomes the prefix for deep links into your app.
Assuming your `scheme` is `myapp`, here are some examples of how you would link to a page in your app from a web page or another app:
```
âââ app/
    âââ about.tsx  # myapp://about
    âââ profile/
    â   âââ index.tsx  # myapp://profile
    âââ users/
        âââ [username].tsx  # myapp://users/evanbacon
```
With app links and universal links, you can also link to your app with an `https` URL. For more information, see [Universal linking](/linking/overview/#universal-linking).
## Initial routes
When opening a deep link to a page in your app, you will likely want back navigation to work as if the user navigated to the page from your home page. To do this, you can specify an `initialRouteName` configuration, which defines the page in a layout that should be loaded before the deep linked page.
Consider the following file structure:
```
âââ app/
    âââ index.tsx
    âââ stack/
        âââ index.tsx
        âââ second.tsx
        âââ _layout.tsx
```
`stack` is a stack navigator, and `/stack/index` is always the first route in the stack.
To ensure that `/stack/index` is always loaded first, even if the user deep links to `/stack/second`, you can set the `initialRouteName` in **app/stack/\_layout.tsx**:
```tsx
export const unstable_settings = {
  // Ensure any route can link back to `/`
  initialRouteName: 'index',
};
```
By default, the `initialRouteName` is only considered when deep linking and not during navigation within your app. However, you can use the `withAnchor` prop on `Link` to force the initial route to be loaded when navigating directly into another stack inside your app.
So, if **app/index.tsx** contained a link to `/stack/second`, add the `withAnchor` prop to ensure that `/stack/index` is loaded first, which will cause the user to go back to `/stack/index` when they press the back button from `/stack/second`:
```tsx
<Link href="/stack/second" withAnchor>
  Go to second
</Link>
```
> **info** If you are missing a back button when testing deep links, this can often be fixed by setting an `initialRouteName`.


## Common navigation patterns in Expo Router

Apply Expo Router basics to real-life navigation patterns you could use in your app.

Now that you know the basics of how files and directories are named and arranged in Expo Router, let's apply that knowledge, looking at some real-life navigation patterns you might use in your app.
## Stacks inside tabs: nested navigators
If the typical starting point for your app is a set of tabs, but one or more tabs may have more than one screen associated with it, nesting a stack navigator inside of a tab is often the way to go. This pattern often results in intuitive URLs and scales well to desktop web apps, where the primary tabs are often always visible.
Consider the following navigation tree:
```
âââ app/
    âââ (tabs)/
        âââ _layout.tsx
        âââ index.tsx  # single page tab
        âââ feed/
        â   âââ _layout.tsx  # tab with a stack inside
        â   âââ index.tsx
        â   âââ [postId].tsx
        âââ settings.tsx  # single page tab
```
In the **app/(tabs)/\_layout.tsx** file, return a `Tabs` component:
```tsx app/(tabs)/_layout.tsx
import { Tabs } from 'expo-router';
export default function TabLayout() {
  return (
    <Tabs screenOptions={{ headerShown: false }}>
      <Tabs.Screen name="index" options={{ title: 'Home' }} />
      <Tabs.Screen name="feed" options={{ title: 'Feed' }} />
      <Tabs.Screen name="settings" options={{ title: 'Settings' }} />
    </Tabs>
  );
}
```
In the **app/(tabs)/feed/\_layout.tsx** file, return a `Stack` component:
```tsx app/(tabs)/feed/_layout.tsx
import { Stack } from 'expo-router';
export const unstable_settings = {
  initialRouteName: 'index',
};
export default function FeedLayout() {
  return <Stack />;
}
```
Now, within the **app/(tabs)/feed** directory, you can have `Link` components that point to different posts (for example, `/feed/123`). Those links will push the `feed/[postId]` route onto the stack, leaving the tab navigator visible.
You can also navigate from any other tab to a post in the feed tab with the same URL. Use `withAnchor` in conjunction with `initialRouteName` to ensure that the `feed/index` route is always the first screen in the stack:
```tsx app/(tabs)/feed/index.tsx
<Link href="/feed/123" withAnchor>
  Go to post
</Link>
```
You can also nest tabs inside of an outer stack navigator. That is often more useful for displaying modals over the tabs.
## One screen, two tabs: sharing routes
Route groups can be used to share a single screen between two different tabs. Consider a navigation tree that has a Feed tab and a Search tab, and they both share pages for viewing a user profile:
```
âââ app/
    âââ (tabs)/
        âââ _layout.tsx
        âââ (feed)/
        â   âââ index.tsx  # default route
        âââ (search)/
        â   âââ search.tsx
        âââ (feed,search)/
            âââ _layout.tsx  # layout shared between the two tabs
            âââ users/
                âââ [username].tsx  # shared user profile page
```
Each of the tabs is put in a group so you can define a third directory that shares routes between two groups (**app/(tabs)/(feed,search)/**). Even with the extra layer, **app/(tabs)/(feed)/index.tsx** is still the nearest index, so it will be the default route.
```tsx app/(tabs)/_layout.tsx
import { Tabs } from 'expo-router';
export default function TabLayout() {
  return (
    <Tabs>
      <Tabs.Screen name="(feed)" options={{ title: 'Feed' }} />
      <Tabs.Screen name="(search)" options={{ title: 'Search' }} />
    </Tabs>
  );
}
```
Both the `(feed)` and `(search)` route groups contain stacks, so they can also share a single layout:
```tsx app/(tabs)/(feed,search)/_layout.tsx
import { Stack } from 'expo-router';
export default function SharedLayout() {
  return <Stack />;
}
```
It's also possible for shared groups to only contain the shared pages, with each distinct group having its own layout file.
Now, both tabs can navigate to `/users/evanbacon` and see the same user profile page.
When you're already focused on a tab and navigating to a user, you will stay in that current tab's group. But when deep-linking directly to a user profile page from outside the app, Expo Router has to pick one of the two groups, so it will pick the first group alphabetically. Therefore, deep-linking to `/users/evanbacon` will show the user profile in the Feed tab.
## Authenticated users only: protected routes
For mobile apps requiring authentication, you will likely have a set of routes that should only be accessible to authenticated users.
For example, consider the following navigation tree in which you have a bottom tabs layout, a sign-in page, a create account page, and a modal that should only be visible to authenticated users:
```
âââ app/
    âââ _layout.tsx  # Root layout
    âââ (tabs)/
    â   âââ _layout.tsx
    â   âââ index.tsx  # Protected
    â   âââ settings.tsx  # Protected
    âââ sign-in.tsx
    âââ create-account.tsx
    âââ modal.tsx  # Protected
```
When your app is first launched, the router will try to open the root index, **app/(tabs)/index.tsx**. If you wrap this screen in a `Stack.Protected` with the `guard={false}`, the screen will become inaccessible and the next available screen will be opened instead. In this example, the `sign-in` screen will be opened, since it is the next available route.
```tsx app/_layout.tsx
import { Stack } from 'expo-router';
import { useAuthState } from '@/utils/authState';
export default function RootLayout() {
  const { isLoggedIn } = useAuthState();
  return (
    <Stack>
      <Stack.Protected guard={isLoggedIn}>
        <Stack.Screen name="(tabs)" />
        <Stack.Screen name="modal" />
      </Stack.Protected>
      <Stack.Protected guard={!isLoggedIn}>
        <Stack.Screen name="sign-in" />
        <Stack.Screen name="create-account" />
      </Stack.Protected>
    </Stack>
  );
}
```
This way, you can fetch your auth state from a store and show the appropriate screens. If the auth state changes, the layout will re-render, so if `isLoggedIn` changes from `false` to `true`, the app will automatically navigate to the root of the `(tabs)` group.
Another benefit of protected routes is that they are checked even if you deep link into a page directly. For example, if an unauthenticated user deep links into the modal screen above, they will be redirected to the sign-in page.
Protected routes can also be used to conditionally show bottom tabs. In this example, the `vip` tab will only be shown to authenticated users who are VIP members:
```tsx app/(tabs)/_layout.tsx
import { Stack } from 'expo-router';
import { useAuthState } from '@/utils/authState';
export default function TabsLayout() {
  const { isVip } = useAuthState();
  return (
    <Tabs>
      <Tabs.Screen name="index" />
      <Tabs.Protected guard={isVip}>
        <Tabs.Screen name="vip" />
      </Tabs.Protected>
      <Tabs.Screen name="settings" />
    </Tabs>
  );
}
```
## Sometimes the best route isn't a route at all
Separating your navigation states into distinct routes is meant to serve you and your app. Sometimes the best pattern for the job will not involve navigating to another route at all. Since layout files are just React components, you can use them to display all sorts of UI around, besides, or instead of a navigator.
Thinking back to authentication, the protected route setup works great if the user should simply not be able to visit certain pages without logging in. But what about when unauthenticated users can browse an app in read-only mode? In that case, you might want to show a login modal over the app, rather than redirecting the user to a login page:
```tsx app/(logged-in)/_layout.tsx
import { Modal } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Stack } from 'expo-router';
export default function Layout() {
  const isAuthenticated = /* check for valid auth token / session */
  return (
    <SafeAreaView>
      <Stack />
      <Modal visible={!isAuthenticated}>{/* login UX */}</Modal>
    </SafeAreaView>
  );
}
```