Routing in an application is the ability to change urls and go from one page to another. It's a major component in any web application. Thankfully, Next.js comes with a built-in logic concerning routing.

This tutorial will be focusing on static routing and cover:

  • How to create routes in Next.js
    • Index Routes (such as /)
    • Static Routes (/about)
    • Nested Static Routes (/products/new_arrivals)
  • How to navigate between pages and pass query parameters with:
    • Next.js Link Component
    • useRouter Hook
    • withRouter HOC

To better illustrate this concept, I will be using the example of an online store. This store will have three pages: Home, About and New Arrivals. We will be going over the different ways how to implement routing between them. Here is the end result!

The end result for our Next.js Static Routing tutorial
The end result

(Optional) Starter project

There is the code for the online store: https://github.com/mariesta/next-routing-store-project. This repository has two branches: main and final. The main branch has all the pages, components and styling but no routing. The final branch has all this + routing.

This project is a sample online store and includes three pages: Home, About Us and New Arrivals.

As a result, we will need three different URLs:

  • / for my homepage
  • /about for my about page
  • /products/new_arrivals for the page displaying the new arrivals

Want to become a Next.js pro?

I am putting together an online course on Next.js. If you are interested, sign up and I will keep you updated.

    We won't send you spam. Unsubscribe at any time.

    How to create different routes in Next.js

    Next.js uses the concept of pages to create routes. Every new Next.js project comes with a pages folder in the root directory. The structure of the pages folder determines the structure of your routes and every file inside that folder maps to a route in your application.

    Essentially, every time you want to create a route, you need to add a file in the pages folder.

    There are three ways to add static routes in Next.js depending on your needs.

    1. Next.js Index Routes

    Index routes are the root of a directory. By adding a index.js file to a folder, you create a new route. The pages folder itself maps to your base URL (meaning /).

    Therefore, for my homepage, I will create an index.js file inside the pages folder.

    pages/index.js would then map to /.

    2. Next.js Static Routes

    You can also create routes by naming the file. For my about page, I want the url /about. To do so, I have created a file called about.js that I will put in pages.

    This way, pages/about.js maps to /about.

    3. Next.js Nested Routes

    Next.js also supports nested routes. For my page with my new arrivals, I want my URL to look like /products/new_arrivals. I will create a product folder and then add new_arrivals.js inside.

    pages/products/new_arrivals.js maps to /products/new_arrivals

    Index routes can also be used for nested routes. Say I wanted a page for listing all my products, I would add a index.js file inside my products folder.

    pages/products/index.js maps to /products

    I now have all my routes mapped out and it looks like this:

    pages/
    │   index.js
    │   about.js    
    │
    └───products/
            new_arrivals.js
    

    Note: Folder vs file? If you are wondering which to choose, ask yourself: "Will I have child routes?".

    I am not planning to create any child routes under /about, therefore I am using a file for this page.

    Products however could have many children routes (/products, /products/new_arrivals, /products/[id], ...). All these children routes will need separate js files. Hence, the products folder.


    Now that we have all the pages set up, it's time to implement routing between them.

    The simplest way to navigate between pages is with Next.js Link Component. This component is very straightforward. Like an anchor tag, it accepts an href as a props.

    Here is the Header Component for my store. I want to redirect users to the homepage when clicking on the logo. I can do so by adding a <Link> component around my anchor.

    import Link from 'next/link'
    
    export default function Header() {
      return(
        <header className="store-header py-3">
          <div className="row flex-nowrap justify-content-between align-items-center">
            <div className="col-12 text-center">
              <Link href="/">
                <a className="store-header-logo text-dark">My Store</a>
              </Link>
            </div>
          </div>
        </header>
      )
    }
    Header.js

    It's the same for nested routes. Take my navbar where I have two links to the New Arrivals and the About pages. Here is the component with routing implemented.

    import Link from 'next/link'
    
    export default function Nav() {
      return(
        <div className="nav-scroller py-1 mb-2">
          <nav className="nav d-flex">
            <Link href="/products/new_arrivals">
              <a className="p-2 text-muted">New Arrivals</a>
            </Link>
            <Link href="/about">
              <a className="p-2 text-muted">About us</a>
            </Link>
          </nav>
        </div>
      )
    }
    Nav.js

    Access your Next.js router and navigate with the useRouter hook

    Another way to implement routing between pages is to access the router and push a new page. Next.js provides us a useRouter hook to accomplish this.

    Going back to our Header Component, here is another way to link to our homepage:

    import { useRouter } from 'next/router'
    
    export default function Header() {
      const router = useRouter()
      const navigateHome = () => router.push('/')
      
      return(
        <header className="store-header py-3">
          <div className="row flex-nowrap justify-content-between align-items-center">
            <div className="col-12 text-center">
              <a className="store-header-logo text-dark" onClick={navigateHome}>My Store</a>
            </div>
          </div>
        </header>
      )
    }
    Header.js

    With the useRouter hook, you can access the router object. The latter comes with many useful functions including push(), back(), reload() and more.

    Access your Next.js router and navigate with the HOC withRouter

    The last option is, of course, with a HOC for classes. For this one, Next.js offers withRouter to access the router through props.

    import { withRouter } from 'next/router'
    
    function Header({router}) {
      const navigateHome = () => router.push('/')
      
      return(
        <header className="store-header py-3">
          <div className="row flex-nowrap justify-content-between align-items-center">
            <div className="col-12 text-center">
              <a className="store-header-logo text-dark" onClick={navigateHome}>My Store</a>
            </div>
          </div>
        </header>
      )
    }
    
    export default withRouter(Header)
    Header.js

    Passing query parameters

    The ability to pass query when navigating between pages is an important one. Next.js also covers this use case.

    In these examples, I will be using my Header and Nav components to pass the query ?sort=asc to my url. This will result in urls like  http://localhost:3000/products/new_arrivals?sort=asc

    Next.js Link Component also accepts URL objects in href. The URL object must be composed of pathname (the name of the page we are trying to access) and query (the parameters you want to pass).

    import Link from 'next/link'
    
    export default function Nav() {
      return(
        <div className="nav-scroller py-1 mb-2">
          <nav className="nav d-flex">
            <Link href={{
              pathname: "/products/new_arrivals",
              query: { sort: "asc" }
            }}>
              <a className="p-2 text-muted">New Arrivals</a>
            </Link>
            <Link href="/about">
              <a className="p-2 text-muted">About us</a>
            </Link>
          </nav>
        </div>
      )
    }
    Nav.js

    Query Parameters with useRouter

    The same logic is used with the useRouter hook. Instead of router.push('/'), we replace it with router.push({ pathname: "/", query: { sort: "asc"}).

    import { useRouter } from 'next/router'
    
    export default function Nav() {
      const router = useRouter();
    
      const navigate = (href) => router.push({
        pathname: href,
        query: { sort: "asc" },
      })
    
      return(
        <div className="nav-scroller py-1 mb-2">
          <nav className="nav d-flex">
            <a className="p-2 text-muted" onClick={() => navigate('/products/new_arrivals')}>New Arrivals</a>
            <a className="p-2 text-muted" onClick={() => navigate('/about')}>About us</a>
          </nav>
        </div>
      )
    }
    Nav.js

    Query Parameters with withRouter

    And finally, with the HOC withRouter. Again, simply pass the object to router.push().

    import { withRouter } from 'next/router'
    
    function Header({router}) {
      const navigateHome = () => router.push({
        pathname: "/",
        query: { sort: "asc" },
      })
      
      return(
        <header className="store-header py-3">
          <div className="row flex-nowrap justify-content-between align-items-center">
            <div className="col-12 text-center">
              <a className="store-header-logo text-dark" onClick={navigateHome}>My Store</a>
            </div>
          </div>
        </header>
      )
    }
    
    export default withRouter(Header)
    
    Header.js

    There you go! We have now implemented static routing in our application. For a tutorial on dynamic routing in Next.js, don't hesitate to check it out.

    And if you would like to deploy your brand new web app, what about doing it on Heroku? Here is a quick tutorial for deploying your Next.js app to Heroku in 5 minutes.

    Stay tuned for a future tutorials on Next.js!