ProNextJS
    Loading
    lesson

    File-Based Routing with App Router

    Jack HerringtonJack Herrington

    Next.js has always been a file-based routing system, though the syntax has changed over time. With the introduction of the App Router, file-based routing continues to be an intuitive way to define routes in your application.

    File-Based Routing

    File-based routing in Next.js means that the location of the page.tsx or route.ts file inside the app directory defines how it maps to a given URL. By organizing your files and directories in a specific way, you can create routes that correspond to the desired URLs.

    Let's build a quick demo app to experiment with the different types of routes you can define in a Next.js application using the App Router.

    Creating the Demo App

    To create a new demo app, run the following command:

    pnpm dlx create-next-app@latest --use-pnpm route-test
    

    Like before, say "yes" to all of the options you are presented, then navigate into the route-test directory and open it in your code editor.

    Basic Routes

    The most basic route in a Next.js application is the homepage, which is defined by the src/app/page.tsx file. This file maps directly to the root URL (/).

    When we trim down the page.tsx file to just say "Home page", we'll see it displayed when we visit the root URL.

    // inside page.tsx
    
    export default function Home() {
      return (
        <main className="...">
          <h1 className="...">Home page</h1>
        </main>
      );
    }
    

    Special Properties

    Every page.tsx route receives two special properties: params and searchParams. For the homepage, we don't have any parameterized routes, so we'll focus on searchParams.

    Here's how we would add the searchParams property to the Home component:

    export default function Home({ searchParams }: { searchParams: Record<string, string | string[]> }) {
      return (
        <main>
          <h1>Homepage</h1>
          <h2>Search Params:</h2>
          <pre>{JSON.stringify(searchParams, null, 2)}</pre>
        </main>
      );
    }
    

    If we add search parameters to the URL, such as ?q=5&a=10, the searchParams object will contain the corresponding key-value pairs. If a parameter appears multiple times in the URL, its value will be an array of strings.

    params displayed on the home page

    Nested Routes

    To create a specific route within the application, we can nest directories inside the app directory. For example, to create an /about route for the application, we would create a src/app/about/page.tsx file.

    This can be further nested to create more complex routes. For instance, an /about/you route would be defined by the src/app/about/you/page.tsx file.

    Copying and pasting the page.tsx contents into these files would display the corresponding content when visiting the respective URLs:

    the nested route

    Parameterized Routes

    Parameterized routes allow you to handle dynamic segments in the URL. To create a parameterized route, you can use brackets ([]) in the directory name to specify a dynamic segment. For example, to create a /product/:productId route, you would create a file at app/product/[productId]/page.tsx.

    The page.tsx file for a parameterized route receives a params prop, which is an object containing the dynamic segments as keys:

    export default function ProductDetail({
      params,
      searchParams,
    }: {
      params: { productId: string };
      searchParams: Record<string, string | string[]>;
    }) {
      return (
        <main>
          <h1>Product Detail Page</h1>
          <p>Params</p>
          <pre>{JSON.stringify(params, null, 2)}</pre>
          <h2>Search Params</h2>
          <pre>{JSON.stringify(searchParams, null, 2)}</pre>
        </main>
      );
    }
    

    Now if we visit /product/foo, the params object will have a productId property with the value "foo":

    the product detail page

    However, navigating to /product will give us a 404 erros since no page is defined for that route. In order to fix this, we'll have to create a /product/page.tsx file for the Product Home Page.

    Catch-All Routes

    Catch-all routes allow you to match any number of URL segments after a certain point. To create a catch-all route, you can use the ... syntax in the directory name, followed by a parameter name.

    For example, say we wanted to create a setup that would allow for routes for /setting/a, /setting/a/b, /setting/a/b/c, and so on. We would create a src/app/setting/[...setting]/page.tsx file.

    The page.tsx file for a catch-all route receives a params prop with an array of the matched segments:

    export default function SettingPage({
      params,
      searchParams,
    }: {
      params: { setting: string[] };
      searchParams: Record<string, string | string[]>; 
    }) {
      return (
        <main>
          <h1>Setting Page</h1>
          <p>Setting: {JSON.stringify(params.setting)}</p>
        </main>
      );
    }
    

    If we visit /setting/a/b/c, the params prop will be { setting: ["a", "b", "c"] }.

    setting catch-all route

    Like before, a page.tsx file will have to be created in order to have a Setting Home Page.

    Optional Catch-All Routes

    Optional catch-all routes allow you to match any number of URL segments after a certain point, including the case where no additional segments are provided. To create an optional catch-all route, you can use double brackets ([[...slug]]) in the directory name.

    For example, for an Info page we could create a src/app/info/[[...item]]/page.tsx file.

    If we visit /info, the params prop will be undefined. If we visit /info/a/b/c, the params prop will be { item: ["a", "b", "c"] }.

    Route Groups

    Route groups allow you to create a maintainable structure inside the app directory by grouping related routes together. To create a route group, you can wrap the folder name in parentheses like app/(teamA)/editor/page.tsx

    The teamA directory is not included in the final URL, so (teamA)/editor corresponds to /editor.

    the editor page

    Routing Cheatsheet

    Through these examples, we've created a useful routing cheatsheet:

    Here's the fixed table with proper markdown formatting:

    PathURL Examples
    /page.tsx/
    /about/page.tsx/about
    /about/you/page.tsx/about/you
    /product/[productId]/page.tsx/product/foo, /product/bar
    /product/page.tsx/product
    /setting/[...setting]/page.tsx/setting/a, /setting/b/c
    /setting/page.tsx/setting
    /info/[[...item]]/page.tsx/info, /info/23, /info/23/detail
    /(teamA)/editor/page.tsx/editor

    In addition to page.tsx files, you can also use route.ts files to create route handlers at specific URLs. However, you can only have either a page.tsx file or a route.ts file for a given route, not both.

    Transcript