This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
Redirects and rewrites
Edit page
Learn how to redirect and rewrite URLs in Expo Router, in the app and on the server.
You can redirect or rewrite an incoming request to a different URL. Expo Router supports this for both in-app navigation and for server requests.
In-app redirects
Using <Redirect>
You can immediately redirect from a particular screen by using <Redirect>:
import { View, Text } from 'react-native'; import { Redirect } from 'expo-router'; export default function Page() { const { user } = useAuth(); if (!user) { return <Redirect href="/login" />; } return ( <View> <Text>Welcome Back!</Text> </View> ); }
Using useRouter
You can also redirect imperatively with the useRouter hook:
import { Text } from 'react-native'; import { useRouter, useFocusEffect } from 'expo-router'; function MyScreen() { const router = useRouter(); useFocusEffect(() => { // Call the replace method to redirect to a new route without adding to the history. // We do this in a useFocusEffect to ensure the redirect happens every time the screen // is focused. router.replace('/profile/settings'); }); return <Text>My Screen</Text>; }
Server redirects
Use the redirects option of the expo-router config plugin in your app config to redirect routes that no longer exist in your app directory. The server matches each rule against the request URL, not the screen name, and responds with a redirect status code and a Location header.
For redirects that depend on properties of the request, such as headers or cookies, use middleware.
See RedirectConfig in the API reference for the properties of a redirect rule.
Rules
source and destination are URL paths, not the route files on disk. Do not add the /index suffix for a directory route or +api for an API route.
Permanent redirects
Set permanent to true when the resource has a new permanent URL. Clients should then use destination for all future requests, and can cache the redirect. The default is false, which means the resource is temporarily at a different URL.
The status code depends on permanent and on the request method:
Dynamic segments
source and destination can use the dynamic route syntax. A segment name that appears in both source and destination keeps its value.
A segment that only appears in source becomes a query parameter of the destination.
With the rule above, the server redirects /redirect/apple/carrot/beef to /target/carrot/apple?meat=beef.
A catch-all segment matches the rest of the path.
With the rule above, the server redirects /redirect/docs/router/intro to /guides/router/intro.
HTTP methods
To redirect only some HTTP methods, list them in methods. Screen requests use the GET method. The supported values are GET, POST, PUT, DELETE, PATCH, OPTIONS, and HEAD.
Server rewrites
Rewrites only work with
web.output: "server". Static output does not support them. See Server rules in the app for the in-app behavior.
Use the rewrites option of the expo-router config plugin to serve one route at another URL. The server handles a request for source as if the client had requested destination. The URL in the browser does not change, and the server does not send a redirect status code.
See RewriteConfig in the API reference for the properties of a rewrite rule. The rules for redirects also apply to rewrites, with one difference: an external URL is not a valid destination.
Dynamic segments work the same way as in redirects.
Server rules in the app
The app reads the redirects and rewrites rules from the app config at runtime on Android, iOS, and web. It applies them to the initial URL, to incoming deep links, and to every navigation call, such as router.push() or a Link press. This keeps the behavior consistent between a server request and in-app navigation. The in-app behavior differs from the server in the following ways:
- The app treats a rewrite rule as a redirect rule. Navigation to a rewrite
sourcegoes to itsdestination, and the URL changes. - The app ignores
permanentandmethods. There is no HTTP response in the app. - The app opens an external
destinationwith the device's URL handler instead of navigating. - The app drops a dynamic segment that only appears in
source. It does not add the segment as a query parameter.