 everyone in today's video will be looking at protected routes and for the record I'll be using Firebase Auth. Realistically you could use any authentication provider like SuperBase, PocketBase it should all just work the same because the code is just agnostic to the platform that you're using and I will be using the app router well technically I'm using Next14 but it doesn't really matter because Next14 is really new but there's no new API changes so you do everything the same way as with Next13 and so doing a quick rundown of what the problem looks like. So right now I have my page here I have two routes secret one secret two if I click on secret one you see it brings us to slash protected slash secret one and the problem is right now we're not logged in so if I log in like that and now I'm logged in you can you can see that I have access to secret one and secret two pages but if I log out I'd still be able to see these pages and that's not good because I want all of my pages my routes after slash protected to not be visible until the user is logged in and so to do that I have written a custom use user hook that looks like this so the main the core component the core part of this hook is this onauth state changed event listener I'm calling this I'm subscribing to this event listener and I'm returning the handle to use effect hook so that this only ever runs once whenever this hook is mounted I don't want to be subscribing to multiple event listeners in one run so that's why it's in use effect and this is coming from Firebase so if I go up to my imports here you can see onauth state change is imported from Firebase slash auth and I'm providing the auth handler to this hook here and then there's a callback function that runs every time our authentication state changes so every time we make a change like if we log in or if we log out then this callback function would run and we would set our user's state variable to be the value of that user passed into this callback function really really simple so and in our layout function component layout component here in our protected route we have subscribed to this hook in our component and we have access to this user object and if we're logged out it just the user object is just null and if we're logged in then we'd have a user object so to do that to make use of that I have an if statement here that says instead of just blindly returning the children which is the nested routes every single time we only return the nested routes whenever the user is not null because if the user is null then we want to return an auth guard component that component looks like this it's just a div that says you have found a secret place please log in to continue the login is a link to the login route which is a constant defined in this routes document and then I am using the use path name hook from next slash navigation this gives gives us a current path name so that tells us what what's the path name we're currently at so now I've implemented that if I go to secret two you can say you can see it says you're trying to access slash protected slash secret two and it tells us to log in we go click on login and then we log in and now we can actually access the secret two page okay so now if I click on log out it hides that page and the page is hidden by the auth guard component telling us to log in before we can continue that's really good and that works and that's perfect now say for example I was I'm I'm not logged into that website but someone a friend sent me a location on discord for example or in an email telling me to go the secret two route and I'm not logged in so I click on the link to follow the link in my browser I get to this page tell me to log in and so I do I log into my credentials and whoops we're on secret one now we ended up on secret one when I was initially trying to access the secret two page so that's a problem and I'm going to solve that problem by going over to my auth guard component here seeing that we already have access to the path name inside of this component instead of just plainly returning uh plainly linking the user to the login route using our link component here in the next js I'm going to use a format string I'm going to append a search string or a url parameter here we can name it any arbitrary name for for this case I'm just going to say continue to equals to the path name so what this does is if I come I came back here click on log out we go secret two or let's just go with secret one for for now for this one time we right click on login copy link address and now when I paste this address you can see that it's actually going to redirect us to the login page but not but we don't stop there we have an additional parameter there in the url that tells us to continue to the secret one route after we're done with the login process same goes for secret two click on copy link address it tells us to continue to instead of continuing to secret one this time we're continuing to secret two and I can click on login now still doesn't do anything because we have to right now we're only sending out the information from the auth guard component we have to also receive that information from our login page here now I know that there's a lot of new code here that you haven't seen prior to this point but don't get intimidated just yet because most of the code is just basic html this is an html form for the username and password and I'm subscribing to this use router hook which is important from nyx slash navigation remember if you're getting weird errors when you're using use router hook make sure you're importing that from nyx slash navigation and not from nyx slash router because that's what it used to be from before nyx 13 and that's what github copilot was trained to do because majority of the training data that github copilot uses is from before nyx 13 so I had problems where github copilot was trying to automatically import this from nyx slash router it was just giving me a bunch of errors and that's probably why you're getting your errors too if you are indeed getting them so down here I have a constant which is continue2 it points to secret1 route and that's coming from my constant defined this file here slash protect slash secret1 that's the default route that I set my router to redirect to after the sign in is successful so this is my sign in function call and after that's successfully ran I will just redirect the user to this continue2 link instead of just hard coding this to be secret1 route we can use to use searchparams hook from nyx slash navigation I just say use searchparams I don't know why github copilot is trying to do this because you don't need this array you just need to set it to a variable here like that yeah github copilot is still kind of wonky in terms of nyx 13 and onwards because this is still a relatively new API I guess and then here instead of just setting this to secret1 route we say searchparams.get and that should be continue2 I don't know why I went back to my browser there to check because I already know it's called continue2 that's what we defined here in our authguard so that's the name of our search parameter and I'll just leave that there you can see that the continue2 label should change to depend on the url parameter so I'm going to log out here let's go and try to access protected slash secret2 I click on login it gives the continue2 parameter and you can already see that that's updated to be secret2 instead of just being hard coded to secret1 which is the default which used to be the default route which is defined by this constant up here and now when I click on login it sends us to secret2 so we're done if I click on log out now and instead of having trying to log in from the authguard component I'll just click on the vanilla login link which doesn't have any which just means we're just trying to log in and we're not trying to access any page prior to this click on login and it sends us to secret1 which is a default route that's good one last thing before I end the video though see if I click on secret1 and secret2 from the navbar the transition is seamless that's because we're using the next js layout components and we're using the next link it's like kind of emulating a single page component however say I were to refresh the page I were to force a hard refresh you can see do you catch that for half a second there the authguard component flashed and if I were to say open a new page you can see that half a second had the authguard components telling us to log in before we can continue despite us already being logged in now that's caused by this on auth state change here and our use user hook the way it works is we first set our user state variable to a default value and then after that we have a use effect hook that goes out and does the server call and it takes some time for the server call to reach out to the firebase authentication servers and fetch the current state of the user that's what causes that delay now in order to fix this instead of just setting my user to null I have a third state value here false so that's what I gave into the default because if our user is logged out this user object returns null that tells us we are currently logged out if the user isn't null if it's a firebase user then it tells us we were logged in this third state variable here tells us that it's not null it's also not firebase user type it's just false that means we haven't initially initialized our user yet we are still loading our authentication state so that's a third state that we're keeping track of you know layout component instead of just saying oh if user is not defined if it's null then we return the auth guard component but instead of just doing that we add a third if statement here saying if the user is equal to false which is the first initial state before the user is initialized before firebase has had the chance to reach out to firebase servers and fetch the load at the auth state we first return a small component here that says auth loading now it still it still doesn't avoid the fact that there's still a jarring flash of auth loading but at least now we're not misleading the user and telling them that they have to log in before they can continue when they're already logged in we just instead tell them a less confusing message telling them that there's uh the auth is still loading or you can implement a spinner instead of just flashing them with this auth guard component which is very inappropriate so let's go and test that and see how that works come back here force a hard refresh instead of giving us that login prompt which is very aggravating we had uh we have a slightly less confusing message that says auth is loading or you could also just implement a spinner and with that my friends we are done and we have completely implemented protected routes in Next.js I will see you in the next one