2024-10-19 Web Development

Next.js: Routing in Next.js 14

By O. Wolfson

Currently Reading: Routing, from the Next.js Docs.

The bare bones of every web application is its routing system. This article introduces the fundamental concepts of web routing and the specific methodologies used in Next.js 14, focusing on its powerful and flexible routing system.

  1. Basic Terminology
  2. The App Router
  3. Roles of Folders and Files
  4. Special Files in Next.js
  5. Static Routes
  6. Advanced Routing Patterns

Basic Terminology

Before diving deeper, it's essential to understand common terms you will encounter in routing documentation:

Component Tree Terminology

  • Tree: A way to visualize a hierarchical structure, like a component tree with parent and child components.
  • Subtree: A section of a tree starting at a new root and ending at its leaves.
  • Root: The first node in a tree or subtree.
  • Leaf: The last nodes in a subtree, having no children.
Image showing a component tree, from the Next.js documentation.

URL Anatomy Terminology

  • URL Segment: A part of the URL path separated by slashes.
  • URL Path: The section of the URL that follows the domain, made up of segments.

The App Router

Next.js 14 enhances its routing capabilities with the App Router, built on React Server Components. This router supports:

  • Shared layouts
  • Nested routing
  • Loading states
  • Error handling

App Directory

In Next.js, the app directory works alongside the traditional pages directory, allowing for incremental adoption. This setup means you can gradually transition routes from the pages directory to take advantage of the new features without disrupting existing routes.

Important Note:

The App Router takes precedence over the Pages Router. Ensure that routes across directories do not resolve to the same URL path to prevent conflicts.

Roles of Folders and Files

Next.js employs a file-system-based router where:

  • Folders define routes. A route represents a path made up of nested folders down to a leaf folder containing a page.js file.
  • Files within these folders create the UI for each route segment.

Route Segments

Each folder in a route corresponds to a segment in the URL path. For nested routes, folders are nested within each other. For example, a /dashboard/settings route involves nesting two folders within the app directory, each corresponding to a segment of the URL.

Special Files in Next.js

Next.js introduces special files within routes to handle various aspects of routing:

  • layout.js: Shared UI for a segment and its children.
  • page.js: Defines the unique UI of a route, making it publicly accessible.
  • loading.js: Provides a loading UI for a segment.
  • not-found.js: Handles UI for unmatched routes.
  • error.js: Serves as a React error boundary.
  • global-error.js: Handles global errors.
  • route.js: Defines server-side API endpoints.
  • template.js: Used for re-rendering layout UI.
  • default.js: Acts as a fallback UI for parallel routes.

File Extensions

Files can use .js, .jsx, or .tsx extensions.

Static Routes

  • A static route is a predefined, fixed path in the URL, without any dynamic segments or variables. It always matches the same URL and does not change based on user input or variables.

  • Example: /about matches only /about and no other variants.

  • Folder Structure:

    app
    └── about
        └── page.tsx
    

    In this case, visiting the /about path will render the content from the page.tsx file located in the about folder.

Nested Static Route

  • A nested static route contains multiple predefined URL segments, representing a hierarchy of static paths. Each segment corresponds to a folder in the file structure, and the nested folders represent deeper levels of the URL hierarchy.

  • Example: /dashboard/settings matches only /dashboard/settings and no other variants.

  • Folder Structure:

    app
    └── dashboard
        └── settings
            └── page.tsx
    

    In this case, visiting the /dashboard/settings path will render the content from the page.tsx file located inside the settings folder, which is nested within the dashboard folder.

Advanced Routing Patterns

Next.js also supports advanced routing patterns such as:

  • Parallel Routes: These allow simultaneous display of multiple pages in the same view with independent navigation, useful for dashboards with split views.
  • Intercepting Routes: These enable intercepting a route to display it within the context of another, maintaining the current page's context.

With a foundational understanding of Next.js routing, you're now equipped to explore and implement complex routing patterns that enhance your application's navigation and structure. In Next.js with the app router, you can create several types of dynamic routes beyond the simple [slug] pattern. Here are the various kinds of dynamic routing patterns you can utilize:

1. Dynamic Segments (e.g., [slug])

  • This is the most common dynamic route where the segment inside square brackets represents a dynamic value in the URL.
  • Example: /blog/[slug] matches /blog/hello-world, /blog/another-post, etc.
  • Folder Structure:
    app
    └── blog
        └── [slug]
            └── page.tsx
    

2. Catch-All Segments (e.g., [...slug])

  • The catch-all route matches multiple segments or a single segment. It’s useful when you want to match an arbitrary depth of nested paths.
  • Example: /docs/[...slug] matches /docs/intro, /docs/guides/installation, or even /docs/guides/installation/linux.
  • Folder Structure:
    app
    └── docs
        └── [...slug]
            └── page.tsx
    

3. Optional Catch-All Segments (e.g., [[...slug]])

  • Optional catch-all segments match zero or more URL segments. It’s like a catch-all route, but it also matches the base route.

  • Example: /docs/[[...slug]] matches /docs, /docs/intro, or /docs/guides/installation/linux.

  • Folder Structure:

    app
    └── docs
        └── [[...slug]]
            └── page.tsx
    

4. Named Layout Segments (e.g., (auth))

  • Named segments allow you to define layouts that are conditionally used, such as for authentication. This is especially useful for providing layouts for specific sets of pages without affecting other pages.
  • Example: (auth)/login/page.tsx renders a layout specific to authentication-related pages.
  • Folder Structure:
    app
    └── (auth)
        └── login
            └── page.tsx
    

5. Route Groups (e.g., (group))

  • Route groups are used for grouping related routes under a common parent but without affecting the URL structure. They help to organize the codebase while not impacting the routing.
  • Example: (admin)/users/page.tsx allows the grouping of admin-related routes, but the URL remains /users.
  • Folder Structure:
    app
    └── (admin)
        └── users
            └── page.tsx
    

6. Parallel Routes (e.g., @auth, @marketing)

https://nextjs.org/docs/app/building-your-application/routing/parallel-routes

  • Parallel routes enable multiple routes to be rendered side by side, allowing you to serve different UI sections based on specific URLs.
  • Example: app/@auth/login/page.tsx and app/@marketing/landing/page.tsx can render in parallel in different parts of the layout.
  • Folder Structure:
    app
    └── @auth
        └── login
            └── page.tsx
    └── @marketing
        └── landing
            └── page.tsx
    

7. Interceptors

  • Interceptors act as middleware-like components within the routing layer that can intercept and modify the behavior of a request.
  • Example: Using interceptors for route transitions or previews of pages without fully navigating to the new page.

8. Colocation of Layouts and Pages

  • You can colocate layouts alongside pages within the same route folder. This layout will wrap only the routes in that folder.
  • Example: Each folder can have its own layout.tsx file that wraps the page.tsx file inside it.
  • Folder Structure:
    app
    └── blog
        ├── layout.tsx
        └── [slug]
            └── page.tsx
    

9. Route Interpolation

  • You can interpolate dynamic segments into the URL using brackets. This is great for when your paths need to contain multiple dynamic parts.
  • Example: /blog/[year]/[month]/[slug] matches /blog/2024/09/hello-world.

Conclusion

With these patterns, Next.js provides a robust and flexible routing system, allowing for dynamic, nested, and deeply structured routes. Each pattern can be combined to build complex and scalable routing architectures while keeping code organized.