Next.js Routes: Navigate Between Pages

By Josip Miskovic
Definite guide on how to use Next.js Routing

Next.js is an extremely popular framework for React development that allows developers to create single-page apps with ease. One of the outstanding features of Next.js is its use of routes. Routes let you handle links in a clean and concise manner so your app's logic doesn't get muddled up by all the different pages on your site. In Next.js, you can easily configure routing so you don't have to code it yourself!

This article will teach you everything you need to know about Next.js routes and will provide you with a broad understanding of this helpful framework!

File-system based routing

Next.js uses a file system to provide routing and URL structure for the app.

Every file with the extensions .js, .jsx, .ts, or .tsx inside the /pages is considered a routable page. Files inside the /pages folder are React component with a route based on the file name.

Example folder structure for routing in Next.js

Example /pages folder structure for routing in Next.js.

File names are crucial for routing:

File path Matching routes
/page/index.js /
/page/[page-id].js /page/1 or /page/2, but not /page/1/2
/page/[...slug].js /page/1/2, but not /page/
/page/[[...slug]].js /page/1/2 and /page/

Static index routes

Next.js router automatically loads index file at the root of the directory.

For example, if the index file is located at vegetables/index.js. Opening the http://localhost/vegetables URL will load the page component found in vegetables/index.js.

Nested routes

Next.js supports nested routes inside the pages folder to create nested URL structures. For example, if the index file is at vegetables/index.js and we want to create a nested path called celery, we would create:

/// img

By nesting the route this way, Next.js will load the page component found in vegetables/celery/index.js.

To create a nested route inside the vegetables/celery subfolder, we would add a file with the route name:


Now, visiting vegetables/celery/kale will load the page component found in vegetables/celery/kale.js.

If you are attempting to use Next.js routing without an index file, you will encounter an error.

Dynamic routes

Next.js supports the dynamic route syntax to create dynamic URLs. In Next.js, you may add brackets to a page [slug] to produce a dynamic route slugs for that page.

/// img

Dynamic Routes with Parameters Next.js also supports creating dynamic URLs with parameters inside the page component.

The bracket syntax, which is [vegetable-name], is the dynamic segment and may be used with files as well. It can also be utilized with directories like the one shown below, allowing the author to be found at /vegetables/:vegetable-name/recipes/`, making it more flexible.

Route parameters are exposed as query arguments that may be accessed in any of the connecting components involved in the route with the useRouter() hook's query object.

Catch-all routes Catch-all routes extend the dynamic routes. We can add three dots (...) inside the brackets.

For example:

`pages/vegetables/[].js matches /vegetables/kale, but also /vegetables/kale/recipes, /vegetables/kale/recipes/new and so on.

The parameters will be sent as a query parameter to the page, and it will always be an array, so the path /vegetables/kale will have the following query object:

{ "name": ["kale"] }

If the path matches one of /vegetables/kale/recipes, and any other matching path, additional parameters will be added to the array as follows:

{ "name": ["kale", "recipes"] }

Manual imperative routing useRouter hook can be used to manually route with imperative code.

This can be useful for cases where we want to transition between pages with different paths.

The useRouter() hook can handle routes in this way:

import { useRouter } from 'next/router'

export default function Footer() {
  const router = useRouter()

  return (
    <a onClick={() => router.push('/about')}>

Shallow routing

Shallow routing allows you to alter the URL without calling data fetching methods getServerSideProps, getStaticProps, or getInitialProps again.

The router object will update the state without losing data, as you'll receive the new pathname and query through it.

Only router query state will change, the actual server-rendered HTML won't update. That's useful when you want to update the URL, for instance after a query parameter changed.

Next.js uses the Link component from next/link to link between pages.

The benefit of using the <Link> instead of just <a> tags is the ability to generate URL's for route switching. Also, if we use the <a> tag, it will force a full page reload and you won't be able to take advantage of client-side routing via React's Virtual DOM.

The Link component can handle many parameters, but only the href attribute is required. We use a <a></a> tag as a child component to link pages in this example. Alternatively, you may link pages using any element that supports the onClick event on the Link component.

A Link component's href property may also be a URL object with parameters such as query, which are converted into a URL string automatically.


The passHref properties make the Link component pass down the href property to the child component. This is required if the Link component wraps a component that generates a hyperlink <a> tag.

URL Object

A Link component's href property may also be a URL object with parameters such as query, which are converted into a URL string automatically.

    pathname: '/vegetables',
    query: { name: 'kale' },

The href property also has a URL type. A URL string is a structured string that has many meaningful components. When a URL is decoded, the resultant object contains properties for each of the parts.

Custom route configuration

Next.js supports custom route configurations inside the next.config.js file.

Routing configuration rewrites allow you to map an incoming request path to a different destination path.

For example, to map /about route to /, we can add the rewrites key in next.config.js:

module.exports = {
  async rewrites() {
    return [
        source: '/about',
        destination: '/',

It's important to note that users won't be redirected, but instead, the requests will be passed to the new path. This allows Next.js to fallback to the routing logic defined in the pages themselves and for dynamic routes to still work.

Difference between React Router and Next.js Router

In Next.js, the routing system differs from the React Router. Routing is directory-based, and there's no need to write any code to build your routes. In the project root, you'll find a folder named "pages."

React Router has a top-level navigation file that is responsible for its routes, while Next.js has a page for each directory in the "pages" folder.

React Router needs to be configured manually through adding code, but Next.js handles routing automatically by watching your directory structure and inferring simple rules from it.

Next.js has built-in support for Server-side Rendering, while React Router needs to be paired with other backend frameworks.

React Router is a low-level component, and Next.js is a high-level framework which means that Next.js makes certain assumptions about how you'll make use of its routing features and handles many configuration issues for you out-of-the box.

Routing is a crucial feature of Next.js

Routing is crucial for a Next.js application, and it's reflected in the file-system-based router, which builds on the idea of pages. Pages define route patterns.

Next.js makes routing simple by providing a file system-based approach to pages and URL structure. With no custom configuration required.

If you are considering switching an existing React application to Next.js, or if you are building a new React application with dynamic routes, it is important to consider the trade-offs between using built-in routing capabilities and manually managing your routing state. Next.js offers many features to support dynamic routes, but there's no one-size-fits all solution.


Does Next.js remove trailing slashes?

Do pages impact my bundle size?

How to get the current page route?

Josip Miskovic
About Josip

Josip Miskovic is a software developer at Josip has 10+ years in experience in developing web applications, mobile apps, and games.

Read more posts →
Published on:
Download Free Software Developer Career Guide

I've used these principles to increase my earnings by 63% in two years. So can you.

Dive into my 7 actionable steps to elevate your career.