ExpressJS like API in NextJS
Tags: nextjs, webdev, api, typescript
Published: 2022-10-26 06:00:00

Have you ever wanted an ExpressJS like API structure in your NextJS app? A good structure and easy to extend.

Let me give you **three examples** with having an easier API with the NPM package called [next-connect](https://npmjs.com/package/next-connect).

**FYI: This is not the whole code, it's just the core of the functionality I wanted to present you.**

- [✅ Advantages](#middleware)
- [🚏 Route](#route)
- [🚪 Middleware](#middleware)
- [🛑 Error handling](#error-handling)

## ✅ Advantages
Here are quickly **five advantages** of using _next-connect_.

- **Clean and nice structure**
- **Fast and scalable**
- **Easy to implement**
- **TypeScript support**
- **Lightweight**

## 🚏 Route
Create a POST endpoint for /user.

**NextJS:**
```ts
// api/user.ts
export default function handler(req: NextRequest, res: NextResponse) {
  if (req.method === 'POST') {
    res.status(200).send('Worked!)
  }
}

```

**Next-Connect:**
```ts
// api/user.ts
const handler = createRouter<NextApiRequest, NextApiResponse>();

// Process a POST request
handler.post(middleware, async (req: NextRequest, res: NextResponse) => {
  return res.status(200).send('Worked!)
});
```

Now let's imagine you have an endpoint for GET, POST, PATCH, PUT and DELETE method. Your handler will be full of if else statements and not very clean.

## 🚪 Middleware
Let's create a middleware for two routes.

**NextJS:**
```ts
// middleware.ts
export function middleware(request: NextRequest) {
  if (request.nextUrl.pathname.startsWith('/about')) {
    console.log('Middleware fro /about');
  }

  if (request.nextUrl.pathname.startsWith('/dashboard')) {
    console.log('Middleware fro /dashboard')
  }
}

// api/about.ts
export default function handler(req: NextRequest, res: NextResponse) {
  if (req.method === 'POST') {
    // Process a POST request
  } else {
    // Handle any other HTTP method
  }
}

```

**Next-Connect:**
```ts
// middleware.ts
const middleware = () =>
  router.use(async function (req: NextApiRequest, res: NextApiResponse, next: NextHandler) {
    console.log('Middleware ran! 🚀');

    next();
  }


// api/index.ts
const handler = createRouter<NextApiRequest, NextApiResponse>();

// Process a POST request
handler.post(middleware, async (req: NextRequest, res: NextResponse) => {
  return res.status(200).send('Worked!)
});
```

It doesn't look that _next-connect_ would be better, smaller or easier BUT think about having an API with dozens of endpoints and multiple middlewares. With _next-connect_ it's much more clear and structured.

## 🛑 Error handling
The error handling of both parties is very interesting, let's look into it.

**NextJS**
```ts
export default async function handler(req: NextRequest, res: NextResponse) {
	try {
		// Do some API request or something
		res.status(200).json(response.data);
	} catch (error) {
		// Send error to the client side
	}
}
```

**Next-Connect:**
```ts
export default router.handler({
  onNoMatch(req, res) {
    return res.status(404).send('404 Not found');
  },
  onError(err, req, res) {
    return res.status(500).json({
      error: (err as Error).message,
    });
  },
});
```

_Next-Connect_ has a way easier and secure way of handling errors in your application. It's even pretty customizable and nice to use.

**Thanks for reading!**
It was a quick and very superficial overview about _next-connect_ for _NextJS_. I absolutely like it and I hope I could give you a good overview about it.

<a href="https://www.buymeacoffee.com/jannisdev" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-blue.png" alt="Support me" height="20" width="80"></a>