File-Based Routing in Next.js and Expo Router
File-based routing in Next.js and Expo Router means the files you create inside a special app or pages folder automatically become URLs in your application, with no separate configuration file needed. The folder and file names you choose directly define the URL path, and each file exports a component that renders that page. This article explains exactly what each folder and file does in both frameworks, how they differ, and how to use them effectively.
Background: Why File-Based Routing Exists
Before file-based routing, web developers had to write a central route table—like routes.rb in Rails or a router.js in Express—that mapped URLs to components. This worked but became hard to maintain as apps grew. File-based routing flips the model: instead of telling the framework which URL goes with which file, you just create the file, and the framework derives the URL from its location. This reduces boilerplate, makes routes easier to find, and keeps the project structure self-documenting. Both Next.js and Expo Router adopted this approach because it scales well and works naturally with component-based development.
How Next.js File-Based Routing Works
Next.js has two routing systems: the older pages router and the newer app router. In the pages router, any file inside the pages directory becomes a route. For example:
pages/index.jsmaps to/pages/about.jsmaps to/aboutpages/blog/[slug].jsmaps to/blog/anything(dynamic segment)pages/blog/[...slug].jsmaps to/blog/2024/01/hello(catch-all)
The app router, introduced in Next.js 13, uses a similar folder structure but with special files. Inside app/, each folder represents a route segment, and files like page.js, layout.js, and loading.js define the UI and behavior. For instance, app/dashboard/page.js renders at /dashboard, and app/dashboard/layout.js wraps all pages under that folder with a shared layout. The app router also supports nested layouts, server components, and more advanced patterns like route groups (folders in parentheses that don’t affect the URL) and parallel routes.
How Expo Router File-Based Routing Works
Expo Router, built on React Navigation, brings the same file-based concept to React Native apps. You create an app directory at the root of your project, and every file inside becomes a screen in your navigation stack. For example:
app/index.jsis the initial screenapp/profile.jsbecomes/profileapp/settings/index.jsbecomes/settingsapp/post/[id].jsbecomes/post/123(dynamic route)
Expo Router uses the same app folder name as Next.js, but the internal mechanics differ. Instead of HTML pages, each file exports a React component that renders a screen. The router automatically sets up a native stack navigator, and you can use special files like _layout.js to define a layout for a group of screens—similar to Next.js layouts. Expo Router also supports tabs, drawers, and modals via folder-based configuration, such as app/(tabs)/ for a tab navigator.
Key Differences and When to Choose Which
Both routers share the same mental model, but they serve different platforms. Next.js is for web applications, producing server-rendered HTML, while Expo Router is for native iOS/Android apps (and web via React Native Web). If you’re building a website, choose Next.js; if you’re building a mobile app with Expo, choose Expo Router. They are not interchangeable—you can’t use Expo Router in a Next.js project or vice versa. However, if you’re building both a web and mobile app, you might use Next.js for the web and Expo Router for the mobile app, and they will feel similar because the file structure is nearly identical.
Common Folder and File Conventions
To get the most out of file-based routing, you need to know the special files and folder names. Here’s a quick reference:
- Next.js (app router):
page.js(the UI),layout.js(shared wrapper),loading.js(suspense fallback),error.js(error boundary),not-found.js(404),route.js(API endpoints). - Next.js (pages router):
_app.js(global layout),_document.js(HTML shell),api/folder for API routes. - Expo Router:
_layout.js(layout for a folder),index.js(initial screen),+not-found.js(404 screen),+html.js(custom HTML for web).
Dynamic segments use square brackets: [id].js for a single parameter, [slug].js for a named one. Catch-all routes use [...slug].js in Next.js and [...slug].js in Expo Router (though Expo Router uses a slightly different syntax for optional catch-all: [[...slug]]). Route groups, denoted by parentheses like (marketing), allow you to organize files without affecting the URL. For example, app/(marketing)/about/page.js still maps to /about.
Common Mistakes and How to Avoid Them
One frequent mistake is naming a file index.js inside a folder and expecting it to be a sub-route—it’s the folder’s default page, so app/about/index.js maps to /about, not /about/index. Another is forgetting that the app folder in Next.js is for the app router, but if you also have a pages folder, Next.js will use both, which can cause confusion. In Expo Router, a common error is placing a file outside the app directory—it won’t become a route. Also, remember that dynamic segments are URL-encoded, so a space in a parameter becomes %20; use decodeURIComponent in your component if needed.
Performance and Best Practices
File-based routing isn’t just about convenience—it also affects performance. In Next.js, the app router enables automatic code splitting: each page is a separate chunk, so users only download what they need. To keep this efficient, avoid putting large components in a shared layout.js unless they’re needed everywhere. In Expo Router, the native navigation is lazy by default, so screens load on demand. Best practices include keeping route files small, using dynamic routes for content-driven pages, and leveraging layouts to avoid repeating navigation code. Also, use the built-in Link component from next/link or Expo Router’s Link for client-side navigation—this avoids full page reloads and preserves state.
Frequently Asked Questions
Can I use file-based routing without the app folder? Yes, in Next.js you can use the pages folder for the older router. In Expo Router, the app folder is required—there’s no alternative.
What’s the difference between page.js and layout.js in Next.js? page.js defines the content of a specific route, while layout.js defines a wrapper that persists across all pages in that folder and its subfolders. Layouts can include headers, footers, or navigation that shouldn’t remount on every navigation.
How do I create a dynamic route in Expo Router? Create a file with square brackets, like app/user/[id].js. Then use the useLocalSearchParams hook to access the id parameter in your component.
Can I have both a pages and app folder in Next.js? Yes, but it’s not recommended. Next.js will treat them as separate routers, and you’ll have to manage two sets of routes. Migrate fully to the app router to avoid confusion.
Why is my route not working in Expo Router? Check that the file is inside the app directory, the filename is correct (no uppercase letters unless you’re on a case-sensitive filesystem), and the component is exported as default. Also, ensure you’ve installed expo-router and set it as the main entry in package.json.
Does file-based routing work for API routes? In Next.js, yes—files in app/api/ or pages/api/ become API endpoints. In Expo Router, there’s no built-in API route support; you’d use a separate server or cloud function.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.