Using Next.js Route Handlers
Tags: nextjs, webdev
Published: 2023-05-17 18:46:13

**Written by [Elijah Agbonze](https://blog.logrocket.com/author/elijahtrillionz/)✏️**

[Next.js](https://blog.logrocket.com/tag/nextjs/) is a popular React framework that simplifies [server-side rendering](https://blog.logrocket.com/improve-app-performance-react-server-side-rendering/) and the building of static web applications. One of the core features offered by the Next.js framework is its flexible routing system, which allows developers to create custom routes and define how they handle incoming requests. With the [recent release of](https://nextjs.org/blog/next-13-2) [v](https://nextjs.org/blog/next-13-2)[13.2](https://nextjs.org/blog/next-13-2), Next.js has introduced several new features and changes to routes that make it even more powerful and easy to use. 

Whether you're a seasoned Next.js developer or [just getting started](https://blog.logrocket.com/best-next-js-starter-templates/), understanding Route Handlers is essential to building fast, scalable, and maintainable web applications. In this article, we'll take a closer look at the newly improved Route Handlers in Next.js, the added perks, how it is similar to [Remix’s routing system](https://blog.logrocket.com/understanding-routes-route-nesting-remix/), and how you can implement it in a Next.js application. 

_Jump ahead:_

*   [What are Route Handlers in Next.js?](#what-route-handlers-next-js)
    *   [What can we do with Route Handlers?](#do-with-route-handlers)
*   [Next.js Route Handler improvements](#next-js-route-handler-improvements)
*   [Similarities between Next.js Route Handling and the Remix routing system](#similarities-between-next-js-route-handling-remix-routing-system)
*   [Getting started with the Next.js Route Handler](#getting-started-with-next-js-route-handler)
    *   [Creating a new API route](#creating-new-api-route)
    *   [Building nested and dynamic routes](#building-nested-dynamic-routes)
    *   [Creating secured routes](#creating-secured-routes)
*   [Dynamic and static generated functions in Next.js Router Handlers](#dynamic-static-generated-functions-next-js-router-handlers)
    *   [Static Route Handler](#static-route-handler)
    *   [Dynamic Route Handler](#dynamic-route-handler)

## What are Route Handlers in Next.js? <a name="what-route-handlers-next-js">

Route Handlers in Next.js are functions executed when site routes are accessed by a user and are responsible for handling incoming HTTP requests for the defined URLs or routes to produce the required data. In essence, when a user visits a particular page or URL in a Next.js application, the corresponding Route Handler handles the request created by the user and returns the appropriate response thereby rendering desired content. Route Handlers in Next.js can be in the form of functions exported from a page file as a middleware function that intercepts incoming requests, and custom server-side functions for handling requests and responses for specified routes in the web application.

### What can we do with Route Handlers? <a name="do-with-route-handlers">

With Route Handlers, we can create [dynamic routes](https://blog.logrocket.com/implementing-ssr-next-js-dynamic-routing-prefetching/), which consist of a URL that contains variable parameters that can be used to generate dynamic content. Here, the variables can be appended to the URL based on the user’s site action and can help to carry information to different routes of the web application. Overall, Route Handlers are an essential part of Next.js, allowing developers to define custom routing logic and handle incoming requests in a flexible and efficient manner.

## Next.js Route Handler improvements <a name="next-js-route-handler-improvements">

Routing is essential for web applications as it is tasked with handling what content is made available on different web URLs/routes. In earlier versions of Next.js, when you created a Next application, you would get a `pages/api` directory within the application file structure. API routes were defined in this `pages/api` directory; this was because, with earlier versions of Next, there was not yet a system in place to handle routes within the [`app`](https://blog.logrocket.com/next-js-13-app-directory/) directory. 

The new Next.js v13.2 release has added a Route Handler feature to Next applications and also added support for dynamic route imports. This addition means that pages can be loaded on demand, ultimately improving performance and reducing initial load times. Creating a new Next.js application with the latest v13.2 now places the `api` directory within the `app` folder. These Route Handlers provide built-in functions for handling various kinds of requests and responses, allowing developers to specify custom behavior for specific routes, allowing more flexibility and control over how routes are handled, including redirecting to other pages, and providing data responses. 

With this new feature, we can create API request handlers inside the `app` directory by exporting functions that match to HTTP request methods (such as `GET`, `POST`, `PUT`, etc.,). This is typically done with the following steps:

*   A `route.ts` (can also be `route.js`) is created within the `app` directory
*   This file will export an asynchronous function named with your desired HTTP verb: `GET`, `HEAD`, `POST`, `PUT`, `DELETE`, etc.

> Note that Route Handlers in Next.js v13.2 are no longer available in the `pages` directory as with earlier Next versions (i.e., `pages/api`), as they are meant to be a replacement for API Routes. Instead, we can now use the file created in the steps above

## Similarities between Next.js Route Handling and the Remix routing system <a name="similarities-between-next-js-route-handling-remix-routing-system">

The [Remix routing system](https://blog.logrocket.com/understanding-routes-route-nesting-remix/) is built on top of [React](https://blog.logrocket.com/migrating-react-router-v6-guide/) [Router](https://blog.logrocket.com/migrating-react-router-v6-guide/), and as such, it bares some similarities to Next.js route handling patterns. Below is a list of similarities between how these two frameworks handle routing in applications:

*   Defining and managing routes: Remix and Next.js v13.2 allow developers to define and manage routes for their web applications using created TypeScript/JavaScript files that contain handler functions
*   Route-based code splitting: Remix and Next.js v13.2 use route-based [code splitting](https://blog.logrocket.com/dynamic-imports-code-splitting-next-js/), which means that each route loads only the code necessary for that particular page. This practice significantly boosts site performance because it reduces the amount of code that needs to be loaded on the initial execution of the application
*   Nested route support: Both frameworks have support for [nested routes](https://blog.logrocket.com/understanding-routes-route-nesting-remix/); allowing pages and components to be created within folders in such a way that the components created with a nested folder structure within the directory will be treated as nested routes of a defined parent route

## Getting started with the Next.js Route Handler <a name="getting-started-with-next-js-route-handler">

In this section, we will demonstrate how we can use the new route-handling features of Next.js. To get started, we will first need to create a new Next.js application. Do this with the following Bash commands in the CLI:

```bash
npx create-next-app@latest router-handling
```

For this tutorial, we will be using the following configurations during the setup process: ![Next.js Route Handler Example](http://blog.logrocket.com/wp-content/uploads/2023/05/next-js-route-handler.png) 

When the installation process is completed, we will have a Next.js project folder `"router-handler"` using Next.js v13.2\. In this folder, we have the following in the `app` directory:

```javascript
┣ 📂app
 ┃ ┣ 📂api
 ┃ ┃ ┗ 📂hello
 ┃ ┃ ┃ ┗ 📜route.js
 ┃ ┣ 📜favicon.ico
 ┃ ┣ 📜globals.css
 ┃ ┣ 📜layout.js
 ┃ ┣ 📜page.js
 ┃ ┗ 📜page.module.css
```

Here, we have the `api` directory in the `app` folder and an example API route `hello` is created by default.

### Creating a new API route <a name="creating-new-api-route">

To create a new API route, in the `app/api` directory, create a folder with the name of our route, and within it, create a `route.js` function that exports our HTTP verb. In this case, we will create a route called `"test"`. To do this, create a new `test` folder in the `app/api` directory, create a `route.js` file, and add the following code to it:

```javascript
// In this file, we can define any type of request as follows:
// export async function GET(Request) {}
// export async function HEAD(Request) {}
// export async function POST(Request) {}
// export async function PUT(Request) {}
// export async function DELETE(Request) {}
//  A simple GET Example

export async function GET(Request) {
  return new Response("This is a new API route");
}
```

Here, we have a `GET` request that returns a simple text response. To access this API route, start the application server with the `npm run dev command` in the CLI. Then, open up the `localhost` server in the browser and append the `API URL: /api/test`. For example, if the `localhost` runs on `port 3000`, we will have `localhost:3000/api/test`. This will produce a result similar to the image below: ![Next.js API Route in the Route Handler](http://blog.logrocket.com/wp-content/uploads/2023/05/next-js-api-route.png)

### Building nested and dynamic routes <a name="building-nested-dynamic-routes">

Next.js v13.2 also supports dynamic API routes. To create a dynamic API route, in the `app/api` folder, create a `username` folder for the route and define a dynamic route. For the purpose of this example, we will create a dynamic route `[user]` in the `app/api/username` directory. Then, inside the `[user]` route, create a `route.js` file with the following:

```javascript
export async function GET(request, { params }) {
  // we will use params to access the data passed to the dynamic route
  const user = params.user;
  return new Response(`Welcome to my Next application, user: ${user}`);
}
```

To access the API, open up `http://localhost:3000/api/username/[your username]` in place of the username. Keep in mind that you can enter any string, for example, `http://localhost:3000/api/username/eric`. This will produce the following result: ![Example of the LocalHost in Next.js ](http://blog.logrocket.com/wp-content/uploads/2023/05/next-js-local-host.png) Creating nested APIs in Next.js is a simplified process. To create a nested route, first define the parent API route in `app/api`. Any sub-folders added to the created `parent route` are treated as nested routes rather than separate routes. In the example above, we created a `username` route and nested a dynamic route `[user]` within it. In the `app/api/username` we can define the `parent route` in a `route.js`, as shown below:

```javascript
export async function GET(request) {
  // username parent route
  return new Response("This is my parent route");
}
```

The `parent route` can be accessed via the URL `localhost:3000/api/username`, like so: ![Example of the Parent Route in Next.js](http://blog.logrocket.com/wp-content/uploads/2023/05/next-js-parent-route.png) Accessing the defined nested route `http://localhost:3000/api/username/[your username]` will produce the earlier result.

### Creating secured routes <a name="creating-secured-routes">

To create secured routes in Next.js, middleware functions are required to [authenticate and authorize the requests](https://blog.logrocket.com/implement-authentication-authorization-next-js/) made to the route before allowing access to it. Defining a secured route usually follows the pattern below: 

First, create a middleware function that examines the incoming request headers, cookies or query parameters, etc., and determines if the user is authorized to access the requested resources. In the event that the user is not authorized, a `401` or `403` status can be returned. 

The route to be secured should be defined using the middleware function. Below, we will illustrate an example of secured routes made with the next-auth package. To install the next-auth authentication package, enter the following in the CLI:

```bash
npm install next-auth
```

With that installed, we can create a secured API route in the `api` directory. First, we will define the authentication option with its provider. Create a folder `auth` and in this folder, add a new file `[…nextauth].js`. This file will contain the options for whatever authentication measure you choose. 

For example, using Google authentication providers, the option will be defined as follows:

```javascript
import NextAuth from 'next-auth';
import GoogleProvider from "next-auth/providers/google";
const authOptions = {
    providers: [
      GoogleProvider({
        clientId: process.env.CLIENT_ID,
        clientSecret: process.env.CLIENT_SECRET,
        authorization: {
          params: {
            prompt: "consent",
            access_type: "offline",
            response_type: "code"
          }
        }
      })
    ],
  // Add your session configuration here
  session: {
    jwt: true,
  }
};
export default NextAuth(authOptions);
```

For the secured route, create a new folder `session` in the `api` directory and add the route to be secured as a `route.js` file. In `session/route.js`, add the following:

```javascript
import { getServerSession } from "next-auth/next";
import authOptions from "../auth/[...nextauth]";
export async function GET(Request) {
  const session = await getServerSession(authOptions);
  if (session) {
    // Signed in
    console.log("Session", JSON.stringify(session, null, 2));
    return new Response("Welcome authenticated user", {
      status: 200,
    });
  } else {
    // Not Signed in
    return new Response("Unauthorized access detected", {
      status: 401,
    });
  }
}
```

Now, attempting to access the `/api/sesssion` route with authentication will display the following result: ![Next.js API Session in the Route Handler](http://blog.logrocket.com/wp-content/uploads/2023/05/next-js-api-session.png) 

Here, the response `"unauthorized access detected"` is returned and the status code is `401`.

## Dynamic and static generated functions in Next.js Router Handlers <a name="dynamic-static-generated-functions-next-js-router-handlers">

In addition to routing functions, Next.js v13.2 also provides features to use server-side dynamic functions such as [cookies](https://blog.logrocket.com/guide-cookies-next-js/), [headers](https://blog.logrocket.com/using-next-js-security-headers/), and [redirects](https://blog.logrocket.com/redirects-next-js/). Dynamic functions are executed on the server side when defined routes are accessed. This is best suited for handling tasks such as data upload or requesting and accessing a database. By defining router handler functions as dynamic, developers can ensure better performance as the function is only executed when the specified route is accessed, thereby preventing unnecessary server-side processing. 

On the other hand, static Route Handlers allow the developer to generate static content for specified routes, which is created at the build-time of the application. This is particularly useful for frequently accessed routes containing content that is not subjected to frequent changes and as such can be pre-rendered ahead of time. 

With static functions, developers can reduce the load on server-side processing for dynamic functions required to generate content for a defined route. Combination and proper use of dynamic and server-side functions make for a high-performance and more efficient Next.js application. With dynamic and static functions explained, let's take a look at examples under both categories: the static Route Handler and dynamic Route Handler.

### Static Route Handler <a name="static-route-handler">

For this example, we will use the [GitHub search user API](https://docs.github.com/en/rest/search). Make the following changes to `route.js` in the `app/api/username` directory:

```javascript
import { NextResponse } from 'next/server';
export async function GET() {
  const res = await fetch(
    "https://api.github.com/search/users?q=richard&per_page=3"
  );
  const data = await res.json();
  return NextResponse.json(data);
}
```

In the code block above, we are performing a `GET` request to the GitHub search API and returning a response containing three users with the name `"richard"`. Navigating to the `username` route will produce results similar to the image below: ![Final Example of the Next.js Route Handler](http://blog.logrocket.com/wp-content/uploads/2023/05/next-js-route-handler-username.png)

### Dynamic Route Handler <a name="dynamic-route-handler">

For dynamic server-side functions, we can use [cookies](https://blog.logrocket.com/guide-cookies-next-js/), [redirects](https://blog.logrocket.com/redirects-next-js/), and [headers](https://blog.logrocket.com/using-next-js-security-headers/). To use redirects, we need to add an `import` for the `redirect` dependency and specify the redirect URL. For example, we can create a redirect URL in the `username` route, as shown below:

```javascript
import { redirect } from "next/navigation";
const name = "John Doe";
export async function GET(Request) {
  redirect(`http://localhost:3000/api/username/${name}`);
}
```

Here, we are redirecting users to the dynamic `[user]` route, and passing along a `name` variable. Redirects can also be used with external URLs to other webpages. With server-side functions, we can also specify route headers. This is particularly useful in cases where you need to specify different headers for different routes, especially if the routes require a different authorization bearer or authentication token, as shown below:

```javascript
// Import for the headers dependency
import { headers } from 'next/headers';
export async function GET(Request) {
  const useHeader = headers(Request);
  const header = useHeader.get('content-type');
  return new Response('We are using the content-type header!', {
    status: 200,
    headers: { 'content-type': header }
  });
}
```

In the code block above, we are using the `headers` function from `next/headers` to get the headers from the incoming `request` object passed to the Route Handler. Then, we use the `GET` method from the Route Handler to extract the value of the `content-type` parameter. Finally, we create a new response with a status of `200`, a message, and set the headers to the value of the `Request` header. One major improvement with Next.js v13.2 to the route headers is that they can now be executed dynamically based on the responses of incoming requests or the data being fetched.

## Conclusion

Congratulations on making it to the end of this guide to Next.js Route Handlers. In this article, we discussed Route Handlers in Next.js v13.2, the features offered by the new version as against older versions, and the Remix routing system. We also demonstrated how you can get started creating API routes in the new Next.js v13.2.

---

## [LogRocket](https://logrocket.com/signup): Full visibility into production Next.js apps

Debugging Next applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try [LogRocket](https://logrocket.com/signup). 

[![LogRocket signup](https://blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png)](https://logrocket.com/signup)

[LogRocket](https://logrocket.com/signup) is like a DVR for web and mobile apps, recording literally everything that happens on your Next app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your Next.js apps — [start monitoring for free](https://logrocket.com/signup).