This course has been updated! We now recommend you take the Introduction to Next.js 13+, v2 course.

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

Scott demonstrates how to create a catch-all route, and refers to it as a glob because it captures all the routes within the same folder. Catch-all routes are useful when a developer has multiple pages with similar if not identical layouts, but have different content and need a unique URL.

Get Unlimited Access Now

Transcript from the "Catch-All Routes" Lesson

>> Again, I just want to emphasize that that ID that I put in a bracket is simply the same name as the file, right? So it's query, which is an object, and it has tons of properties on it. That will match the file name. And I say tons because you can actually have more than one parameter in there in one file.

[00:00:18] And that might not make sense because you might be thinking like, whoa, I can't have two parameters in one path. I can't have something like, something like this where you had a route that was like slash, user slash and then you had like some parameter here called ID.

[00:00:35] But then you had another parameter here. That was like, thing. Yeah, you can't do that. There's not gonna be two parameters in there. So when would you ever have two parameters? Inside of a query object for one page, yeah, I mean, technically that's not possible. But next js gives you something called catch all routes, which kind of make that virtually possible, which is really interesting.

[00:00:56] And I think it's a very nifty feature that I take advantage of all the time whenever I can. But basically catch our routes are exactly what they sound like. They basically are like a glob pattern you can say, versus if you're writing a git ignore and you're like, I just want a git ignore everything after this folder and you put two stars, right?

[00:01:14] So it'll capture everything after that path. You do the same thing with the router, you can say I want to go to this path. And I want to capture everything after here. And it's really amazing. And in my opinion, it's kind of lazy because yeah, you can just make a page for every single possible parameter that you'll ever have inside your pages directory.

[00:01:35] But why would you do that, you should just be lazy because lazy developers are good developers, remember that? So, that's basically what we're gonna do. So what is the syntax look like for a catch all route, it kind of looks like this. So you just make a file with the same brackets, except for you put this ellipses in front of a parameter, that ellipses has got itself next js that you want to catch everything after docs, it's gonna capture everything there.

[00:02:03] And then we're able to use it inside of our params. So let's go back, and let's just make a new page just for the fun of it. I'm gonna make a new one here. Or maybe not in those, I'll just refactor the id one to do it, just for fun.

[00:02:18] So I'm gonna make this one but dot, dot, dot. And again, you don't have to put params here. Input whatever you want. It doesn't matter, but I think params makes sense. And you'll see why in a minute. So I'm gonna put params here. This ID is no longer gonna be ID because I don't have ID here.

[00:02:34] It's now params. So that's not gonna work. So I need to change this too. You guessed it param. Not that params. So this matches with this. So the only difference is whereas before Id was, the value of that Id, params is gonna be an array. It's gonna be an array of all the matching params that match in order that you route it to.

[00:02:59] So for instance, if I had a route that looked like this, in this case, it was /notes/1/2/3/4, oops, that's a comma. /2/3/4, params is gonna be an array of 1, 2, 3, 4, right? In that order, that's what params is gonna be. So, let's actually just log this out so you can see what I'm talking about params and we can even just, yeah, I'll just do that.

[00:03:27] Do that and then we'll log those params and then we will route to it. So right now, this still renders right, everything still works. Obviously this isn't gonna show because I got rid of it, but if we open up the DOM and we look at this all here.

[00:03:43] You can see, I have one thing inside of it and that's the first ID. So let's do something a little more human readable. So I'll put one here. Boom, and then I'll put slash and I'll put two, boom, there's two that I'll put three, right? And it just goes on forever.

[00:03:58] We can capture all those parameters. In an array, which is extremely useful, and it's not something we'd normally done in most applications, in fact, you might be thinking like, well, when the hell would I ever use this? Like, when would I ever use a scenario where I want to use the same component for many different pages, right?

[00:04:19] So you might not even be thinking about a use case where it was actually never, at least in my opinion, I've never seen or had the need to do something like that. And it wasn't until I saw this feature that I realized that like, wow, it actually can be applied to a lot of things that I've done in the past that would have made it a lot easier.

[00:04:33] And we'll talk about some of those things. It's really cool to do the catch-all routes. They're really impressive, one extra feature on top of that is what they call the optional catch all routes. And basically what that does is when an optional catch or in a catch all is that the optional catch was also like inclusive.

[00:04:51] So it will also include the parent path inside of it. And the way you do that is you just add another bracket around your brackets there. So not only will this match all the frames that we did above, but it will also match ducks. Basically that's what you get and the value of that parent paths will just be an empty object because it doesn't have any params.

[00:05:14] There's nothing there. So just be an empty object in place. For that path there. So again, just extremely powerful. The other syntax looks kind of weird. If someone came and looked at your file system, they're like, why are you naming your files that way? Yeah, they might think you were weird, but this works very well.

[00:05:33] I haven't used the catch-all. I'm sorry, the optional catch all in production yet, but I use the catch all one all the time, consistently all the time. And specifically for some of the things that I use it for is basically useful for whenever you have a bunch of pages that have pretty much the exact same layout or very close to the same layout.

[00:05:56] But they need their own URL. So if you think about it in that case, what is something that pretty much has the exact same layout? They have, but they have different URLs, documentation. Documentation is a big one. Like if you go to any documentation website, the layouts always the same.

[00:06:09] I don't care, I don't care what thing you click on the left, but the layouts always the same. The styling is always the same. Is only the content is different. And they all have their own URL, for SEO searchable reasons. So documentation is perfect for this. So instead of generating a page for every single documentation page that you want, you can make one route that does a catch all and says, yeah, I want to catch all these documentation stuff.

[00:06:32] And yeah, that's basically and then you can do whatever you want with those perhaps which is really impressive. So you get to save some time versus a smart developer would know, generate all those pages, but then they will go make like a template, or layout, they will reuse that layout on every single page, and that way, they're not writing the same thing over, and over again.

[00:06:50] This is taken to the next level, you don't even need the layout, you don't even need a template, you make a one page, and you don't have to generate the rest, which can also save you time. When you generate these pages, when we get the static generation and stuff like that, so really, really good ability, really good feature here.

[00:07:07] Cool, so the last thing I want to talk about is like, okay, we talked about pages. That's cool, but what about like non pages? I mean, this is a component based framework. So how do I create components that aren't pages. Because what if I was gonna put a button but if I put a button inside of pages, it's gonna make a route called button and I don't want to do that.

[00:07:26] Okay, yeah, good point. So, what there's no convention inside of next js, that tells you how to create your pawns aware, but the community mostly just creates a source folder. Not in there though. Creates a source folder on the root. And normally we just create a folder called components, just like you would do in any old react app.

[00:07:48] And that's where we put our components. You just put your components in there, right? The other thing to note is that if for some reason, this bothers you about having the pages directory. On the root, which I can see why it would, especially now that we have a source folder.

[00:08:03] Okay, I want everything in source if that's the source. I don't want pages on the root, if we have a source. That's kinda gross. You can move the pages into the source, and that will work as well. But if you have both, next js will the pages on the root.

[00:08:17] That will take precedence. So if it's really bothering you, you can move the pages into the source and it works just fine, just don't put both. So just remember that. And again, if you didn't feel like following along, if I was moving too fast, you can check out on the repo to this branch.

[00:08:35] We just copy and paste that and you should check out to exactly where we just ended. Now the code that you'll check out to exactly be all this code that's in here. So all this code is copy and paste tables, everything you see here comes directly from the repo.

[00:08:49] So it'll be the same thing that you see here. And it'll probably be slightly different than what I just live coded right here. So, this is the source of truth.