Skip to main content

Command Palette

Search for a command to run...

Dynamic routes recipes from Next.js App Router

Learn about dynamic routes and other routing essentials from the Next.js App Router in a beginner-friendly way, with many code examples and visuals.

Updated
โ€ข7 min read
Dynamic routes recipes from Next.js App Router

Next.js App Router has brought many improvements over its predecessor, Page Router. One of the significant improvements is the routing itself.

Next.js App Router uses the file-system-based router, where you create directories(aka folders) to define routes. You must create a special file called page.js(or .ts/.jsx/.tsx) under the directory to create a page for the route.

The top-level app/ directory acts as the root route(/), and any directory you create under the app directory will create other route segments that map to a URL segment. You can also create the nested route by creating the subdirectories as shown in the image below.

Next.js Routing

In Next.js App Router, a page is unique to a route. You can create one page per route by creating a page.js file under a directory that signifies a route segment.

// /app/page.js
export default function Page() {
  return <h1>Home Page</h1>
}

If a directory doesn't have a corresponding page.js file, the respective route will be inaccessible and result in a 404, page not found error. The image below demonstrates that each route directory has a page file that creates the page for that route segment.

Next.JS Page Routes

So far, all the routes we have discussed are static and pre-defined, known beforehand to developers to construct the route segments. But what if we do not know the value to form a route segment? What if it is dynamic, like an id, name, or slug?

Welcome Dynamic Routes

You create dynamic routes when you do not know the route segment name and want to create with dynamic data. For example, you may have a static route called /blog. Creating individual blog post routes under it will be too much overhead. You may want to create them using any dynamic data like id, name. or a slug.

๐Ÿ’ก What is a slug?

Slug is an unique part of an URL that provides information about a web page. You should keep them simple, human-readable to help out with SEO. It appears at the end part of the URL after the backslash (โ€œ/โ€). For example, how-to-learn is the slug of the URL https://tapascript.io/blog/how-to-learn.

dynamic routing

Let's Understand Things With Code

We understand things better with code. Let's do that. All the code used in this article is available on the tapaScript GitHub repository.

First, we will create a project with the latest Next.js version. Open a terminal/command prompt and execute the following command. Make sure you have installed Node.js 18 or above.

npx create-next-app@latest

Please provide the details asked. A few important things to note here.

  • Opt for App Router

  • The selection of TypeScript is your choice. If you are comfortable with it, you can select Yes. I'll use JavaScript code in this article as most developers will likely use it(however, I am a big TypeScript fan!).

  • You may opt for the src/ directory. I do that as I like to keep my project configuration files under the src/ directory but outside of the app/ directory. Here, we will assume to opt for it.

steps

Once done, change the directory to your project directory and install the dependencies using yarn/npm/pnpm/bun, whatever you want. Then, start the server locally using the yarn dev or its npm/pnpm/bun equivalent commands.

> cd teach-next-js
> yarn
> yarn dev # or npm run dev or pnpm dev or bun dev

The app will be available on the localhost:3000 by default. As you see in the image below, the app/ directory under the src/ directory signifies the top-level route /. The page.js file under the app/ directory provides us with the page for that route.

folder to route

Let's clear the existing code in the page.js file and put a simple ReactJS component like this:

export default function Home() {
  return (
    <div className="flex justify-center p-2">
      <p className="text-3xl">
        Home Page
      </p>
    </div>
  )
}

Now, our home page(on the route segment /) will look like this:

Home Page

Create More Routes

Let's create a /blog route segment. To do that, we will create a blog/ directory under the app/ directory.

Added Blog

Now you will have a /blog route segment. However, it will not be accessible publicly because we have not defined a page for it yet.

404 page

Let's create a page.js file under the blog/ directory with the following content.

const BlogPage = () => {
  return (
    <>
      <p className="text-3xl">Blog Page</p>
    </>
  )
}

export default BlogPage;

We will see the blog page rendered successfully. It is a simple page with a paragraph of text.

blog page

Create Nested Routes

Let us now create a couple of nested routes like /about/form and /about/tax. You guessed it right! We will have to create an about/ directory and then two sub-directories under it. Those are form/ and tax/.

Now, to make all three routes accessible, we need to create a page.js file under each of the directories.

About Page

Here is an example page for the /about route segment. You can create something similar for the pages of /about/form and /about/tax.

const AboutPage = () => {
  return (
    <>
      <p className="text-3xl">About Page</p>
    </>
  )
}

export default AboutPage;

Here is how each of the pages may appear for each of the routes.

All Pages

Create Dynamic Routes

Now it's time we start understanding dynamic route segments with code. You can create a dynamic route segment by wrapping the directory name in square brackets([]). For example, [name], [slug], [id], etc.

Taking forward the example of a blog and its posts, the individual posts can include a route like this, /blog/[slug]/page.js. Here [slug] is the dynamic route segment.

Create a directory named [slug] under the blog/ directory and a page.js file under the blog/[slug]/.

blog with slug

All dynamic segments are passed as the params prop to the page. We can destructure the dynamic route segment value from the params prop. Let's create the content for the dynamic route page with the following code.

const BlogPost = ({params: {slug}}) => {
  return(
    <p className="text-2xl">
      Showing the blog post for the 
      slug <strong>{slug}</strong>
    </p>
  )
}

export default BlogPost;

The page has received a params prop, and we can extract the slug value from it. Now, you can do whatever logic you need using the slug value. You can use it to make a network call and get details to render on the page, or you can just render it on the page, as shown below.

blog slugs

Create Dynamic Catch-all Segments

You can broaden the use of the dynamic route segment([slug]) to a catch-all route segment by adding an ellipsis inside the brackets[...slug].

For example /app/store/[...slug]/page.js will match /store/book, /store/design, and also /store/book/novels, /store/design/shoes, /store/design/shoes/boot, and so on.

Create a store/ directory under the app/ directory. Now, create a directory with the name [...name] under the app/store/.

ctach-all

The page.js file under the app/store/[...name] will define a page for the catch-all route segment. This page component is quite similar to the page component we have seen above for the dynamic routes. However, notice that we are extracting name instead of slug here because we have used [...name] as the directory name.

const StorePage = ({params: {name}}) => {
  console.log(name);
  return(
    <p className="text-2xl">
      Showing the store page for the 
      name <strong>{name}</strong>
    </p>
  )
}

export default StorePage;

Now, when you try the route localhost:3000/store/a, the params returns {name: ['a']}. We are printing that on the console and browser.

catch all example 1

You can also catch the route localhost:3000/store/a/b with the same, and the params prop value will be {name: ['a', 'b']}.

catch all example 2

Create Optional Dynamic Catch-all Segments

But hang on! How about the route /store? It gives us 404, page not found.

store route

Yes! One way to fix that is by creating a page.js file inside the app/store/ directory. If you don't want that, you can make the catch-all segment as an optional catch-all segment by wrapping the parameter(or directory name) in double square brackets, [[...name]].

optional catch all

Now even the /store route page will be served from the app/store/[[...name]]/page.js. However, in this case, the value of name will be undefined and the params prop value will be {}.

optional catch all 2

That's all. Thanks for reading it. I hope it was insightful. If you liked the tutorial, please post likes and share it in your circles.

One Last Thing...

I am a self-declared Next.js evangelist who loved this framework from its very beginning days. With the inclusion of the App Router, the affection has gone higher ๐Ÿ˜Š.

I have a full-fledged playlist on my YouTube channel(tapaScript) that will teach you to build projects with Next.js, from clarifying fundamental concepts to coding and tasks.

You may want to check it out.


Let's connect. I share knowledge on web development, content creation, Open Source, and careers on these platforms.

S

I learned a lot again from you Sir Tapas.

1
T

Great ๐Ÿ‘

J
jon2y ago

good

1
S

Next.js App Router enhances routing compared to Page Router, offering dynamic route recipes. This improvement allows for more flexibility and efficient navigation, enhancing the overall user experience and developer workflow.

1
T

Thanks Warner for commenting.

J

Weโ€™re truly amazed at your decoration skills. This looks great!

1
T

Thanks a lot.

N

Thank for sharing !! Do you have resource to learn about Next.js

1
T

Hi Nihal,

Iโ€™m making this: Full Stack with NextJS App Router https://www.youtube.com/playlist?list=PLIJrr73KDmRwz_7QUvQ9Az82aDM9I8L_8

1
F

Thanks for sharing!

I have a question, what if you want a specific dynamic route, like on /a and /b and nothing else?

So if /c is entered you'd go to the 404 page.

I wanted to implement this but couldn't figure it a while back.

1
T

Hey Favourit, How are you, man? It's a great question. I can think of two ways(but I haven't found any other direct way yet!)

  • If the routes are specific, then they may not be dynamic. Specific routes can be static and deal with them as the static routes.

  • The problem with the first approach is, what if the route segments are way big in number? And What if you do not know about the segments beforehand? In this case, control it at the segment generation level, not the route level. Routing goes by pattern. If the pattern is the same, and for that, you want to opt out of a few segments, take them out in our logic where you generate the segment... Let's say, your dynamic route pattern is /blog/${slug}, in this you want to take /blog/what-a-good-day and /blog/i-am-great but I want to ignore /blog/not-so-great, ignore it USE NEXT.JS MIDDLEWARE. With that you can include named parameters: /about/:path matches /about/a and /about/b but not /about/a/c

You can read about them from the middleware doc, and I will also teach these concepts in my nextjs playlist on YouTube :)

F

I'm doing great Tapas Adhikary

Yeah, like you mentioned, though I could specify the routes segment by what if they are a large number.

I expected the [https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes#generating-static-params](Generating Static Params) to work.

I'd read more on middleware, thanks. Also, looking forward to the YouTube playlist

1
T

Favourite Jome very cool.. please let me know when you have additional findings on this. Take care.

1
B

Good article!! Thanks for sharing !!

1
T

Hey, thanks a lot for reading Bernardo Gomes de Abreu.

S

๐Ÿ‘ Impressive insights on dynamic routes in Next.js!

1
T

Thanks a lot :)

Build with Next.js

Part 3 of 7

Next.js is the coolest React-based framework on the planet(at least I think that way!). How about learning to build something useful, practical, and fun with it? Please join me get started.

Up next

Integrate SuperTokens Passwordless Authentication with Next.js

Learn how to integrate SuperTokens Passwordless authentication using OTP and magic link with Next.js applications.