Next.js and Django JWT Authentication | Part 2 - Frontend

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
all right welcome to the next part in the series where we're going to build out the front end of this application and to do that we're going to be using next JS along with typescript we're going to be using Redux for Global State Management we're going to be using rtk query to make a lot of these API requests and have caching behind the scenes for them and we're also going to be using Tailwind for The Styling so if you're jumping straight into the section I'm also going to do a quick rundown of what you need to do in order to just be all set up for this stage of building out the front end in case if you're just interested in xjs and want to see how to manage authentication with nextgs using a backend API so you're going to need to clone the repository where we built out this backend API and this is using Django and then I'm going to have a link to the repository for this and then you're gonna have to set up a few things so first of all you're going to have to create a virtual environment you're going to want to activate it and then inside of that virtual environment you're going to install all of the requirements which are in this requirements TX t so this has all of those and then you're also going to want to set up environment variables so you're going to want to create a DOT env.local and then this is what I have inside of here so in particular when we're doing email handling in this application we're going to be using Amazon's simple email service so you're going to need to activate that and you're going to have to verify a sender and receiver email in there and then you're going to have a user which can manage that and it's going to have an access key and a secret key which you're going to be placing here then you're also going to have the region and then you're also going to have the email that's sending so I'm going to quickly show that so if you go to aws.amazon.com you can log in and you can either log in with a root user or if you have a user set up like I do you can also log in with that so in particular I have an admin user and it's typically good practice to have a user that's not the root user that you can log in with and then in order to do that if you have a root user then you can just go to the IAM service and then from there you can create an admin user under this users tab so this is where you have an admin user so it's just called user and then this has administrator access as a permission attached to this and then to do that you would just go to this add permissions and you can add permissions and look for this one here so that's the account I'm logging in with now for the simple email service you can just search for SES you'll find Amazon simple email service and then from there you can go verified identities and then you're going to want a sender and a receiver email so this is my sender this is my receiver and then you're going to want to verify them so for these emails you're going to receive an email you're you're just going to click on a link and that's going to verify you so I have this email here which is this jongo 1357915 gmail.com I also have this one here John Doe 1357933 gmail.com so those are going to want to verify and then after you do that you're going to go to the SMTP settings and you're going to create SMTP credentials which is going to go through a process of creating a user and then that user you're going to be able to find in the IAM service and that's going to be under the users and in my case this is the user that got generated and that is what manages this sending of emails with the service and then after that you're also going to want to add this particular permission in order to have things to work and you also might have to go into your security credentials and you may need to generate a new access key because I found I've had issues with the one that gets generated at the beginning so you might have to delete that one and just create a new one if things aren't working so that's for the email handling and then you're also going to take notes for the simple email service the region in which you created this so in my case I'm using C Central one so I'm going to need to take note of that and then back to the IAM service so with that user you're going to just grab whatever access key you create and then you're just going to grab the ID the secret and you're just going to plug those in right over here and over here along with your region and the email that's sending now you have to have both the sender and the receiver verified in order for this to work so if you go to the dashboard for the simple email service by default your account is going to be in a sandbox environment which is why you need the sender and the receiver verified but once you go to a production version of this then you won't have to do that so that's for the email sending the next step is going to be if you want the Google and Facebook oauth 2 to work and then for that to work you're going to want to adjust these four settings here now you won't need the other environment variables here as well except those will be the same so you're going to have development mode of true you're gonna have a Django secret key and you can just put whatever here you're going to want debug of true and then you're going to want domain of low cost 3000 off the cookie secure a false so that cookies don't require an SSL connection that's going to be during development mode since we won't have an https connection and then you're also going to have your redirect urls that's for these settings here as well as these ones here you're going to want to change those from what you see here so for Google and Facebook oauth I went extensively into how we set that up but I'm just going to briefly go over it here as well so for Google you're going to want to go to console.cloud.google.com you're going to have some kind of project and then from there you can just go into the apis and services credentials and then you can configure a consent screen so if you don't have one it's going to prompt you to do that and then you can just create credentials for the oauth client ID which I have here I'm going to grab that client ID and the client Secret and you're going to plug that here and here and then you're also going to want to set up a few things in here in particular the authorized JavaScript Origins you're going to want to have this and this and then these are the ones I have in production in the last part I do show how to deploy this on digitalocean so if you want to see how to deploy the backend API then I'd suggest going to that part and skipping to where I deploy so that's going to be for the Google oauth 2 so that's all you're going to need and then for Facebook oauth 2 you're going to go to developers.facebook.com you're going to need a Facebook account which you're going to go over here and then you're going to create this developer account I'm going to go to my apps and then you can create an app in my case I have this one and then you're going to configure it to have Facebook login as a product so that's what I have here Facebook login and then you're gonna have some settings there that you can configure and then you can have valid oauth redirect to our eyes now localhost redirect Uris by default you don't have to put here unlike we did with Google oauth 2 like you saw in those settings so in the development mode you don't have to configure anything here really and then for the settings if we go to the basic settings this is where you're going to grab your ID and your secret and those you're going to be plugging in here and here and then for app domains you're just going to set up localhost you're also going to want to set up app roles so under this rules you're going to add a tester and then to add a tester you just click on this add testers and you put the Facebook ID so I have a Facebook account so in particular I have another window open here with this account here this is the one that would be logging into the application with Facebook oauth 2 and in particular in the URL when you go to the profile you'll see that here so you can just grab that user ID and you would just plug it in here to add that tester and then the place where you would see that because you're originally going to see it as pending when you go to create it so then this account here which is the one that's logging in we'll just go to developers.facebook.com and then from there once you go to my apps and then from there you're going to go to this drop down and you're just going to see like a notification where you have to accept this request to be a tester and from there you're good to go so that's how you set that up so if you have all that then you're pretty much good to go so I'm going to close this and then back into the code to run this server so I'm just going to open up a terminal window I'm going to navigate into this project and then I have a virtual environment set up right now and then you're just gonna have to do a python manage dots Pi migrate so that's going to be the first thing you run that's going to migrate everything to your database which is going to be a SQL Lite database in development and then after that once you run that you're going to do run server localhost colon 8000. and that's going to be running the back end so with that you're all set up now the next step is going to be to have a front-end client which is going to be able to communicate with this backend API which has a full authentication system setup so I'm going to open up a new terminal and then in here I'm just going to deactivate this virtual environment and then I'm going to generate a next JS project so if I go to the next JS documentation I'm going to be using nextges 13 with the new app router this is a new feature index.js which uses server components and then server components are something new to react 18 and then xjs integrates with that very nicely through this new app router and then the server components will just render out your components on the server and then it's going to send out the HTML and minimum JavaScript needed in order to render things out on the client and then this is as opposed to having a massive JavaScript bundle which is going to render things out so this is both SEO friendly and very efficient as well so it's a very nice feature to have and then the app router just makes it very easy to work with these server components so then under here what you're going to do is you're just going to run the install command so that's MPX create next app at latest and then after that you're going to be prompted with a few things and then maybe when you're watching this video you might be prompted with some other things but you're just going to see them listed out here since nextges is something that's constantly evolving so inside of this terminal window so I'm going to be in the root right now and that's where I'm going to run this command then I'm going to put the name of my project which is going to be full dash off what I like typescript yes yes lint yes Tailwind CSS I'm going to click yes do I want a source directory I'm going to click no and then use the app router I will click yes and then would you like to customize the default import Alias no because I'm good with the default one and then I'm also going to show you what the default one is so this finished up so I'm just gonna clear and then if I open this up and I'm also going to minimize this API folder and here if we look at the TS config Json this is where you can see this default Alias so then you can do this at slash and then your folder name and it's a very easy way to do Imports so we're going to see a lot of examples of that you're going to see exactly how that works just makes it so you don't have to do like relative paths whenever you want to import things and then the first thing I'm gonna do is I'm just gonna try to run this and then that way we could see if everything's working and then I'm just gonna have the server running and that way I can see anytime I'm writing code did I make a mistake and I can just catch that immediately so first I'm going to navigate into this folder for my client and then I'm going to do an npm run that this is how I run the development environment and then also one thing just to show you before I do this the node version I'm using is 18.16.0 so that way if maybe you run into some kind of issue it could also be just have an old version of node so that's one thing to note so let's try this out now I'm gonna flip on back and there we go it runs perfect so now let's set this up for our project since we do have a big default template there first thing I'm going to do is inside of here I'm going to create a Styles folder I'm just going to move this Global CSS into that Styles folder I'm going to remove everything except for these Tailwind Imports and then inside of my layout we're going to be importing this differently so now here is going to be the first example of that Alias import so you do at slash and then I can do Styles Global CSS like this and then you can also have fonts that you can import so in this case there's this inter font from Google and then this is how that gets set so we have this constant enter is equal to this enter with the subsets of Latin and then they just apply it here to the class names so that's how you can set up these fonts I'm just going to use this default one since it's a pretty nice font you can also have metadata and then the metadata you can have on all your individual pages so for the title I'm going to do full auth it's going to be like my default title and then the description is going to be full auth application that provides JWT Authentication and then I'm going to save that I'm going to get some formatting that's going to happen because of my prettier formatter and then the next thing we're going to do is I'm going to go into this page.tsx so this layout this is going to be a layout on all of the pages so all the pages are going to have this HTML with the link of En they're going to have the body tag and this is where the page is going to go so this is a very nice place where you can create a nav bar and a footer so I'm going to show an example of that so I'm going to create a components folder inside of full auth and then inside of there I'm going to organize things in a particular way I'm going to have some subdirectories for some common components and then I can also have some other folders here as well so one thing in particular is I'm going to have forms inside of this application because I'm going to like that sign in the sign up as well as things like requesting to reset your password so there's gonna be quite a few forms and then the other thing I might do is also have some utility type components as well so the navbar and footer in particular I'll put inside this common so it's just a nice nested folder structure that you can have and there's not really any kind of like best practice way to do this you can also just have all of your components inside of here without any nested structure but I like to have some organization so inside of here this is where I'm going to create my navbar.tsx and also my footer.tsx [Music] so for the nav bar I'm gonna export a default function of navbar and that's just going to have a nav element with an H1 of navbar and I'm going to do something very similar for the footer so I'm just going to copy this and paste it here and I'm going to have footer then instead of nav I'm going to put a footer element and then inside of my layout I can import these two things so I can import nav bar that's going to come from components common navbar so you can see this import syntax is very nice I don't have to go like back a directory and then go into components I can just do this at and then I can do the same thing for footer and then I can place my nav bar right above here and then the footer and then this is where the pages will go and I can also be wrapping div around this which then I can style a particular way as well and there we go and then another thing that you can do to also make these Imports even nicer is inside of this common what I can do is I can create an index.ts I can export default as far from and then I can also have the same thing for footer footer I'll do above and then what I can do here instead of importing this way so I'm going to remove this and then I can just import footer and nav bar like this so I can just destructure from components common so just makes this a little bit nicer and more organized and then I'm going to go to this page TSX I'm just going to remove everything inside of here and then instead of home I'm just going to call this page that's how I like the name the page components then there I'll have my main with an H1 of home page for now and now let's take a look at how things look so back in here now we see our home page so it's going to be at the slash route then because of that layout component we have the nav bar above my page in the footer below the page and that's going to be the case for all of my pages so now let's go back and start to configure some things first I'm going to do is I'm going to set up my different routes and then we're going to see how the routes work so page TSX is how you do your pages layouts how you do your layout and you also have some other options as well for what you can do and the next.js documentation does outline these things so here we have this whole routing section and then here kind of goes over some of these things that you can set up so in the app directory if we scroll down we see talking about the page.js how to do nested routes and then here's some of the file conventions so let's say page.js that's how you create your different routes for your pages route.js if you have API routes so in our case we won't have that because we're using Django with the Django s framework to manage our API you can also have a layout you can also have template which is similar to layout and here it shows some of the differences with that you also have this loading error and also not found and then not found is going to be whatever renders for a not found page so this just kind of shows you these file naming conventions so now let's go and use these in action so the first thing I'll do is inside of my app I'll create an auth folder and then here we're gonna have a couple things we're going to have a route of auth Slash login we're gonna have a routes of auth Slash register we're also going to have auth slash Google and auth slash Facebook now in the first part I went over the auth Google and auth Facebook routes so these are the routes that are handling those redirect Uris for Google oauth 2 and Facebook velost2 and then these are going to handle that post request which is actually going to create and lock you in and then by create I mean like create the account using your Google account or Facebook account and then inside of here what we need to do to make these routes work is we create a page.tsx and make sure to actually call it page.tsx and we create that in all of these so there we go and then inside of here I can do export default function page which is going to return and then we can have something like let's say a main tag with an H1 that says register this will be for my register page I'm just going to copy this go into my login page change this to be login go into my Google page change this to be Google and go into the Facebook page and change this to be Facebook and then now we can test this out so if I go to a route of slash auth slash register let's say I should see my register page and there we go we see the layout is putting the nav bar and footer above and below my page on the page itself just has an H1 with text register then login will have login there we go and then we have Google and we have Facebook so as you can see setting up routing is very easy with nextgs so if you ever worked with react you would have things like reactor out of Dom where you'd have to set up all of this routing but with nextgs all you have to do is just tap things in the correct folders with the correct file namings and you have your routing that's it it's quite nice so the next thing I'm going to do is set up the endpoint for the activation route because we're going to have a route that's going to be activation slash duid slash the token that's going to handle activating an account so inside of here I'm going to have activation and then I'm going to have in square brackets uid so this right here is going to handle a dynamic route so it'll be activation slash something here which I can extract from the parameter in the URL and then I'm going to do the same thing with token so it's going to be activation slash uid slash token and then in here is where I'm going to create my page.tsx this is what's going to handle the activation and I'm just going to paste this in here with the text of activation so this is what I'm going to have here as a placeholder for now I'm going to minimize some of these things and then the other routes I'm going to need are for the resetting of the password so I'm going to create a folder of password Dash reset then inside of here I'm going to have a page.tsx this is going to be where I'm going to have a single input element where you put in an email and you can request to reset your password and then you're going to receive an email with a link and then that link is going to bring you to another route which we're also going to have nested inside of here which is going to be password Dash reset slash the uid and then slash the token within there so you're going to need the square bracket syntax because these will be dynamic and then in there inside of that token folder I'm going to have my page TSX so this is where I'm going to have the two input elements for creating your new passwords they're going to create your new password you're going to type it in and you're gonna have a confirm password field you're going to submit and that's going to reset your password so that's going to be this page and what I'm going to do is I'm just going to paste what I had and put request password reset this will be the temporary page for this I'm going to paste this in here this will be set view password and then the last pages I'm going to have are for my dashboard it's going to create a dashboard folder and then within there I can create a page.psx and that's going to have the text of dashboard so there we go we have all of our Pages set up and then we have some placeholder Pages for each of those routes so we can even test some of those out so I made my dashboard route there we go we got dashboard we have activation slash some uid slash some token that's going to load up my activation route then we have password Dash reset request password reset and then if we do slash uid slash a token of some kind we're going to have set new password so there's all of our routes I'm going to go back to the home page so one thing we're going to be setting up in this app is Redux toolkit along with rtk query and then that's what's going to help us with global State Management as well as making our API requests with caching behind the scenes so I'm going to be showing you how to set those things up so here I have the documentation for Redux toolkits and then we're going to be using this a bit to help us with setting this up so back inside of my project I'm just going to minimize a few of these things I'm gonna open up this terminal window I'm gonna stop running my front end I'm going to install some packages I'm going to npm install save at Redux slash or sorry Redux JS slash toolkit I'm gonna have react Dash Redux and then for now I'm just going to install these two these are going to be what we need for Redux toolkits and then I'm gonna run my server again just to see if there's typos and whatnot so I'm going to keep an eye on this and it's also a very nice way to develop just going kind of back and forth between your application running and seeing the terminal window and if you ever make a typo you just catch it right away so to manage my Redux I'm gonna go inside of full auth and create a folder which is going to be called Redux this is where I'm going to do my Redux setup I'm going to show you how to do the Redux setup and then before I do the Redux setup there's just one quick thing I want to go over with the server components so when you're using App router your components themselves by default are going to be these server components and then if you don't want them to be server components what you're going to do is you're going to put a string of use client so there's somewhere in the documentation that it goes over this and I'm not sure exactly where it is so I'm just gonna do a search for use client and I might find it so they use client directive so this kind of goes over this so they use client directive is a convention to declare a boundary between a server and client component and then you just have to put this string of use client anytime you're using a client component so a client component is going to be anything that uses something like EU State use effect so those are those like life cycle hook methods from react also if you have event handling like handling inputs and also form submissions anything like that you're also going to want to have use client and then I think there's also somewhere where it goes over yeah right here you can see this so this is going to be for Server components when you want to do things like this but if you have interactivity like vent listeners like on click on change that's where you use the client component lifecycle methods client components if you have browser only apis like local storage and whatnot you're also going to want client components also if you have custom hooks which use any like life cycle hook methods as well as interactivity with event listeners and whatnot you're also going to want to use these client components and then there's something additional in our case which isn't listed here and that's when you're using Redux toolkit so anytime you use something like a hook generated by rtk query or using a hook like you selector use dispatch from Redux toolkit you're also going to want that component that's using those things to be a client component because if it's a server component it's not going to work you're going to get an error so with that in mind let's now go through this setup so instead of my Redux folder one thing I'm going to need is a store.ts this is where I'm going to create my Redux store so I'm going to import configure store in order to help me do that and then I can export a constant of make store which is going to be a function I can call which is then going to configure my store and then we have to pass some settings we're going to have our reducer which I'm just going to leave as an empty dictionary for now but we're going to be adding things to this reducer option and then I'm also going to have Dev tools which I'm going to do process.env dot node EnV doesn't equal production so if we have our node environment set as production then we're not going to show the dev tools otherwise we will and then what's meant by these Dev tools is this extension here so this is a Redux Dev tools extension which you can search up you have this on Chrome and I also believe you have this on Firefox and then it just makes it easy to manage like what's going on when you're using Redux so then when we're in production we don't want someone who has this extension to be able to like monitor what's going on so it's going to be disabled but in development it's nice to have and then after that I'm also going to export a couple types from here I'm going to export a type of App Store this will have a return type of type of make store I'm just going to export a type of root state so I have a return type of App Store and get state and I'm also going to have an export type for app dispatch which will be App Store and dispatch so this in particular is for typescript and I'm going to be using these types A little bit later when I set up some Hooks and I guess I can do that now so these hooks are going to be what I use for things like the U selector and use dispatch when I'm using typescript and the way that this is going to look is I'm going to import use selector and use dispatch that's going to be coming from react Redux then I can export a const of use app dispatch this is going to be a function and then I'm gonna have to import some of those types I'm going to import a type of my root state just coming from my store as well as app dispatch and then one more thing I'm going to import is a type of typed use selector hook from react Redux and then this use app dispatch is going to be app dispatch which is equal to use dispatch so now anytime I want to do use dispatch so typically when you don't use typescript you would just import this use dispatch from react Redux and then you could dispatch your action creators but with typescript instead we're going to be using this right here which are going to be importing from a Redux Hooks and that will just give us some typing when we're doing dispatch then I'm also going to export a constant use app selector this will be my typed use selector hook with root state equal to use selector so then typically without typescript we'll just import use selector and then we can use any Global state that we have in our Redux store but with typescript instead we're going to be using this right here and that's going to give us some typing when we do our use selectors I'm going to close that up and then the next thing I'm going to work on is my provider so my provider is what's going to end up going inside of my app layout and that's going to be wrapping this stuff here and then that provider I need in order to provide my Global Redux state to the children components to it so inside of my Redux folder I'm going to create a provider.tsx and then this is going to be an example of a client component so at the top I'm gonna have to do use client and that is because this is going to be the provider from react Redux and we're going to be using inside of our layout so we need to have this use client otherwise we're going to get issues I'm going to import my make store function from my store I'm going to import the provider component from react Redux and then we're going to export a default function of my custom provider that's gonna have children and then to not have typescript issues with this I'm going to create an interface of props which will have children that's going to be react.react node and then this props I'm going to pass as a type to this right here which is my props empty structuring somebody structuring children and now I have the correct typescript typing so it doesn't complain and then I can return my provider just going to have store equal to make store which I'm going to be calling and then between here I'll have children so I'll save that and then to use my provider let's go to my layout TSX and then right over here I'm going to import provider and it's not going to be the one from react Redux instead it's going to be the one from Redux slash provider and then I'm going to grab this and I'm just going to wrap these components with my provider there we go and then also one additional thing I'm noticing which I also want to quickly do is also import a type of meta data which is coming from next and just apply that to this thing here since I am using typescript so it's good to put on the type here so with that I'm going to close some of this stuff up and I'm going to continue with some configuration for Redux because right now we have our store but we don't have any reducer set up so let's get started on that so the first thing we're going to do is I'm going to create a folder in here called features and then here I'm going to set up an API slice which is going to have some kind of global state that I want access to I'm going to call this auth slice dot TS and then to create a slice I'm going to import create slice which is coming from redux.js slash toolkits and then in here I'm going to create some initial state that'll be my object and I'm going to have two pieces of global State one will be is authenticated and that by default will be false so this is what I'm going to use to see whether a user is locked in or not and then based on this I can do various things like let's say show either a sign in and a sign up button or a dashboard any logout button on the nav bar or I can do things like let's say if someone's trying to access the dashboard and they're not logged in we can redirect them that's a way to also easily have protected routes so that's what I'm going to be using this particular piece of State for and another one I'm going to have is is loading default will be true so this is loading this is going to be our initial state of our app where it's loading and in particular this is going to be used in conjunction with our verify endpoint so with our JWT authentication our verify endpoint is something we can use to see do we have a valid access token so in particular when someone refreshes the page if they're logged in we want to keep them logged in we don't want to have them lose their authentication state so the way we can do that is we're going to have the access token in their cookies when they log in when they refresh the page we're going to use that cookie send it in a verify request that access token will be passed along in that verify request and the cookies we're going to verify is this person locked in and then if they are we're going to say yes they're logged in this right here is going to be flipped to false because we've finished loading and they're going to be authenticated and then in particular we will need this because when we hit authorized routes like let's say if we hit a dashboard route where someone needs to be authenticated by default this is going to be false that verify request is going to be asynchronous it's going to take some time so we need something to tell that route to be like hey you need to wait until we see whether this person is is verified and then once we figure that out then we're going to decide Can you view the dashboard or do you need to get redirected to like a login page so that is the point of this piece of State here so hopefully that clarifies what we need here for our Global state I'm also going to create an interface called auth state and here I'm going to have is authenticated which is a Boolean and I'm going to have my is loading which is also a Boolean and then I can just do as auth state to this initial State just to have some typescript typing because if we are using typescript we might as well use its features and then I'm going to do my auth slice creation so I'm going to make a constant off slice equal to create slice and then here we're going to pass some configuration options this is going to have a name of auth so all of our slices need to have a name they're also going to have the initial state that they start off with and we're also going to set up the reducers and then based on what we set up for the reducers we're also going to have action creators that also get created through this create slice so we don't have to separately create action creators and separately create reducers this create slice will do both for us and then you'll see that in a moment so we're gonna have inside of here set off and then we're gonna have state Arrow function and then we'll do state DOT is authenticated equals true and then the way that Redux toolkit works is that unlike traditional Redux where you have to create a new object or you return a new sort of state and here we can directly access state DOT is authenticated and set it equal to true because we have a package called immer behind the scenes which is going to be doing things properly with three Ducks which is create a brand new state so don't just mutate the current state directly so Ember behind the scenes is going to sort of do these operations but when we're using this create slice we can do it like this which is sort of a convenience thing for us then particular that's really nice especially if you have like nested sort of States like State one which is like an object state two which is an object with traditional Redux you'd have to use a lot of spread operators and whatnot whenever you have to adjust the Redux State well because of immer we can conveniently just access pieces of States directly then we're also going to have logout and then this will have state Arrow function and then also here another thing you can have is State and action but I'm just doing State because that's the only thing I need so I'm just doing State Arrow function but if you were to have also the action you could do like action Dot payload so sometimes you're gonna have action creators which have a payload so that's where you would use like a second argument but in our case we don't have that so we're just using State and then what this is going to do is just set state DOT is authenticated to false and then finally I'm gonna have one final one which is finish initial load and this will set state DOT is loading to false so we're going to dispatch this once our verify is complete that's going to flip the state to false so that we can see let's say on a protected route like our dashboard okay we finished verifying now let's check if this user is authenticated so if the verification failed they're not authenticated if it worked they are they can view this route so that's how that's going to work and then in here right now in order to export my action creators what I can do is export const and this is going to come from my auth slice dot actions is where I can grab the action creators and they're gonna have the same names as what we set up here and this reduces so we're gonna have a set off action Creator a log out action Creator and a finished initial load action creator and then on top of that I'm also going to have a default export and that's going to be for the reducer so you do export default auth slice dot reducer so now that I have a default export for my reducer what I can do is now go back to my store and I can use that here so the way I do that is I go here I have my default export of auth slice and then I can grab that go into this reducers I'm going to have auth which is going to be my off actually I meant to do auth reducer not auth slice because remember my default export is the reducer itself so then it's just more appropriate to have a name of auth reducer it would still work with something like auth slice but I just want a name that makes sense my default export is the reducer of the slice so I want this to have the name of auth reducer then in here I have this key of auth which is my auth reducer which means that once I use things like my use app selector hook then when I have something like State Arrow function State I can do dot off and then in there I can access my different Redux states that have to do with this auth slice so things like my is authenticated and is loading and we can see that typescript is auto filling these for me which is quite nice so there we go now the next thing that we're going to work on is setting up our TK query now rtk query has a very nice feature of reauthorization which we're going to be using in this app and we're going to see how to configure that and then what that's going to do is any time that we get some kind of 401 status code which is like 401 unauthorized so if we hit an authorized route and we're not authenticated we will get a 401 and then what this reauthorization is going to do for us is it's going to hit our refresh endpoint which is going to get us a new access token and we're automatically going to retry that endpoint which we were unauthorized to hit previously so if we hit the refresh endpoint then we have a refresh token we'll get back an access token and when we retry it's going to work so this is a very nice way because like right now let's hear access tokens they expire every five minutes so we don't have to log in every five minutes so this reauthorization is going to see anytime we get a 401 let's get a new access token let's retry that request which we were unauthorized for and that failed and now it's going to work but of course if our refresh token expires then this reauthorization isn't going to work but I refresh tokens they expire after a day so that's fine so with that in mind I'm going to go to the Redux toolkit documentation then what I'm going to do is actually I'm going to search for this I'm going to search for re-authorization so here we have a whole section on automatic reauthorization so this is something that extends fetch base query so that's something that you set up when you want to use Redux toolkit with rtk query but we want to extend this thing with this whole reauthorization functionality now there's this automatic reauthorization example in typescript that you can follow here but we also have another version which uses this async mutex and what this does is it prevents multiple calls to your refresh endpoint when multiple calls fail with a 401 unauthorized error so this is a nice thing that I'm going to also include so I'm going to be using this example here now for this example to work we're gonna have to install this async mutex package so I'm going to go open this up stop running my server I'm going to do an npm install for async new text so there we go small package then installed quickly and I'm going to rerun my Dev server and then inside of my Redux folder I'm going to create a Services folder and then inside of there I'm going to create an API slice TS file and this is where I'm going to set up this reauthorization with the base fetch query so I'm just going to copy the code that's in here and we're going to modify it to work with our app back in here I can I can paste this and I'm just going to click save to do some reformatting so the first thing I need to do is here they have this token received and logged out these are not the action creators that we're using so I'm going to be modifying this instead I'm going to have set off and log out and that's going to be coming from my features auth slice so those are those action creators which I'm exporting from here we also have our mutex we have some types imported here to have some typing with typescript we have fetch based query which is coming from here and I can also bring that in from the query react paths here and then one thing I'm going to be modifying here we have this const base query and this is setting up this base URL now when we're running in development what we're going to do is we're going to have nextgs running on localhost 3000 and our API on localhost 8000 so this right here is a relative path which means by default it's going to add the current domain here when it makes requests but we don't want that we want it to go to localhost 8000 which is a cross domain request and also in production it's going to be a cross domain request as well so to set up this path here and to make it convenient for setting this for both development and production inside of my full auth folder I'm going to create a DOT env.local I'm just going to set up some environment variables here I'm going to have a host name of localhost gonna have a port of 8 000. and then next public host of HTTP colon slash slash my hostname colon my ports so when I use this environment variable here of next public host that's going to be my localhost 8000 which is my backend API that's running right now and then also in production it's pretty easy to configure this as well I just have to set this to be my production API URL which in my case would be the https colon slash slash API dot linkedwebapptesting dot info and then I'm also prepending this with next public so that this environment variable is exposed to the browser which is something that I need and then back in here instead of these quotes I can use backticks so the backticks are that button right above your tab key and then I can bring in my process.env.next public host and then slash API so with rtk query this is going to be my base URL it's always going to be localhost 8000 slash API and then I can do whatever I need like slash JWT slash create slash or slash JWT slash refresh whatever it is but this is gonna be my base URL then one more thing I need to have here is a setting of credentials include so what this is going to do is it's going to attach cookies automatically in my requests which I need for my ACCESS and refresh tokens because when we log in they're going to be set as cookies in my browser and I need this to be set and then we also configured our backend API to also make this work it's something I mentioned during the section of creating that backend API but our backend API what it's going to do is it's going to have a cross origin allow credentials header which is going to be included in the response and it's also going to have the cookies set with some properties which is also going to allow for these cross origin requests to work on top of that we have things like the cores headers which are also included we have things like the same site flag which is set to none so all of these things we configured on our back end so that these cross origin requests will work with the cookies being sent along but here with the Ajax request it's one thing we do need is credentials include for it to also work when we're sending these requests off from the client so with that we're going to go down we have some type set up here we have the arguments we have some comments which we don't need so this is where we do the whole mutex waiting for an unlock and then we have if we get an error and we get a 401 unauthorized then we're going to do this mutex check for if we're not locked then we're going to go ahead go through this and then after it's done we're going to release the lock I'm going to remove some of these comments and then this is where we do this request for our refresh endpoint now our refresh endpoint is going to look different than this I'm going to remove this part instead I'm going to have an object here which is going to have my URL which is going to be localhost 8000 slash API which is my base URL and then slash JWT slash refresh slash so don't forget that trailing slash and then I'm going to have my method epost there we go this is going to be how I do my refresh and then if this was successful then we're going to API dispatch set off and that's not going to take any arguments so I'm just going to remove that and then if this wasn't successful then I'm going to dispatch my logout there we go I'm just going to remove some of these comments to clean this up and now this is configured to work with our particular app now there is one final thing I have to do here which is I'm going to import create API I'm going to use this so right at the bottom I'm going to export const API slice which is equal to my create API import this is going to have a reducer path which is going to be API it's going to have a base query which in my case is going to be this what I set up here it's going to be my base query with the re-auth so I'm going to paste that in here and I'm also going to have my endpoints which will be Builder Arrow function and then for now I'm going to do it like this and actually not even for now this is how it's going to be and what I'm going to do is I'm going to show you a way where you can inject endpoints to this which is quite convenient so I have to have all of my endpoints in this file I can have separate files which inject the endpoints here so that's something we're going to go into so I'm going to close this for now then go to my store and then in my store to use this first of all I'm going to import that API slice so import API slice from Services API slice and then in my reducers I'm going to have apislice dot reducer path which is that API string that I set up that's going to be API slice dot reducer there we go with that now we have our DK query which is also configured for us the only thing left to do is have the endpoints so the endpoints is going to be the next thing that I tackle so under features I'm going to create a new folder called auth API slice.ts and this is where I'm going to create my API slice so I'm going to inject those endpoints so I'm going to have to import my API slice which is what we just created here and then from there I can do const auth API slice is equal to my API slice dot inject endpoints so this is how I can inject endpoints so that I don't have to configure them here so that way if I had like multiple files or if I had like nested folders with many files I don't want to have all of my endpoints just here I want to have a sort of nice configuration where I can have each file responsible for endpoints related to a specific thing like in this case authentication if I'd like an e-commerce app maybe I want to have endpoints related to things like products or managing a cart or whatever it might be so what I do in here in this configuration object I can put endpoints this is going to be Builder Arrow function and this here so this you might notice looks very similar to what we have here so we do have to put this here but we're going to be injecting them like this so it's just going to give us a bit of separation of concerns and then to set up these endpoints what we do is we can create let's say a retrieve user endpoint and then we can do Builder dot query so you can set up both queries and mutations so queries are going to be when we get some data mutations are going to be when we do things like post requests put requests and we send data along and then you're going to have query and then the endpoint so we have the base endpoint which is low cost 8000 slash API and then we're going to add to that slash users slash me slash so this right here if you remember is the endpoint for retrieving our user and it doesn't take any like special parameters or anything because what you can do here is you can pass arguments and then you can use those arguments like if you have some kind of dynamic endpoints but in this case we don't so it's just going to be set up like this and then from there what we can do is we can export a const of use retrieve user query which is going to come from our auth API slice so this is going to be a hook that gets generated based on the name we have here so it's going to have a use before and then this first R right here is going to get capitalized and then we're going to have it end in query then the mutations are going to do something very similar except they're going to end in the word mutation so this all gets generated based on what we pass here so with that what we can do is we can set up the rest of our endpoints and then once we have that we just have this all set up and we can freely use these hooks so this is pretty quick to set up which is why I think it makes sense to just go through this so next I'm going to have my Google authenticate and then this is going to be an example of setting up a mutation so here when we did the query with the builder dot query now we're going to do Builder dot mutation and then we're going to have query in here and then you're going to notice that when we did our query we had query in here we also have query in here even though we did this Builder dot mutation so the query is like the query that we're making and then within here we're going to have the URL so in our case we're going to have a URL which is going to be slash o slash our provider which is Google Dash oauth 2. and then slash question mark state which is equal to our state and code which is equal to our code which I'm going to set up in a bit next we're going to have the method which is going to be a post request I'm going to set up my headers I'm going to have an accept header which will be application Json and then I'm also going to have a content type which in this case isn't going to be application Json but instead it's going to be application slash x dash www Dash form Dash URL encoded that is what this endpoint expects to receive so this is sort of a different kind of post request where we're passing this data then in the URL instead of like in the body of the request so that's just the way that this works and then from there we're going to be passing some arguments and in particular we're going to want to pass the state and the code that we want to put here so in this example we saw when you don't have anything it's just a URL that doesn't have anything dynamic in it but this is one that does have something dynamic in it and that is the state and code so you can put in state and code and then one thing to note here with Redux toolkits when you want to have multiple parameters you can't do it like this because this first parameter is going to be your arguments the second parameter is going to be something completely different so when we want to have multiple parameters what we actually have to do is we have to have this in an object like so and then from there I can use my state and then in order to embed this I'm going to use an interpolated string so instead of these quotes I'm going to have my backticks then instead of the state I have dollar sign curly brace state instead of code dollar sign curly brace code and then one additional thing I'm going to do is I'm also going to wrap these in a function called encode URI component and this is just the JavaScript function which makes these URLs safe so if you have any sort of characters that aren't URL safe like let's say spaces it's just going to encode those so if you had a space character that's going to be encoded to something like percent 20 or whatever I'm gonna wrap this as well and then I'm just going to save so that this gets reformatted now we're also going to have Facebook authenticate and then Facebook authenticate is pretty much going to look the exact same except for this provider so because that's the only difference one thing that we can actually do to make this better is instead of calling this Google authenticate I can just call this like social authenticates and I can just pass an extra argument of the provider and then the provider is just what's going to go here so this is just the way that I can have a little bit more reusability then inside of here this is the way that my mutation Hook is going to look so I can do use social and then here I get this Auto completion with typescript so use social authenticate mutation so now I have this hook which is generated as well based on the name I provided here and the fact that this is a mutation I'm going to save that and then next I'm going to set up my login this is also going to be a mutation so Builder dot mutation with my query and then to log in I'm going to expect an email and a password now remember to pass these in a single argument as an object and then I'm going to return an object by the way that's what this syntax means this is the equivalent of me doing this but instead of doing that it's just nicer to have this right here so that's the way that I do this just to return the object and then in here I'm going to have my URL so my URL to log in is low cost 8000 slash API slash JWT slash create slash and that's going to put my access and refresh tokens in my HTTP only cookies this is going to have a method of post and in this case I'm going to have a body that I sent with email and password and then all I have to do after that is export to my hook which is use login mutation and I'll save that just to have this reformatted then after login I'm going to have register which is going to be pretty similar so I'm just going to copy this and paste it I'm going to call this register it's going to be Builder dot mutation and then to register I'm going to have a first name last name email password and re password then I should have to pass those in the body so first name last name email password and re password and then by the way you can also make this much smaller you can do something like args and then your body is just those args and then you can maybe have some like typescript typing where maybe you have like a user but the way I'm going to do it is I'm just going to have it be explicit like this so I can see the exact fields that are being passed to this I just like it being formatted this way and then also one thing to note with the typing so what I can actually do with something like my retrieve user is I can create an interface of user what I expect to receive is a first name last name and email and then I can use this user in conjunction with this and then the way I do that is after this query I can have a less than a greater than sign put in user and void and that's going to give me typing when I retrieve my user and then I get that data I'm going to be able to just have typescript autofill like first name last name and email for me and then another thing I'm going to do is I'm also going to add some typing to the social authenticate I'm going to add another interface here which is going to be my social auth args and have a provider which is going to be string states which is a string and code which is a string and I'm also going to have an interface for my create user response which I'll have success which is a Boolean end user which is my user so this in particular is going to be for my oauth requests and then what I can do is right here I can have my less than greater than sign I have my create user response and my social auth args and that's just going to add some typescript typing to this so after my register I'm going to create my verify endpoint and that's also going to be a mutation so I'm just going to copy this register and paste it I'm going to call this verify it's going to be Builder mutation and then the verify it's not going to be taking any arguments so I'm just going to delete all of these and then it's also not going to have anything in the body so I'm also going to remove this and then the end point is going to be to JWT slash verify slash so that's for the verify and then I can export my use register mutation as well as my use verify mutation just to have those here and then after verify I'm going to do my log out so I'm going to copy this and paste this is going to be my logout which is also a mutation and then that's not going to take in any arguments and that's just going to hit my slash logout slasher out and make sure to have that trailing slash and then I'm just going to export that use logout to mutation and then after logout I'll have my activation which is going to be a mutation as well so make that easier I'll just paste this and put in activation so that'll be my Builder dot mutation and then to activate I need a uid and a token so in an object I'll have uid and token and then this right here is going to be an interpolated string so I'm going to use the backticks and then that'll be slash users slash actually it won't be an interpolated string it'll be a normal string and I'm going to have slash users slash activation slash so again the trailing slash and then in the body of the request I'll have the eyd and the token and then also by the way rtk query is going to handle Json stringifying these so I don't have to do anything like json.stringify that's handled behind the scenes and then after that I'm gonna export my activation mutation and then after activation I'm gonna have my reset password which is also a mutation I'm going to paste this and I'm going to call this one reset password so this is going to be the one that requests a password reset so the only thing I need for that is to receive an email and because it's only one argument I'm not going to have that in an object I'm just going to have it like so and then the end point for that is users slash reset underscore password slash that's going to be a poster Quest and that's just going to receive the email and then finally actually I'm gonna also export this so use reset password mutation and just one final endpoint to set up and that's going to be for my reset password confirm and point and that is going to receive the new password the renew password the uid and the token so I'll do uid token and then new password and renew password and then all of these I'm going to expect to be received in the body and then as for the end point it's going to be user slash reset underscore password underscore confirm slash and then the last thing you have to do is export this so use reset password confirm mutation and I'll save that and there we go I'm going to zoom out for a second just so that I can go through this whole file so this right here is all of our endpoints for authentication that we're going to need set up in our app so that we can very conveniently use these so we got our retrieve user social authenticate login register verify logout activation reset password and reset password confirm so very easy to set these up and have caching happen behind the scenes so now the next exciting part is going to be actually using these so I'm going to close these up and then we're going to see how to actually use these so I think a pretty good place to start is going to be with our register page just so that way we can create a page that we can actually test out so under this auth register page this is where I'm going to set up my register page and then to make the creation of this page easier what I can do is I can go to the Tailwind documentation and I can go to this components and this is going to bring me to the Tailwind DUI documentation now Tailwind UI is a sort of paid service but there are some free samples that you can use here which is kind of nice so if I go down one thing that I can look for we also have 404 page which is Handy and that's something we're going to use and then anytime you see this lock that means that you have to pay to access these but when you don't see a lock that means that there's some components there that you can use and then one that I'm interested in just to make creating this sign in and register convenient is under this forms we have sign in and registration I'm going to click on that and then this first one here I can actually get the code for now the ones after that you actually have to pay for but I do have access to this one so just to make creating this right here a lot easier I'm just going to use the code that's provided and then we have HTML but you also have react and view so I'm going to click on react and then that way I can grab whatever code is in here so the js6 is what I'm going to copy and then once I have that copied I'll go back to my code and I'm just going to paste that in here and then save to reformat so with that if we go back to our application and we navigate to slash odd slash login let's see what happens and then actually it's not my login it's my register so there we go we now have on our register all of this created and then of course we have to edit this so let's do that so first thing I'm going to do I'm just going to adjust this alt text to be a company of full off and then for the text it's going to be sign up and then for an account so sign up for an account and then we're going to have a couple more fields in here and we're also going to want some management for the form so in particular here they have this action method that's not something I'm going to have I'm going to have it on submit Handler and let's start setting this up and copy this paste it here and then this is going to be for my first name this is going to have an html4 a first underscore name an idea first name a name a first name a type of text and then I'm going to remove this autocomplete I'm going to grab this class name I'm going to cut it and I'm just going to place it higher up just because I like having the ID and then the class name and then I'm going to remove the rest of these so there we are I'm Gonna Leave This button and then this button is going to have the text of sign up in my case and then I'm going to scroll up I'm going to copy this I'm going to paste it I'm going to have a last name so this right here is going to have last name for my html4 for my ID and the name and then I'm going to have my email this will have text of email address this will have email for the html4 the ID and the name and it'll be a type of email and then we're going to need our password this will have password for all of these the html4 the ID name and type and then we're also going to have the confirm password so this is going to have re-underscore password for the html4 the ID and the name the type will still be password so I'm going to save that let's see where we're at so there we go we have a more proper looking form so now going back to my code the next thing I have to do is have some State Management so to do that I'm going to need to import use state for react and because I'm using a lifecycle method I'm gonna have to put use client at the top here to make this a client component and then here I'm going to have my const form data and set form data which is going to be use State and then in here I'm going to have my different fields for registering like the first name which by default will be empty last name email password and read password so I'm just going to fill these out so last name email password and and re password that I'm going to destructure these fields from my form data so first name last name email password Android password and then the reason why I'm de-structuring them is because each of these input Fields is going to need a value and an on change Handler so this one here the first name is gonna have a value of first name which is that value ID structured and that was the structured from the form data last name same thing except here we're going to have last name and then email address will have the email and we're gonna have the value of password and the value of free password so this is how you handle forms in react and then I'm going to have a function which I'm going to call on change this will take an event and then what this will do is set my form data and it's only going to set one of the fields here so my form data right now is an object so what I can do is I can do the spread operator on form beta and then I can just adjust one of the values based on the value that a person is typing in the input so I can do that with event Target name which is event Target value so then this right here event Target name is either going to be first name last name email password or read password and then the value is going to be the value that someone's typing and that'll be adjusting the actual string value on the right here that's the way that's gonna work right now I'm getting an error with typescript so what I need to do is pass a change event I'm going to put that as a type and I'm going to put in as a generic type HTML and then input elements and that's going to get rid of that and then I can also further clean this up by destructuring from the event targets you can destructure name and value and then I can just pass those in directly here so I can just have in the square brackets the name and value and now that I have this on change I can go to my different inputs and then say above the value I can put on change is my on change function which automatically is going to have the event sent along as that argument I'm just going to copy this and put it in each of these and one more so there we go now we have the on change and the value so now our form should work at least for the typing aspect of it so now if we go here and we click one thing you're going to notice there is no cursor so something that we have to actually do is install a particular package in tailwind and set it up as a plug-in that's going to be the Tailwind form package so I'm going to open up my terminal I'm going to stop running things and I'm going to do an npm install for at Tailwind CSS slash forms so that's going to install that and then the next thing you have to do is open up my tailwind config.js and then we have this plugins section here so what I want to pass in this plugins is a require for at Tailwind CSS forms and then after that I can rerun my Dev server I'm going to close that up go back to my code and then if I refresh the form should be good so there we go now we see that we actually have the cursor and I can also type and this is going to be saved in that state and then another thing I want to do is just get rid of this text at the bottom as well actually instead of getting rid of it I actually want to more adjust it so what I'm going to do is I'm just going to change this text it's going to be already have an account and then you're going to log in and instead of an anchor tag I'm going to bring in link it's coming from next link I'm going to scroll down I'm going to use the link tag here instead that's going to have an href going to slash auth slash login and I'm going to have this styling and then instead of this text here I'm going to have login here so there we go so if I go back now we have this text instead so if I already have an account you can click this and that'll bring me to the login page now the next thing I'm going to tackle is our form submission so right now we have a form or we can type in the elements and the state is going to be stored but I need to handle my submit so I'm going to create an on submit Handler function we'll take an event and this is going to be supplied to my form that is going to have an on submit which is going to use my on submit Handler function and by default I'm going to have the event get passed to this so I don't have to specifically pass the event like this and then into here as an argument I can just pass it like so and then typescript is going to complain so what I need to do is import my form event pass that as a type and I'm also gonna have a generic value of HTML form elements and then by default when we submit a form it's going to refresh the page I'm going to do event dot prevent default and call that in order to prevent that default behavior and then the next thing I'm going to do is I'm going to use that hook that we set up with rtk query to register so at the top here I'm going to import my use register mutation and then this is how we can use that top I can do const register is equal to my use register mutation and I can call that and then I can use this register this is going to be my function to actually register and then on top of that I can also grab some other values and then I can do that here instead of this options so I have things like it's loading is success is error and a couple other things but in particular I'm interested in is loading and then that way when we go to submit our form we can either show that button which we have right here or I can show some kind of spinner which is something we're going to set up a little later and then inside of here now that I have that register call it and then I can pass the arguments which we're going to pass in an object because remember it has to be passed as one argument so we do that with an object and then there I'm going to have all of these values so I need the first name last name email password and read password and then after that I can chain on a DOT on wrap and call that which from there we can have eight then Handler and also a catch Handler that we can chain on here so if this register is successful what I want to do is I want to show some kind of toast message that shows hey this was successful you registered your accounts now you need to activate it and then I also want to reroute them to the login page if it wasn't successful then I want to have some kind of toast message that says there was an error so to handle this sort of like toast alert thing I'm gonna install another package to help me with this I'm gonna stop running this I'm gonna do an npm install for react toastify so there we go and I'm gonna rerun and then close that up and then the next I'm gonna do is instead of my components utils I'm going to create a sort of like setup type component which is going to set up this toast container so the way that this works is you need a sort of like toast container component in your app and and from there you can import this toast function which you can do things like toast dot success and Toes dot error which you call and then that's going to use the toast container to display like a success toast and an air toast so this is how it's going to look I'm going to import my toast container and then I'm going to export default function setup and then from there I can return my toast container and then I'm also going to quickly go to the documentation for react toastify so inside of here it's going to show you kind of like what these toasts look like what you have to install and then also one line here that you have to set up so you have your toast container and you also have toast which you can use from here and then one thing I want to do in this setup is have this import as well and that's going to be for the styling of the toast so back in here in my setup component I'm going to paste this in here and then I'm also going to create an index.ts and I'm just going to export default as setup from setup and then what I can do is inside of my layout I can import this setup component from components utils and then within the provider I can just have this setup component which is going to be my toast container so now that I have that I can bring in the toast from reactostify and I can do things like toast.success so toast dot success along with a message has an argument and I can also do things like toast dot air along with a message and that's going to go display that toast message with either the success styling or the air styling so in the case of a success I'm just going to have the text of please check email to verify accounts and in the case of an error I'm going to say failed to register account and this is going to tell the user there was some kind of issue and the other thing I want to do is redirect the user to the login page to do that I'm going to import use router and then by default it's going to do this next router import but I don't want to do it from next router I want it from next navigation so that's the way this is going to work when you're using xjs13 with the app router and then here at the top I can do const router is use router and then with the router when we're successful I can do a router dot push to slash auth login so there we are now one thing inside of this page that we have is we brought in this is loading to show a spinner but right now we're not using that so what I'm going to do is inside of my common folder I'm going to create a spinner.tsx component and then I'm going to create my spinner here and then this is something I'm going to be able to reuse in my other components I'm going to export default function spinner and that's going to return some kind of spinner jsx component so the way I'm going to handle this is I'm just going to have some kind of Icon which is in the shape of a spinner and then I'm going to use Tailwind CSS in order to apply an animation that's just going to be rotating it and that way it's going to look like a spinner so to grab the spinner what I'm going to do is I'm going to install a particular package which is called react icons and then here you have a bunch of different icons that you can use one that I'm going to use to help me accomplish this is the IM spinner and then I'm going to use the I am spinner 3 which is this one right here so first of all we need to install this package I'm going to stop running my server npm install save react Dash icons and then within here you have icons from all sorts of places like fonts awesome let's say or hero icons or whatever you want is all in here and then the way that I can use these so I'm gonna actually rerun my desk server minimize that terminal and then at the top I'm going to import that icon so import IM spinner three from react Dash icons slash IM and then from there inside of here I can have a div with a roll of status and then I can put in my IM spinner three and then I'm going to be setting up the class name and then I want to be able to pass a couple options to this thing so I want to be able to pass options to make this like a small spinner A medium spinner or a large spinner so in order to accomplish that I'm going to install another package I'm going to stop running this do an npm install save class names that's the name of this package and this works in conjunction with Tailwind CSS very nicely and you're gonna see that in a second so what I can do is I can import a default import of let's say CN from from class names and then from there I can do const class name is equal to a call to this class names function and then I can pass in some default styling along with some optional type styling which will be based on different conditions so this spinner component I'm going to expect it to get some different kinds of props so if I pass like small or medium or large to this thing I want it to be styled in different ways so when I'm using this component I want it to be used something like this or I can just pass something like SM and that's going to be a small spinner or medium spinner or large spinner like so and then to accomplish that first I'm gonna fix this typescript issues so I'm going to create an interface for props which will have small which is a Boolean and it's going to be optional and this should be SM I'm gonna have medium which is also Boolean and large also a Boolean all optional and then I can pass in the props type here that'll get rid of the typescript issues and then here what I can have is if I have small which is truthy then I'm going to apply The Styling with Dash forum and height Dash four that's going to be for a small spinner then I can also have a medium and a large spinner so this package right here makes it very convenient for me to have conditional type styling this should be large that's what I'm going to have with dash six is going to get applied if I have medium set and then I'm gonna have dash eight for the width and height if I have a large pass to this and then this class name I can just pass to this here there we go and then I'm also gonna have some default class names in order to have this thing spinning so the Tailwind class for that is animate Dash spin I can have text white 300 fill Dash white Dash 300 and have a little bit of margin to the right let's say and there we go now we have a spinner component and another thing I can do is have a span with a class name of S Bar Dash only which is going to be loading so that way if this doesn't work then we're going to have the text of loading be like a default backup and then from there I can go back here I can import my spinner and then I can go down to my button and then here we can have some conditional checks so now what I can do is I can check if I'm loading and actually I'm not going to have this here but I'm going to have it here so it is loading in that case I'm going to show my spinner and I'm going to want it to be a small spinner otherwise I'm going to have the text of sign up and there we go that is now our complete register page so now we can test things out so back inside of here if I were to fill out the first name the last name the email which is my receiver email and the password I want to set now this may fail because actually I didn't clear my database so that's actually something I'm going to have to do I think about it because in the previous part I didn't do that so the way you can clear a database if you have data in there you can do a python manage dots Pi flush on your backend server you're gonna do yes and that's just going to clear the data and then I'm going to rerun this and then from there I can submit this request so when this is loading I should see a spinner and then either I'm going to see a toast of success and get redirected to the login page or I'm going to see an error so here we go moment of truth let's see if this works looks like I had some kind of issue okay so the reason why things aren't working is that we forgot to set up some middleware in our store so that's something that we actually have to go do so I'm going to go into Redux store and then Above This Dev tools I'm going to set up middleware which is going to be get default middleware and then I'm going to call this and do a DOT concat to API slice Dot middleware and then put my comma and I'm going to save to reformat this so this is something that we need in order for the rtk query to work so that's what we're calling the API slice middleware in here and then I'm just going to rerun my front end and then let's try to register for an account again so back in here I'm going to refresh I'm gonna put in the first name of John then do put in my email so I saw the loader there but I didn't see any toast pop up let's also see what else happened so if I open things up so I guess one thing I noticed we didn't even have this API request go through so that is interesting so let's see why that is in order to debug that what I can do is I can open up my API slice and then inside of here I just want to make sure I'm getting the correct value for this so I'll do next public host and that'll be my process EnV next public host so I'll go back here look at my console and refresh and it seems that we're getting localhost 3000 here so what I'm going to do is I'm going to adjust my environment variable and here it seems that I put in post instead of Port so I'm going to adjust that see if that fixes things I'm going to rerun I'm going to refresh and I'm going to see what shows up in the console so it seems even with that update I still get localhost 3000 so it seems that we have a port environment variable with next JS which is overriding this so what I can do instead is I can just remove this and maybe I can remove the host too and I can just put in localhost Colon 8000 here and that should fix things up for me so I'm gonna go ahead and restart then going back here now I see the correct value is showing up so there we go localhost 8000 so now we should be able to fill this out then if I click enter so now it seems that I ended up hitting my JWT create route that is not the correct route I expected to hit here so let's go see what's happening and then I'm also going to fix up this toastify so I'm gonna do that first just so I don't forget is it my setup component one thing I have to do is I have to put use client at the top here and that should fix the toast messages showing up so that's going to be the first thing that's just because reactostifier relies on some things which I need a client component for then I'm going to remove this console log and then I'm going to open up my auth API slice and I'm going to look for my register and then I'm just going to fix up this endpoint so this should be slash users slash not JWT create slash so we'll update that that'll be our post request passing this data and with that things should now work I'm just going to restart the server make sure everything is good and then we're going to test this out so we should end up with a request for our create endpoint and hopefully things will work so let's try that out so I'm going to now refresh put in John though the email enter and there we go we get our toast message now it says please check email to verify account so it seems that things worked and I'm also redirected to my login page so now I should also receive an email and there it is so now I can click on this so I can activate my account so if I were to click on this there we go my next JS client now handles this route so that's my activation route and then all I'd have to do is extract this uid and this token and hit my activation endpoint in order to activate my account so before I get to that there are some things I want to address with the way that things are right now with the register I'm gonna go back to this register routes and then back to the code I'm going to close up all of these and just have my page TSX open so this right now we have a pretty large file to handle all of this logic so we have what over 180 lines so we have this whole form here we have all of this logic so this component I think we can refactor and make it a lot cleaner so that's going to be the next step that we work on and then this refactor is going to help us a lot also going forward with other things because let's see our login our activation page password reset Pages all of those use a form so if we can make some kind of reusable form and also somehow clean up some of the logic we have here that should help a lot with going forward so first thing I'm going to do is create a custom hook so inside of full auth I'm going to create a hooks folder I'm going to call this one use Dash register dot TSX actually TS because this is not going to be a jsx component it's just going to get custom hook so I'm going to export a default function of use register and then to this I'm just going to grab a lot of the logic that we have in here and I'm just going to have this hook handle all of this form logic it's going to handle the use router with the navigation to the login under successful it's going to handle our huge register mutation it's going to handle our form data and it's going to handle our on change and on submit handlers as well I'm just going to cut all of that just to clean that up I'm going to paste all of that in here and then I'm also gonna have to bring in these Imports I'm going to bring in this import so that import is going to go in here and then I'm going to bring in these three Imports as well and those are going to go in here and then I just have to return an object and that's going to return everything that I need so it's going to be all of these fields and then after that I'm also going to need my is loading and then I'm going to need my on change and my on submits and that should be everything I need for this hook and then what I can do is in this hooks I can create an index TS and I can export default as use register from use register and this will just clean up the way that I import inside of my page so here I can just import use register from my hooks and then I can destructure all the properties from a call to use register and then what I need just to make this easier I can open up that hooks use register go to my return and just copy all these values and paste them in here so I'm destructuring all of these and there we go that's going to be my first refactor so that already cleans up a lot of my logic that'll be the first thing and then the next thing I'm going to do is I'm gonna have a form component so already inside of my components directory I created a forms and then in here I can make a form dot TSX and then I want to create some kind of reusable form here so let's go back to our page and I'm going to grab this entire form so this whole thing and it ends right here I'm going to cut it and then inside of here I'm going to export default function form I'm going to return all of that which I cut and I'm just going to save and then this form in particular is going to be one associated with my register so what I could do is I could actually make this a register form that's going to handle everything to do with registering and I'm going to rename this to be register form and then I'm going to have a separate form.tsx and then the form TSX it's going to be my reusable form which then in my register form I can pass like which inputs do I want so with my register form I want like a first name last name email password and a confirmed password and then with my login form I would want just an email and a password so the register form login form those are going to use the form so let's see how we can do this so this right here I'm going to do export default function form so this is where I'm going to have this form and already we have a little typescript here because we need this on submit and it's not even a typescript there it's just a JavaScript there so I'm going to create an interface for my props and one of these props is going to be this on submit and then on submit it's going to take an event and it's going to return void and then this event I'm going to import my form event and that's going to be the type on this thing and we're going to have HTML form elements and then this on submit is going to be a prop that I destructure and I'm going to pass the props so that'll get rid of this error so now let's move on to the next thing so we're also going to have these sorts of elements inside of here I'm going to copy this first element and paste it in here and let's try to make this reusable somehow and then something that we can do to help us out with this whole process is actually even make a separate further component which can be an input TSX and this will deal with just this input so I'm actually going to cut this thing do an export default function inputs this will return some jsx and this is where I can just deal with this input element so for this label I think a good way to deal with this is when we're using this input you can use it something like this we're then in between here can be our label like first name so then in order to do that this will be our children prompt which I can destructure and then we're going to want some typescript typing to this so I'll do interface props children which will be react.react node and then I'll pass this here that'll be one prop we need but we'll also need some other props so we're gonna have this right here so instead of having this hard coded this can be something like let's say a label ID so that's going to be something I need which is going to be a string and then I'm going to pass that as a prop here I'm also going to want to control this type in some way I'm going to pass a type which is a string I'm also going to pass that in and also let's use this children prop I forgot that that's going to go right here type is going to go right here so we can do type of text or email password whatever we need we're also going to need an on change and also we're going to need the value so the value is going to be a little bit different it's not going to be some kind of hard-coded string it's going to be the value that gets displayed in this input and used so first I'm going to deal with my on change is going to be an event that void and then let's get some typing for this with our change event from react now I'm going to pass the generic type of HTML input element and then I'm also going to have my value which will be a string and then I can bring these in so on change and value and then the value is going to get used right here and then I'm also going to have this required and then required I'm going to have as an optional Boolean and I'm going to do a default value for this of false so by default it's going to be false and I'm just going to do required equals required so now we have this input refactored so now I'm going to go back to my form and I'm going to import that input element now another thing I want to do just to make the exporting easier I'm going to create an index TS just like before I'm going to do an export default as form from form I'm going to do that for all these other components as well so we have our inputs and we have our register form and then inside here I can import input that's going to come from components form and there should be forms there we go and now we can use this input so here we're going to have our label text so we're going to have something like first name and then to this we can pass our label ID which is going to be first underscore name we're going to have the type of text we're going to have the on change so we're going to want to receive some kind of on change prop then I'm going to bring in that change event I'm going to apply that and I'm going to pass a generic type of HTML inputs elements and then I'm going to pass the on change then after that I'm going to have the value so here I can do value is equal to and then each input it's going to have a different value this is where now we have the thing so we're going to have multiple inputs like first name last name email password and so forth so I think a good way to deal with this is to just have some kind of configuration which is going to be an array and then we can map through it and create these inputs so that's the way I'm going to deal with that so I'm going to create first of all an interface for this config and then what I want this config to have is some kind of label text a label ID so the label text is what's going to go between here then the label ID is what we pass here it's also going to need some kind of type for each of these inputs so I know if it's a text a password email it's going to need the value which will be a string and then it's also going to need the required which will be an optional Boolean and then inside of my props what I can do is I can have a config prop and that's just going to be an array of these configurations so that way I can have let's say five different input fields that I configure and then from there what I can do is I can map through this config and then I also have to bring in the config inside of here and then I'm going to have an input and then each input is going to have these values that I can use and pass on through here and I'm also going to want to use the round parentheses so it'll just directly return jsx for me and then from there I can just do input dot label text here I can do inputs dot value then here for the type I can do input DOT type and then for the label ID I can have input dot label ID and then I also want that required and that's just going to be input dot required and then the other thing that this form is going to need is also the button so I'm gonna go here I'm gonna look for the button which is right here I'm gonna cut that go back to the form and I'm gonna paste so I'm gonna need some additional props and also I'm going to need the spinner component so first let's import the spinner that's components common it seems I didn't export that from here so let's fix that there we go so now that should fix that up and then I'm gonna need some kind of is loading prop so below here I'm gonna have is loading that's going to be a Boolean and then I have to pass this in and then also we have some hard-coded text here so that's probably going to be another thing I'm going to want to have some kind of configuration for so I'm just gonna have a button text prop and that's going to be a string which I can pass and that way I can adjust that text there so instead of having this I can have an interpolated string with that button text I'm just going to save that and there we go now we have a nice reusable input field and we have a form and then if you want you can take this even further right now in our application the only thing that we really need in our forms just normal input Fields but also you might have things like select tags or text areas so what I would do is I'll just create another component for like a text area or for a select tag or radio button whatever you need and then inside of the form in the configuration I can maybe somehow adjust what I want I can have let's say the form input type and that can be like selects or it can be inputs or whatever it is and based on that then I can render out the appropriate component but our application is not going to be quite that complex so I'm just going to leave that out but that's the way that I would do this going forward so now the next steps for us so right now this entire form we don't need anymore so I can just remove that because we've completely refactored that now instead what I'm going to want so inside of here I was using this spinner along with this use register hook right now I don't need this anymore so I can remove that and also this use register instead I'm going to handle inside of this use register form so I'm just going to paste that in here and I'm going to grab this and I'm going to bring that in here instead so now Oliver used register logic isn't here instead so we're using a custom hook right now which has a vent handlers and also life cycle hooks so what I'm going to want to do at the top here is do a use client and now back inside of here we're no longer doing anything with life cycle hooks or with event handling so what we can do is we can now remove this use client from this page so this is now going to be a server component and then what we're going to end up doing is we're just going to import our register form and that thing is just going to get placed right here just like that so now back in our register form what we're going to do is we're going to set up the register form itself so I'm going to need is my form that's going to come from my components forms and then I can use this component and then I can pass a couple things to it so I'm going to end up having some kind of configuration which is going to be an array and that's what I'm going to end up passing for the config now I am getting an error right now because I need some values in here but we're going to deal with that soon next I'm going to want this is loading I'm going to want the button text which in this case is going to be sign up I'm going to want the on change which will be my on change which I'm getting from my use register hook and then finally the on submit and then from there I just have to set up this config and then we have our form and everything is very neat and tidy so we're going to set up our first configuration we're going to need the label text the label ID and I can even just go here and grab these just I don't have to try to remember them and we're gonna have to type and then the value and then finally required which is going to be true so our very first element is going to be the first name I want that to have the label text the first name the label ID will be first underscore name type will be text value will be first name and it'll be required I'm just going to copy this I'm going to paste it we're going to have the last name last underscore name and last underscore name for the value type of text then the next input element is going to be my email address it's going to be email so if it label ID string of email value email type email then I'm gonna have my password fields so for the text password and then all of these will be password so string up password for the label ID for the type and value of password and then we just have one more field and that's going to be our confirm password field that's going to have free password the type is going to be password and the value is going to be re password so I'm going to save that and now let's see if this refactors get so going back here I could do a refresh and our form looks the exact same we have the input text we have all of these we can still type and we should be able to submit as well so what I'm going to do is I'm going to test out this register endpoint one more time so that email ended up deleting at some point so that's good I'm going to open up my terminal I'm going to stop running my back end I'm going to do a python manage.pi flush that's just going to clear my database and then I'm going to rerun my backend API then I'm gonna try to register for this account again so John Doe put in my email and let's see if this works there we are please check email to verify accounts and we got an email with our registration endpoint beautiful so this ended up actually working so now everything is much cleaner you can see the register page right now it's only 34 lines of code we have this register form which is much simpler we just have this form component which we passed config to and then the form itself also relatively simple we just have this input element that we're mapping through passing in our config values that's going to have the button with the loading where it's gonna have a spinner if it's loading and button text if it's not and there we go everything is nice and clean now and on top of that we also have this use register hook which also cleaned up a lot of our logic with the registration so going forward this is going to make things a lot easier with our other Pages because we're going to be able to reuse a lot of these components that we made and the logic that we made so I think the next thing that makes sense is our activation endpoint because that is what's going to allow us to actually log in so let's tackle that one next so I'm going to open this one up and then another thing I want to do before I tackle that is also make a little tweak to my layout so that is right over here and then this is going to be the last tweak to my layouts so I'm just going to pass some styling to this with MX Auto so margin on the horizontal axis will be set to auto then Max width 7 XL and then padding on the horizontal of two and then on a small screen padding of six and then large screen px-8 and margin top I want to be eight and maybe instead of margin top I'll just do margin along the y-axis will be eight so top and bottom I'm just going to save that and then what that's going to do for me is just have a little bit of spacing between my nav bar and the footer and also it's going to position this a little bit more centered so I think that's just going to look a little bit nicer once we end up having our nav bargain footer and now I'm gonna go back to this page so I'm going to put some styling on this I'm going to have a div instead it's going to have a class name and we're going to apply flexbox to this midnight full Flex Dash One Flex Dash column justify Center padding along the horizontal of six along with the y-axis of 12 and on large I'll have padding X of 8. then I'll have another div in here this will have a sem MX Auto and then smw full SM Max W small and then I'm gonna have an H1 element and that one's gonna have the text of activating your accounts I'm gonna apply some styling to this it's gonna be margin top 10 text Center text to excel font bold leading nine tracking tight to gray 900 and let's see how that looks so if I were to click on this link I'm going to be navigated to this route and that's gonna have my uid and token and I'm going to have activating your account so that looks pretty good next I'm gonna freaking use effects and then this use effect is gonna end up calling that activation endpoint and because I'm using use effects what I do at the top is also to use client to make this a client components then in here I can have my use effect and this is going to get cold when this component mounts and then to use my activation I'm going to import my use activation mutation I'm going to call this thing and then here I'm going to have my activation function that I'm going to be able to use which in the use effect I'm going to end up calling and then I need to pass the uid and the token to this so what I can do is as a prop something that I have available is my params so because I have this uid and token these will be present in a prop called params and then I can extract the uid and token from there then I'm also going to make an interface props this is going to help me with the typescript typing I'm going to have params which I expect to have a uid of string and token of string and then I'm going to pass the prop type here and then inside of here what I can do is I can destructure my uid and token from the prams and then I can pass them in I can chain on and unwrap and then have my then along with my catch and then the only thing I'm going to do is I'm going to have those toast messages depending on if we're successful or not so inside of here I'm going to import toast from react toastify then on LinkedIn I'll do a toast success and I'll pass a message of accounts activated and I'm gonna have a toast air if we fail and it's just going to say fail to activate accounts and then I'm also going to have a finally block which no matter which of these we hit we're going to redirect the user so to do that I'm going to import use router from next router set router equal to use router and then here I can just do a router.push and that's just going to go to auth login so after we activate we'll redirect to the login page and then that's going to allow the user to then just fill in their email password to log in and with that I can just save to reformat everything and this should be good to go so back inside of here I can refresh and also right here I have to actually fix this this is not coming from next router but from next navigation because I'm using the app router and there you go already I ended up hitting that endpoint I see the toast message of account activated and in the finally block we got redirected to our login so I'd say the next thing that makes sense is putting together our login page I'm also going to delete this email now since I don't need it anymore and the login page will be relatively straightforward just because it's going to be very similar to our register page and we're going to be able to reuse a lot of those components and then also a quick thing I want to do before I do that is also go into my register page and I also want to set some metadata something I noticed so I'll do cons little export const metadata and I'm also going to import a type of metadata and I'll set that here so on your server components you can export this metadata and then from there you can set up a title and description so here I'll do full off and then register and I'll have a description which will be full auth register page and then from there if I go to my register here I'm going to see full auth register perfect and then I can do something similar from my home page as well I'm just going to copy this open up the page and I'm going to paste and this will be home and home page so that way when I'm on the home page instead I'll see something like full off home there we go I'll navigate back and now let's start dealing with the login page so to make the login page easier I'm just going to copy everything that's in the register page I'm going to open up the login page I'm just going to paste it in here and I'm going to tweak it so here for the title I'm going to have login for the description I'll have full auth login page this will still be page and let's go through this so all of the styling is going to be the exact same but just this text here I'm going to change so I'm going to do sign into your accounts that's going to be my H2 instead of register form I'm going to create a login form which eventually I'm going to be able to import from here for now I'm going to get an error but that's going to be gone in a moment and then here for this link we have this text of already have an account instead I want don't have an account then you can register here and then this is going to be my register route and then also here inside of the text we have this apostrophe one thing that you can do is also use this and a pause colon and that's just going to be the sort of HTML encoding which you can use for the apostrophe so there we go that is now our login page set up the next thing we have to do is set up that login form so inside of my components forms I'm going to create a login form dot TSX I'm also going to go into the index TS here and I'm also going to copy down a line and this is going to be my login form and then here I can export default function login form which is going to return my form so let's take a look at our register form because this is actually going to be quite similar so in particular I'm going to import the form I'm gonna need the use client because I'm going to end up putting together a custom hook for the login and then I'm gonna end up calling that I'm gonna have some kind of configuration so I'm just going to copy this config and I'm going to paste it in here and then for logging in we don't need the three password all we need is the email and password configuration that we're going to pass to that form component so those are the only things I'm going to have present in here now we're getting errors for this because we need to set up our custom hook for the login and then finally we're just going to have this foreign component that we return so I'll just paste that in here and then also our custom hook for logging in is going to have these fields as well that it's going to return so for now we're going to get an error but we're going to fix that in a moment so inside of my hooks what I can do so I can have use login.ts and then I'm going to grab everything that's inside of the use register I'm going to copy it I'm going to paste it in here just so that I have an easier place to work from and then let's start tweaking this so first of all this use register mutation instead we're going to want to use our use login mutation and we're going to have a login I'm going to call this use login for the form data we don't need a first name and a last name we don't need a read password and then for destructuring I'm only going to destructure email and password from the form data the on change will look the same however the on submit will look different instead I'll use my login which I'm grabbing from the call to the use login mutation to this I'm only going to pass an email and a password and then just like before I'm going to unwrap call the then now if I'm successful instead of pushing to auth login I'm going to push to my dashboard so for successful navigate to dashboard we do have a route for that right over here and then for this I'm going to have a text when we're successful of logged in and then if we failed I'm just going to say failed to log in and then finally I'm going to be returning the email password is loading on change and on submit and there we go now the next thing I'm going to do is just to make importing this hook easier I'm going to open up my index TS I'm going to copy down I'm gonna have a use login which is from use login and then this way I can just import directly from the hooks folder and then back in my login form I can import use login from hooks and then in this component I can call use login and then I can destructure the values I need and then to make this easier inside of my use login I can just copy all of these return values I can paste them in here and I'm just going to save to reformat there we go we have our login form so now all you have to do is go back to our login page and save and this should all be set up so going back here if I now go to my login routes we should have our sign in page so sign into your account don't have an account register here now there is an additional thing that I want on here and that is on this password I want there to be some kind of link for forgot your password and I want it to be right here so to do that I'm going to edit my form a bit and it's going to have this sort of additional configuration that I can pass to a particular input in order to have present what I want there so first of all I'm going to open up my inputs and this is where I'm going to have this optional logic I'm going to have some kind of prop that I can pass called link and if I have this link then I'm going to return some jsx it's just going to be a div with a class name of text small and I'm also getting complaints so I guess I'll just put this in here this will be an optional prop and that's going to be an object which is going to have the link text I need along with the link URL since I'll link to both of those things and then I can just bring this in here that'll get rid of typescript complaining and then from there I'm going to need a link so I'm going to import the link component from next link and I'm going to use that in here and then what I can do is use the link dot link text here and have an href which is going to be link dot link URL and the last thing I'm going to do is I'm just going to style this link because I'm going to pass a class name and I'm going to have font semi bold text Indigo 600 and then on Hover I'm going to have text Indigo of 500. so there we are and then in the form I need to be able to pass this forward to these inputs so back to my configuration I need to have an additional configuration which is an optional link which is going to be an object which again is going to have that linked text it's going to be a string and Link URL which is also a string and then we can just pass that forward so into this input I can just do link equals link and there we go and then I also have to have this coming from the inputs so there we are and then another thing that I think would be good to do is also on this button you can also pass a disabled prop and this I can pass is loading so if is loading is true this button will be disabled if it's false it won't be I think that's just a nice additional thing so you can't keep clicking the button if we're loading and then our next step is to go into this login form and now here we can just pass this additional link configuration option with our link text and our link URL so for the link text I'm just going to have forgot password question mark and this is going to be slash password Dash reset there we go and then back here now I can see it's showing up now I don't particularly like how this is showing up here since I want this to the left this to the right so let's also fix that up and then also another thing that I'm realizing is here I also forgot to pass the key prop so whenever we have a list of components we want to have some kind of key this will be input.label ID so this just has to be some kind of unique identifier this just has to do with react Dom rendering so that's going to be one fix and then inside of here this is where I'm going to have my other fix so I'm going to need to have a div wrapping these and then the stiff I'm going to pass some styling of flex justify tween and line Center so let's see how that looks and there we go so that styling works fine for when we just have this and it works great for when we have the link and then this link we can click and that'll bring us to the request password reset so there we are and now that we have that configured and also I want to test this link perfect and now let's try logging in so I'm going to refresh go to the network tab put in my email and then the password and I also noticed I have the text sign up here so let's actually fix that so that's in my login form here I want sign in for the button text so you can see it's very easy to configure this and I'm gonna have to retype this in now and there we go logged in now let's go to application cookies hmm well I don't have any cookies here and then here I can see that this was successful I got a 200 okay on top of that to my server it did receive this request however I don't see those cookies there and then if I go back to off login if we try it again I still don't see those cookies show up so there is a reason why these cookies aren't showing up and this is a behavior with only Chrome so if you use Firefox or Safari you won't see this behavior and in particular this has to do with one of our cookie options so for the same site property on our cookie we set a property of none and when you set a property of none what is required of the cookie is to have the secure property of true and to have an SSL connection so it has to go through https and that is also the case even if you're on localhost so that means right now if this app we had in production with an https connection which we will have once we get to deploying this everything will work on Chrome but right now during development annoyingly enough things will not work on Chrome because chrome doesn't have this Behavior work even though you're on localhost so that is a little bit unfortunate I wish Chrome didn't do that but that's just the reality of that so if I were to open up something like Firefox or Safari and in this case I'll use Safari and if I navigate here I can go inspect and then I can open up the storages so this is where I'm going to see my cookies and then I can navigate to auth login and then let's try to log in and we're logged in if I refresh there we go we have our access and our refresh token so that worked we can see the domain is here the path is here we have secure isn't checked HTTP only is checked and same site is none indicated by this line here so in Safari this works and then also if you're using Firefox this will also work so pretty much going forward with our development if we want to test this authentication that we have set up in our development environments unfortunately we are going to want to use a different web browser so if you're on Windows just use something like Firefox and then if you're on Mac use either Firefox or Safari it doesn't really matter now I'd say the next good thing to perhaps tackle is this navbar component so that way we can have our login and sign up buttons and easily navigate to those pages and then we can also have the dashboard button and log out button when we're logged in and then it's also a good indication of if we're logged into the application depending on which buttons we see so let's tackle that next so I'm going to close up some of the stuff I'm not working on anymore and now let's open up our navbar component this is where we're going to be working and then I'm gonna go into the Tailwind UI documentation once again and then there is a navbar component in here that we can grab and it'll just help us put this together a little bit more quickly and have a nice looking nav bar so right under navigation I have nav bars and then this first one this is what it looks like now it does have some additional things like this notification area and also this profile area and also some additional navigation buttons which I'm not going to want so we're going to tweak it a bit but for the most part we're gonna have something very similar to this so I'm going to switch over to the react click on the code and then I'm going to grab the code in here so I'm just going to grab the jsx so everything in here so there's quite a bit of code and we're going to edit this quite a bit then going back to my nav bar I'm going to paste this in here and then we'll fix up the indenting and then the next thing I'm gonna fix the Imports so one thing I need is this disclosure and this disclosure is something that comes from headless UI so headless UI actually have the documentation open and then the disclosure is this thing right here and then also from what you can see here this is a completely unstyled fully accessible UI components and they're designed to be integrated really nicely with Tailwind CSS so that's pretty nice for us and then it's a project also by Tailwind labs then we can click on this disclosure and then you can take a look this is pretty much what it is where you can have things that you open and close and that's what we're gonna have with our nav bar because when we're in the mobile view so if I go back to the nav bar in the preview right now we can open and close so we want to have that ability and then we can see the same thing here now to use headless UI we just have to run the npm install command so I'm going to go back open up my terminal and then I'm going to go to the one running the next GS front end I'm going to stop running it and then I'm just gonna npm install the Headless UI react there we go and then another thing that we're going to need so this nav bar it's also using some icons which come from hero icons react so I also have the documentation for that here and then you can see like these are all these different icons that come from this Library so we're also gonna have to install that so back in my terminal I'm gonna npm install save at hero icons slash reacts and then I'm going to rerun the development server and then back in here I can just grab these lines go back and then paste in these Imports and then I'm not going to need the Bell icon because that's for that notification then I'm also not going to need these two here so I'm just gonna import the disclosure the Bars 3 icon and the xmark icon and then those icons so if we look at the bar icons we have this bars three so that's just like our hamburger button then we also have the x mark and that's just this sort of x so when the menu is open we're going to see this x when it's closed we're going to see the hamburger and that's going to be on a smaller screen so back to the code I'm now going to save just everything reformats nicely and then I'm going to clean up some of this code so this is where we have our button which when it's open we have that x button otherwise we have the hamburger button and then down below so right here this is where we have that icon for tailwind and in particular I don't want the icon for Tailwind so that's something I'm going to adjust also there's this whole navigation looping so this is something I'm not going to do so I'm going to just remove that and then this is where we're gonna have our different Navigation links and then this is where we have things like the Bell icons and the notifications so this whole button I don't want and then also this whole menu which is for that profile I also don't want so this entire menu area I'm also going to remove so that's going to clean up a lot of our code and then we don't need this whole block here that was also containing that and then the next part we have is also this navigation here and then this was for those links for the mobile menu so I also don't need that so now we're gonna continue from this point so first I'm gonna get rid of this here and then instead what I'm gonna want is a link and that's just gonna say like full auth so I also need to import link so at the top I'll import link from next link and then right over here I'll use that link and that's gonna have the text of full auth and then it's gonna have an href of Slash so let's see how things look so far and then also we're having an issue because this needs to be a client component so at the top I'm just going to put use clients and Save and there we go now we see the text full off and then I don't like that this is black text so let's also edit that I'm going to put a class name of text White it's going to be rounded medium padding on the X and the Y and then also font medium and then actually instead of the text white I'm going to put text Gray 300. so let's see how that looks there we go that looks better and then going back now we're going to deal with the other links and then also remember how we're managing these links so we're going to check if we're authenticated and if we're authenticated we're gonna have a dashboard and a log out to link and then if we're not authenticated we're gonna have the sign in and sign up links so let's have some Logic for that I'm going to import my use app selector as well as my use app dispatch also I need to use this patch because I'm going to have my logout action Creator which I'm going to need to use and then that's something that I can also Import in here so I'm going to import logout and that's coming from my features auth slice and then here I can do const dispatch is use app dispatch and then I can also do const is authenticated which is going to come from I use app selector then States and state DOT optional so here you can see you can select because of typescript helping us and then to do the logging out itself we also created that hook with rtk query so as our use logout mutation hook so I'm also going to use this and I'll use that say right here I have logout is equal to a call to this hook and now we also have a bit of a conflict between these two names so this one I'm just going to call off logout and or maybe even set logout might be a better name so I'll have this as set logout and this will be the actual logout action itself so this one here all it's going to do is set the is authenticated state to false that's all this is doing so to do the logging out itself we could have a function called say handle logout and then that will call logout we can do a DOT unwrap and then a DOT then any dot catch then we also have typescript complaining here that we have to supply an argument so we can actually just pass undefined here and that'll fix the typescript errors because the logout doesn't actually take any parameters and then if the logout is successful all we have to do is dispatch set log out and then that'll set or is authenticated to false and then if anything goes wrong um we're not really gonna handle it actually so all I'm gonna have is just a finally block instead and that's just going to navigate someone back to like the home page so in order to do that I'm going to import my use router and that's going to come not from next router but next navigation and then I can have const router is use router and then I can router.push to the home page so the log out button is what's going to be utilizing this and then I'm going to have const auth links which is just going to be some jsx and I'm also going to have my guest links auth links is going to be for when I'm logged in guest links is going to be for when I'm not logged in and then I'm going to change this to be guest links and then what I can do is over here where I'm going to end up having these links and actually they're not going to be here they're going to be between here so I'm going to have links between here and also between here so between here I'm gonna have is authenticated if that's true then I'm going to have my auth links otherwise they'll have my guest links then I'm going to have the exact same thing here as well all right so let's see how that looks so there we go right now we have our guest links because we're not logged in so let's Now log in and see if this updates to auth links so if I Navigate to slash auth slash login so it seems it didn't update even though I'm logged in so let's see what we did wrong so if I go into my use login hook we should be dispatching a set off when we're successful although we're not doing that so let's go ahead and fix that right up here I'm going to import set off and then I'm going to dispatch set off and then I'm going to have to set up this dispatch so maybe right over here I'm going to import my use app dispatch and then I will do cons dispatch is use app dispatch and then that way I can dispatch set off so now let's try that again so there we go we're back to the login page put in the email and the password and now I see auth links perfect now we will have one issue still which is if we refresh we see guest links we're not persisting our login so why don't we go ahead and tackle that so in order to handle that we made a component called setup then here I can have some logic in order to handle this whole verification so pretty much we want to use our verify endpoint and then if we have a valid auth token then what we can do is we can just persist the login so at the top I'm going to import use effect I'm also going to import use app dispatch I'm going to import set off then I'm also going to import my use verify mutation and then in this component I can call use effect and then I'm also going to need that to verify which is going to be from use verify mutation and then in the use effects when our component mounts I can call verify we dot unwrap and then a DOT then and then in the dot then I can just dispatch the set off and then this dispatch what I need to do is const dispatch is use app dispatch so that way I can dispatch that and I get typescript complaining here because we're not passing an argument so let's pass undefined since verify doesn't take an argument and then another thing that I need to do this is something I've explained before inside of our Redux auth slice we also have this is loading which is true so when we're finished verifying another thing we're going to do is we're just going to flip this to false and we can do that using our finished initial load action creator so that's another thing I'm going to import so finish initial load and then I'm going to have a Dot finally block that's just going to dispatch the Finish initial load which is going to set is loading to false and then another thing that we can do if we want to refactor this a little bit which I guess we might as well do so we can also create a use verify dot TS hook then exports a default function use verify and then go here and then everything we wrote out we can pretty much just tap in this hook and also custom hooks they don't need to return anything like we did with our other ones or returned an object with some values we can also just not return anything and then all of these Imports a cut and put in this custom hook there we go we now have a use verify hook and then in my index just like before I'm going to export the default as use verify from use verify and then what I can do is in my setup component I can just import use verify from hooks and just call use verify and that'll do the exact same thing it's just that this is a little bit more lean now and then with that we should now be able to go back to our app and now we see auth links again so if I refresh there we go auth links perfect so now let's actually have some auth links and guest links and actually have the work so that's going to be our next step and then for these links the links are going to have a bit of logic so the links are going to be styled differently depending on if we're on desktop or if we're on mobile they're gonna have different styling in that case and also if we're on the current route they're also going to have different styling and then also our log out button is going to be slightly different because it's not going to be a link so because of that one thing that would help is creating a custom component that has all of this logic and then we can just use that in here so inside of my common in my components I'm going to create a nav link component and that's going to house all of this logic so first I'm going to need link from next link and I'm also going to need to import CN from class names this is going to help me with that logic like we did in our other components then from there I can export my default function nav link and then this thing we're going to want a couple props I'm just going to destructure these props and then the way I want this thing to be called is to do something like nav link and then here I can put the text for the MAV link like let's say sign in and that's going to happen href which would be like slash auth slash login and then I also want to be able to let's say have things like selected and then that's going to put the selected styling maybe I want to have like is mobile and that's going to apply mobile styling so I just want to be able to pass these like Boolean values to this so to do that I'm gonna have a selected maybe I can even do like is selected it's going to be one value I need also is mobile and then I'm going to use this to help me decide is this gonna have mobile styling or desktop styling I'm also going to have a is Banner this one in particular is going to be used for this styling here of our Banner and then I'm gonna have the href and I'm gonna have children so let's start with that I'm gonna have an interface props I'm gonna have is selected it's going to be optional and it'll be a Boolean I'm gonna have is mobile it's also optional in a Boolean and then is spanner same thing then href will be a string and children will be react dot react node and then we can just apply the props to this and that'll have typescript not complain and then from there oops already got my return from there we can return our link with a class name and an href which will be href and then another thing I'm going to do is I'm also going to have over here a spread operator on rest so if I have any additional props like let's say a class name or an on click I can also have that within here and then what I can do to have typescript be happy with this as well is have rest string in Brackets mapped to any and then from there what's between the link is just going to be our children prop then the next thing I want to do is have our styling set up so I'm going to have const class name is is equal to c n and then here I'm going to have rest dot class name also going to have some default styling I applied to this so I'm going to have text White rounded medium padding on the left and right padding on the top and bottom and font medium this is what I'm going to have by default for my links and then I'm also gonna have an object and then here I'm going to be able to have some kind of additional styling based on these props so I'm going to have styling based on is selected based on if we're on mobile also if we have a banner I'm also going to have styling based on if we're not on mobile then I'm also going to have some styling based on if is not selected and if it is not a banner so if it's selected I'm gonna have a background Gray 900. if it's not selected and it's not a banner I'm going to have text Gray 300 and hover background gray 700 as well as hover text white so I don't want any of this hover Behavior happening on the banner which is why I also want to check if it's not a banner and then if it's not selected it's going to have this gray text and when I hover over it it's going to have a great background with some white text so it's just going to have like a hover Style and then if I'm on mobile the way I want these to be styled is with block and text face if we're not on mobile I want these to be text small so this block and text base it's just going to function with that sort of drop down that we're going to have and then text small is going to be for when we're on desktop and then for the banner I just want it to be text Gray 300 which is going to override the default text White so there we go now we have a nice nav link component which we can use so then inside of my nav bar I can just import that and then I also want to create an export for that so that was inside of here and then below the nav bar I'm gonna have my nav link and then I can import my nav link from the components common or I could have also just imported it from the current directory that's another option and now I'm going to go down to my guest links and let's edit this I'm going to remove what's here and then the jsx that I'm going to have is a fragment which is going to surround my two links that I want so I'm going to have my nav link component then I'm going to have my login as well as my register and then as for the props I'm gonna have is selected and then the way that this is going to work I'm going to check the current path and I'm going to see if it's equal to like the login path if that's the case we're on the path for login and then we're going to put the is selected styling so the way that we can get the current path we're going to go to the top and import use patterning and then below my use router I can do a const path name is use path name and then back down to my component what I can do is I can compare path name is equal to slash auth slash login if that's the case I'll return true otherwise I'll return false next I'm going to have is mobile and then for this what I'm going to do is I'm going to expect the guest links to receive a parameter so I'm going to turn this into an arrow function and then I'm going to have is mobile which is a Boolean so that's an argument I'm going to receive and then based on if this is mobile or not I'm going to apply either the mobile styling or I won't then I'm also going to have the href now the href is going to be slash auth slash login and then the register is going to look pretty similar so I'm just going to copy this paste it here and then for the comparison I'm going to have register and then here I'm also going to have register now here I have a little bit of repeated code so one thing I can also do is create a function called is selected it'll take a path argument and then that's just going to do the comparison between path name equal to the path argument if they're equal return true otherwise false just like the logic we have here and then instead of doing this I can just call is selected and that's going to return my Boolean and I just have to pass in this path name to compare so if our current path name is equal to this path name return true otherwise false and same sort of thing here is selected and there we go just a small refactor so that's going to be for our guest links now we're also going to have our auth links so this is also going to be an arrow function now and it's going to receive a parameter is mobile which is a Boolean then we're gonna have something similar to this I'm just going to copy this and paste it so here we're going to have our dashboard which is gonna have an href of Slash dashboard and then this is selected it's also gonna have slash dashboard that it's comparing and then as for the logout button this one's going to be a little bit different so I don't want this to be a link so I'm not going to pass this href and I'm going to need some kind of way to designate that this is a log out button and then another thing is this is selected I also don't need that's not going to be relevant for a log out button and what I will need is some kind of on click which is going to be captured by that rest prop inside of the nav link and this is just going to have my handle logout so now we have to go back to this nav link and somehow have it handle a log out button then on top of that I also need to apply this class name here that's something I forgot to do let's do that and then one way that we can designate this is a log out button or not is we can just check do we have the href if we don't then it's just going to be a normal button if we do have an href it's going to be a link so that's the way I'm going to handle this so if we don't have an href return R button so the button is going to have a span with a class name of classening so that's just going to have our default styling so it's not going to have any of this special styling and then this will have a roll of button and it's going to have an on click which is equal to rest dot on click so that's how we can capture that on click and then it's also going to be text of logouts there we go so now going back to my nav bar we still have typescript complaining and that's because we actually have to make the href now optional so let's do that and then another thing I'm gonna have to do is also this right here I'm noticing I just hard coded logouts what we actually have here is the children prop and then we can pass the logout text and then back back here right now the other thing we're gonna have to adjust is that previously we didn't have these as Arrow functions where we pass is mobile and also these right here shouldn't be curly braces let's also adjust that to be the round parentheses because this should be returning jsx so that was a bit of an accident and then let's scroll down so this is where we have this logic here and now these ones are going to be functions instead and we're going to pass false because I want is mobile to be false for the ones here and then for the ones here I'm going to pass true because I want the ismobile styling on these ones so there we are now let's take a look oh and also one other thing I just noticed I also have this link so I no longer have to have it like this I can just remove this class name and then I can use the nav link and then I can pass the is Banner property and then that's going to give me the styling I need so let's go back this is how things look right now so I have my banner it doesn't have any hover style and then if I go to the login we saw we have this hover style if we're on the current page we have this styling here so perfect now we can navigate things look proper and then if I log in let's see how things look there we go we're logged in we go to the dashboard and I see the dashboard and the logout button so if I refresh now we stay logged in perfect I can go to the home page and I can log out if I refresh I'm not logged in so we got rid of those cookies so perfect things are working so far so now let's also adjust this footer so I'm going to close the nav bar we're now wrapped up with that one gonna go to the footer and let's adjust this so for the footer I'm going to have a class name it's gonna have a background degree of 100 and it's going to have a height of 16. and I'm going to remove this instead I'm going to pass a div with a class name of H dash full take up the full height and then have some padding on the left and right I'm gonna have another div in here this one's gonna have a class name with flex items Center justify Center and H pull to take up the full Heights and then in here I'm gonna have a paragraph and then this one's gonna have the text which is going to be and copy to have that copy symbol 2023 full auth Inc let's say all rights reserved so you typically see some kind of text like this and then I'm gonna just put some styling on the paragraph it's going to be text Gray 400 and text extra small so there we go that's all we need for the footer let's take a look how it looks and there we go looks pretty good now let's tackle this home page so for the home page I'm going to go into the Tailwind UI I'm going to go back to the components and let's look for a home page so for the home page all we're really going to want is a hero section so you're going to find that under page sections and we're just going to create a component that looks something like this then here I have react selected you can go to the code and I'm just going to grab the code that's in there and I'm going to tweak it to look good on our app so everything inside of here I'm going to copy so quite a bit of stuff there we have this header here so that's a lot of code just for this but we already have like this navbar heading so we're just going to get rid of that code and also a couple of other things so back inside of our page that's going to be this one here I'm just going to paste all of that in here I'm going to save and then I'm going to start to edit so let's find where that whole nav bar is so that's this header I'm just going to delete all of this code because I don't need that this rapid div I'm going to change to a main tag then this whole clip path I don't want this so I'm going to delete that and then this here this is this section here the announcing our next round of funding so I don't want this section either so I'm just going to get rid of this whole thing and also be wrapping div and then we have the H1 and a paragraph along with the buttons which are going to have links and then below that we have this clip path so I'm also going to remove that so we're just going to be left with something clean like this so let's go back and see how things look and there we go we have a decent looking home page so now let's just edit the text so for the text I just have some text on my other screen that I'm just going to copy and paste here so I don't have to type all this so for the H1 I'm just going to have full off tutorial application and then for the description I'm just gonna put this kind of General description here you can put whatever you want for these doesn't really matter and then I'm going to set up my links import link from next link instead of these anchor Tags I'm going to have links and then for the href on this one this one's going to be slash auth slash login and the other one's going to be slash auth slash register and then the text for this one is going to be log into your accounts and then for this one here I'm going to have or create and also we have this arrow symbol here another thing we can do is ant r a r r with a semicolon so this is going to be a right arrow so that's kind of the way I'm gonna do it instead and there we go we should now have a complete home page so let's take a look full off tutorial application along with our description and then our two links so I can click login bring it here and then we can have this which will be for register so next I want to tackle the forgot to password so if I click on this forgot password link I'm going to be brought here so let's go edit that so I'm going to close this and then I'm going to open up the password reset page TSX and then within here I'm going to do an export const meta data just like I've been doing on the other pages and then I'm also going to import a type of metadata and for this one I'm going to put a title of full off password reset along with a description and also let's apply this so I can have typescript completing this description there we go and I'll have full auth password reset page and then here I'll have a div which I'll Style with the class name and this whole styling here is going to be very similar actually to the login page so I'm just going to copy what I have in the login page then go back here and just paste that here and then for my text I'm going to have reset your password and then I'm going to have a form which is going to be a password reset form that's going to be something that I create and then I'll be able to import it we'll put in the import for it and that'll end up coming from my components form actually it'll be components forms so then that's something I have to create and then for this don't have an account section I don't need any of that so the next thing I'm going to tackle is this component so just like we've been doing before inside of forms I'm going to create this password resetform.tsx sport default function password reset form which will return my form and then in the index what I can do is just copy down on one of these and that's going to be my password reset form so that way my page I can actually import it so now let's go back to the actual password reset form so for this one something we're going to need is our use password I guess use reset password mutation we're going to meet this and because we're using rtk query in here we're also gonna have to do at the top use client on this form and then another thing I'm going to want is my perform components which will help me create my forms and that's coming from components forms and then in here what I can return is just my form along with the configuration I want I'm gonna have const config that's going to be my Beret and this one's just going to have one item it's going to be the label text of email address it's going to have a label ID of email type will be an email field I'm going to have on change which I'm gonna have to set up along with the value and required so what I can actually do is just like I was doing before I can create a hook and just have a lot of this Logic for this sort of stuff in there along with the on chains just like we've been doing with like the login the register I'm going to cut this from here I'm going to go into my hooks I'm going to create a use reset password dot TS export a default function of use reset password I'm going to import this then I'm going to go to something like my use login or maybe I use register might be more similar and then I'm just gonna copy some of the logic in here so things like the form data the destructuring and all of this stuff paste added here to have a good start and then if we scroll up the only thing we need is an email field so because of that I don't really need to do this whole form data part instead I can just do const email and set email is use States and then I'll need a couple Imports so I'll need to use state from reacts and also the change events and the Forum events and I'm also going to need my toast and then for my on change this is just going to be set email and then that is going to be equal to events Target value and I'm gonna get rid of this the structuring then on my on submit this is where I want to use this use reset password mutation top I'll do const reset password and is loading will be coming from a call to my use reset password mutation and then I can use this reset password instead of this register then the only thing I need to pass here is the email and then also I'm passing that directly instead of inside of an object because that's the way that this handles it so if we take a look at the reset password we just take an email unlike these other ones that take multiple parameters or we pass them in an object and then if we're successful I'm not going to do any kind of rerouting so I'm going to remove that and then I'm just going to have a message that's something like request sent check your email for reset link then if we fail we're going to do is fail to send requests which we should never hit just because this will always return a 204 no content and then I'll just get rid of these fields here and the only thing we should have is email is loading on change and on submit and there we go this is our hook in place so now we can go to the index and we can just export this will be use reset password from use reset password and then back in my form now what I could do is I can just import to my use reset password hook and then I can use this right here so I'll call that and then I'm going to de-structure from that my email is loading on change and on submit all right so now I can pass this on change I can have the value of email and required true so I can finish this configuration so now that that's complete I can now pass it to the form along with the other fields so is loading I need and then the button text which I'll do requests password reset change and then the on submits and there you go just like that's our page should now be complete so I can close everything up and let's take a look so reset your password and put in the email enter and there we go request sent check your email for recent link so let's do that here if I refresh there we go and get the reset link and now I can actually visit this I'm just going to copy this I'm going to go back to this window and visit this link and this is where we can set our new password although now we have to set up this page so that we can actually do that so let's go ahead and take care of that so that we can reset our password on next.js so that is going to be inside of this uid token page so this is where we set this up and also this right here it's going to be very similar to what we just did so what I'm going to do I'm just going to copy everything inside of my password resets page I'm just going to paste it in here so that we can kind of start off from this point and then for the title I'm going to want password reset firm and then this will be the full auth password reset confirm page and then for the heading I can just use the exact same heading the only difference is now it's going to have like two inputs for changing my password and then I'm going to have a different component so this component I'm going to call password reset confirm form so I have to create this so instead of my components forms I'm going to create a new component which will be called password reset confirm form.tsx and this one's going to be very similar to this one here so I'm just going to copy the code that's in here close this one and paste it here and then this is going to be for my password reset firm form and then I'm going to create a custom hook specifically that works for this so for now I'm just going to remove this I'm going to have some kind of configuration and this here but first I want to take care of that to hook logic so let's do that so that way we can just grab it from here and continue it's on the hooks I'll create a use reset password confirm dot TS I'll open up my use reset password copy what's in there and paste it here I'm going to call this hook use reset password confirm and then I'm going to want to use a different hook so that's going to be the use reset password confirm mutation which I'm going to call and then this will be reset password The Firm that's what I'm going to call this and I'm going to call it here on the on submit and then I'm also going to need my use router and that's going to come from next navigation so when I reset my password I want to redirect them to the login page that's the reason I want that another thing I'm going to need is use params because I want the uid and the token I want to be able to extract those so you're going to have router is use router and I'm also going to have the uid and token the structured from use params and actually there's maybe even a better way I can go about this instead of doing use params I can grab those params from the component and then I can just pass them in as arguments here I think that's I'm going to do it instead so let's do that and not import to use params and the next I'm going to do is I'm going to have form data and set for data which will be my object and in here a lot of new password and three new password and I'm going to destruction these and then we got the on change so I'm going to destructure the name and value from events targets and then I'll do set form data with spread operator on form data name and value and then for the on submit I'm going to be calling this and I'm going to be passing as arguments the uid token the new password and re new password gonna do the unwrap and then when we're successful for the text of the toast I'll do password reset successful and then I'll do a router push to the slash auth login routes and then on a fail I'm just gonna do password reset fields and then as for what I'm returning I'm gonna have new password renew password is loading on change and on submit and then also for these two values let's just pass some types to them so I'm going to have string and string that way type script doesn't complain so there we go and then back to my component what I can do is I can grab the params then I'm going to create an interface of props which will have params where I have uid and token and then I can further destructure the uid and token straight from here and just use them directly and then I can just pass the there we go and then let's import that custom hook I made use and actually before I do that I actually need to go into my index and then right above I'll have my use reset password confirm which will be imported from here and now I can actually go back to my components and import it like this straight from the hooks and then I can call that and I can grab the values I need so we have the password three new password we have is loading change and on submits and then the other thing we have to do is also pass arguments to this of uid and token there we go and now let's just finish setting up our config and then we're good to go so this first one is going to have a label of new password and then this will be the password the value is going to be new password and the type of the field will be a password field so there we go I'm gonna copy this and paste it down then the next one is going to be confirm new password this will be Wii new password and the value same thing type of password and there we go now we are all set so now we can test out changing our password and let's also make sure things are good here so we do need to actually go into the forms index and then we need to export this new form we made so I'll do that right here and then it's actually password reset confirmed form so let's fix that there we go password reset confirm form so we got that there and then the last thing we have to do is just extract the parameters from here and pass them down onto here should be a better way that we can pass those down we don't have to do it through this params way we can just have let's say uidn token and then I'll just save three format and I'll just do it like this so that's a little bit cleaner and then in the page itself what I'm going to do is I'm going to have that params and then uid and token here and then I'm just going to set up the interface of props very half grams with uid string and token string apply that here and then just pass uid and token so there we go should be good now so let's test this out we have reset the password I'll set a new password send the request password reset successful and then redirect it to the sign in page so let's see if it worked so I'll put in the old password so that fails then if I put in the new password there we go logged in and redirected to the dashboard so the next thing I will tackle is this dashboard so back to the code I'm just going to close everything up so we're almost done with this app so let's open up the dashboard now and then the dashboard I just want something that shows this is a dashboard and just have like a list of the first name last name and the email and that's pretty much going to be it for the dashboard so inside of this here I'm just going to configure this a little bit different I'm gonna have like a main section this is where I'm gonna have my list and then above that I'm gonna have sort of like dashboard header it's like a class name of background whites with a shadow then within here I'll have a div that'll have a class name MX Auto MX with and then 7xl padding on the left and right top and bottom on small I'll have six and on large I'll have eight on the left and right for the padding and that'll have my H1 which will say dashboard and then here I'll have a class name on this which will be text 3XL font bold tracking types text Gray 900. let's save that there we go looks a lot better so it's in this sort of like box with a shadow this is where I'm going to have this list and then for this list I'm going to have some styling on the main just gonna have MX Auto actually this should be MX Auto not auth gonna have Max w 7xl py-6 margin Y dash eight small will be px6 large will be px8 and then I think also on the home page I might have I know I have MX Auto here but I know somewhere else I definitely did MX auth ah that was here this was on let's see which page on my activation page so yeah that should have been MX Auto there we go so I'll close that up and then back to the dashboard what I'm gonna do here is I'm gonna create a sort of list component which I can pass some configuration to because I'm gonna have like a list of different like list items so inside of my components common this is where I can create this list component so I'm going to export default function list which will accept some kind of config prop and I'm going to set up some typing for that it'll just have a label which is a string and it'll have a value which is string or undefined and I'll have my props which will have config and that'll just be a list of these configuration objects after that I'm going to return and let's go to the Tailwind UI real quick instead of the hero sections I want to look for a list component and then here under lists you can find stacked lists and then here we have an example so I'm going to grab the react example just to help me out so we're going to have a UL which is going to have some styling like this and then between there we're going to have list items so let's grab these list items and paste one of these in here now our list items are going to be much simpler than this because the ones here look like this although we don't have any images and it's not going to have all of this styling so I'm going to get rid of this key and then I'm going to flex justify between with The Gap and the padding on the top and bottom then this whole image I'm not going to have so I'm just going to get rid of this and I'm also going to get rid of whatever's between here and then also I'm not going to have this styling here so let's div here what I'm going to have is a paragraph it's going to have a class name with text small font semi-bolds leading six Gray 900. and here is where I'm going to have my label and then for this one here I'll have a paragraph the class name which is going to be the exact same and then this is where I'm going to have my value so the way that this is going to work now is that this config I'm just going to map through it so config dot map and then I'm going to destructure label and value and just return a list item with those values plugged in so for the label you can just pass in label then for the value I can pass in value and then if this is undefined what I can do is I can just have like a spinner I'm going to import my spinner component and that's from components common so if this is undefined I'll just have my spinner and then I'm just going to set it to be a small spinner so there we go we have our list so back to the dashboard I can import that let's also make sure that in the index we have an export for the list so I'll have that right here and that way I can just import the list like this and then I'll have that component here and it's going to have some kind of config which I'm going to Define now so that's going to be an array with objects that are going to be labeled and a value so I'm gonna have one that's for the first name it's gonna have a value then I'm just going to empty for now because these values themselves are going to come from our retrieve fuser hook last name and email and let's utilize that hook I'm going to bring in my use retrieve user query and because we're using rtk query I'm going to declare this as use clients and because we have used clients I'm not going to be able to do the export to metadata and I'm okay with that because for like a dashboard page you don't really need a title description kind of tag although you could also refactor things so that you could have that in here but I'm just going to leave it like this and then I'm going to do const data is coming from use retrieve user query and then I'm just going to rename this to be user and I'm also going to grab is loading and is error from here and also this config I can now pass and then I'm just going to set these values you can have user question mark DOT first underscore name so this is undefined this will just be undefined if it's not undefined we'll grab the first name we'll grab the last name and we'll grab the email and then another thing I'm going to do is I'm going to bring in the use router this way I can navigate someone if this fails so if we get an error let's show a toast message and navigate them so I'm also going to need toast and then if we're loading I'm going to show a spinner so that's another thing I'm going to import it's over here I can have it is loading return a div with a class name Flex justify Center and then margin on the top and bottom I'm gonna have my spinner which is going to be a large spinner and then if I have an error what I'm going to do instead is router push and also I have to router is use router and then I can write a push to slash auth login and I can show a toast with an error that says please log in then here we get a bit of an issue with next router was not mounted and that is because use router I grabbed from here it should be from next navigation so let's fix that there we go we got our dashboard with the first name last name and email and then if I log out I get redirected and let's see what happens if I try to visit dashboard directly I get to please log in so that's good so we can see that we already have some form of protection on here now another thing I want to do for protecting routes so right now we're protecting this route by doing this whole retrieving of the user although we might have protected routes where we're not doing it with this sort of method this is more just like we're retrieving our user and then if we have an error let's just reroute them however I want to have a sort of like default way of protecting routes so what I can do is in my utils I'm going to create a component called require off dot TSX I'm going to export defaults function require off and then how this is going to work is I'm just going to use that is authenticated piece of state and I'm going to see whether it is true so if it's true we're just going to render out whatever this is wrapping so we're going to have some kind of children prop and this is going to be a pretty simple component in terms of jsx we're just gonna children being wrapped and now let's create our interface and I'll pass that here and then what I'm going to do is I'm going to import my use app selector and then I can use this thing to grab my is authenticated piece of State so I can do that like this and because I'm using Redux toolkit here I also have to make sure I have use client at the top and I'm also going to bring in use router because if we're not authenticated then we want to reroute them to the login page and also let's make sure we update this to the next navigation because we're using the app router and then from there I can do const router is used router and then I'm going to check another thing I want to bring in is that is loading so by default let's say if we directly go to the dashboard page so from the URL then I want to make sure that we're not loading and then if we are I'm just going to show some kind of spinner so I'm going to import my spinner components and then I'm just going to return a spinner in this case and this will be a large spinner and then if not is authenticated so in this case we're going to know that we're not loading so now we're going to check for if we're not authenticated if that's the case I'm going to show a toast with an error I'm going to import toasts and do toast air with a message of must be logged in router push to slash auth login and there we go now the next thing I'm going to do is in this dashboard I can create a layout TSX so these layouts you can create in subdirectories as well they're not limited to just here so this layout will now wrap this layout and this layout will wrap this page that's the way that's going to work and then I can just import my require off and then also inside of the utils index TSX I want to make sure I export it from here there we go and that way I can import it like this so I'm going to have some children props I'm gonna require auth and that's just gonna have children so the children will just be the dashboard page which we're gonna wrap and I need my interface of props and then I'll apply that here and there we go now we have some route protection by using this sort of mechanism of using our Redux States so pretty much when we first go on the dashboard page if let's say we're loading it up then that is loading it's going to be true we're going to hit our verify route the verify is going to determine are we authenticated if we are it's going to set that is authenticated to true it's going to set the is loading to false and then here on the layouts the require auth is going to handle that and just return the page if the verify determines that we're not authenticated then is authenticated will be false the is loading will be false and we're going to get redirected to the login page so that's how that's going to work so that way we can have like a universal way that's just going to work and I'm also placing this in the dashboard because I'm assuming anything under this dashboard route you're probably gonna have to be authenticated for so this is a nice way to do this or you can just have this on like the layout component and then every other page you know it's going to be like a protected route and then you can also do this on like a page itself but I think this is a pretty nice way to do it so that's why I'm doing it here so that's now literally everything for the dashboard page now we just have a little bit left to go so the only things you have to do now is just create a little not found page so I can do that with not Dash found.tsx this is going to handle my not found page and then the only other thing I believe after that is the Google and Facebook oauth and then just deploying the app and testing things in production so we're almost there so let's keep going so inside of here I'm going to look for a not found component so there we go 404 pages and then gonna grab the code in here just going to grab all this jsx and then export default function not found and that was just going to return all of this and then I'm just going to fix this up a bit so this right here is just going to have an href going to home and then here let's see we have contact support I'm just going to leave this contact support it's just going to go to the home page and then you might maybe create some kind of additional page here that could be like a contact page or something but I'm not going to do that but I think it'll just look nice to have this and then we also have some apostrophes here so I'm just going to change these to be the and the POS colon so that's just the HTML for an apostrophe this should look pretty good so let's see how it is I'm gonna go to a route that doesn't exist sort about maybe this routes and there we go 404 page not found and we can go back home perfect so I'll close that up and we only have one thing left to go so one thing that we're gonna need to do is we're going to need some way of hitting that get request which gets us the like authorized URL and then we're gonna have to visit that URL and that's where we can log in with either like Google or Facebook whatever we're using and that's going to redirect us back to the Google page on the Facebook page and these pages will handle that post request so the first thing I'm going to tackle is inside of this full off I'm going to create a utils folder inside of there I'm going to create some kind of like utility function to help me with that get request so I'm going to call this continue with social auth.ts it's going to be my function for handling this I'm gonna Sports default async function continue with social off and then this thing is going to take a provider that I want which is going to be a string and it's going to take the redirect which is going to be a string so redirect is going to be either Google or Facebook the provider is going to be either Google oauth 2 or Facebook so this way it's a little bit more reusable and then this function I'm going to have a try catch and then in the catch if anything goes wrong I'm just gonna have like a toast message so I'm going to import toast and just do like a toast error of something went wrong while we were trying to do this and then within here I can have my const response is a weight and then fetch and then this is where I'm gonna have my URL along with some additional options so the URL itself I'm just going to make a constant and then this is going to be an interpolated string we have process dot env.next public post so this is going to be my localhost 8000 because I'm going to be hitting my API and that's going to be at slash API slash o slash the provider which is Google oauth 2 or Facebook I'm gonna have a trailing slash then I'm going to have a redirect URI and then this right here is going to behave a little bit differently in development and a little bit differently in production so the way I'm going to handle this is I'm going to check for process EnV node EnV equal to production and then in production I'm going to handle it one way and then in development another so in production I'll do process EnV next public redirect URL is what I'm going to expect to receive here so this will be something like my linked web app testing dot info and then in development I'll have http localhost 3000. and then this will have slash auth slash the redirect which will either be Google or Facebook that we're going to pass in here so that's going to be the URL and I'm going to pass that to the Fetch and then I'm going to set these options so method will be a get request it's gonna have the headers with the accepts header of application Json and then I'm gonna have credentials include then I'm going to get the data which will be awaits response Json and then from there I can see if response dot status was 200 and then I can also do another little like safety check for type of window isn't undefined so that's if we like use it in a server component or something then we know that it's going to be safe and then in this case I can do window dot location dot replace so because we're using this window we want to make sure that it is defined and then we're going to replace it with data dot authorization URL so that's where we're going to expect receipt in this data we're going to replace the window with that so that we can bring them to like the oauth screen and if something goes wrong I'm just going to show a toast with an air that says something went wrong so there we go we have our utility function in place and then to make this utility function easier to use I'm going to create an index TS I'm going to import this continue with social auth and I'm going to export a cost of continue with Google which will be a function which we'll call this continue with social auth passing in the sort of parameters it expects for the Google oauth so this is going to be Google oauth 2. and Google so the provider and the redirects gotta copy down and have another one for Facebook and for Facebook the provider will be Facebook and then the redirect will also be Facebook so there we go now I have these two that I can conveniently use and then I just have to create some buttons which then when we click the on click is going to be utilizing these so inside of my components common I'm going to create social buttons dot TSX and Export default function social buttons div with the class name of flex justify between items Center gap2 and margin of top five and I'm gonna have two buttons so the first one will be the Google one the other one is going to be the Facebook button is this button will have the class name of flex dash one just White rounded medium PX3 margin top three and then the padding top bottom two font medium background red and something I can actually do is also bring in class names and then I'm just gonna cut this and put it here and then actually I'm gonna want to have this in a sort of like sub component which I'm going to call social button and then this thing is going to receive a prop which is going to be the provider and then here I can pass either Google or Facebook and then depending on the provider we're going to apply different styling and then this thing here it's gonna just return a button for us and then we're gonna have something like this here actually I'm gonna have to bring in class names install that and then depending on our provider we're gonna have some different styles so if I have a provider of Google so I can do that with provider is is equal to Google then I'm going to have my Google styling and also the sashes to be in an object and I'm going to copy down and if I have Facebook I'm gonna have different styling so for Google I'm going to have background red 500. and I'm also going to have hover background red 400. and for Facebook I'm gonna have background blue 500 and then hover is going to be background blue 400. and then I can just do class name is class name and then I'm gonna have a children prop and that's what I'm going to pass between here we go let's now create some exports for these so I'm going to have social button and social buttons plural and then in my social buttons I'm gonna just remove this and I'm gonna bring in my social button and then I can use social button here instead then the provider All Passes Google and then the next thing I'm going to pass is a span which is going to be class name of flex justify starts and item Center and then in here I'm going to have an icon then I'm gonna have another social button which is going to be for Facebook and both of these are going to have this in common that's what I can do is I can just cut this from here go into my social button and that's going to wrap this children so there we go it's going to be the span wrapping the children and then back in Social buttons what I need to do is I just need to import these icons I want and then also these icons I'm going to have to have use client for them to work and they're gonna both come from the react icons Library so react icons slash IM is where I'm going to grab these from then I'm going to have I am Google and I am Facebook and then this one here I'm just gonna pass like this I'm gonna have the Facebook one as well and then I can go back here and another thing I can pass is rest ring and any and then I can just tap the rest of the props and then here I can just do rest so this way I can just pass like an on click or something so if I go back here now I can have my on click and I need to bring in those utility functions I made so import continue with Google and continue with Facebook and then this button is going to have an on click which is going to be continue with Google and the other one continue with Facebook and there we go this should now work so the last step here is to go into my login and register pages and use these components so log in and register and intercept it import that so import social buttons and I'm just going to use that right below the form and same thing in the login all right let's check it out so login oh yeah we're kind of missing the text so let's fix that that's in my social buttons I don't want just the icon but I want the text Google and the text to Facebook after so let's fix that up and then the only thing I would probably add is maybe a little bit of margin and I'm also going to change the text to be Google sign in and Facebook sign in and then just apply a class name to both of these of margin rights three and there we go looks a lot better and the register page will also have these exact same buttons perfect so now it's not quite enough to have these buttons I also need to have the Google and Facebook page handle this post request so because the Google and Facebook page will be doing something very similar I'm going to create a custom hook which is just gonna be utilized by both of these and help me implement this I'm going to call this use social I'm going to export a default function of use social auth and this is going to take an authenticate function so this authenticate it's going to be the authenticate function which is going to be returned by that to use social authentication hook so that's one that we defined in the Redux features auth API slice so we made this social authenticate and then that will take in the provider State and code and the provider is going to either be Google oauth 2 or Facebook and that's going to handle the post request so this mutation Hook is going to give us the authenticate that we're going to pass in here and use next I'm going to have a use effects so when this component mounts I'm just gonna go hit that poster Quest and then if it's successful I'm just going to reroute the user to like the home page or the dashboard I think the dashboard makes sense and then if it fails I'm just going to redirect them to the login so to handle a redirect I'm going to import to use router and that's going to come from next navigation there we go and then here I'm gonna get the code and the state so the code and state I'm going to get from the parameters in these pages and I'm just going to pass them on through as additional arguments in here so code will be a string States will be a string and then this use effect it's just going to depend on like the authenticate State and code and then inside of here I can I can check if state code so if these are both true theme so if we have values here then I can do the authenticate passing in these states and the code and I'm also going to need the provider so that'll be another argument I expect to receive and then I can pass that here then I can do an unwrap than the dot then and the dot catch and then in the dot then I'm just going to set the is authenticated piece of state so in order to do that I'm gonna have to import set off and I'm also going to need the use dispatch this one here dispatch set off and then I'm also going to have a toast message so I'm going to import toast it'll be logged in and router push to the dashboard and then in the catch I'm gonna have a toast air it'll say failed to log in with a router push to slash off login and then something I'm actually realizing so this state and code these are going to be query parameters so actually a better way to handle these isn't to expect them inside of here what I'm gonna do is here I'm going to bring in use search params from next navigation and I'm going to bring them in using this hook so I'm going to have const and then State and code which I'm going to destructure from use search params and then if we take a look here state does not exist so a better way I can do this I can just have a con search params and then within here I can do con state is search params.get States and then code will be search params.getcode and then I'm going to get rid of the dependency right here and there we go this is going to be our use social auth hook so now inside of Google what I can do is I can import the use Google or actually the use social authentication mutation hook it's going to be one thing I need I'm gonna also need my use social off hook and actually I need to create an export for this so I didn't do that that's inside of my hooks file index and then I'm gonna do use social off so there we go now we have an easy import for that that's coming from my hooks and then I'm also going to import my spinner components that's gonna be the only thing I show on here I'm just gonna have like a div with a class name with some margin at the top and bottom I'm just gonna have like a spinner and it's gonna be a large spinner it's gonna be the only thing on this page and because I'm using these Redux hooks I'm gonna do use client at the top of this page and then here I can do const Google authenticates is use social authentication mutation and then I can use my use social off and then I can pass in this here and then the other thing that it expects is the provider so authenticate and provider and then in this case my provider will be Google Dash oauth 2. so this should now all work out so this provider we're gonna end up passing here along with the state and code that's going to hit our post request and it should log us in and then for Facebook it's gonna be very similar to this so I'm just going to copy paste here and then I'm just going to call this Facebook authenticate and then the provider is going to be Facebook and there we are so now the Google oauth 2 and Facebook oauth 2 should now work in development so let's test it out so here on the sign up maybe I don't want to sign up by filling out all these fields so let's click this Google sign in it looks like something didn't work out so let's see what it is and it seems that the issue is that we forgot the question mark here this should be a query parameter so let's fix that that should be in our utility function so not this utils but the one down here and let's make sure that here we have our question mark so this is going to be a query parameter with this value so that should fix things up for us let's try that again I'm just going to refresh Google sign in there we go now I can click on my John Doe account and then log in and then if I already am logged in I would just get redirected there there's our spinner we're logged in and we should have gotten redirected but we didn't so why didn't our redirect work let's find out now there's some other things I can try to fix up that might maybe make this work like I expected for one I should have the provider inside of this dependency array and then another thing I'm going to do is I'm just going to import the use ref hook I'm going to use this to make sure that this right here runs only once I'm gonna have const effect ran is use ref and then I'm gonna have false and then here I'm going to have an and for if not effect ran dot current and then in my cleanup function I'm going to return an arrow function which is going to do effects Ram dot current is true so this is going to ensure that this only gets run once so back to my code I'm going to refresh so I am logged in which means I have those cookies and I can log out it's not gonna get redirected here so back inside of login let's click on the Google sign in let's try this one more time and there we go this time it worked perfect so there seems to have just been some strange Behavior around the use effect probably with the strict mode I'm guessing so now that that worked let's now test things out with Facebook oauth so here everything should be set up let's make sure it's good so I'm just gonna log out and get redirected here must be logged in so that's because I was on the dashboard page then I can click login Facebook sign in and there we go because I'm already logged in with this account here I just automatically get signed in with John Edwards and I can see if that worked now one thing I don't like is when you're on the dashboard and you click on log out you see that air toast so I'm just going to open up that require auth component I'm just going to remove this air toast if you're not authenticated it's just going to redirect it to the login I think it's a little unnecessary to have that so I'll put that there now if I go to Facebook sign in I'm on the dashboard then if I click on logout I just get redirected and in particular get redirected to the home page so that's good and then I also just want to make sure that the logout itself isn't redirecting I may have included that in the handle logout and looks like I did so actually I don't like this Behavior so I'm going to do is I'm just going to get rid of this router push to slash and I'm only going to dispatch set logout because if we're on an unauthorized page and we log out we're going to get redirected anyway so I'm just going to keep it like this so let's test out that behavior sign in so if I'm on the dashboard now and then I click on logout I expect to get redirected to like the login page and there we go we're on the login page perfect and I think that's a better Behavior everything seems to be working right now with the app so the next step will be some cleanup and then testing the production build and then after that we'll get to the final stage of deploying the app so let's go back to the code so I guess for cleanup I like one thing I see is I have the router that's being unused as well as this link so I'm just gonna clean that up real quick and then I'm also going to get rid of this import so save that and then I'm just going to close up these pages and the first thing I'm going to do is I'm just going to do a build it's going to stop running npm run build and just make sure that we can actually build the production version so here I'm getting an error that's inside of our list components so I'm going to go there first and maybe minimize some of these things so let's find our list components that is right over here and then we have to provide the key prop because we are returning a list of jsx elements and then for the key I'm just going to use the label we're also getting warnings about the image tag you could always use the image component from next.js but I'm just going to use these image tags they're just really being used for those like Tailwind icons next I'm going to do is run another build see if everything's okay which it should be that was the only error that was showing up and now let's go see how things run with our production build so I'm going to do an npm Run start and make sure that everything's in order so I'm gonna refresh and I'm gonna try to log in again and interestingly enough we just see a loader here so let's figure out what exactly is going on so one thing that we can do to help figure this out we can go into Redux in our store let's just change this right here the dev tools to always be true and that should be lowercase and then I'm going to do a rebuild and then that way we can just see what's inside of the Redux store so I'm going to open up Firefox navigate here so we have our Redux Dev tools and we can click here and then I can actually see my state itself so is authenticated and is loading so let's try to log in now with the production version and I get this loading so let's see what's happening so over here you're gonna see a couple things you can select so make sure you don't have next router otherwise you're going to see something that looks like this and then in here I see is authenticated as false and is loading is false interesting I also don't see the nav bar updated go back here and then I see is loading is true now and is authenticated as false let's refresh okay let's see the dashboard I see logout then going back here is authenticated as true is loading is false okay so let's navigate back here and suddenly I have this authenticated as false and is loading is true so our Redux state is not preserving its value and that's quite interesting because in our development environment everything is working just fine the Redux state was preserving its values but right now when we do the production builds we have some unwanted side effects happening than if I refresh everything appears to be okay but I navigate and now we're logged out again so let's address this so I'm going to flip this back to what it was so only in our development environment I want the dev tools to be activated and then to actually debug this it is quite a difficult thing to actually see what's happening but what is happening is that make store right here we're returning a function that we're calling so instead what we want to do is just have store is equal to configure store and then we're just going to have to adjust these types here so I'm going to remove this one we're not going to need it and this is going to be type of store dot gets state and then as for this one here this is going to be type of store dot dispatch so you can either do the dot notation or you can also use this notation here that's another option then I think in the Redux toolkit documentation it shows it with this notation so I'll just do it like this and then what we have to do from there is go to our provider and just update this to now be an import for storm instead of calling a function store we're just going to provide the store which is our configure store so let's test this out and see if this fixes things so I'm going to rebuild to get our production version okay that finished building and I'll just do an npm Run start and see how things are working now in the production build because it's the production build that's going to end up actually getting deployed and running so we want to make sure things are working with that so back over here if I now refresh the page I see the dashboard log out if I go to the dashboard there we go dashboard log out still there and I can navigate around also this didn't quite seem to update okay no it did we don't have the actual like Redux store that we can analyze here we just have this next router so that's good and there we go everything is now working properly I can go to the dashboard I can refresh and now things are proper with the Redux store so that's a little bug which is quite difficult to actually find so just make sure that when you're configuring your store you don't do it as a function returning configure store otherwise things will work in development but they won't in production alright so the next thing I want to tackle in terms of cleanup is going to be in require auth this isn't completely necessary but right now I require off it's doing a router dot push to auth login but instead what I want to do is use the redirect function which comes from next navigation and then use that here instead just because this will treat this as more of an air whereas the router dock push won't and if you're trying to go to an unauthorized route I do want to treat that as a little bit more of an error so I'm going to use this redirect here and then after this change the last thing I'm going to do is go into the app dashboard and then I'm just going to tweak some things here a little bit so one thing that when we use a query from Redux toolkit with our TK query we get this is loading we can destructure but we also get is fetching that's another thing I'm going to bring in and then for the loading State I just want to see if we're loading or if we're fetching and then also right here we check if we have an error and then if we do we router push to log in and we also have a toast so one thing for sure I don't want is the toast I think it'll just be a nicer behavior that if you try going directly to the dashboard and you're not logged in then you just get redirected to the login without the toast and then also this part right here we have our require auth already handling this for us with this redirect so we don't actually have to do this part here so I'm just going to remove this as a final cleanup remove is air from what's getting destructured remove router move the toast import remove this import and then just clean up our component to be like this and there we go and then there's just going to be one final thing I want to tackle and this is going to be more on the back end side so right now on our app let's say if I were to inspect and then if I go to the network Tab and I do a refresh right now what we're going to notice is even though I have an access token like I'm not logged in right now because more than five minutes has passed so this is one issue that I have right now so this API JWT verify we hit and we're getting a 400 because we don't have an access token that we're passing to this so what we need to do is in our cookies so if I go to my storage not this but the storage so the access token it expired now it still kind of like shows up here but it's not getting sent along in my requests so then when it hits the verify route the verify route doesn't see that there's an access token and gives me a 400 battery Quest now instead what I want to happen is for this access token to get sent along in the request even if it's expired and then once we have the verify route then the verify route will determine this is not a good token it's going to give me a 401 then once I hit my 401 then the rtk query re-auth logical kick in and then it'll hit the refresh endpoints get me a new access token and then it's going to retry the verify and then it's going to work and that's going to log me in so that's what I want to happen and then to make this happen it's quite a simple fix now this is more something on the back end so if I were to Now open up the full auth API go to my full auth settings there's one setting here I need to tweak so right here is where I have these settings so auth cookie access max age this right here is the max age for my ACCESS tokens and then this here is the max age where my refresh tokens and this in particular is the max age for the cookies themselves not for the token for the actual token lifetime you can configure that in the simple JWT settings and then you can set the access token lifetime also accidentally open this so that you can figure in here this is just for the cookie that's holding the value so what I can do instead is I can just do something like off cookie max age let's say and then that can be equal to this value here and then I can just let's see remove this and just have one of these so the axis and refresh token will have the exact same lifetime which will be a day and then all I have to do is go into my users views and then make sure that I'm using this setting that I just adjusted so I'm going to go and find wherever I have max age and just replace that with this setting so both for the axis and the refresh token so we're using that here we're using that here and here then we're using that here and then here in the verify route we're not so there we go that's all we have to adjust and then we're all set now because I made that change I will have to now push that change up so I'm just gonna get add dot get commits and then adjust off cookie lifetime and then get push or gin name just so that I can get that change up there and then what that's going to do it's actually going to trigger a redeployment because from the first part of the series I deployed the back end and then the back end is deployed right here in this app so that should trigger a redeployment to now happen so that's for like the production build also I'm going to close up a lot of these tabs I don't need anymore so now that we have that the next thing I want to do is just go push this into a git repository so I can deploy it to another digital ocean app platform instance so I'm going to stop running this do I get status git add dots so I'm committing all of these files do we get commit Dash M initial commits and then after that I'm gonna have to go into GitHub and create a repository for this so I'll click on new repository I'll call this full dash off it'll be a public repository create that so we already have all of these things done for us you can also do a git Branch Dash M main so if I do it get status right now the branch is already made because that's what it's configured to when you generate a next.js project and then you can go add the remotes and then push so I'll do this step here now as for this step this is going to be slightly different for me this is something I went over in the first part but I manage multiple GitHub accounts so instead the way that I'm going to do this is with Git at github.com Dash linked web and then a colon then linked web Dash full auth.get and then just to explain that here as well side of my thought SSH I have a config and then that config has this setup right here and then that has the host of GitHub with this identity file and that's for the specific GitHub account that I'm pushing this up to right now so if you're not managing multiple GitHub accounts you're not going to do it like I'm doing it here but because I am this is the way that I'm gonna do it and then I'll do a get push Dash U origin Main so this will push to the main branch with the Upstream which is the setting and then from there if I go here and refresh we should have our git repository then we also tested things that they work with the production build so the next step is going to be get this repository on an app platform on digitalocean and then we can test things out if they work in production so back in here I'm also going to see what's the status of this deployment so it's still doing its thing that's fine so what I'm going to do is go to create apps and create a brand new app here we have GitHub selected I'm going to find that repository so full dash off there it is and then I'll do an auto deploy checked here so anytime I deploy to the main branch it's going to go deploy that I'm going to edit the plan I'm gonna use a basic plan that's five dollars a month then I'll click next and then I'm going to set up my environment variables so then for the environment's variables I believe we have two that we have to configure so inside of my EnV local we have this next public host that's the first one I need to configure this is going to be our backend API so I'll paste that and then our backend API that we set up in the first part is https colon slash API dot linked web app testing dot info and of course here you'd use whatever domain you have set up and then we have one more environment variable we have to set and that one comes from our utils continue with social auth and that's this one right here so when our environment is set to production which it will be when we do the npm run build then we want to use this right here as a redirect URL and then by default we use localhost 3000 so instead of having glucose 3000 slash auth slash let's say Google oauth 2 or slash Facebook we're gonna have instead we're an xjs app is running in production so that's going to end up being https colon slash slash linked web app testing dot info now after we do the build and deploy we are going to have to go and configure this to use this domain but we're going to do that afterwards so for now I'll click save I'll click next and then next and then we should be good to go so I'll create these resources and then now pretty much what we have to do is wait and then also a nice thing if I go and there is a setting if I actually click on the component itself right now we have these commands and already for us we have the build command and the Run command there for us so with the text this is a nextgs project and then it's going to do the npm run build for the build and npm start to start the next GS project so that's already configured for us so all that's left to do now let's go here wait for this to finish and then once it does we'll go back to the settings and configure the domain alright so our build and deployment finished and succeeded so the next thing I'm going to do is go to my settings Now find the domains setting click on edit add domain and then add my domain which is linked web Dash app dash testing dot info and then I'll say we manage your domain and I'll add that domain and that's pretty much it now just go back to the build logs wait for it to do its build deploy so that already finished up so perfect so one thing that we had as an issue during development was with when we were using Chrome the cookies because they had the same site property as none they required an SSL Connection in order to get sent along in our requests and in the responses so because in the development environment we didn't have https setup those cookies couldn't get sent along and we had to use something like Firefox or Safari but right now we do have an SSL connection so that means that these cookies should Now work on Chrome so I can actually just on Chrome go to linked web apptesting.info and then because I just configured this domain this will take a little bit of time before it's set up so I will have to wait until that finishes propagating in the system but one thing that did happen after we configure that domain is that if we go to these domains now we will see some additional domains get set up here for us automatically so right now we have this pointing to our app so now it's just a matter of waiting until this finishes propagating and then we should see our app so I'm just going to pause and come back once that's finished and then we'll continue alright so things finished propagating so we have our app right now in production with this domain so perfect so now back over here if I go to my app one thing I want to make sure is that my backend app this API link to apptesting.info I want to make sure that the database is clear now you wouldn't normally do this sort of thing on a production app but this is just more of a test app and I want to see if things are now working in production so I'm going to go to this console so this is where I have my backend project I'm going to do a python manage dot Pi flush and that's just going to clear all the data in the database that way I can make sure that I can register for an account and test out like the registration the login and everything so there we go now I have a clear database that I'm working with so now I should be able to go back to my app and test this out so let's try to register for an account I'm gonna do John Doe with that email then we're going to sign up and there we go please check email to verify account and I'm redirected to the sign in page beautiful now let's see if we receive that email so I'm going to refresh there's the email now we see right here we have the actual link correctly with the linked web apptesting.info doming so I can just click this and that will activate my account there we go account activated just like that so the next thing to test out is logging in so let's do that and there we go we're logged in and we're redirected to the dashboard perfect and I can also navigate around that all works perfect I can refresh and now when I refreshed we can see that we ended up with a result that was a little bit unexpected so if I go to the Home Route things seem to work I can navigate around I can log out go to login register but if I refresh the page I end up getting something like this now this right here this is currently a bug with the version of next JS and in particular it's more when you Deploy on something like digital ocean app platform so one thing that we noticed was when we were running this locally the production environment everything was working fine but as soon as we were on digital oceans platform things suddenly weren't fine so what is different between our local environments and digital oceans well the digital oceans environments with the app platform there is a CDN that's in front of our application and that is cloudflare so on my other screen I'm going to bring in a certain post here so this is one of the issues when you have a CDN like cloudfront cloudflare on the app directory then things end up breaking and you end up getting a result kind of like the one that we saw now in this post if you scroll down Tim newtkins who is one of the authors of next JS and also the lead of next JS he ended up commenting on this and they are working on solving this particular issue where you have something like cloudflare and in particular what happens there's this very header and cloudflare right now doesn't respect this very header that's something we can actually see if we inspect and then we go to the network Tab and then refresh if I take a look here we can see that there's this very header so this right here is a standard with cdns and they're supposed to be respecting this header and things are supposed to render properly but with the server components right now we end up getting this showing up in particular because it's a server component and what's getting cached isn't actually HTML but it's this right over here and the Very header isn't working with cloudflare right now so the very header is a standard that is supposed to be respected by these cdns but unfortunately it's not so the next JS team is aware of this particular issue and they are working on a fix for this for cdns that don't respect the very header so this is something that will get fixed just for the time being this is the kind of thing you are likely to see when you do page refreshes unless it's going to be like the home page then it'll probably work fine and then also Dynamic pages will also work fine so something like password reset slash uid slash the token something like this will probably work fine but something like password reset when that gets cached and then in particular with the server components you're going to end up with something like this which is not cached HTML but instead it's something that looks like this so when you end up actually seeing this video this might be an issue that's resolved with the current version of next.js however if you're watching this video when there isn't this fixed yet then you'll probably get a very similar result but anyway this is something that is more temporary it is something that will get fixed and so I wouldn't think it's something to worry about too much so anyway that's something I wanted to bring up now if you were to deploy this application on something like first cell you wouldn't get this issue but if you are doing this on digital ocean app platform at the moment you will get this issue but I do still think it's good to see how you can do this sort of deployments in app platform and ultimately when this does get resolved then of course everything will be fine you'll know how to deploy on digitalocean and you're not going to get this issue of page refreshes showing this strange cached Behavior so anyway with that side note let's now test out some of the other features in this application so one in particular is the password reset which we didn't go over so let's test it out right now in production there we go request sent check your email for reset link so there's the link so I can click this to reset the password and there we go password reset now if I put in the old password I should fail to log in if I put in the password I just reset to there we go we're logged in and we can see the dashboard perfect and if I log out I should get redirected to the login page and then the final things to test out in this app are going to be the Google sign-in and the Facebook sign-in so I'm going to click on the Google sign in link gonna log in with my John Doe user and I get redirected and I'm logged in successfully so perfect Google oauth works so I can log out go back to the login page and then I can also go to Facebook sign in and I'm going to continue as John and there we go now in this particular case I ended up logging in with this Chando account but that works too so there we go we have our Google and Facebook oauth working and then also one final thing to kind of note so here if I go to a not found page and then these links when we were putting this app together we put these together as anchor tags so if I actually go back to the code and I open up the not found page so these here were these anchor tags instead of the link tags and in particular that was because there was actually a bug with next JS app platform with this not found page where if you use the link tags it wouldn't redirect you properly but with the latest version currently of nexjs you can turn these into link tags and then it should redirect you properly so that's the reason why I use these just because if you were to click them then you would still see the 404 not found content on the screen so that is another change that you can make but just not waste any more time I'm just gonna leave it at that and then on the final GitHub code I'm just going to have it with the link tag and with the latest version of next.js so there we go that is everything done for this tutorial you've now seen how to build a full authentication system using the nextgs app platform along with Django on the back end you also saw how to do social authentication with Google and Facebook oauth 2. and we have a fully functioning application right now minus the bug we see with the page refreshes but that is something that will get resolved pretty soon in the future and then on top of all that you've also seen how to deploy this application with digitalocean app platform so I hope you enjoyed the series if you did please leave a like on the video subscribe if you want to see more content like this hit that Bell icon if you want to get notifications when I release a new video and that'll be everything for this series so I'll see you in the next one
Info
Channel: Bryan Brkic
Views: 11,962
Rating: undefined out of 5
Keywords: website development, web development, app development, mobile app, mobile app development, django, REST API, django rest framework, react, node, express, mongodb, postgresql, development, websites, apps, django react app, django react, full stack, mern stack, node react, redux
Id: EsDMs3zB6L4
Channel Id: undefined
Length: 265min 16sec (15916 seconds)
Published: Mon Jun 12 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.