Check out a free preview of the full Introduction to Next.js 13+, v2 course:
The "Creating API Routes" Lesson is part of the full, Introduction to Next.js 13+, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Scott walks through creating API routes with Next.js and discusses how this handles middleware. Student questions regarding versioning the API and how the API would handle websockets are also covered in this segment.

Get Unlimited Access Now

Transcript from the "Creating API Routes" Lesson

>> Let's walk through how a Next.js can make APIs and how simple it is. So if you're following along with me, you know that we have this hello.ts that was generated from create-next-app. Let's look at this, let's see what's going on here and we can see how we can create our own APIs.

[00:00:13] So if we look at this, it's actually quite simple. All you have to do is export a function, that function takes in a request and it has a response. And then because it's server side, you can do whatever you want. You can access the file system. You can do literally whatever you want on the server and just send a response back.

[00:00:30] Just like if you wrote an Express app, just like any app, I mean, Python, it doesn't matter, they all do the same. They take a request, they use a response, and they send it back. This is the same thing, it's just broken down so simple that it's just a function, right?

[00:00:42] So if you want to make some API routes, it actually follows the same convention as the naming conventions for the app side here. So for instance, if I wanna make an API route for, let's say, /api/user/me, so I would go into the API folder, I'll make a new folder called user, and then I'll make a file called me, and that's gonna create a route for /api/user/me, right?

[00:01:14] And then inside of here, I can do whatever I want as long as I export this function. And it has a request and it takes a response and I just gotta send something back. There's nothing to stop me from doing whatever I want here. So I'm just gonna say, res.json {data}, this is me, hello, I could that.

[00:01:40] This thing's freaking out cuz it doesn't know the types, but we're good, right? So now I can go to the browser, I go to /api, /user, /me, and let's see what happens. So let me grab that /api/user/me, and there it is, It's me, and that's how quick it was to make an API route, fairly simple.

[00:02:12] That's it, you don't have to worry about setting up all the ceremony you do with any other server, you just make a function and you export it. And when you deploy this, this is gonna be a Serverless function. So some things you might be thinking of is, but what about my middleware?

[00:02:26] Where do I do that? Well, there's so many ways to get around that. In fact, there's Express plugins that will make this look like Express, and you can still use the Express middleware if you want, if you wanna go all the way. But most of the time that I've seen is like you just make a file somewhere that takes a request or response and it manipulates it that way.

[00:02:45] Or they'll make a higher order function that wraps this and it'll do it that way. There's a lot of ways around it. For instance, you might make something with authentication, you might say withAuth, right? And withAuth is a function that returns a function that takes a request and a response and then it just checks the Auth somewhere in here, right?

[00:03:10] So you might do something like, actually it'll be like this. It'll be like this. So you have this, but then inside here is where you'll check your Auth, right? So you'll check your Auth in here. And then if the Auth is bad or whatever, then you'll come in here and like, the Auth is bad, so we're gonna do a 401 or something like that and just reject it.

[00:03:36] And then all you have to do is just, when you export this, you can wrap this with a withAuth, right? You can say withAuth, and then you would just wrap it like that, something like that. And that's a higher order function that I see people make. So that's one way.

[00:03:49] I don't like higher order functions, because I think they're sloppy. I would just rather just make a function that just looks at the request of the response and do it that way. You can also use middleware, which we probably won't cover too much in here cuz it's kinda advanced, but middleware can intercept any route in Next.js, not just a page.

[00:04:06] It can intercept API route, it can intercept a public file, static, or anything, anything that's ever requested for your Next.js app, it can intercept, and you can check things there. The thing about middleware, though, is that it runs on the Edge Runtime. So if you visualize the runtimes, you have the client, right, that's the browser.

[00:04:26] And then over here, you have the server, right? And then over here, there's a database. The Edge Runtime is right in front of the server in between the client, it's the CDN that's closest to you. That's the Edge Runtime, that's why it's called the edge. It's literally on the edge of the network, which is the closest CDN to you, so you only have access to certain things on that runtime, and there's limitations of the type of code you can write.

[00:04:51] So in order to do that with authentication, you would need something like cookie-based authentication, cuz you can actually check a cookie in that edge runtime. But you won't be able to check local storage cuz you're not on the browser, or else you got to think about how your authentication works and things like that.

[00:05:05] And you also can't use most node modules on that at runtime, because there's limitations on how Edge Runtime works. Because they can only be so big in a file size that they can't use the standard Node.js runtime that we've come to love. They use a modified version that can only use static code and that dynamic code is kinda weird, but there's tons of articles about it.

[00:05:30] So it's a little weird, that's why I didn't wanna talk about middleware cuz it gets crazy. But that's what people will use it for.
>> What would be the best way to version your API?
>> Best way to version your API, I don't know if there is a best way.

[00:05:43] I mean, the way you make your API doesn't really change how people have come to do things like versioning. So I mean, you could just do the same thing you've probably always done, make a new folder here, v2, bam, now you got it, so /api/v2/your routes. You could totally do that, there's nothing stopping you.

[00:06:04] I don't think there's a perfect way or a wrong way to do it. Just note that we didn't specify a method, right? Cuz if you think about an API route, it's a route and it's a method, it's a verb combination. We didn't specify any verbs here, so is this a GET request or is it a POST request, what is it?

[00:06:22] You have to do that yourself, right? So you have to come in like, if req.method, equals POST, then it's a POST request and you can do your stuff, otherwise, do whatever you want here. You have to do that part yourself, because by default, it's gonna respond to any request to this URL.

[00:06:41] It doesn't matter if it's a post, put, delete, option, get, doesn't matter, it's gonna respond to it. So do those checks if you don't want those potential verbs messing your stuff up. Yeah, APIs are easy, it's a quick section cuz it just makes sense. Yes.
>> This might be a bit out of the scope for this, but I'm just kinda curious.

[00:07:08] You mentioned that the API runs like on a Serverless kinda backend, how would it handle kind of maybe WebSockets, like real time connections?
>> Yeah, so let's talk about this. This personally hurts [LAUGH] because I adopted Serverless functions when first announced them, when I was running a startup.

[00:07:32] And we were just way too early and we needed what's now a service database, so we needed WebSockets and nothing existed. So we had to build a lot of it from scratch, so I learned a lot. So traditionally, up until just recently, you couldn't attach something like a WebSocket or anything like that to a service function because it's not long lived.

[00:07:53] You would typically have to do a proxy almost. You would have to use some third party provider, like a very popular one that I think is called Fanout WebSocket, something like that. Yeah, something like Fanout. So something like Fanout or PubNub or even Firebase, or Pusher, one of those.

[00:08:13] You have to use a third party cuz that's Serverless, because it's hosted somewhere else and you only talk to it over an API. So anything that's basically API driven, that's what you'd have to use. That way your client's not connecting directly to your backend, is connecting to this thing, and then this thing is notifying and triggering your backend.

[00:08:31] So there's an extra step involved. And for the most part, that's still the case. I have seen recently people trying to get Socket.IO to work with service functions and stuff like that, but I wouldn't wanna scale that. So yeah, I think traditional things like that just don't work very well without compromise or without a dedicated team who is really serious about figuring out all the constraints of a familial environment such as Serverless.

[00:09:01] It's very complicated, but definitely doable, but for the most part, you're gonna need a proxy, whether you build it yourself. So you might have to make an express server over here that hosts your own WebSocket instance, and your frontend connects to that, and then that thing talks to your Serverless thing, right, or you just get one of these things.