Now let's go ahead and let's prepare our authentication routes and our protected routes. So I'm going to be using a concept inside of Next.js calling route groups. So let's go ahead over the basics of routing. Let's say I want to create a new client route called test. I would first create a folder inside of the app folder and inside I would create a page.dsx.
What's missing for this to become a route is a default export. So something like this. And I'm gonna call this test page. I'm gonna return a div calling text page. Like that.
So what's crucial here is that you do a default export. If you just do an export const, this is not going to register as a route. So it's very important that whenever you have a page.dsx somewhere you do an export default. So let's try that out on localhost 3000 make sure you have your app running go to slash test and you should see the test page. So now you know that the folder name will take part of the URL but what if you don't want your folder to be a part of the URL.
You can do that by using a route group. Something like this. Let's call this out inside of parentheses and then inside of here, let's create a sign in route and let's go ahead and create a page.tsx inside. Once again, I'm gonna do a sign in page, default export, div sign in page. And how do you think I'm about to access this route?
I just told you that one way to not have your folder name inside of the URL is by putting it inside of parentheses. So what you can do is instead of going to localhost 3000 slash ALT slash sign in this is a 404 page instead ALF doesn't exist in the URL so it is just a slash sign in so that was a quick explanation of route groups if you created the test route you can now remove it but go ahead and create your own well, route group for our pages so we're gonna create this sign in we can copy this and let's create a sign up page and let's go ahead and change this one to be a sign up page and let's rename this to sign up now you should have a localhost 3000 slash sign in and slash sign up there we go also the default export name of the function does not matter. So this can be called x and it's not going to change anything at all. Right. All that matters is that you do a default export.
Great. One more thing that we're going to do before we add our authentication library is we are going to create a catch-all route. So usually if I wanted to create a route which can accept a parameter like a user ID I would create a folder inside of parentheses user ID and then I would access that inside of my component. But what if I don't know what I'm going to receive? I simply want to catch every single parameter, every single query, whatever is possible in this route.
That's called a catch-all route. You can read more about that in Next.js documentation. So what we're gonna do here is create this double square parenthesis and then I'm going to spread sign in. And very simply I'm going to drag and drop this page inside. That's going to open this weird unsaved page.ts file.
So this is, as you can see, it triggered a .next change. Don't worry about this. Here are the steps to resolve this if this happened to you. First of all, immediately close this .next folder. I see a lot of people accidentally continue to develop inside of here.
This is not your repository. This is cache. So simply close this folder. If this page has opened for you just click save so you no longer have that circle here. And then you can just close it.
If for any reason you think you've done something wrong, don't worry at all. Here are the next steps you can do. Go ahead inside of your terminal here and shut down your app. Then go ahead and remove the .next folder entirely. Then simply go ahead inside of the terminal and run your app again.
Remember, I'm using bun, so I'm doing bun run dev. If you're using node, it's going to be npm run dev. And the moment you run this, you're going to see the .next folder being reinitialized. So you don't have to worry if you mess something up inside. Make sure you refresh your localhost every time you shut down and restart your server.
Now let's go back inside of the app folder out. Inside of here, we started working on this catch all route. So what I've done is I've moved the page.tsx from not just being inside of the sign in folder, but inside of the catch all route here. So what has changed? Absolutely nothing.
This is still on localhost 3000 slash sign up but now this is going to give our auth provider the ability to catch every parameter, every callback URL and everything else it needs to properly handle redirects from this authentication page. Now I want to do the very same thing but for sign up. So go ahead and simply spread sign up here. And again drag and drop this inside and repeat the steps. Go ahead and immediately close the .next folder.
Go ahead and enter this unsaved file and just Save it and close it. Make sure you are not developing inside of the .next folder. And again, if you think you've messed it up, remove the next folder and restart your app. Great! Now you should have the sign-in and the sign-up pages ready to be used.
And now I want to go ahead and I want to create another route group called dashboard. So the reason I'm using route groups is only so I can organize my files in a better way. So I could have created the sign in and sign up purely inside of the app folder but I like my files organized and this is very useful because then inside of this out folder I can also create a components folder if that's something I want so I can co-locate items here. Great! So I'm gonna remove this empty folder.
Make sure you didn't accidentally remove this components. We need that. Great! So inside of this dashboard what I want to do is I want to make this my root page. So I want this, what's on localhost 3000, this button.
I can do this very easily. Since dashboard is inside of parentheses, it means that it will not be a part of the URL. So I can just drag and drop the page.vsx inside. And then again close the .next folder. Go ahead and save this cache file and close it and don't open .next again.
If you accidentally messed it up you can remove the folder and just restart your server. And nothing should change now. So inside of your dashboard page.esx you should still have this button and when I refresh everything is still working fine. I'm now gonna remove this button and instead I'm going to render a paragraph which will say this is an authenticated route. So only logged in users should be able to see this, this authenticated route.
So we have an issue. We are not logged in but we are able to see this route. That's not something I want. When user tries to access the dashboard, the root page, I want them to be redirected to either sign in or sign up. So let's go ahead and install Clerk inside of our project.
So head to clerk.com, create an account and find a way to create a new application. If you already have a couple of projects you're gonna see a screen similar to this. If it is your first time you're gonna be redirected to a screen like this. So I'm gonna call this finance and go ahead and select any amount of providers you want. You can even select some of that three options here.
I'm gonna keep it simple with Google and email login. In fact, I'm just gonna keep Google or basically whatever you want. Go ahead and create your application and then we're gonna follow the steps to add this inside of Next.js So in here, let's go ahead and install Clerk Next.js I'm gonna be using bun, so I'm gonna be using bun add instead of npm install you can use npm or yarn or pnpm, it really does not matter so let's go ahead inside of the terminal here I will shut down the app for now and I'm gonna do bun add clerk nextjs or you can do npm install clerk nextjs. And while this is installing let's see our next step. So our next step is to set your environment variables.
So inside of dot environment dot local we need next public clerk publishable key and clerk secret key. I'm gonna go ahead and copy both of those. I'm gonna go inside of my project. Let's see if we already have a .environment file. Looks like we don't.
So let's create one. In the root of our application create .environment.local. Here's what's important. Whenever you're working with environment files, make sure that they are inside of gitignore. So inside of here you can see that I have .environment.local which means that this file will not be committed to GitHub.
Do not commit to GitHub if you haven't put that inside of your gitignore. You can also directly write .environment.local. You don't need to know these wildcards at all. So let me go ahead and do something. I'm gonna press command shift p or ctrl shift p on Windows and I will reload the window.
The reason I'm doing this is because I want to show you that this .environment.local has a bit of a darker or a grayed out color as opposed to for example public folder or the file below that. Same as node modules. So this is a visual cue for you to confirm that this file is not going to be committed and that will tell you that it's safe to put these two environment variables inside. So let's just repeat where I got those right here in step 2, set your environment variables. I copied the two of those and I've simply pasted them inside of our newly created .environment.logon file.
Let's see what our next steps are. So we are using the app router and we have app folder and layout.tsx So it's asking us to add clerk provider to our app. I'm gonna copy the top line here. Let's go inside of app folder, layout and in here I'm gonna go ahead and add that here. And then I'm gonna wrap my entire project inside of that.
There we go. But we are not done yet. One crucial thing we are missing is middleware. So what we can do is we can copy the entire middleware from here and let's create a root file middleware.ts. Make sure you don't misspell this file as middleware is a reserved keyword in Next.js.
Let's paste that in here and let's go ahead and try and run our app. Actually before we do that let's just see. Okay, they tell us to run our app. So I think it should be good enough for us to try this out. So inside of terminal, bun run dev or npm, let's visit our local host and let's see what's going on.
There we go. So this is still telling us that this is an authenticated route. So we can still visit this, right? So let's learn how we can protect this route. So a big change has happened in Qlerq since my last tutorial.
Usually the Qlerq middleware by default protected all routes. That is no longer the case. From now on we decide which routes are protected, which means that all routes are public by default. So how about we explore the documentation here, the guide. So while we are here we can already do this.
We can build our sign up and our sign in page because we have this exact structure already set up. Let's take a look at it here. So I'm gonna collapse this and let me expand my file browser here. In the app folder we already have sign in and sign up. Let's go inside of this catch all page.psx and let's go ahead and copy this.
And I'm copying sign up so it's a better idea to go inside of sign up, right? So we can literally select everything and paste it here. And make sure the path aligns. So slash sign up. Slash sign up.
Let's save this and now let's do the same thing for sign in so step two I'm copying it and going inside of here replacing everything slash sign in So this is the correct route because remember the out is a route group and this is a catch all so none of this will interfere with the fact that the only route we have is sign in and sign up. Great! And now let's go ahead and update our environment variables. So they need to match as well. Let's go inside of .environment.local and let's add next public clerk sign in is slash sign in and sign up is slash sign up.
Perfect. And now what I want to do is I want to learn how to protect our routes. So as it says right here, we should now be able to manually visit our routes. So localhost 3000, there we go. We have our sign in route here.
And if I go to localhost 3000 slash sign up, there we go. We have the sign up route here. So both of this seem to be working just fine. But we still have this issue. Why can we visit localhost 3000?
So inside of this guide I'm gonna go ahead and I'm gonna look at clerk middleware here. And inside of here we should get a quick guide on how to protect our routes. So this is our current case if I'm not mistaken. So if I go to my middleware there we go. So just an empty clerk middleware with a matcher which catches pretty much everything except the static assets.
So let's go ahead and do this. Let's create the isProtectedRoute using the createRouteMatcher. So I'm gonna go ahead and paste that here and we can import the createRouteMatcher from clerk next.js server. So let's just add this. There we go.
But we don't have slash dashboard. Instead all we have is a slash route. And make sure that you remove this wild card asterisk here. Because what this represents is dashboard and everything after dashboard. So in our case it would be slash and everything after slash.
But that's not true. Because we there are some routes which we want to be, well, not public but not specifically protected by the next JS middleware. And also remove this. So for now just add this. But we're not done yet.
So this just created a constant. What we have to do now is we actually have to create a logic which is going to, well, work on protecting the routes. So this is what I recommend that you do. Go ahead and open this method. In here, in the parameters, you have access to out and request.
Let's also prepare by adding an import of next response from next server. And if is protected route, the current request. In that case let's call the out.protect. Otherwise let's return nextResponse.next. So just like any other middleware if you've ever used Express or Node.js before it's gonna return next meaning it's gonna go further.
There we go. So now if we've implemented this correctly and if I try and go on localhost 3000 there we go. I am now redirected. And you can see how now I have this redirect URL parameters right here. So all of that will now work flawlessly because we made sure that we added these catch-all routes.
If you don't use these catch-all routes, I think Qlrk is actually going to throw you some errors. So I didn't come up with the idea of these catch-all routes, right? I simply knew it because I already went over clerk documentation. So that's where I found out those guides. Great!
What I want to do now is I want to make our pages just a bit prettier, right? So let's go inside of signinpage.tsx and let's go ahead and wrap this up like this so we have more space to work with. Let's open up a div here and inside of here I want to give this a class name of min-h-screen so it takes up the full height and I want to work with grids so I'm going to initialize a grid calls one and now this doesn't make too much sense right why am I initializing a grid if I'm only going to have one column That's because I'm working on a mobile first design. So on mobiles it's going to have one column. But the moment we hit a large breakpoint it's going to be grid calls too.
And now let's go ahead and open up another div. Wrapping up our sign in here. And inside of here I want to give this a class name of full height. On the large devices we're gonna work with flex. We're gonna have a flex column, items center and justify center and px is going to be 4.
Like this. And then inside of that div let's create another one with a class name of text center space y4 and padding top of 16. Let's create a heading element here which says welcome back. Let's give this h1 element a class name of font-bold, text-3-excel and let's go ahead and give this a text-muted foreground. Or perhaps how about a specific hex color 2e2a47.
There we go, that looks better. And now below that I'm going to open up a paragraph, so like this. And I'm going to say login or create account to get back to your dashboard. Now let's give this a class name of text base and let's give it a text again a specific hex color of 7E8CA0. There we go.
And now Let's go ahead and open up a div here. We're just gonna wrap our sign-in element inside. Let's give it a class name. FlexItemCenter, justifyCenter and marginTopOf8. There we go.
So it's nicely moved and centered now. And what I want to do now is I want to add a little loader here. And let's expand just so you can see how it looks like. So this is how it's going to look on desktop, right? So our login is going to be on the left side and in here we're going to have the logo of our application.
But on mobile, it's just going to collapse to the middle here and on tablets as well. So what I want to do now is I want to make sure that when I refresh you can see how there's this blink right where this element doesn't exist. So we can take care of that by leveraging couple of things from Clerk Next.js called clerkLoaded and clerkLoading. And let's also import loader2 from Lucid React. If you're wondering where we got this package from, it's from chat-cn-ui.
So the moment we run chat-cn-ui latest initialize and then it offered us two styles default and New York. If you chose default as I told you to do in the tutorial, you're gonna have Lucida React inside of your package. So if you go ahead here, there we go. You're gonna have Lucida React. If you chose a New York style, you're gonna have radix icons.
Whatever you have you can manually add this one if you want. So make sure you just add some kind of loader icon and then let's go ahead and do the following. I'm gonna wrap this inside of clerk loaded. So this will only show when Clerk has finally loaded. And below that we're gonna add a Clerk loading.
And inside of here I'm gonna render that loader2 element. And let's give it a class name of animate spin and text muted foreground so now when I refresh there we go we have a nice loader right here perfect and now what I want to do is I want to go just by the end of this div right here. So let's go to our top div. As you can see in here, let me try and expand this so it's as clear as possible. So our top div initializes a grid, which means that this is the first column.
So in order to take care of the second column, this is where we do that. So I'm going to go ahead and give this a class name of HypeFullBGBlue600 and then by mobile first, it's going to be hidden on mobile but on the large it's gonna become a flex component and Then we're going to Center all the items inside and also just if I center all the items inside as well. So let's take a look. If I expand now, there we go. You can see how this is now blue.
But if I go to mobile, it's just a single view. What we have to do now is add the logo of our application. So we add assets inside of the public folder here. You can use any logo you want. I'm gonna be using the logo Ipsum right here.
So I already have this but let me download the SVG again, drag and drop it inside of the public folder right here. I'm gonna go ahead and rename this to logo.svg and since this is an SVG file, we can easily find colors like this and change them to be white. There we go. So these two instances, you don't have to do this, right? Or you can use any logo you want let's head back inside of our app out so whatever file you did this to It doesn't matter if you did it in sign up or sign in because we're gonna copy and paste either way.
So I started working here right I added bg blue and let me just restart my window because it looks like my tailwind extension stopped working. There we go. Yeah about that Tailwind extension. So if you're wondering how I have this useful little snippet here and how come when I hover I get this or how come when I type I get out the completion here. That is all thanks to the Tailwind CSS extension library.
There we go. So just make sure you have this installed if you're working with Tailwind. It's extremely useful. Now, let's go ahead and let's import image from next image. It's actually default like this.
There we go. So in here let's add an image and let's give it a source of slash logo.svg or whatever you put inside of your public folder. So I put logo.svg so that's what I have. And let's give it a height of 100 and a width of 100. And an alt of logo.
And let's try it out. There we go. What I want to do now is I want to copy and paste this entire thing and I want to add it to the other signup page. So let's quickly do that. I will select everything and paste and I'm simply gonna change this to import signup from clerknext.js and add signup here.
Make sure you also fix the path so this is inside of the signup folder. Signup. Let's try it out now. If I click on sign up here, there we go. So both of my routes are now working.
Let's try this one more time. If I go to localhost 3000, I am immediately redirected here. Now let's try logging in. And there we go. We are redirected back here which says this is an authenticated route.
If you want to log out here's a quick way you can do that. Go inside of your app, inside of dashboard, page.tsx and go ahead and import the user button from clerk nextjs and in here just render the user button. And let's add the after sign out URL to go back to the root page. Make sure you add this and refresh your page. I'm going to zoom in and now you're going to have an icon of the currently logged in user.
Perfect. So in here you can manage your account and you can see some stuff here or you can just sign out and there we go we are back to the root page. Perfect! You just implemented signing in with Qlerk and in here you should actually be able to see your first users and then you can manage the users, you can ban them, impersonate them and do a bunch of other things. Perfect!
So in here you also have this labor secured by clerk. If for any reason you don't want to see that, you can go inside of customization, branding and you can turn it off there we go so now if I refresh there we go no more clerk instances perfect you now have a fully working authentication What we're gonna do next is we're gonna learn how to write API routes inside of next.js and we're gonna incorporate Hono as an alternative way to write API routes And I think you're gonna like why we are gonna be doing that. Great, great job.