Register Now: Use Visual Dev + AI to Ship 10x Faster on July 24

Announcing Visual Copilot - Figma to production in half the time logo
Contact Sales
Contact Sales










Visual CMS

Drag-and-drop visual editor and headless CMS for any tech stack

Theme Studio for Shopify

Build and optimize your Shopify-hosted storefront, no coding required



Get StartedLogin

‹ Back to blog

Web Development

A Visual Guide to Routing in Next.js 14

June 9, 2023

Written By Vishwas Gopinath

Routing plays a crucial role in the world of web development, allowing seamless navigation between various pages or views within an application. In this blog post, we will explore Next.js's routing capabilities, focusing specifically on the new App router.

Getting started

To begin, create and run a new Next.js 14 project using the following commands in the terminal:

npx create-next-app@latest routing-app
cd routing-app
npm run dev

Open the project in your preferred code editor and expand the src folder. For a fresh start, delete the app folder to create routes from scratch.

Next.js employs a file-system-based routing mechanism, where URL paths in the browser are determined by files and folders in the codebase. Following conventions is crucial for proper routing functionality. Let's discuss and understand the different conventions.

To create a route for the root URL (localhost:3000), follow these steps:

  • Create a src/app folder.
  • Inside the app folder, create a page.tsx file. This file represents the route.
  • Define a simple React component in the page.tsx file, to represent the “Home” page:
export default function Home() {
  return <h1>Welcome home!</h1>;

By following these conventions, we've successfully created our first route. Open your browser and navigate to localhost:3000 to see the "Welcome home!" message.

Let's now proceed to create two more routes: one for the About page and another for the Profile page.

  • Create a src/app/about folder.
  • Inside the about folder, create a page.tsx file. This file represents the route.
  • Define a minimal React component in the page.tsx file to represent the "About" page:
export default function About() {
  return <h1>About me</h1>;
  • Similarly, create a src/app/profile folder.
  • Inside the profile folder, create a page.tsx file. This file represents the route.
  • Define a simple React component in the page.tsx file to represent the "Profile" page:
export default function Profile() {
  return <h1>My profile</h1>;
  • When you visit the root URL, localhost:3000, the home page will still be displayed. However, if you navigate to localhost:3000/about, you will see the About me page. Similarly, changing the URL to /profile will render the My profile page.

This demonstrates that routes are associated with a file based on the containing folder's name within the app folder. The page.tsx file within the about folder corresponds to /about, while the page.tsx file within the profile folder corresponds to /profile.

What happens if you enter a URL that cannot map to a file within the app folder? For example, /dashboard. Next.js will automatically respond with a 404 Not Found response. You don't have to explicitly handle non-matching routes, as Next.js takes care of this for you.

In addition to basic routes, Next.js offers support for nested routes, so you can establish a hierarchical structure within your application. Let’s aim to render a page when the user navigates to the URL localhost:3000/blog. Furthermore, we need to render pages for localhost:3000/blog/first and localhost:3000/blog/second.

To implement nested routes, follow these steps:

  • Create a src/app/blog folder.
  • Inside the blog folder, create a page.tsx file for the main blog page:
export default function Blog() {
  return <h1>My blog</h1>;
  • Navigate to localhost:3000/blog to see the My blog page.
  • To implement /blog/first and /blog/second routes, create page.tsx files in the src/app/blog/first and src/app/blog/second folders:
export default function FirstBlog() {
  return <h1>First blog post</h1>;
export default function SecondBlog() {
  return <h1>Second blog post</h1>;
  • Now, navigating to localhost:3000/blog/first displays the first blog post, and localhost:3000/blog/second shows the second blog post.

By creating a nested folder structure, Next.js automatically routes the files accordingly. This simplifies the process of creating nested routes and enhances the organization and structure of your application.

Predefined paths like /blog/first and /blog/second may not always be suitable for complex applications with hundreds of routes. Next.js supports dynamic routes to handle such scenarios. Let’s create dynamic routes to handle a product listing and detail page.

To create dynamic routes, follow these steps:

  • Create a src/app/products folder.
  • Inside the products folder, create a page.tsx file to display a list of three products:
export default function ProductList() {
  return (
      <h1>Product List</h1>
      <h2>Product 1</h2>
      <h2>Product 2</h2>
      <h2>Product 3</h2>
  • By navigating to localhost:3000/products in the browser, the list of products displays.
  • For the details page, within the products folder, create a new folder named [productId]. The square brackets indicate a dynamic route segment.
  • Inside the [productId] folder, create a page.tsx file:
export default function ProductDetail() {
  return <h1>Details about the product</h1>;
  • Now, when you navigate to localhost:3000/products/1, you'll see the product details page. Similarly, accessing /products/2, /products/3, or even /products/100 will display the same details page. [productId] is the dynamic route segment which can accommodate values like 1, 2, 3 and so on.
  • To display the specific product ID, you can make use of the params object made available in each page. Modify the component as follows:
export default function ProductDetail({
}: {
  params: { productId: string };
}) {
  return <h1>Details about product {params.productId}</h1>;
  • Now, when you navigate to localhost:3000/products/1, the details about product 1 display. Similarly, visiting /products/100 will display details about product 100.

Dynamic routes are beneficial when implementing the list-detail pattern in any UI application. By understanding how to create dynamic routes in Next.js, you can build flexible and scalable applications that adapt to varying user interactions.

In the previous section, we learned about dynamic routes. Now, let's take it a step further and explore nested dynamic routes.

Complex applications often require multiple dynamic route segments. For instance, when navigating to /products/1, the user expects to see the details for product 1. Similarly, visiting /products/1/reviews/1 should display the first review for that product. Let's see how we can achieve this using the App Router.

To create nested dynamic routes, follow these steps:

  • Create a src/app/products/[productId]/reviews folder. This structure takes us to the route "/products/productId/reviews." However, we also need a dynamic reviewId.
  • Within the reviews folder, create a new folder named [reviewId]. Once again, the square brackets indicate a dynamic route segment.
  • Inside the [reviewId] folder, create a page.tsx file where we'll define a React component to display both the productId and the reviewId.
export default function ProductDetail({
}: {
  params: { productId: string; reviewId: string };
}) {
  return (
      Review {params.reviewId} for product {params.productId}
  • Now, if we navigate to localhost:3000/products/1/reviews/1 in the browser, the expected text displays. Similarly, navigating to productId 100 and reviewId 5 will reflect the corresponding IDs in the UI.

The key takeaway from this section is that it is possible to create nested dynamic routes by having dynamic segments in the folder names.

Next.js provides the catch-all segments feature which allows for flexible routing. Let's say we want to create a documentation site with multiple features and concepts, where each concept has its own unique route. Instead of creating separate files for each route, we can use the catch-all segments route.

To implement catcha-all segments, follow these steps:

  • Create a src/app/docs folder.
  • Inside the docs folder, create a folder with a special name recognized by Next.js. Use square brackets and three dots (for example, [...slug]) to enclose a name of your choice.
  • Inside the slug folder, create a page.tsx file with a basic React component representing the documentation home page.
export default function Doc() {
  return <h1>Docs home page</h1>;
  • By using this structure, the page.tsx file will match any URL that contains the /docs segment in the path. This way, we can define a single file that handles all the route segments in the URL.
  • To access the different segments in the URL, utilize the params object provided by Next.js. For example: localhost:3000/docs/routing/catch-all-segments can render the following component:
export default function Doc({ params }: { params: { slug: string[] } }) {
  if (params.slug.length === 2) {
    return (
        Viewing docs for feature {params.slug[0]} and concept {params.slug[1]}
  } else if (params.slug.length === 1) {
    return <h1>Viewing docs for feature {params.slug[0]}</h1>;
  return <h1>Docs home page</h1>;

With catch-all segments, you can create a hierarchical structure for your routes, allowing better organization and SEO, while reusing a single file for different variations of the URL. This approach is particularly useful for documentation websites.

Next.js provides several features to help you organize your project while following routing conventions.

Each folder in Next.js represents a route segment, but a route is only publicly accessible when a page.js or page.tsx file is added to the respective segment.

For example, accessing localhost:3000/dashboard with the following folder structure /app/dashboard/line-chart.tsx will result in a 404 error until a page.tsx file is defined. Only the content returned by page.tsx is sent to the client. Files colocated inside route segments within the app directory won't accidentally become routable.

Private folders in Next.js are a feature that allows for effective project organization. By prefixing a folder name with an underscore, it becomes a private implementation detail and is excluded from routing.

For example, accessing localhost:3000/_lib with the following folder structure /app/_lib, containing a page.tsx file. This file is unroutable and trying to access it in the browser will result in a 404 error. Private folders are useful for separating UI logic from routing logic, organizing internal files, sorting and grouping files in code editors, and avoiding naming conflicts.

Route groups allow logical grouping of routes and files without affecting the URL structure. They can be created by wrapping a folder in parentheses: (folderName)

For example, (auth)/register , (auth)/login and (auth)/forgot-password can be accessed at /register, /login, and /forgot-password. The auth route group helps organize routes more efficiently.

Routing is an integral part of web development, so users can navigate between different pages within an application. Next.js simplifies routing through its file-system based routing mechanism.

In this blog post, we explored the basics of routing in Next.js 14, specifically focusing on the App router introduced in the latest version. We discussed routing conventions, created routes for different scenarios, and highlighted Next.js' convention over configuration approach for routing.

With Next.js, you can easily define and manage routes by leveraging the file and folder structure of your codebase, eliminating the need for additional routing configuration. In the next blog posts, we will delve into more advanced routing concepts to help you build dynamic and complex applications with Next.js. Stay tuned for more exciting insights!

Introducing Visual Copilot: convert Figma designs to code using your existing components in a single click.

Try Visual Copilot


Hand written text that says "A drag and drop headless CMS?"

Introducing Visual Copilot:

A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

Like our content?

Join Our Newsletter

Continue Reading
The AI-Driven Evolution of CMSs: From Text Boxes to Generative UI
WRITTEN BYSteve Sewell
July 18, 2024
The Truth About AI's Impact on Software Development Jobs
WRITTEN BYSteve Sewell
July 17, 2024
Structured Data: What It Is and Why You Need It
July 15, 2024