Transcript for:
Full Stack App Development with Next.js and FastAPI

in this 90minut video we will walk through step by step how to create a full stack application that includes a UI wrote in nextjs in a backend with full authentication registration a database and all that good stuff wrote and fast API we'll be creating this app in three major Steps step one we'll be creating the backend project in Python fast API step two we'll be creating authentication and registration routes and databases and all that to create the entire functional aspect of the back end step three we will be creating a UI in nextjs so users can interact with the application so overall tons of great stuff jam-packed in this video so go ahead and grab your tea or coffee today I'm drinking from my St Lucia cup beautiful island in the Caribbeans if you've never been now that you have that let's go ahead and dive into the video all right so for this video we are going to be building a full stack application utilizing nextjs and fast API now I have an empty screen for vs code now the very first thing I'm going to create is a new folder that's just going to be called Fast API and inside fast API I'm going to create a new file called main.py all right and as you know once we create this I'm going to create a virtual environment so if you're in VSS code we can just come down here Say Hey I want to create a new virtual environment of v andv and when we select one it's going to create a virtual environment based on our python dependency perfect so now if we go ahead and open up a terminal we can see that we're activated on our VV now just to make sure that I have all of the dependencies that I need I am going to create a new file called requirements. text and inside here I going to just paste a bunch of uh dependencies just to make sure that mine and your application aligned with dependencies these are pretty much the newest dependencies as of this video recording so what I can do here is PIP install dasr requirements. Tex o and I need to jump into the fast API directory first all right so now that we have all of our dependencies installed I am going to go ahead and create a new folder called API this is going to be the directory that holds all of our business Logic for fast API and I'm actually going to grab my main.py and stick it right inside here so now our fast API directory should just be fast API with an API folder and requirements. text which has all of our dependencies all right and now inside our main.py what we can do is just say from Fast API import fast API and just to make sure everything works we can say aa. an empty slash and I'm going to say def health check and just return a health check complete and now the only thing we need to say above here is app equals fast API and now what we can do is CD into API and we can say fast API run main.py and you can only use this command if you're running like the newest version of fast API so once you do that we can see that our application has kicked off and now if we go into our our docks we can see our one um health check API where if we execute it we'll see health check complete perfect all right so now that we have our health check complete we can go ahead and add a little bit more code now the very first thing we need to do is add a middleware and this middleware will allow us to be able to get past cores errors that may come from our next JS so what we want to do here is make sure that we import from Fast api. middleware doc import cores middleware and now underneath our app equals fast API but before our app.get let's go ahead and say app. add middleware our cores middleware where our allow Origins is equal to http colon real quick if youve enjoyed the video please subscribe to be notified of upcoming videos and check out my bestselling fast API course linked below Local Host Port 3000 which is our default nextjs port and then allow credentials equals true allow methods equals a star and allow headers equals a star and this just going to allow us to be able to consume all endpoints from Local Host Port 3000 all right Perfect all right so now the next thing we want to do is let's go ahead and create our database and we can do that right here inside our API directory so let's go ahead and say new file database. piy and inside here we want to say from SQL Alchemy import create engine from SQL alchemy.com basee from sqlalchemy.orm import session maker and then we want to create our URL for SQL light so we can say SQL Alchemy database URL equals our sqlite colon SL SL slash so three slashes workoutcore app. DB where our engine is equal to create engine where we're going to pass in our SQL Alchemy database URL with our connect arguments which is only for our sqlite equals um our check same thread of false our session local is going to equal session m maker with our autocommit equal to false our autof flush equal to false and our bind equals engine and then we want to declare our Base by saying base equals declara of Base all right perfect and now the next thing that we want to do is create our models so we're going to have users we're going to have workouts and we're going to have routines so let's go ahead and create a new models.py and now inside our models.py we want to say from SQL Alchemy import column integer string foreign key and table we then want to say from sqlalchemy.orm import relationship and then from. database import base we then want to create an association table so we can say workoutcore routine uncore Association because we want workouts to be inside um routines so we can say equals table of our workout routine base. metadata where we're going to have two columns a workout ID which is an integer and a foreign key to workouts. ID and a column which routine ID integer and foreign key is routines. ID and now we want to create our three classes so we can say class user base is equal to our uncore uncore table name uncore uncore equals user where ID equals column where we pass in integer primary key equals true and index is true username is equal to column string unique equals true index equals true and then hash password equals column string perfect and now we want to create a new class of workout where we're going to have table name is equal to workouts ID is the same as users so column integer primary key equals true and index equals true and then we want user ID to equal column integer forign key is going to be our user's ID name equals column string index equals true description equals column string index equals true and then we're going to create a routines class so but ahead of time I'm going to create the relationship so I can say routines equals relationship routine where we're going to pass into secondary equals our workout routine Association back populates to our workouts and then lastly we want to say class routine base table name is routines with an ID that's column integer primary key equals true and index equals true and then user ID is going to be the same as workouts so we can say um column integer forign key is user's ID with the name column string index equals true description is column string index equals true but this time we're going to say workouts equals relationship workout secondary equals workout routine Association back populates to routine so this just kind of gives an overview of the relationships allowed so what we can say here is just simply workout. routines equals and we can say this exact thing right here and just place it in there all right so once we have these models down we can close out of all of these right now and inside our API directory let's go ahead and just create an initialization file by saying uncore uncore init.py this is just for our folder structure later on to work as we are expecting and let's go ahead and create a newv file now this is just good practice for us to be to stick certain things in here now the very first thing that we're going to need in here is an off secret for our authentication so let's go ahead and say oore secret underscore key and you can make this really whatever you want right here I have this long string of random numbers and letters but add anything you want right here we want an off algorithm so we can say oore algorithm where here we can just say hs256 and then an API URL and this is going to be the URL of the Local Host that's coming in which is going to be our next JS so we can just say HTTP loal host Port 3000 Perfect all right we can close out of this now let's go back into our API 4 folder and create a new file called depths. piy now this is going to be for our dependencies So within our application we're going to have some dependencies for authentication and for our database and we're just going to make it a little cleaner by having all of our dependencies in one file so what we can do here is say from typing import annotated from sqlalchemy.orm import session from Fast API import depends HTTP exception and status from fast api. security import ooth to password Bearer from pass li. conts import crypto context from Jose import JWT and JWT eror and then for our environmental variables we can say from. EnV import load. EnV and import our operating system and then lastly from our own local files we want to say from database import session local we then want to load our um EnV and then we can say our secret key for our application so secret key is going to equal our os. GV off secret key and just to make sure we don't spell this incorrectly go ahead and just open up your EnV and paste that in here and then our algorithm equals the exact same thing except for we want to grab our off algorithm we then want to create our dependency for our database so we can say def get DB DB equals session local try yield DB and finally db. close perfect we then want to say dbor dependency equals annotated our session depends on get DB so we're setting up our PCY injection we can then say bcrypt context equals Crypt context schemas of bcrypt and deprecated is Auto o off2 bear equals o off2 password bear with our token URL of off/ token and our o off2 bear dependency which is equal to annotated string depends o off to [Music] Bear all right and now once we have all these Imports and um dependency injection setup we can do our get current user which is what we're going to be using to be able to fetch our current user so we can say async defa get current user pass in our token of O Off 2 bear dependency we can try and unload the GWT so we can say payload equals gt. decode where we pass in our token secret key and algorithms of algorithm our username is going to be of type string which is going to equal our payload doget sub our user ID is going to be an integer which is equal to payload.exe equals status. HTTP 401 unauthorized and our detail is equal to could not validate user and if that works out well well then we can just return our username of username in ID of user ID however if anything fails well that means we're having a j JWT error so we can raise our HTTP exception throw in a status code which is equal to status. http 401 unauthorized with a detail of could not validate user lastly we want to say user dependency equals our annotated of dictionary depends get current user and that is our last step for our dependency injection setup all right and once we add that we can close out of our dependencies and we can start working on our routers all right so now the next thing we need to do is set up our routers so inside our API folder let's go ahead and create a new folder called routers and the first thing we want to do is create a new file with uncore anitore dop all right and now inside here let's go ahead and say new file off. py now inside here we need to set up a few things now again it's going to start with all of our Imports so we can say from date time import time Delta date time time zone you can then say from typing import annotated from Fast API import API router depends and HTTP exception import status from pantic import base model from fast api. security import ooth to password request form from Jose import JWT from EnV import load. EnV and import OS and now our um imports from our own files is from api. Models import user and from api. dependencies um import DB dependency and bcrypt contacts all right and now what we want to do is say load. EnV which is going to load all of our um environmental variables from ourv file we then want to set up our router so router equals API router where we're going to have our prefix of this file be slash off and then our tag is going to be off within our Swagger documentation we need to set up our secret key and algorithm which is secret key is going to equal our os. getv from our off secret key and our algorithm is going to be os. GV off algorithm we then want to set up some of our pantic um requests so we can say class user create request of base model is username of string and password of string and our class token which is also going to be of base model where our access token is string and our token type is string all right and now we want to create some functionality for our um authentication so what we can say here is defa authenticate user where we're going to pass in a username of type string password of type string and a DB and we're getting our DB from our dependencies and then we could say user. dbquery user. filter user. username equals username doir if not user return false so if user doesn't come back from the database if not bcrypt context. verify the password and the user hash password so we're going to encrypt um the password to see if it matches the password that's in the database return false if so return user we then want to say create our access token so we can say def create access token where username of string user ID of int and expires Delta of time Delta we want to encode our GWT we can say encode equals brackets sub of username ID of user ID expires equals dat time. now time zone. UTC plus expires Delta with the incode do update of our exp of expires and lastly return the JWT do encode and code secret key and algorithm which is equal to our algorithm once we have that we can create our endpoint for create user we can say at router. poost which is going to be an empty slash with our status code that's equal to status. http 2011 created async def create user DB of our DB dependency create user request of user create request where we're have create user model equals user where we pass in our username which is equal to our create user request. username and our hash password which is going to be our bcrypt context. and then we're passing in our create user request password so we're going to encrypt and hash the user password and then we want to add our create user model to the DB and then commit it and then lastly we want to be able to create a token and return that token so we can be authenticated and use that for like authorization so we can say router. poost toen response model equals token where async def login for Access token is going to be our form data of annotated oof2 password request form using our dependency injection in our DB of DB dependency user equals authenticate user form data. username and form data. password and passing in our DB so we're going to be creating a form data of our username and password if not user well then we want to raise our HTTP exception of status code equals status. HTTP 401 unauthorized with the detail could not validate user but if user is valid then we want to create a token which is equal to create access token which is our function above user. username user. ID with a Time Delta of minutes equals 20 and then lastly we just want to return that token so we can say return access token of token with token type of Bearer all right and then after we do that let's go into our main.py where right under app equals fast API and right before app. add middleware let's go ahead and say base. metadata. creat all bind equals engine and we need to import this so say from. database import base and engine and then we want to say from. routers Import off and then right under our health check let's go ahead and say app. include router off. Router Perfect all right let's go back into our terminal and let's go ahead and say fast API run main.py let's go back into our application where we can now see that there's two more um offs right here let's go ahead and say create user where I'm going to say try it out and my username is going to be coding with Roby and my password is going to be test 1 23 4 exclamation mark and click execute and we can see that it might have worked cuz we got a 2011 so now if we go into our off token and we say try it out we can pass in our username of coding with Roby and our password is test 1 2 3 4 exclamation mark and if we execute we can see it all worked and we got our access token right here perfect stuff all right so now if we go back into our application we can start working on our next route and we can see right here in our in our uh directory of API we have our new database workoutcore app. DB now that we have our off created let's go ahead and create workouts so inside our routers let's go ahead and create a new file called workouts. py and now inside workouts we want to say from pantic import base model from typing import optional and from Fast API import API router in status and then from our own files we want to say from api. Models import workout from api. depths for dependencies import DB dependency and user dependency and then we want to say router equals API router where our prefix is slw workouts and our tags is workouts let's go ahead and create two classes so class workout base which is part of base model and pantic we'll say name is string and our description is an optional string that is equal to none and then we want to say class workout create which is part of our workout base that we just created and we're just going to say pass inside and here we're going to create a couple um endpoints we're going to say at router. git SL where we're going to have defa git workout where DB of type DB depend user of user dependency so our authentication is going to be required and then workout ID is an integer we then want to say return dbquery of workout. filter workout. ID equals our workout id. first so we're going to get the first record in our database that matches that ID and then let's go ahead and create a new endpoint which fetches all of the workouts so we can say router. GW workouts defg workouts DB of DB dependency user of user dependency and then we can say return dbquery workout. all we want to be able to create a new workout so we can say at router. poost SL and then we want to say status code equals status. HTTP 2011 [Music] created def create workout passing our DB of DB dependency user of user dependency and workout which is our workout create DB workout equals workout where we want to do starstar workout. model dump to convert all of this into a workout and then we want to add our last variable of user ID which is equal to our user. ID let's go ahead and do d db. add DB workout DB commit and DB refresh our DB workout so we can return our DB workout back to the screen and then next we want to delete a workout so we can say at router. delete which is going to be an empty path and then defa delete workout DB of DB dependency user of user dependency and then we'll pass in our workout ID of type integer we can say DB workout equals db. query where we're going to pass in our workout. filter workout. ID equals our workout id. first if DB workout well then we want to do a db. delete our workout and then commit this DB and then return the DB that we just deleted all right so now we can go ahead and run our application what we actually need to do after we start that up let's go into our main and right here let's do comma workouts and then we can do pretty much the same thing right here except for this is going to now be workout so we now have two routers attached rerun our application in our terminal go back into our browser and refresh and something new that we have is this authorized button up here and that's because we have some locked apis now and this lock means that authentication needs to happen so let's go ahead and just say username is going to be my coding with Robi and my password is test1 234 x exclamation mark and once you click authorize this will automatically attach our uh bear token to these requests so if we come in here and we say um we want to create a new workout we can say name is push-ups and the description for this is do 20 push-ups and we can say execute if we scroll down we can see that it was created successfully if we go ahead and we say let's do another one real quick actually Let's do let's make this situps and we'll say do 30 situps execute again if we go ahead and say get all workouts and we say try it out and execute we can see that we get all of the workouts now if we go into this first one we can pass in an ID and this fetches the single workout so this is push-ups has an ID of one while sit-ups have an ID of two let's go ahead and create um a fake one so I'm just going to say test and I'm going to say test again execute and now let's go ahead and get all of them once more we can say execute and we get them all well this one doesn't really make sense and it has an ID of three so inside our delete we can just go ahead and pass in an ID of three we can see that that workout was deleted if we see right here and now if we go back into our get all of our workouts we can see that it's just back to push-ups and situps all right cool so now we have a um two workouts push-ups and situps what we want to do now is go ahead and create routines now a routine is like a complete workout so a workout is like push-ups or sit-ups while a routine is maybe doing both push-ups and sit-ups all right we want to create something called routines. py all right so now that we have pretty much everything done let's go ahead and go into routers say new file and we want to create something called routines. py all right and now inside routines we want to say from pantic import base model from typing import list and optional from Fast API import API router and then from sqlalchemy.orm import joined load and now from our own dependencies we want to say import api. models import workout and we want to import our routine and then from our dependencies we can say from API depths import DB dependency and user dependency router equals API router with a prefix of/ routines and tags of routines all right so now we want two more classes so we can say class routine base and we pass in our base model name of type string and description of optional string which is equal to none and then class routine create which is going to be um passing in routine base and then workouts which is going to be our list of integers so we're going to be saving a list of integers and then when we do our speal query we are going to be fetching um the workouts along with all the information of a routine and we're going to be using joined load to do that so how we can do this we can say at route. g/ where we want to get routines so inside here we can say router. routines def get routines DB DB dependency user of user dependency we then want to say return dbquery of routine. options where we pass in a joined load routine. workouts. filter routine. user ID equals user. id. all so what we're doing here is we are able to create workouts and everybody will be able to see the workouts but what we can do now is create our own personal routines based on these workouts we can create a new routine for ourself by doing an router. postdec create routine where we pass in our DB of DB dependency user of user dependency and our routine of routine [Music] create DB routine equals routine where we pass in name equals routine. name description equals routine. description and user ID equals user doget and we're going to pass in our ID e and then we want to save four workout ID in our routine workouts so we're going to be fetching each workout and we can say workout equals dbquery workout. filter workout ID equals workout ID first if workout so if it's true if it's valid in the database well then we want to do a dbr routine. workouts. append workout lastly we want to say db. add our DB routine DB commit and then DB refresh our DB routine and now just so we can see what it returns we can say DB routines equals dbquery routine. options joined load routines. workouts. filter routine. equals DB routine. first and then lastly just return that DB routines and we're going to want to be able to delete our own personal routines so we can't really delete workouts but we can re but we can delete routines so let's go ahead and say at router. delete with a slash as our path def delete routine DB of DB dependency user of user dependency and routine ID of int DB routin rtin equals dbquery routine. filter routine ID equals routine id. first if our DB routine is valid in the database well then we want to go ahead and delete that DB routine commit the database and then return our DB routine all right so now once we got that let's bring up our terminal again let's rerun our application go back into our browser let's refresh everything let's go into our main up here we now need to pass in routines and then right here let's go ahead and just say routines. router to add it to our application let's rerun our application go back to our browser refresh the page and here we can see our routines let's log in authorize and now let's go ahead and create a routine so to create a routine we need a name so I'm going to say the name is um full body workout and the description is going to be this routine Works your whole body and then our workouts we need to pass in an integer well we remember that there's two workouts um so if we look at them both real quick we need to pass in the ID so we can see that IDs are one and two so here we want to pass in one comma 2 and execute and here is our full routine we can see the name is full body workout description is this routine Works your whole body the user that created it it has an IDE of one and this routine has an IDE of one and inside has two workouts the push-ups and sit-ups so if we come over here and we say hey we want to fetch all of them we can see that there's the routine for this user now I'm going to create a um another one which is just going to have identical data but a different ID so we can see that there is now two um routines this routine and this one but this one has an ID of two we are just going to go ahead and delete it just so we can um make sure that this is working properly so once we do that we can see that that routine was deleted and if we come back up here and we say execute again boom we're back to one routine that has both workouts inside so what the next thing we need to do is just go ahead and close all of our um folders and all of our code and then we can go ahead and just shut this terminal real quick awesome awesome stuff we now have our fast API application ready to go with authentication um some some little bit of um authorization and now we're ready to create our nextjs front end part that'll bring this whole application to life and this is awesome stuff and I will see you right here where we get back into it we need to create our next JS application all right so now that we have um our fast API complete we need to create our next JS application and we can do that by opening up a new terminal remember we need both applications running at one point so I'm going to leave this first terminal open for fast API and the second one is going to be for nextjs and make sure you already have node.js installed on your computer you can get that um by Googling how to download nodejs but after you get that what we need to do is npx create next app where I'm going to name this just nextjs and then click enter it's going to ask you what version I'm going to say yes and there's going to be a couple different notices so I'm not going to be using typescript we do not need um es Lent we do not need Tailwind CSS we want a source directory we want our app router we do not need an alias all right so now we have our next JS application the first thing we want to do is CD into our new nextjs directory and let's go ahead and do an mpm install for axios and bootstrap this will just make um development speed a little bit quicker all right so what once we're inside our source we should have an app folder inside of this now inside our app folder let's go ahead and create a new folder and this is going to be called context now inside context we want to create a new file and this is going to be off context. JS and this is what's going to be holding a lot of our um authentication and authorization logic so the very beginning let's go ahead and just type in use client and let's go ahead and do import create context use state from react import axios from axios import use router from next SL navigation where const off Contex is equal to create context we want to export const off provider equals parentheses brackets children Arrow function into um two pieces of State well one piece of State const user set user equals UST state of N and const router equals use router all right now the next thing we want to do inside here is const login equals async where we pass in our username and password Arrow function and then inside here we want to say try const form data equals new form data where we can say form data. append username username form data. append password password and here we're going to call our fast API application so we can say const response equals await axio St poost before we pass in HTTP col localhost Port 8000 off toen we're going to pass in our form data of username and password and then inside here we want to create headers of content type application SLX www dform - URL uncoded because of our form data we then want to say axios do defaults do headers do common of authorization to equal our bear response.data do access token so when we get the response of our token we want to add that to our default axios we then want to add um that token to our local storage so we can say local storage. set item of token to be our response.data doax token set user to response.data router. push slash and then catch our air if something happens where we can just console log login failed and then we want to create a new function for log out so const logout equals parentheses Arrow function set user to null delete axio default. heads.com of authorization and then we'll push the user to login and at the very end we just want to return the off context. provider value of our user login and log out to all of the children and then lastly export default off contacts all right and after we do that let's go ahead and create a new folder inside app that is called components and inside components let's go ahead and create a new Javascript file called protected route all right and now inside here we want to say use client import use context and use effect from react import use router from next navigation and then import off context that we just created from do do/ context SLO context we then want to create a new um constant protected route which is equal to our children Arrow function we're going to say const user is equal to use context of our o context and use router is equal to our use router we want a small use effect um where we're going to say if user is none or not available we're going to say router. push login and we're going to have the use effect recall based on the user and route then we can say return user question mark children colon n export default protected route all right perfect now we can close out of both of these all right and now the next thing we want to do is create a new folder and app and we're going to call this login and now inside our login um directory let's go ahead and create a new file called page.js and now inside page we will say use client import use context and use state from react Import off context from our uh context off context we then want to say const login equals um parentheses Arrow function const login of used context of our o context then we want to create two pieces of State one for username and one for password we then want to say constant handle some equals e and then an arrow function that says um we want to prevent the event from happening and then log in to our function of username and password and then for this next part which is mostly HTML go ahead and just paste it from the code that's provided below um we're going to do that for the HTML because uh it can get along typing in all these class names but really what we're doing is we're just creating a new container that just says login where a user can um type in their username and password click the login button and then we call this functionality in this login functionality which brings us to our off context login that we just created created and then lastly we can wrap this up by saying export default login perfect and now let's go into our layouts. JS that is already created here there are a few things that we want to add in to our Imports and a few things that we want to add into our root layout so let's go ahead and add the Imports first so right here we can go ahead and just delete everything right here except for our global. CSS first we want to import our bootstrap CSS so we can say import bootstrap slist CSS bootstrap.min.css we then want to say Import off provider fromc context SL off context and then right here it says export default function root layout of children we want to return and above this HTML we want to wrap off provider and then right here where it says body of class name we can just go ahead and remove this class name and just say hey we just want to return a children of our body and now the very last thing that we need to do is go into your web browser and grab bootstrap.css about JavaScript go back into the code and we can paste this right above the second body now because we're using nextjs scroll all the way over where you see cross origin go ahead and just make that a capital O So cross capital O for origin all right now for the very last thing hop into your page um JS the one that is default that came with the project and what we're going to do here is just copy and paste all of it because this is a ton and ton of code and this will just stretch out this video and make it super super long but we're going to have another use client with use context use date use effect our off context protected route and our axios we have our user and our logout coming from our off context with our workouts set workouts routines set routines workout name set workout name Workout description all this as pieces of State in our application we have a token which is going to be our local storage of git token and this token is going to be our uh JWT here inside our use effect where we fetch our workouts and routines we have all of our apis set up to connect to our fast API application so we have our workoutworkouts which is gets everything and then we have our workout then we just have our routines which is just slash routines we then want to set up all of this and we throw an error if something's wrong inside we can also create new workouts here create new routines and then here we have all of the code which is a bunch of HTML which just makes our application look a little bit better when we're trying to present all of the data so what we can do here is go into your fast API terminal and say fast API run Main .p to get everything started and then over here we can say mpm run Dev this will start up our nextjs application from here we can go to our Local Host Port 3000 it should automatically redirect us to login all right and then we type in our username of coding with Robi and our password of test 1 234 exclamation mark all right it says create workout create routine it says your routines which is a full body workout this workout this routine Works your whole body with push-ups do 20 push-ups and sit-ups do 30 sit-ups now what we can do is we can create new workouts so let's say we wanted to add like Squat and the workout description is um do five squats and we say create workout and then we want to do some lunges so maybe we want to say uh lunges and we want to do 10 lunges well what we can do now is go to create routine where the routine name is going to be um lower body workout the routine description is get leg swo and here we can see all of our our workouts what we want to do is grab um squats and lunges you can do that by like clicking your control button so control let you click around so I'm going to say lunges and squats we're going to say create routine all right and there we have it we created our full stack application using nextjs and fast API all right and now there's one one more piece that we want to get to um to be able to register a user because we can log in we can do all that kind of stuff but we want to be able to register a user right so let's go inside page.js all right now inside our page.js we need to create two new pieces of state right here under username and password we want register username and we want register password so we can say const register username set register username equals a use State and the same thing for password all right and then after this let's go down to where you see handle submit let's go right under handle submit and let's create a new handle register and we can do this by saying const handle register equals a sync where we're going to pass an e just like we're doing up here of brackets e. prevent default and now we want to try and register our user so we can say try const response equals await axio stost where it's going to be our HTTP col localhost Port 8000 off we're going to pass in our username of register username and our password of register password and then we want to say login register username and register password so we're automatically going to log in once a user success successfully creates an account if anything goes wrong we want to catch it so we can say Catch Air console. a failed to register user of erir all right and then once we do that since we're going to be using axios you might see this red line that just means we need to come up here and import axios all right and now let's go ahead and make an area for us to be able to oops this is actually a space right here but we still need to make sure that we have this axios right here and then let's scroll down until you can see this login form now right at the end of this form let's go ahead and just paste in the register HTML code from the code provided this will allow us to just be able to Simply add um the register in here which will just make this part significantly quicker this is just going to be a form where we can submit a new user so now if we go back into our application we can see that there's now a register along with a user so now if we go ahead and try coding with Roby test 1 2 3 4 exclamation mark right here we can see that we log in and we can see our routines if we log out and we register a new user so I'm going to say um new user password is just test and I say register it's going to successfully submit the new user log in with that user and here we can see there's workouts that we can create and it's going to have all the original workouts because all the users share the same workouts but they don't share the same routines so boom now we have a full stack application that has login and register functionality which have their own routines and can share workspaces sweet stuff and I'll see you in the next video