How to build & deploy a MERN stack web application (typescript, mongo, express, react, node)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
how's it going everyone welcome back so I'm going to be showing you how to build out a full moon stack application um this is fully deployed to a secure domain at flashcardstage.com so I'm going to show you how to set up a domain how to get that hosted and then also this is connecting to a live API that's also secured with a subdomain api.flashcardstage.com and this is hosted on a VPS so I'm going to show you how to like Association to a VPS how to set up a node application how to run it and how to also set up https forwarding using something called caddy so we have a really basic application where you can create flash card and decks so in this case we'll create a deck called like I don't know hosting and once you create that deck you can actually click into this and behind the scenes we're using a react router to basically manage the routes of our single page application and once you're inside the deck you can start creating flashcards like so for example I can make a card called caddy a tool for hosting your files and setting up reverse proxies on a VM or VPS but you can basically have these cards have their own data nested in them and you can go and add new cards if you want to kind of practice memorizing some tools and all this is just using plain CSS we're not using any Frameworks we're not using any CSS libraries we're just using plain CSS because I think it's good to understand how to build out uis using CSS before you start pulling in some other third-party libraries like material UI or meantime UI yeah if you're interested in learning out how to build a full stack more an application be sure to stick around and we'll just go ahead and start figuring out how to do this together so before we actually jump into learning how to build this project out with the merge stack I do want to mention that this video is sponsored by hosinger and all the deployments are going to be happening on this hostinger's service more specifically we're going to be using their premium shared host for hosting the react compiled application and then for the API we're going to host that on a VPS so I do want to mention that hostinger is having a Black Friday sale where you can basically get four years worth of hosting and a free domain for a very affordable price of 249 a month and also if you were to sign up for this Black Friday deal you can use my link that's in the description below or I'll put it on the screen here and additionally there's a code that you can use web dev junkie which will give you a 10 discount on an already great discount and deal for a Black Friday sale so keep that in mind definitely go check it out if you're interested in hosting your UI or your application on a web service so if you want to sign up for the premium shared hosting basically click on this claim deal button and you can go down here and you can click the most popular one which is premium shared hosting and we're gonna go ahead and add that to our carton so after adding it to your card I would recommend that you do the 48 month plan because that's going to give you the most savings but any plan that you decide to choose is still going to give you a good bang for your buck because this is a pretty affordable web hosting company and like mentioned below you get a free domain for the first year on all of these plans as well and then after selecting your plan go ahead and just set up an account and then enter in your credit card information and and be sure to if you have that coupon code I kind of talked to you about click on have a coupon code and type in web dev junkie and you will also get a 10 off on this deal so it's a great deal really affordable definitely check it out and I just want to note that there is a 30 day money back guarantee so if you do decide that you don't want to go with this service which I doubt you will because they are extremely fast and they have a 99.9 up time guarantee you can do so and you can get a refund if you don't like what you've purchased so after you purchase your plan you'll be redirected to your hpanel your dashboard where you can start setting up this premium shared host like I mentioned in this project we are going to be building out a single page react application and we're going to host that on hostinger's premium shared hosting so let's just go ahead and set that up and get claim our domain so I'll click the setup button and I'll kind of walk you through the process it's really user friendly so let's just go ahead and click Start now and I'm going to say that I already have a website and I don't need extra help with creating anything there's also an option to skip preferences if you want but I'll say I already have a website I'll just go and say other and then I will say I built it myself and once you kind of answer the questionnaire you have the ability to migrate an existing website or create a new one I'm gonna go ahead and click create a new website because we're going to upload our own single page application to this premium shared host so that we don't have to um migrate anything right now I'll go ahead and click select create a new website and I'm just going to go ahead and say create an empty website because we don't need to use hostinger's website builder or you set up a WordPress or do any other type of CMS we're going to kind of do our own thing but just note that they do have additional features with their own website builder if you need some additional assistance with building your own website and definitely go check that out but in our case we're just going to skip and create an empty website and we are going to go ahead and claim our free domain here so I'll go ahead and click select and the domain that I want to use for this application I'll go ahead and click.com and then I want to do flash card Sage right we're making a flash card application and I want to make sure that I can buy this domain and it says it's available so let's just go for it so at this point you can change your server location if you want to you can also change your domain since I live on the east coast I'm going to go ahead and just click North Carolina and I will change that location and let's just go ahead and click finish setup and then of course let's just fill out some additional information I'll say USA and this is just going to be for personal website I'll click next and then for contact details so I don't want you guys to see my actual address so I'm gonna go ahead and skip this part but just know that you can fill in your information and these are required Fields so you have to put them in um to get a new domain and now that domain is being registered so let's just go ahead and give that a second and they got a nice little loader here to let you know that everything is getting set up so let's just go ahead and let this finish and then we'll go ahead and continue on the setup process all right so we're all done now what I'm going to do is I'm going to go ahead and go to manage site I mean we could view the default site right here and notice that here we are flashcardsage.com and we have a basic site set up but what we really care about is managing our site so let's go to our control panel and let's just kind of look through this so there's a lot of options that you have when you're on the hostinger dashboard but we're not going to cover a lot of this stuff on this video the main thing that we care about is the file manager and this is how you can basically upload your compiled a single page application to their servers so we'll see later on I can just drag and drop my compiled application here and that will display on that website that we had basically set up if I go back to the dashboard you also have the ability to set up databases which is great if you ever need some type of SQL database where you want to kind of create some tables and maybe store some information you can do that here kind of great that they give you a free database that you can kind of play around with so one thing that's also cool is you get a free email with this domain that you have set up so if you go to manage you can actually select the free setup which we're not going to do in this video but just keep that in mind it's a cool out of the box service that you get when you do the premium shared hosting plan that I mentioned they also Daily backup your files so like if you ever mess up your files those will be backed up daily and just in case something goes wrong you can just restore those from an earlier date now I do want to point out at the top you can go to your domain section which we might actually need to do in this tutorial where if you need to set up some type of custom records like an a record or a cname you can go to your Main and you can actually configure those settings so for example I'm gonna go over to DNS name server and I believe I can start managing my DNS records this is useful when you want to domain the point to a particular server or if you want like a sub domain such as API dot flash card Sage to point to a VPS which we should hopefully be doing later in this tutorial so stick around if you want to kind of watch how I'm doing that but out of the box we seem like we have a bunch of records that are already set up that'll get you started with your email getting started with FTP and all these other things so unless you really know what you're doing I would not go through here and like delete the existing ones but sometimes you need to add new records to point to backend services and again if you ever need to get back to your website's dashboard or panel you can just click on this website's link here and that'll get you right back to all your websites that you have and I can go ahead and click manage here if you want to create a new website let's say you have multiple websites you want to get set up you can do that remember this plan gives you up to 100 websites but we're going to go ahead and go back into manage and I think that kind of wraps up the overview of this website manager dashboard and some of the features that we're going to be covering later on so let me move on to the next part of this process which is setting up our VPS plan so the reason we're using a VPS is because we are creating our API using node.js and you actually need a physically running server to run your node service if you wanted to just stick to PHP you can simply just upload your PHP files to your premium shared hosting and you can kind of interact with the database that way but if you know anything about my channel I can use next I like using node but in this project we are actually going to SSH into a VPS and we're going to set up and install whatever tools that we need on whatever operating system that we choose in our case we're probably going to use Ubuntu and then we can get our node server running so let's just go ahead and click setup here for the BPS server plan too and before I configure the VPS I do want to just quickly mention it so if you go to the main home page of postenger and click the VPS drop down and go to VPS hosting that's where you can actually start setting up your VPS in our case we're going to be using the vps2 plan which is five dollars a month we you get you know two gigabytes of RAM 40 gigabytes of disk space two terabytes of bandwidth which is more than enough to host a simple node server you get a dedicated IP and some weekly backups and if you want the finer details of what the machine's Hardware is going to be you can kind of look through here vps2 is going to be two cores two gigabytes of RAM and a bunch of other features so in our case let's just go ahead and select this plan and we'll kind of walk you through so in our case we'll select the VPS plan and again like you can use that code that I mentioned at the start of this video the web dev junkie code to get 10 off discount on these so you have the option to pick from any of these plans depending on what your needs are for your actual business or your website or web application obviously the more time you buy the more months you buy the more bang for your buck you're going to get and same process as before enter your email and go ahead and just enter your credit card information and that'll kind of give you the option to set up your VPS like we did with the premium web site hosting and again use that web dev junkie coupon code to get 10 off and uh yeah let's just go ahead and continue the setup so for the VPS server plan 2 let's just go ahead and click setup and kind of walk you through this so like we saw with the premium web hosting we are also getting a nice little wizard that kind of helps you set up your VPS and I'm gonna go ahead and select my location as USA because that's where I live so at this point in the Wizard you have the ability to set up an OS with a control panel if you want and this will basically allow you to manage your VPS a little bit easier if you're kind of newer at this technical type of stuff but I'm the type of person who likes to just deal with plane operating systems and just start installing stuff just for fun so I'm gonna go ahead and click the plain OS also you can set up Minecraft if you want they have Game servers as well but I'm gonna click the plain OS here because that's what we're going to need for our project and you can select from Debian or Ubuntu I'm going to say Ubuntu um it honestly it doesn't really matter too much like there's some differences between the different os's and like the different package managers and stuff but I think just get good at one and they're all going to be able to be pretty performant behind the scenes so after selecting Ubuntu I'll click continue and at this point you have to give a host name to your VPS so what I'm actually going to name this one is API dot slash cardstage.com and this will be useful when we set up an a record later on and you can set your own root password here I'm actually just going to use the default but if you want to rotate that you can do it later on and then you also have the ability to set up an SSH key if you want to which which might make it a little bit more convenient to SSH into the machine and start installing things but in our case we'll just use the root password I'm going to click save and continue and now we can finalize our setup I'll move ahead and click finish setup and like the other setup we have a nice little loader that'll tell us progress of our setup and we'll come back and check this in just a bit so after the VPS is done provisioning you will get redirected to this uh control panel where you can actually see some different information about your VPS service so for example we set up an Ubuntu machine and we have the IP for this machine which we'll later use for setting up the a record for the subdomain but using this you can actually SSH into the machine and use that root password to start installing different things on that Ubuntu operating system some other cool features that you get are you have the ability to reboot reboot your VPS or stop your VPS if you scroll down a little bit it tells you the CPU usage the memory usage the disk usage and bandwidth of this VPS as well so you can kind of monitor your API and see how much traffic is coming into your API at a higher level if you need to and some other cool features that we get are we can kind of configure the server over here so for example if you wanted to update or change the root password you can do it here in this panel so over here in the SSH key panel you can add new SSH keys or remove old ones that you need to kind of rotate and then in your main setting you can go and you can change your hostname if you want to and you can also change a couple of other settings that we won't really get into it and again you can go to server usage over here if you want to get a high level overview or more like fine-grained detail report of how much CPU and memory and load is being put on the server over 24 hour period last week last month and last year they also provide you snapshots and backups if you want to take a snapshot of your VPS just in case you want to make sure that if anything bad happened you can restore it that is a cool feature that hostinger provides as well you have the ability to go and see what were the latest actions that were applied to this box so for an example if someone were to change a root password that is documented here and then finally there's the option to restart or reinstall your operating system so for example let's say you just wanted to wipe the Box clean you can go ahead and click reinstall which will just change and reinstall your operating system or you can go and you can actually change it back to any of these provided operating systems out of the box I'll change it back to the OS with control panel or game server it's really up to you so those are some of the features that are provided with the VPS now again like what we're going to be using really is just sshing into the machine to install maybe node npm and maybe git so we can clone our project and run it and then we might also need to install caddy so we can set up an https SSL certificate and and do some type of um proxy passing on the API box as well so that we have http PS access on our api.flashcardstage.com domain so that kind of wraps up the overview of the different hostinger plans we're going to be using on this project and after we finish building out our murn stack application we're going to come back and see how we can deploy this to these different plans that hostinger provides so at this point let's just go ahead and jump into learning how to build out a myrn stack application for taking and creating and deleting some flash cards that you can study with but let's just go ahead and get started again we mentioned that we're going to be using Express for the backend and I'm going to be using react for the front end so the first thing I like to do is just load up whatever documentation that would help you get through these processes so let's just start off with Veet and I'll just say set up react type script I'm going to try to use typescript for this entire project because that's kind of like what I've been using lately but if you go to okay that's not the right site let's go to get started with Veet now the reason I'm using V to over create react app is speed is a little bit faster or a little bit faster I don't know how you want to say it but you can use whatever you want this that's not the important part the important part is building out the actual application so let's just go ahead and run npm create Veet latest and I'm going to go ahead and do that inside a client folder so I like to make a mono repo and I like to make a client folder and then like an API folder so that I can just deploy them separately if I want to when you do this you are asked what language or framework do you want to use I will say react obviously typescript and you can CD into that folder and say npm install and that'll go ahead and just set up all your node modules both you're familiar with how npm and node modules work basically all these languages and libraries require a bunch of dependencies and npm is a way to basically manage those dependencies and download them from the internet so that when you mpm install you get a billion dependencies in your project that kind of lets it all work all right so again let's verify that we can run the client so in my terminal I'm in the clients directory if I say npm run Dev let's verify I can go to this URL that kind of asks us about or tells us about and we have our react app running so again I'm using Veet to create a single page react application uh the reason I'm doing that is it's just what I chose for this video you can use next you can use remix everything has its own pros and cons but really if you're a beginner let's just focus on learning more about react and how to integrate react with a backend API okay that's the important part all this other stuff is not as important so we have successfully set up a Veet react typescript project and I will explain the structure of this in a little bit but let's also move on to the back end let's see if we can set up an API using Express so again let's not be scared let's go to express and I'll say documentation npm or something like that and let's go to express.js express.js is a simple web Library you can use to build out rest apis now a lot of people use other things like there's restify there's something called uh nest.js if you really like using that the reason I'm picking Express is just because that's what I've always used but there are some other more advanced Solutions out there like there's restify um there's fast defies one as well I just wanted to share these with you in case you're a beginner you don't really know but there's other Solutions you can use in node that actually run a little bit faster than Express and they have more features out of the box but I like Express because it's kind of like it's a lightweight library and it has a ton of plugins you can just go ahead and get set up and I don't want to spend time learning about these other things although they are probably just as good let's go ahead and get started with Express this one if I go ahead and just go here to my project and make a new one called server like to have a server folder in a client folder I'm going to go ahead and click on this to open up a new terminal so typically I have two terminals open I have one for client and then I have one for server and you can see there it prints out claim server so you can kind of like visually know which one you're looking at and I'll go into the server and I'll say npm init hyphen f and that'll create a package.json file which is used for kind of keeping track of what dependencies that will need um the first thing I'm going to do is I'm going to go ahead and just change this to MIT here because I believe that's the uh the license I'm using for all these things I don't know if this one even has a license but again we're trying to focus on building out the the server setup and again I'm in the server folder here I'm gonna go ahead and say npm install and then I'll say hyphen hyphen save and I'll say Express that is how you can install a package dependency or npm dependency inside your package Json so notice when I run this command it'll take some time to download some things from the internet it'll set up a node modules folder and then it also Updates this package.json and I have an Express dependency setup now so I'm also going to make a DOT get ignore here so we are using git which is a way to basically keep track of your file changes over time and commit them to a git Repository I'll try to cover some topics about git hopefully you kind of already understand it but if you don't I'll try to walk you through what I'm doing but in this get ignore file you can put this in different directories and notice that client already has one because V set one up for you but inside the git ignore file you can choose which files and folders you don't want to like commit to your repo now usually we always ignore the node module so I'm going to put node modules here and the reason we do that is because node modules can sometimes be like 600 or you know a lot of disk space so we don't want to commit that to a repo because now we're just like filling our repo with a bunch of unnecessary code that is going to often change so make sure node modules that get ignored and you'll see here it's kind of grayed out that's when you know everything is good all right so let's just keep on going let's see if we can set this up the server I'm going to make a source folder here and inside of here I'm going to do index.ts again we're trying to use typescript for everything we build out um because typescript is going to help you hold it's basically going to hold your hand as you're writing code which makes it a lot easier to build out your application especially if you're a beginner JavaScript does not hold your hand so if you type something wrong you're not going to know until you run your code and it breaks and you spend two hours trying to debug because you've left off an s or something called notes when you should have just put a note as you can tell I've been bitten in the button many times by using JavaScript and typescript is just going to help you out so let's just try to set up Express so if we go back to the express documentation uh which is here we can go ahead and get it set up like this now we might have to do some extra work to kind of get it formatted in the proper way for typescript so I'm going to go ahead and change import Express from Express like this and then go ahead and say app.listen on Port we'll do port 5000. so if this works fine we should actually have an Express service that will run when we try to run this this file okay so I know I kind of covered a lot of things and it could be kind of overwhelming what's going on but basically remember we npm installed expressed as a dependency and now in our actual typescript code we are importing a function from that Express dependency package that we installed and when you call this function it gives you back an app which allows you to configure different endpoints and then tell it to listen on a particular port so in our case let's just do aft.it and I'll explain what the git means in just a second and I want to say when someone tries to do a request on the top level directory of our URL I'm just going to go ahead and send back a message that says like hello world so let's verify this works I'm gonna go ahead and end the package Json actually before we can verify it we do have to bring in another dependency I'm going to go ahead and install remember I'm in the server directory here and you can look over here we have the server terminal selected I'm going to npm install save hyphen Dev TS hyphen node because we're using typescript the way that you can run the typescript files is by using TS node there's other ways you can do it as well but I'm going to go ahead and use this TS node dependency and I'm going to write a script over here called Dev which is going to say TS node space source index.ts so when you write npm Scripts anything you put here if you would install the dependency that includes like a binary typically you can just reference it like this and then you can point it to a file now it really depends on what dependency you're trying to use in our case TS node is a CLI tool that you can pass a file as like an entry point and it's going to Traverse all of the Imports that you're using and bundle them up and run them so let's just try running this npm run Dev and now we should have a server which will basically run on that Port now we are running into some typescript issues and if you ever run into these usually you can just fix them by doing the recommendation that tells you so in this case it doesn't know typescript doesn't know like what the heck Express is so we have to install the types for express by running this command here so again like if you're a beginner just take the time to read through what's going on I know there's a lot of characters and it's super overwhelming but usually they give you hints as to like how you can fix this and you can go to a stack Overflow and understand so I'm going to install that Express thing and hopefully that'll take us a step further to getting this working npm on dev I think it'll still crash again potentially um actually it seems pretty good let's go ahead and go to localhost 5000 and make sure that we get back the message hello world so we have successfully set up a backend API using Express and typescript you listen for or get request on this slash so I do want to talk about like what does git mean okay so the best way to explain this if you're a beginner is if you load up your Dev tools which you can just right click in the say inspect and then click on this network tab I'm gonna go ahead and click on Fetch xhr and if I refresh the page actually I think you need to select all if I refresh the page and click on this request and go to headers you'll see that it is doing a method git okay g-e-t get to this API and then there's a slash here so what we're doing in Express is we're saying I need to set up a server on Port 5000 which corresponds to that 5000 that we saw here and also up here and we're saying when any whenever whenever someone tries to request the default route of Slash or you know there's no slash here we want to run some code so we're saying if someone does a get request to slash let's just go ahead and run this function so hopefully you understand how a callback function Works in JavaScript it's usually a function like in this case this is an anonymous Arrow function that we're passing to express and this Arrow function will be invoked at a later time depending on when the express Library decides to run so you make a request to our localhost 5000 Express is going to look at the request headers and figure out okay what endpoint is he actually trying to call and what method is he using in our case it says okay well he's doing a get request to slash let's just go ahead and return hello world and we're going to be configuring this a lot for our different endpoints when you do credit your credit set up for like create read update and delete you're going to create different endpoints and use different methods but I just want to make sure that you have a solid foundation on like what does the git mean and what is this this slash stuff mean again if I were the changes to like uh hello and go ahead and restart my server one thing I want to point out is we are using TS node so whenever you change the file you actually need to stop your server and restart it and there is a workaround for that using something called nodemon um so I'll say nodemon TS node watch and I do want to walk you through my process of like it's okay to Google for stuff right even senior developers don't know how to do stuff we forget how to do it and usually it's like you set it up once so you don't have to worry about it so this is a stack Overflow that explains how to set up something called node mod to have it automatically refresh your API when you save your files so I'm gonna go ahead and run this command without the TS node here let's go ahead and delete that I'm going to stop my server and again we are in the server directory and we'll go ahead and run this and while that's installing let's look at this command I'm going to copy their example and inside the package Json again we're going to set up a Alias or a script to basically use node mod instead I'll say node Mon and I'll say watch Source star and then I will say extensions of TS Json um in this case we don't need to ignore specs because we're not going to do tests in this and you can also execute something so I'll just go ahead and do that okay so we obviously can't use the double quotes here so I'm going to have to figure out a different solution I think I just need to like back slash these like so and now if I do npm run Dev hopefully and let me double check I didn't screw anything up uh this shouldn't be here let me delete that so we're telling nodemon which is a CLI tool to basically watch for any files that change inside this Source directory make sure that it's only typescript files or Json files and if any of those files change we want to rerun TS node source of index TS so we are just going to run this and hopefully it works okay it looks like it's running fine and if we were to go ahead and go to index TS and just save it notice that it restarts automatically for us so this is what you want to get set up there are many different ways to have a backing API setup but usually node mod is like one of the easiest ways to do it so what I was originally trying to show you is if you change this URL and I go back and do like slash hello we get the right page but now if we were to actually hit the the base URL of our API notice that it fails because we didn't Define a an endpoint or what happens if you were to hit flash okay so if I were to print out a different message for the slash now I'll save the file I'll go back and refresh hit GG otherwise we get hello now the reason I'm putting so much emphasis in the back end is because I like to start my project out with typically back in API endpoints and then I work on the UI and connect those so I want to make sure that you really understand how like a backend API is working how these requests work again like keep this network tab always open for the most part and also your console Tab and look at the requests and understand that it's making a request using the git method to this endpoint and then Express is going to run whatever commands that we decide to set up and run this Anonymous Arrow function and send back some data and we'll slowly learn more and more about like how all this stuff works but we are using typescript so I think it's good to actually put Types on these things so you can actually type these with request and response like this and make sure you import those at the top and when you do that what that allows you to do is you get that good typescript intellisense where when you type res and do a DOT you get all this Auto completion that tells you the methods that you need so it kind of saves you a step of having to go and look at the documentation and let's say you kind of remember the first letter of what you want like let's say headers are set right you can kind of type in SCT and then hover over and it says well this sets a field to value in your headers so now I don't actually have to go and like go back to the API and I don't have to search for set here because it's just a little bit harder to like read through their documentation to understand like okay how do I actually set headers and they'll go to a page and you realize you're on the wrong page and you write a bunch of stuff that's not even related so typescript will help you out and also tell you if you're doing something wrong so if I were to call a method called like send without the in or said it'll warn you JavaScript is not going to warn you when you do stuff like that so this is why I like to use typescript on my my projects and as a beginner I highly recommend that you use typescript as well okay so we have the front end going we have the back end going um we have a nice setup for both of them now what we could probably do is start working on adding a simple API endpoint to allow users to create new flash card decks okay um so let's try to figure out how to do that I'm also going to just put these types here just get into the habit of like making sure you always put types for your things there's also a TS config file that you can set up a TS config.json file we won't get into that in this video hopefully we can kind of hit the ground running without worrying about that but so like I mentioned we're going to be using the mern stack okay so the M part of the myrn stack means mongodb the reason I'm picking mongodb is because usually it's a lot easier for a beginner to learn how to interact with the database using than it is with using SQL now personally for any real projects I would probably just use SQL over but if you're a beginner learning helps you not have to learn about migrations it helps you not have to learn about writing SQL statements or create table statements or update table statements and stuff like that but honestly if you're using Prisma I could kind of take care of all that um but let's just go ahead and look into now I'm going to use something called Atlas this this video is not sponsored by Atlas it's just a tool I like to use when you're playing around with stuff you can also set up locally if you want to which is a solution it's just a little bit more overhead to do you might have to pull in like you might have to pull in uh Docker or something um let me just sign up real quick using Atlas I'm just signing up for a new account with my other email just so I can kind of walk you through this real quick um so I'm gonna use the free the free uh shared plan or whatever usually it's super usually works pretty well for like what we're doing in this case I think you get like one of those I'm gonna just create the cluster um and once you have the cluster set up we are going to just go ahead and put like a username of I don't know flash card uh sage and then the password we'll just go ahead and generate one why not and copy it and I'm gonna go ahead and create that user and this is a user we're going to use the connecting to the cluster right so I know I'm saying a lot of terms let me take a step back is a type of database database is used for storing data in retrieving data so when you're working with production software systems you'll have many many different machines running and they all need to store and retrieve data from a centralized location right so a cluster is basically a database that's built up of different machines and the data is kind of distributed between all these clusters and when you want to save or retrieve that data it will find out which node in the cluster needs to actually pull from and then that's what's returned to your UI that you can use to display it way probably way more advanced um topics than you guys even care to hear about but I think it's good to get exposed to these this terminology because when you get into a real production environment with you know a real Software System you're going to be hearing these terms and it's good to kind of understand it um and then I'm gonna go ahead and just do my current IP and add that in so now we have a cluster that's set up and we're going to try to connect to this cluster from our API so that we can actually door a new deck in our in our database okay so let's go ahead and go back to our API and what we're going to do is we're going to try to bring in a tool or a library that allows us to easily connect to that database cluster um so we're going to look at Mongoose I think this is like the de facto standard most people use with node so I'm gonna go to this Mongoose documentation I'm going to read through it a little bit usually they have like a getting started area but I'm going to just install this like so go ahead and start my server and I'm going to install mongoose and once you've installed Mongoose you can import it so I'm going to just import that at the top while my stuff is still installing and there should be a way to connect so I'm go ahead and just do this import Mongoose and then we are going to connect to mongoose I'm going to go ahead and say DB equals this now this URL you actually need to provide the URL to that cluster that we just set up so if we were to go back to mongodb Atlas and go ahead and click connect that should give us a way to connect to this cluster um now I have to figure out which one I want to click on connect via your application I think I will say node.js and I think 4.1 should be fine so if I copy this whole thing here I think this should work fine I just need to make sure that I put in the right password which I don't think I even copied so if I go back to the passwords uh I think I have to go to security and go to database access to find what user has access to this I may have to generate a new password go ahead and generate a new one I'm gonna go ahead and copy it and I'll just update the user and I'm going to paste that password right here for now but we are going to refactor this later and make this more secure it's never good to have a username and password or the URL hard-coded into your code you want to pull that into a EnV file but again I'm going to assume that you're kind of learning you're kind of a beginner and I don't want to overwhelm you with too much stuff so what we did is we installed Mongoose which is a library for connecting to our mongodb database cluster whatever you want to call it and you can do a mongoose.connect in pass it a URL or basically getting the code set up to start reading and writing to that um so let's go back to the Mongoose documentation and typically the way that you can use Mongoose is you set up different schemas so let's just Define a new email a model and we're going to go ahead and in the source folder I'm going to make a new folder called models and I'm going to go ahead and make one called deck dot TS and inside deck.ts we're going to go ahead and just copy that code in and we are also going to import Mongoose so if I go back in the top of deck TS let's just import Mongoose here and we are also going to let's see I might have to install some type of um Mongoose related types so typically with typescript like you can just guess what the types are going to be you can see npm install save hyphen div at types Mongoose and if the library or package already has some typescript types published for it those will get installed and set up and uh now we have like all the typescript intellisense for this Mongoose thing although I'm not sure why it's complaining about this so let's try to figure that out it looks like this person online tells you how you can use it I don't know if maybe Mongoose is a little bit older or they need to update their documentation but I'm gonna go ahead and use this instead like that I guess this is the more proper way to do it and again this is a live coding so I'm actually just going off I'm showing you how I developed this and my normal workflow so I haven't prepared I don't have any reference code I'm going off of everything you see me doing is literally what I'll be doing if I was asked to do this on a job so you're getting a real life experience of me running into issues and trying to debug stuff along the way and then also I'm just going off the things that I've done in the past with my memory so when you're setting up a mongoose FEMA or model we can go ahead and rename this instead of blog posts we can call this deck and we're going to go ahead and just allow this deck to have a title and uh that's about it right now we'll just do title and we'll come back and add more stuff to this so what this allows us to do if I go back to the docs I think they might tell you how to use this okay so down here I believe you can do this Mongoose model thing so down here if I were to say model all right if I just say deck and then I can say deck EMA I'm actually going to rename this on the deck schema like this and now we actually have a model here so this would be our deck model and we could export default deck model now this allows us to import this module from other places in our code base and in fact we'd even need object ID here I'm going to copy that out for now we might need it later um we can also access this model by just saying mongoose.model and then pass this string of deck it's up to you which way you want to do they both work but what we're trying to do is like can we just successfully write some data to our mongodb luster and the easiest way to do that is go to your index.ts and we are going to start importing that deck model here so I'm going to say like import deck from dot slash model slash deck yeah so that'll give us access to this deck model and we will see how to use that in just a second um now what we want to do is we want to connect to this database and then we want to actually spin up our API so I'm actually going to do a little bit of refactoring I'm going to pull this code down here and this mongoose.connect call is actually a promise so hopefully you understand how promises work basically it runs some asynchronous code and then some point in the future it's going to call a DOT and then method when the asynchronous code is done so I'm actually going to make sure that the API is not listening for new connections until we're fully done connecting to the database because you don't want a connection to come in and then you try to read from the database but you haven't fully connected and then it crashes so I want to make sure I can fully connect to the database before I start listing for API requests and I'm just going to go ahead and put a console log saying like listening on Port 5000 now at this point you might notice um there's 5000 is duplicated in two places and this is not really manageable so this is called a magic number and we want to refactor this away and keep this kind of defined as a constant so I'll say const Port is equal to 5000. and this allows our code to be a little bit easier to manage because now there's only one place this port variable is declared like so and let's just try this out I don't know if this is going to work off the off the top of um first time doing it so npm run Dev let's say if we run to any errors so far there's no errors which is good and if this would have crashed and not printed this console log if we couldn't connect to the the URL here that we put so good sign good sign now what we want to do next is there's something called rest uh restful apis in the web development world right so typically what you do is you have these different request methods you have git you have put you have patch you have delete there's one called head and those methods all kind of represent different actions that we're doing on different resources so in our case we're building out a flash card application which means you probably want to have a resource URL called X and when you create a slash Dex URL what you typically do is you create different crud operations that allow users to create new decks update existing decks or delete decks so going back what are we trying to do we're trying to allow users to create new decks of flashcards so I'm going to use a different method instead of doing git here I'm actually going to do a post post is the convention we use for creating a brand new resource when you're following restful architecture of your API designs so when someone does a post request Dex what we want to do is we want to just go ahead and create a new deck model and persist that to our database so how do we actually do that I'm going to go ahead and say const new deck is equal to new deck so I'm taking that Mongoose model that we declared in this file remember this is exported here and we are basically creating a new model called deck and we are going to set up a new deck object okay so this is just object-oriented programming we instantiate a new instance of a deck glass and then we can use it over here and again deck requires a title so let's just go ahead and give it a title I'll say early base title I'm going to pass it a JavaScript object this is a JavaScript object and I'm going to pass it a title called like my awesome flash card deck and when you create a new deck this at this point is not going to be persisted of the database you actually need to tell this endpoint to save it so I'll go ahead and say new deck dot save and at this point is going to get saved into the database now this is a asynchronous method if you hover over it with typescript notice that it says promise here which means we probably want to await on it which means that we need to put async on this Arrow this Anonymous Arrow so off the bat we have a endpoint that when you do a post request to slash dicks it creates a new deck instance it saves it and then we probably want to return something back to the user who made the request so I'm going to say res dot Json and I'm gonna go ahead and just say uh over here you can actually get an object back when you create or save the deck so I'll say created deck is equal to a weight and I'm going to send back that Json here so if we did this correctly we can verify this using a tool called thunderclient which I don't think I even have installed so let's install that and we'll say thunder client Thunder client there's also you can use Postman you can use insomnia I like using thunderclient because it's just like right in vs code I don't have to worry about like opening a new tab or a new program but what you can do is you can load up your ThunderClan extension and I can just go ahead and say new request and I'm gonna go ahead and make an HTTP request to a local host 5000 slash decks now this is the exact same thing that happened when I showed you up here when you refresh your browser the browser by default does a git request when you try to enter a URL but if you want to test out a post request you'd have to use something like this so in this case I'll do a post request to Dex and I'm just going to go ahead and run this so my head might be blocking there is a send button up here it's not really too important to see um but just keep that in mind there's like a send button I guess I could do this if you guys wanted to see that um yeah here we go so if I click Send we should get back a response if you look here we get a status of 200 and we got back some data so that means that everything we just wrote in that index.ts file where it's creating a new deck persisting it to the cluster and then sending it back to the user this is all working perfectly fine and one thing you'll see is that you get a unique ID for every entry in that collection we haven't really used the word collection yet but I'll kind of explain that in a second all right so quick recap again hopefully you understand how we did a different HTTP method here there's again there's git post put delete patch so we chose the post request which corresponds to the post here we said do it on this server at slash Dex which corresponds to localhost 5000 slash DX and then when you actually click that send button it sends that payload over to the back end and the backend is going to run this code hopefully that all makes sense this is literally the fundamentals of building out a web API and we're going to be doing this over and over and over again with different endpoints so if you don't understand this at this point it's probably a good idea to stop rewind and understand it because we're just going to keep doing the same thing for every single endpoint changing some of the request methods and changing some of the internals of what happens when you do a request so this all works great but we don't have flexibility right every time someone creates a no card or a new deck of flash cards it's the same title every time and that's not really desirable right we want to allow the user to send over their own custom title so what we can actually do is inside of thunderclient that I have a setup you can go over to this body and I can say okay well I now want to send over some data to the back end and I want to specify the title myself so I'm going to say like hello world is my title and when I send that over to the back end I want the back end to persist hello world make sure you format it properly I don't think I had proper Json before so I'm gonna go ahead and click Send I want to highlight the fact that it's still going to return the same title every time this is not desirable we want this title to match what we sent over to the back end okay now I do want to also highlight how do we get this information right so so thunderclined is doing that request it's actually taking a a packet or a packet of data and it's sending it over to our our node API and it contains all this information it contains the headers the URLs uh it contains this Json but what we want to do is like how do you tell the server to process that information well if you go over here you have this req request object that we haven't really seen yet so let's look at this real quick and figure out how do we get that payload right here that's coming over the wire so I'm going to just console log something real quick I'll say console logrec dot body and I want to show you that I believe this will actually not be defined when I make that request I'm going to click on send here and notice that we get back undefined so it's like how do we actually get the Json body that came over and unfortunately Express is really Bare Bones from the get-go so if you wanted to add in support for different types of payloads you actually have to do app.use express.json all right so New Concept here that we haven't seen before we're using app.use this is something called an Express middleware function right so well technically this is the middleware function and we're telling Express to use this so anytime anyone ever makes a request to our API it's going to first run whatever this code is okay now the benefit of this is we don't need to know what this code does all we need to know is that it allows support for Json post requests so as long as you put this use command before all your endpoints next time you actually do that request you'll see the back end actually prints out the real data okay so this is how you can access that title instead of just putting a hard-coded string here I can say rec.body.title and now let me just show you the cool part if I were to change this to whatever I want click send notice that the data that comes back says hello world with exclamation marks so I know we just did a bunch of stuff it might be overwhelming if you're a beginner but let's go ahead and look at mongodb Atlas and try to like see if we can connect all the dots together okay so let's go over to mongodb Atlas And I want to show you that if I go to database and click on our cluster here you can actually click on something that says browse collections you see this collections tab here I'm going to click that and by default that Mongoose library that we set up is going to create a collection called Dex and if you were to click on the Dex collection you can see all that data that we've just been kind of setting up and if you kind of look closely you have one that says hello world exclamation mark exclamation mark so that's the one that we just set up the one we just sent over and every time we send some data over to the back end like if I said Starcraft 2 and click Send and I refresh this page ignore the refresh button is oh here it is refresh if I refresh this page you'll notice that down here at the bottom we get a title that says Starcraft 2. so we are successfully spinning up a locally running API that a user can invoke that API is connecting to this cluster which lives somewhere in the US I don't know where it is probably somewhere on the East Coast somewhere like Atlanta or North Carolina and it's actually persisting this piece of data over to that data center the data center saving it in a database somewhere and now we can actually view it here so that should be pretty cool I mean if you haven't done this before I mean that should be a pretty cool concept that you're actually purchasing data across the the globe into a centralized place that you can further read from it or fetch it at a later point so I do want to kind of highlight the fact that we're using Source control we're using git and we have done a bunch of stuff but we haven't committed it yet so what I always recommend that you do when you're coding is first of all you should always use Source control and second of all every time you add a new feature or fix a bug you should commit that to your repository so I'm gonna go ahead and say working on setting up the UI in API plus adding the X endpoint okay so you're going to type a commit message here and I'm gonna go ahead and click on this add button that'll add everything that's in my project to the staging area so It's A New Concept that you probably haven't heard about and get where basically you you can make changes to your files and you can pick and choose what files that you want to commit to your repo in our case we're adding everything but if there's some files that you did not want to commit you can actually undo them and like subtract them but once you've selected all the files you want you can just go ahead and click commit and click sync and that's going to push all of these file changes that we did for both the client and the server and it's going to push it to our repo which I haven't even talked about so if we go over to github.com Sage and refresh this page you will see that now we have the same code posted on this git repo on GitHub that corresponds to this exact same code that we saw over here so now what this allows you to do if you're working on a team of other developers they can all clone this repo and they can all start pulling your code playing around with it fixing bugs and then pushing it back and you can kind of keep synchronizing with your teammates as you work throughout the day to get their changes and they can get your changes and then also it's a great way to back up your code because a lot of the times if you keep on adding changes over and over and over again you don't commit at some point you break your entire code base and you don't remember what you did that broke it so doing these small incremental commits and pushing them to your repo is actually really beneficial to yourself because it helps you when you break stuff and you have to figure out okay what did I break and you can do something like a git diff which maybe we'll see maybe I'll talk about um all right so let's kind of talk about best practices right so right now we've just been kind of like hacking everything together into a single index.ts and one thing that is a big No-No in terms of security is hard coding the this whole URL inside your code the reason you don't do this is because the moment you push this to your public repo like I just did everyone has access to this password and username and now anyone can go through and look at my code and they can connect to my instance and they can start being malicious and inserting a ton of data or deleting stuff or doing what they want which is not what you want right so we have to fix that I'm gonna go back to database access I'm gonna change this password because I just exposed the password to the entire internet and believe it or not there's tons of bots that actually look at all these public repos and try to find keys and then they try to abuse your keys especially with your Amazon keys if you accidentally commit your Amazon credentials to a repo you'll have a bot ring up a two thousand dollar bill within a couple of minutes it's it's crazy how how many Bots are looking through GitHub trying to find public keys so instead of committing this code we actually want to do something called putting it in a DOT EnV file some make a file called dot EnV and then I'm also going to dot EnV hyphen sample and what I'm going to do is I'm going to put something called an environment variable so I'm going to say URL and I'll just go ahead and put like nothing for right now just like localhost I don't know 9000 I don't know what the real Port is but this sample thing is so that if anyone else were to clone this project they kind of understand like what environment variables need to be set up so that they can also run the project and typically you have it set up in a way that'll work perfectly fine when you're running this stuff locally but we want to make sure that we never put anything sensitive or Secret inside of this file and then we also have a invite EnV file this is the file that is going to be read from when we start our API and we'll have to get that all set up in a second but what we want to do is we want to put URL here and we want to paste in that URL with our updated password so I just changed my password and I'll probably have to do it again after this tutorial but I'm gonna go ahead and just take that password we changed I'm gonna put it right there go ahead and update that so that we have a new password and the second thing I want to point out is that we never want to commit this this actual URL to our git repo because if we do we expose the password and people can use it so in the git ignore I'm going to say EnV so that we never push that file okay so that's the first part of the puzzle the second part is we need to set up our index file to read that.env when we set up or when we first initialize so I'm going to go ahead and show you how to do that as well I'm going to go to EnV or let's go to npm and then search for EnV this is a library you can use to basically read that.andv file I'm gonna go ahead and just install this stop my server I'll go ahead and install this and let's look at how you use this it's actually pretty straightforward you just run this command okay so I'm gonna go ahead and just run this command like this and technically maybe I should say like import config from EnV to make it more like typescript compliant and I believe I can do that and I'll just call config like this so when you do this basically when you spin up your server it's going to look at your EnV file in fact I'll move it up to the very top just in case it's going to look at this file and it's going to load it into your environment variables so instead of hard coding this right here which is a big No-No I'm going to say process.env.mongo URL which is the same URL that we had in the dot eav file and uh you might get some typescript errors like this if you don't actually like fall back on something so I'll do that for right now just to kind of get rid of that typescript error but there's other ways I think you just also put like a an exclamation mark here if you just want typescript to like not whine about this not being defined so now when we start our API so npm run Dev it's going to load in that EnV file that secret is not going to be exposed to GitHub and that's going to get it's going to connect the way it did before so let's just verify I'm going to just do one more request to make sure it works and we still get back a request so everything's still working as I did before but now we've kind of protected that dot Envy Secret so congratulations you just learned a little bit more about security and why it's important to secure your apps but I will say that I did commit that old password to my repo but it doesn't matter anymore because I changed the password so if any if anyone were to go through that repo and try to find that password they can't do anything with it because I already changed it I rotated the password to a new one and I've just secured my system from a data breach basically our password leak whatever you want to call it all right so again we did a small change let's just go ahead and commit I'm going to say adding dot EnV to secure the app go ahead and add that all and go ahead and just make sure you double check make sure there's no um Secrets anywhere in here and if everything looks good then you can just go ahead and commit link it up there you have it all right so at this point we have a fully working API that has one API endpoint we can connect to mongodb Atlas and we can persist new decks what I like to do is I like to work on a single API endpoint and then I go to the front end and I Implement some logic that can persist something from the UI to my API the reason I like doing that is because it's more following an agile mindset of building out your applications right so instead of building out a git request a method and a post and an update and a delete all at the same time I rather do it one piece at a time because you're going to run into issues along the way with all these endpoints that you want to be able to fix as you're you know learning how to code and as you're learning how to interact and integrate with your API that's the approach I take you can do whatever way you want but notice that we've kind of learned the process of adding an endpoint and really it just becomes a tedious task of doing it over and over and over again for the other endpoints and other resources and the main difference are instead of doing like um a DOT save you might do a DOT update you might do a DOT delete you might do something else okay so I would so we're going to move on to the front end at this point our react application and let's see if we can actually integrate with this back in API so the fun part of react let's understand how Vida set up a little bit I'm not going to dive into the V config because I think it's kind of irrelevant to understanding how to set up an actual application but we have this index file and this is actually what's going to be used to host your UI so if I were to go through that UI again which I believe was over here and just kind of look at the source code right your devtools are your best friend when it comes to coding you can look at some of the stuff here such as the title and you'll see that this title corresponds to this file okay so what V does is it takes this file and after it takes all your react code it injects all the react components inside of this root if and this is all the code that's used for your react application so a lot of stuff you don't need to know about but it's good to know that there is an index file which is basically the entry point for all your react stuff and it's where your react code is going to mount to let's look at the source folder and let's kind of dive into source main.tsx which is this one and further understand what's going on so here you'll notice that it basically spins up uh it calls a function called create root and then we pass it document.getelementbyid and we look for any element that has the idea of root so if you go over to index.html notice that this one actually has root okay so it's going to basically take this div and then it's going to set the root to that div and then it renders out your entire application so that's how react is like put onto the page and you can also import CSS files here and style the page like that and there's a bunch of other stuff that we'll kind of cover as well but the important part or one of the another important part is look at this app component okay so all this stuff is considered jsx and what jsx is is basically a way to take JavaScript code and create components that return HTML when they're rendered out so in our case we're saying that we want to when we render out this react react application to our Dom so we're basically saying when we render out this react application to this root node we want to use whatever this app component is I'm not going to talk about strict mode right now but let's just dive into the app so notice that we're importing this app from this app.tsx file over here so this import statement is corresponding to this app.tsx and if you look at this this will have a default export which if you scroll down default export app and this export is actually pointing to this function so this is what a react component looks like if you're using functional react with hooks basically you have a function that returns some type of jsx that's it and inside the jsx you have the ability to basically interpolate value so if you look here we have a way to print out the count is and then this counts as Dynamic so every time you actually click on this count button you'll see it updates so that's how you do interpolation in react and then every time you click on the button it's calling a on click property event listener which is basically just increment the count by one okay so we'll we'll kind of get more exposure to all this when we actually start working on a lot of this code but just note that the important parts are you can interpolate values to the screen using the curly braces and then you can listen for different events like clicking by doing on click equals curly braces and then you can pass it an anonymous Arrow function in this case we're updating some State using the U State hook it's a lot I'm not going to dive into all this so let's just go ahead and delete all of this boilerplate so we can actually start fresh and we're not so overwhelmed with what's going on so the way I like the code especially with these tutorial videos is I like to do the most simplest thing first and then I refactor the code to make it more production ready and then I keep on doing that right I start with the simplest thing first so if there's anything I do that you're like dude why did you do it so new but like it's because I'm trying to make sure you understand how to write and solve the problem first and then you can come back and you can make it better and then you can make it faster there's a good anal I don't know if it's analogy there's a good saying in software make it work make it right make it fast okay and if you follow this approach of just making it work first then you come back and allocate some time to making it right as in like making it the proper way or making it a better way refactor your code make it clean and then the third step which in my opinion is optional make it fast that's like it could be potentially be a premature optimization which is why I don't worry about making stuff fast especially if you're a beginner because most of the times react is going to run fast your AP is going to run fast you don't need to worry about that stuff anyway that was kind of a tangent so what are we trying to do we have this API that allows us to create Dax right so we want to figure out a way like how do we make the react app allow us to send that data over well when you're dealing with react and HTML typically you want forms okay so you want to make a form and inside that form you want to basically make a label which could we could call it title I'll call a deck title and then we're going to add an input like so and what I like to do is always save your file and then go check your UI and make sure that stuff is showing up you want to every time you make a change make sure that change is updated as you type and as you save so cool we have a nice little input box here and we have a way to basically type in again if you want to make this form accessible which I always suggest you do if you don't want the word accessible means basically it's allowing this application to be easily used for people who have Vision issues or have mechanical issues maybe someone can't have doesn't have access to one of their hands or their you know they have a disability in their hands where they have to use a tab we want to make sure all this stuff is accessible which I'm going to dive too much into because that's a whole other topic in itself but basically at the bare minimum on your labels add an html4 and on your inputs add an ID so I'm going to go ahead and add an ID of deck title here and I'm going to say HTML form deck title and what this allows you to do is now when people click on your label it'll automatically select your input again I'm not going to dive into why this is important but it is important to understand these things and kind of like research them as you you know go through your Learning Journey as to why there's certain things that we do okay so the next step is when someone types into this input we want to keep track of what the type so that we can submit this to the back end all right so with react there's two types of forms there's uncontrolled inputs and there's like controlled inputs for the most part if you go read the react docs they're going to say that you should probably always use controlled components and inputs because if you don't use control components then you're basically going back to The Primitives of JavaScript which we're using react for a particular reason to make our lives easier anytime you use uncontrolled inputs you're making your life more difficult so with all that being said I'm gonna go ahead and say on change and like we saw with the other example the on click we can pass it an anonymous Arrow function and this is going to take an event and we can do something with that event that comes in again we're using typescript so it's usually beneficial to type these things like I say react dot change event and inside that change event I'm gonna go ahead and just pretend that we're going to do something save what they typed so that's what we need to do how do we actually do that well in react typically we can track what people have done by using state so there is a hook called you state that we can use to keep track of what the title is that they are typing in so I'm going to say const title and set title like this and we're going to bring in a u State hook like so so import use state from react and we're going to default this to an empty string and the reason we default it is so that react and typescript kind of know that title is a string and that set title is a way to kind of set the string okay so again like the reason we use State and react is because anytime that you have something that you need to like tell react to re-render to the page you have to use state so in our case when someone types into the input we want to update that state let me go ahead and make sure I add a curly brace here I think this is complaining because I miss a curly brace we want to basically call set title e dot Target dot value like this and notice there I think I may need to put HTML input element like this so that it doesn't complain so typically you have to look at the div or the input type or the Dom element type that you're using and then you'd have to scope using generics and typescript you have to pass it in I know that's like a whole other Advanced topic of generics and typescript and this might be overwhelming so at the very least just memorize like this approach whenever you do on change or on click there's two different things you either have to attach to your types the not make typescript complain so anyway as a user types we are actually storing what they typed so if I were to actually show you this by the way there's an extension called the react Dev tools which you should install if you are going to do reactive element and if you go and click on this components tab after you've installed them this allows you to inspect the internals of react as you're developing right so we have a app component which corresponds to this app.tsx component that we were working on and when you click on it it's going to show you all the state hooks that you have set up so in our case we only have one state hook and it's set to the empty array here but as you type into this if I typed in like hello notice that that State updates this is important to understand the connection between typing and the input and having State automatically update because we need to use the state to send it over to the backend API right so the second thing we need to do is on the input you'll notice that like this input doesn't know how to update so if I were to delete that and go here and just type in like what is up it's in enter notice that the input doesn't update that's because we haven't told the input how to update and what its value should update to when State changes a good Telltale sign is you see how this is kind of great out here this title is grayed out it's a sign that you should probably be using it right so I'm going to say value is equal to the curly bases of title and now if I go here and change this notice that react will automatically update after I click enter okay so now state is perfectly bound up to that input box and as we type and as we delete it gets updated so again like the overall arcing goal of what we're trying to do is like get this title and submit it to the back end so we can persist that deck to the collections so on the form itself what we want to do is we're going to add an on change or sorry on submit listener and also inside the form we should probably have a button that's that's called like create deck so in HTML by default buttons that are inside of forms are automatically going to submit the form so typically you don't need to add any type of Click listener to this button because by default is going to call this form submit so what we're going to do is inside of this on submit we're going to actually make a function up here so we'll say function handle uh create deck and we're going to make that equal to uh this is going to take an event and I can say react.form event like so and I can say e dot prevent default I'll explain what's going on in just one second so the reason we prevent default is because with HTML whenever you submit a form it's actually going to refresh your page so you're going to lose all your data in fact I can actually just show you that let me just go ahead and save this I'm going to type something in I'm gonna click create deck and notice that I just refresh the page and deleted everything that's just a standard way that web browsers work and it's a standard way that all web browsers have decided to work so you have to make sure you tell the browser to hey don't refresh the page because I'm actually going to handle this form submission my own custom way kind of annoying but it's just you know it just is what it is so when this form is submitted we need to talk to the back in API and persist this deck right so how do you do that well inside of browsers there's a method that's built in called Fetch I'll go ahead and do a fetch method and the first argument meaning the first thing that we need to pass this is the URL that we want to do the fetch request to so I'm going to say http localhost and then I want to do the backend API which again if you remember thunderclient it was 5000 slash X so I want to do a request to the fetch endpoint and then I'm actually going to pass this some initial options right so because we want to do a post request you actually need to tell fetch the method you're going to use so I'll just say post and then you also need to tell the body that you want to send over which needs to be a stringified body so I'm going to say json.stringify and then I'm going to pass it title like this okay and you may have to set headers as well uh we'll figure that out and see if that's a possibility of what we need to do but this is actually going to request to our backend using the post method and it's going to send over that that data let's go over and see if this works I'm gonna go to the network tab here I'm gonna go ahead and clear everything out I'm gonna type in like hello and click create deck and notice that it makes a request to this endpoint it does a post request if you look at payload here we sent over hello an object that has title and hello so that's that's cool that's the same exact thing that we did with um thunderclient but now we're doing it from the UI and a real user can actually interact with their UI and persist some data but I do want to point out that we got back an error right we got back a Coors error now this course here is something you're going to see all the time it sounds confusing but it's actually pretty straightforward basically by default a browser is not allowed to access URLs that do not match the same um hostname that you're on right so because we're not on localhost 5000 this request is going to fail when it tries to request localhost 5000 slash decks okay so locally when you're running this locally in your laptop the way to bypass that is you need to set up something called cores on your API so that your browser doesn't just throw errors because of security reasons that we do want so you want this but locally we just don't really care about it so we have to go back to our index file in the API so I'm going to do a command P I'm going to type server and I'm going to type index I'm going to go straight to that file that's a cool little uh shortcut in vs code command p and then type in your file name takes you straight to it super important to understand that I use it all the time so on the on the uh the node server we want to tell Express that like hey we when we're running locally like you can let any API hit us it doesn't matter you can let any hostname hit us we don't care so there is an actual package called course I'm going to say npm install save course and once you install that package you can actually import it's also import cores from cores and I'm going to say app.use course like this so let me show you what's what's actually happening when you do this because I don't think a lot of people actually explain what's going on um okay let me make sure I install my types because it doesn't seem like I can find that try it again all right so now let's go ahead and first of all let's look at X let's see what's going on here so notice that when the request is made the origin is set to one two seven zero zero one and in order for this not to Arrow error out your cores variable has to be set to either a star or you can be more explicit and you can like set it to something else um we'll show that in a little bit we probably have to set that up for production but now if I click create deck notice that it doesn't crash because our backend is actually sending back a request a response header called Access Control allowed origin star so this is a lot of information I know if you're beginning you're probably like dude I can't even I don't understand what's going on so let me just kind of explain it again when I click create deck the browser makes a request to the back end if the back end has a different origin then what was in this request header notice that the origin here is one two seven zero zero one but I'm actually trying to request data from a completely different origin localhost Port 5000 the browser has a security measure baked in to prevent that request from happening it just stops unless the server responds with a Access Control allow origin okay so if your origin matches whatever they put here or if the origin is star then uh or yeah if your browser matches that then it allows the request to actually happen so this is a quick little workaround and again I believe you can actually say like you could say origin here and I could probably put like let's just try this out just for fun um and I'm gonna put I believe I can put this let's try it out I'm gonna put this as the origin and see if that'll also fix it so I'm gonna refresh the page go ahead and click create deck and that didn't actually fix it so there's probably something else I need to consider someone in the comments will probably tell me what's going on here but I I know there's a way to do it typically you have to actually put a real host name so when we go to production we're going to say flash card sage.com and that's basically only going to allow a site that was hosted on this origin to access this API but locally like we don't care like we just want to allow anyone to access it so we can do that and that'll I believe work now right and the default is if you don't pass An Origin star it'll just be origin star so hopefully that was fun to learn about and it was probably more advanced but I'm just trying to expose you to these different things because you're going to run into these issues on your own and you're going to spend days trying to understand what's going on so I just want to make sure that you understand like the purpose of some of these things you're running into and that you don't get too frustrated with like what's going on behind the scenes anyway the main the main thing we're trying to show here is if I go into this mongodb collection remember if you go to the cluster and say browse collections we can actually just look at all the collection items here and I want to clear this out I don't even know how to do that um um I think actually a faster way to do this is just delete the entire collection I'm just going to delete the Dex collection and start fresh and then what I'm going to do is I'm going to go back to our UI which is here I'm gonna go ahead and say like Hello World I'm gonna go ahead and click create deck go back to the mongodb cloud Alice and refresh and we have a collection that was recreated and we have an object so there is an issue we aren't actually putting the right title here so we have a little bug and we gotta figure that out so let's look at the requests we made and let's look at the payload we are sitting the right thing over but I think we are actually missing something so typically when you do fetch you need to provide a header and the header is what tells like the API what what type of data is being sent over so in our case we don't have a request header content type here or we do but it sets the text plane but we're actually sending over Json to the back end right so we want to make sure that we change the content type to um where is it let's go back we want to make sure that the request header content type is set to application Json let me take a step back I don't know if I really talked about headers every time you make a request to your API there is a set of headers that you send over to the backend and these headers again are used for like the course thing we just talked about these headers are used for cash caching control these headers are used for telling the server who you are you can also include cookies in the header but in our case we want to tell the back end like what type of data are we sending over to the API but the API knows how to parse it correctly and there's a set of default headers that just happen when you make requests but in our case we don't want text plane we actually want application Json so if we go to app.tsx and I inside of here if I do headers I can say content type make sure you make this properly operable case and I will say application slash Json and now I believe if I were to do the same request and type in hello world notice that if we go back here and refresh we now get that data showing up okay so there's a lot of stuff to consider when you're building on an application there's a lot of stuff you can screw up on a lot of stuff to understand but now if you look at the request header it says content type of application date Json and our API because we did this setup here express.json it knows what to do when it sees a header that says application slash Json it knows it take the body it knows the pars the Json of the body and then it puts that on rec.body which was here lots and lots of good important information to understand if you're new to backend development and I know a lot of the stuff is probably going to go over your head but again just get used to the terminology because the more you're exposed to it the more familiar you're going to be with working with apis and stuff all right so we have successfully integrated the front end in the back and we literally just saw that we submitted the form it creates data and it puts it in our Atlas cluster that's awesome that's that's a major major step in like understanding how all this stuff works because at this point forward it's literally the same stuff over and over and over again with a little bit of tweaks like when this page loads maybe we need to fetch some data from an API endpoint and we can do that next but I do want to point out that there is a bug when I create the deck we should probably clear out this uh this input right like just clear it out if everything worked fine and let's go ahead and try doing that so inside of app.tsx this fetch method is going to return a promise if you hover over it it'll tell you that it returns a promise here which means we should probably make this an async function we should probably await on it and then when it's done making the request we can clear the title out like this okay so make the request wait until it's done and then clear out the input so let's try it again click create deck and now the input is cleared out and everything is good awesome so now what we need to do next is we need to just do that tedious process of just adding new endpoints and adding new functionality to have it fetch things from the back end so let's go over back to our API again command P LC server slash index and we want to make a new endpoint okay so at this point you might be like well why are we putting all of the endpoints in the same same file that seems kind of hacky and really it is but again this is only 31 lines of code so at some point when your files become 200 300 400 lines then that's when you want to consider okay maybe I should split this up into smaller um subdirectories and smaller files it makes it a little bit easier to manage but again you guys are beginners and I don't want to overwhelm you with too much stuff I think a lot of beginners Focus so much on like what is the perfect directory structure what is the perfect way to build up my application structure honestly the structure the the file directories don't really matter too much if you're a beginner what matters is you understand how all these dots are connecting in your head okay so I'm gonna make a new endpoint I'll just say app.get and what are we trying to achieve the next goal is when our page first loads we want to fetch all of the created decks and present them to the user so we need to First make an API endpoint that allows our UI to fetch all the existing decks and present them to the to the UI right so I want to make a new endpoint called app.get and again this is just a convention we do with rest whenever you want to fetch data you use a get request whenever you want to push data it's a post request and I'm going to go ahead and say slash decks and again I'm going to copy this approach here where we do async this and I do want to point out that like you can have the same URLs like notice how these two URLs are identical but since they have different git requests and post request methods Express treats them as different endpoints okay so let's try to figure out what we're doing again we're beginners and we want to kind of map out what are we doing so we want to fetch all decks and send back to the user so step one how do we how do we fetch the decks from question mark step two how do we send back the array to the UI um and it's actually pretty pretty simple what you have to do is we have the deck model here and what we can simply do is say const Dex is equal to deck dot find and I could literally just do this I believe I don't think I need to do anything else I'll just do find and I'll put in a weight in front of that and this should get us back all of the data that was in the back now I like the console log stuff especially if you're new like just console log stuff out and make sure you're doing it right but honestly when you're using typescript it would have told us if we're doing it wrong right so again how do you verify this if you were to go to thunderclient and I go ahead and change this request to a get request on that same endpoint and click Send notice that our backend actually crashes and the reason is crashing is because we didn't even do step two so I'm getting way ahead of myself I need to slow down and I need to stop but I do want to show you that the console log is printing out an array of all the data that was stored in that collection so it is working step one is working and that's kind of what we wanted to verify now step two how do you send it back to the user who made the request well you just take res dot Json in the decks and that's it I can go here I can click Send now and now I get back all that data in my thunderclient and I can do the same request to the front end as well so we're done we did it we added a new endpoint that fetches all the data from Mongoose that's in that deck collection now if you get more advanced you can actually start doing different queries here like you can say where uh you know a certain title matches a certain regex a regular expression or where a title starts with or ends with X Y and Z but we're going to keep it simple same with authentication like you can add authentication and sync make sure you only select the Decks that belong to a certain user ID but again I'm assuming that you guys are beginners I I'm trying not to overwhelm you with too much stuff from the get-go so the next step we have a endpoint and hopefully this makes sense as how we set this up how do we fetch this data from the front end let's go back to app TSX and let's figure that out so when this app component first what we call mounts in react when it first loads we want to kind of trigger an API request to get that data so the way that you do that with you know hooks and functional react is there is a use effect hook that you can invoke and you pass it a callback for its first argument and you pass it a dependency array for its second argument now if you pass this an empty dependency array then this effect will only run when the component mounts and when it cleans up or when it unmounts right and since we're using something called strict mode you'll see it actually make two requests to our API every time this component mounts don't be concerned or confused why that's happening that is a mechanism that react 18 decided to add in to help you find bugs in your code so don't get all caught up if your API is making two requests to your API or if you're if your UI is making two requests to your API because when you go to production it won't do that it'll just do one request and that's it um but that was a side tangent I think it's important to understand but I probably shouldn't even even explained that just yet so when this component mounts let me let me show you that I'm gonna go ahead and say we are here and the use effect is going to run this code but there's also this concept of a cleanup function so let me just go ahead and return a function that says clean up now this might be a little bit more of an advanced concept but I just want to kind of demo it so you're not completely uh you don't completely or lost what's going on so if I refresh the page know how to print notice that it prints out we are here and then it prints clean up and then it prints out we are here again so this double printing is strict mode which in fact if I were to go to main.tsx and I delete strict mode you'll see that it only prints out we are here once okay so that's like how the use effect works with an empty dependency array it just runs that function once like this and then when you change routes or you change Pages or you are no longer displaying this app component it runs this code but again we want strict mode so let's add it back and you just have to get used to the fact that you're going to see stuff run twice confusing but it's useful so when the component mounts we want to fetch the decks from the API endpoint that we just created how do we do that well we we know how to do that we did it over here we can just go ahead and copy this code and in fact the get requests are typically the default request with Fetch and it's a lot easier you don't have to do all this stuff so I'm going to delete all this and I'm going to do this and I'm going to go ahead and just delete some of this cleanup stuff because we don't actually want it just yet the the cleanup function is an optional return function usually if you're more advanced you want to go ahead and cancel your API request when you when your component cleans up we're not going to get into that all right so the one caveat of use effect is you can't use async away inside of this kind of annoying but there's some workarounds um some people like to make a function called like fetch decks and they will actually just make this an AC function and they'll say fetch decks okay and that'll allow them to do async await inside of their their function like this that's one approach another approach is you could just do a self-executing Anonymous a function like this if you wanted to do that that works as well you pick whatever's best I'll probably just pick this approach because it's probably a little simpler to understand so let's just see what's happening I know I kind of covered a lot of stuff and my ADHD mine just probably jumped over all these different topics but let's go ahead and go to the network Tab and I'm going to go ahead and just go and click on this x but this fetch slash xhr request toggle so when the page loads and it first mounts it's going to make a request to the Dex endpoint like I mentioned and notice that we give back all of our data we have an array of all of our decks here and that's the same thing that happened when we did it with the thunderclient request here we got back an array of all our data now what we want to do is we want to kind of make sure that we store this data somewhere if we plan to display these decks on the page you need to use react date you need to create a state hook that stores an array of this data we know how to do that we did it with the title so we can just go ahead and say const X in set decks equals use State and I'm going to pass any empty array like this um now one thing I didn't even mention that if you're a beginner you might be confused like what is the syntax this is something called array destructuring where basically you can have an array on the right like one two three and on the left I can actually destructure every every variable that's in that array into uh or every element that's in the array on the right into variables on the left so technically what you state is doing is it has it's returning something like this yeah so on the right side it's actually like making an array that has the first element is your value let's say State value and then your second one is your dispatcher that's really all we're doing technically you could like say index zero if you want to get the value or index one if you want to get the dispatcher but that's just another side tangent I'm sorry for confusing you all so much but again this is all super important information to understand and the more you're exposed to it the more you're going to learn it so when the API request down here that we just wrote finishes we want to store that information into that array okay so again we can say const uh new decks is equal to that and I'll say set Dex is equal to new decks you can also put this directly in here if you wanted to but typically if this thing were to throw an exception you want to catch it you want to throw a show an error message and all that stuff but oh make sure you put new decks I don't know why I put set decks actually this is not how you do it good thing I'm using typescript because this actually returns you an object that has a response dot Json method so I actually need to do this okay this is again I always recommend just use typescript you're a beginner because you're going to mess up really basic things that typescript will like yell at you about so fetch returns an object that has a DOT Json method and to get all of the array of decks you actually need to call response.json okay I've seen people do it like this if you know anything about promise chaining you could do it like that [Music] um and like this could be new decks here that's another approach I think it's easier just to do what I did just if you guys want to be exposed to different ways to like do stuff so now when this API request comes in and it's done loading we're going to set that array of decks inside of our state so again if you go to your components tab down here which you should get familiar with using and click on app notice that we have an array of all of the deck information and another the last step is how do we display that to the page well this is going to be the fun part we are going to go down here and we'll do it above the form we're going to make a a component or so we're going to make a um a div called uh we'll call it Dex okay and what we're going to do is we're going to map over all of those Decks that we just got back so I'll say Dex dot map is a function that we use and react to basically Loop over a collection of elements and then return new jsx for every entry in that array so I can say dot map and I can basically return some type of jsx here so I'm going to say this this will take in a deck and then we're also going to return some type of jsx in our case we will do a div or we could do a um a list item if you want to do semantic HTML technically this should be an unordered list this one should be a list item in react we have to put keys on these things so I'll put deck of underscore ID this is the ID that's returned from the back end and then on the list item itself we are going to go ahead and just render out the deck title so hopefully this works I think I might have some uh some issues with my typescript but it should still compile and notice that we do get back five entries and the titles are printed out in a list of things so that is pretty cool now if you are inclined to do some type of styling CSS we could do that and let's figure this out so we are just importing this app CSS file I'm not going to use CSS modules because I don't really like them too much but we can go ahead and clear out some of this app CSS stuff I don't think we really care about it so one way that you can kind of render out these cards is you can use CSS grid so I'm going to make a DOT Dex selector so this will Target the um that Dex class that we just created down here so notice that we said class name Dex we're going to kind of style that now the way you can style it is you can say display of grid and I'm going to say grid template columns repeat oops repeat one and then I will say one ffr maybe I'm also going to give this a hard-coded width of like 500 pixels and a margin of zero Auto now if you're not really familiar or experienced with CSS what I'm doing is I'm saying every time a an item is rendered out put it in a grid now I do believe there is an issue with what I'm doing I think I need to change the Allies to not be displayed list item so I'm gonna go ahead and say the xli display is block okay so that's a little bit better now for some reason it's still not styling them with a CSS grid so I think I need to figure out what's going on here oh okay so the issue is I did repeat one so sorry I just noticed my camera said I was low battery so I had to turn off that notification so I apologize for that but sometimes I go too fast and it's good to just take my advice and just slow down breathe think through your problems think through what you're trying to solve so in our case we actually need to put three columns right one two three but I need to say repeat three times and the one FR is basically saying expand these columns to meet the full width of the container though the container is 500 pixels and we want to split it up into three columns in fact if I made this like 600 that means every column would be 200 pixel width and then the margin 0 Auto is just going to Center this on the page so if I go back here notice that we get three columns one two three and if we actually style these things as cards it would look a lot nicer so let's try to do that I'm gonna go ahead and say this will be a display block I will say with those I don't know 80 percent height of 300 pixels I will say border is one pixel solid white let's make sure that shows something now I am zoomed in a lot with my page that you all can easily see stuff but what I'm actually going to do is I'm going to reduce this to like height of 100. yeah maybe 120 130 I don't know and we're gonna make this an actual card so let's just go ahead and say uh what we what we could do is we could do background one pixel solid white oh wait what am I doing background white let me slow down and then notice that there's no space between these two cards what we could do is either add some margin between them or I think there's a way to say grid gap of 10 pixels and that should space them out a little bit better okay and if you look at the actual container what I actually don't need to do is I don't need to specify a width here I'll just say width of default and now we have some cards what you can also do is you can find like a CSS card generator and you can find like a nice styling to make your cards okay I guess box Shadow would be good let's just click here sometimes don't try to like do it all yourself like find a uh a generator online and that'll basically help you out I don't think this is the best generator but I'm gonna go ahead and just like do something like this and what we could do is grab that styling I'll just go ahead and grab that real quick and we'll paste it into our card and see if it looks good or not or if we're just kind of wasting time with our styling right now sometimes it's fun to play around with this stuff other times it's kind of annoying so I'm actually going to make this white and see what happens okay so that's a little intense maybe I'll do like 999. make a little gray or DDD and I'm going to reduce this to like five pixels as well yeah I don't know it looks looks pretty whack uh all right how about not the Box Shadow I'll just keep this simple I'm just gonna say border radius in pixels and that'll kind of round it as well keep it simple sometimes if you you can spin you can literally spend hours trying to style stuff and if you don't work with a real designer or ux person like as a developer I don't care about that stuff I just wanted to look like someone good and then I can hire someone to like make it look great I can hire someone to make it look real polished and real Snappy but for me I just want the functionality of the work also this create deck button is like pretty hard to see so I think this might be styled somewhere over here if I go to the button I can make this like white and then make this color black that'll make it easier to actually see accessibility is important um again if you can't see it and you're colorblind or if you have bad Vision you want to make sure the contrast is good and then also let's just go ahead and add underneath the decks we could add some margin to space out the depths from the form or on the app itself what a lot of people do is they could potentially this is a class what they could do is they could say display a flex and then Flex direction is column I believe and then gap of 10 pixels I believe that's how you can space stuff out with flex and notice that there is a space now between these things which is a good way to kind of add some spacing and you could do the same thing with this you could use flexbox for spacing this out this is a form so if I said app form like I said display Flex I could say gap of 10 pixels and that should also base out the form a little bit um but now align everything to the left there's different ways with using flexbox to like Center stuff I think it's justify content is Center Maybe there we go and then you can also say align items Center I think and that'll kind of align everything cool so now we just need to render out the text because oh well the text is there it's just really dark so inside the decks we could say color of black and now we have our cards we have our decks [Music] um and if you wanted to Center that too you could do that so like again there's different ways to do it you could say inside the list item itself we could potentially make this a you know let's see how much what's in here hold on all right so inside the list item itself we could potentially just give this list item a display of flex and then we could say justify content enter align items Center I think that'll push that stuff all to the center just like we did here and it looks pretty good right we have our different cards you could probably add some styling so that when you hover over them like if I said decks uh cover I'll say Dex um Eli of hover we want to make the background maybe a little bit lighter so I'll do like EEE and cursor cursor is a pointer how about that okay so now you can actually like hover over these things and they're clickable well it's technically they're not clickable but we could make make them applicable if we wanted to we could also like refactor these to be buttons um but again like always look up the best accessible way to make these things maybe having this whole thing clickable is not a good good approach but instead the text inside of it like this should be an a like some type of clickable thing anyway um let's fix this typescript error real quick and then we're going to commit everything we did because we did a lot of code changes so if you're using typescript it's very important to type the things that you're storing in your state so in our case we could say t type I'm sorry T deck is equal to our Type e deck is equal to title and that's going to have a string as a property so what I'm going to do is I'm going to say this state and variable stores an array of T deck types and then also has an ID on it so underscore ID is a string now if I scroll down here notice that all those typescript errors go away and then also as I like do deck dot I get the intellisense that like tells us what to do all right so we made some good changes let's just commit I'm going to say add everything and then I'll say working on showing the decks on the landing page go ahead and commit that and sync that up all right so we have basically added a way to create records or create resources in our mongodb database using a post request we have figured out how to retrieve using a get request endpoint all of the Decks that are in our system all of all the yeah all the decks are in your system and now we want the ability to basically delete them right so we want to kind of do the the normal crud operations and sometimes if your application is simple enough you don't even need update like maybe at some point you want to be able to come in and update the title of these cards um maybe we can do that as well so we do like cover all the crud crud aspects so let's just go ahead and start clean I'm gonna go ahead and go to the server and go to the index and let's add an endpoint for deleting the card okay so let's say you made a deck and you just don't care about it because you're learning about go laying and you just take golang you want get rid of all the information that you're you know you're storing your flash cards you can make a new endpoint so I am just going to go ahead and go down here and say app dot delete and we are going to do a delete method on Dex slash now this is something new so listen up colon deck deck ID okay so what we're doing is we're telling Express that someone can actually put a dynamic value in the URL and we're going to use that Dynamic value to get the correct deck and delete it from okay so again it's it's good if we list out the to-do's I will say get the deck ID from the URL delete the deck from and then finally return the deck uh return the deleted deck to the user who made the request now this is typically the convention when you delete something you return the thing that you deleted let's figure out how to do this so in Express if you want to get whatever this deck ID is you can say const decid is equal to rec.params dot deck ID in our case if we're trying to delete deck one you do a delete request to deck slash one this will be set to one right so this will be a number and then we want to delete that from so how do we do that well we can say deck Dot I think there's just a delete one there are there might be a delete one by ID as well find one find by ID and delete this is probably the one we want so find by ID and delete and in I believe you actually have to convert the ID to a ID so I could say like uh actually let's just try it with deck ID let's see what happens I think we can just go ahead and say await on that and then I can say const um you know I'm just going to say res Dot Jason and then I'll say message successfully deleted the entry now the proper way to do the delete request at least one standard I've seen is that you want to actually send back the thing that you deleted now I don't know if this is going to give us back the one we deleted so we might need to just print out what deck is and see what happens but at this point we can get rid of all the to Do's because I think we might have solved this problem and we're going to go and go to thunderclient and let's just try to delete this first one that has no title because that's bad bad data so let's change this request to a delete I'm going to say slash and then paste in that ID and then if I click Send let's see what happens so we got back the object we deleted we got back a status at 200 so I think everything's good if you were to switch this back to the get request and just do it on the main page notice that that entry is now gone so we've successfully deleted something from just by using three lines of code and that is now gone from our database super super cool so now what we want to do in the front end is we probably want to add some type of x button that you can delete these things from the UI so let's load up the app.tsx that we've been working off of and I'm going to go ahead and inside the deck itself I'm going to add a button somewhere so let's just go ahead and this I'm going to add a button I'm going to make it X and then I'm going to say on click we're going to call a method called handle delete deck and then I'm going to pass in the deck ID like this okay so when someone clicks on this button we are going to try to call a function that we haven't created yet so let's go ahead and uh go up here and I will just go ahead and say async function handle delete card and this will be a card ID which will be a string I'm sorry deck ID and what we want to do is we want to make our delete request to the back end which is going to follow the same Paradigm as this so I'm going to copy all this code I'm gonna put it in here instead of doing a post request I'm gonna do a delete and then instead of Dex I'm going to say Dex slash deck ID and I'm going to change this to a back tick so we can do JavaScript string interpolation we can't send bodies on delete requests so I'll get rid of that and I don't even think we need to put headers here so I'll delete that as well so that'll delete the resource from the the back end and I think we could try this out and see what happens so I'm gonna go ahead and just click this x button and then I'm going to refresh the page and it did get deleted from the back end so there is a issue where I have to like refresh the page which is kind of annoying we'd probably want the UI to just delete it for us there's two ways you can do this you could basically after this delete request finishes you could refetch all your to-do items probably not the most performant or you could do something called optimistic updates where you basically just go through this Dex array and you delete the one that you manually just deleted so let's just do the optimistic um updates approach so if someone tries to delete the deck by ID I'm going to go ahead and just try to filter out so I'll say set decks as Dex dot filter and we want to basically delete the one that does match uh the deck IDR does not match so basically Loop through the decks and we want to filter out the one that matches the deck ID now it's a little bit different because filter is expecting it to return the item if it's truthy and then omit it if it's falsy so we kind of have to do the not equals equals here but now let me show you what happens if I click on this X these items go away um and now I can just say create a create B create C now there's a bug that we just saw here when you create the item you probably want to add that into your your list right again we could do some type of optimistic updates here so that when we try to create a new deck we could do something very similar now the issue is we don't know what the deck ID is but we can get it here so I can just go ahead and say const response is equal to this I say const DEC is equal to a weight response.json remember we talked about how you have to do this with the fetch request you have to do not Json and then I could say set Dex and I can say new array because in order for react to re-render a raise you have to pass it a new array reference basically so I'm going to create a new array and I'm going to spread the old array into that which basically takes all the elements of Dex and just puts it into the new array and then I'm going to append the deck that came over from the back end okay let's try it again ABC and then d e F there we go now I can delete these things and everything is working beautifully now the last finishing touches is this x probably should be in the top right and it shouldn't be so big so let's see if we can style this let's go to app um app.css and I'm going to say for the for any button so I'll say dot Dex Li button we are going to basically give this a position of absolute and we're going to say the width is 10 pixels the height height is 10 pixels and then the font size could be 16 pixels let's see how this works and then also we probably need to say top as zero and right is zero pixels maybe even five pixels to bring in a little bit does that make sense so that should have put the X um you'll notice that's putting the X in the very top right my head is actually blocking it but it's actually on the top right of my screen which is not what we want like why is it up here that's really weird the reason this happens is because in order to have this properly be positioned the parent needs to have a display or sorry a position of relative if I do that the x is in the right position down there so that's that's good but it's still a little bit off um I don't know why the X's font size is so large it's always good to go in the dev tools and like play around with different stuff like you can you know try to scale it down and see if this is good the height probably should be you know with an height we don't need the set but font size let's just do that don't need a width and a height but font size let's just make that like 14. so it's not as giant okay maybe maybe 10 is better cool and again I don't I don't really like the uh the hover I added so that so let's just go ahead and remove that hover it's kind of annoying there we have it so now we have a way to add Dex remove decks I mean this is just a glorified to-do list application at this point um so let's go ahead and dive into you know how do we actually add cards to a deck we have ways to add new decks Elite decks which is great but how do you if I were to click on this this deck title I want to view all the cards that live inside this deck okay so like we want to be able to store flashcards inside of decks in fact maybe I should kind of put realistic data here like I say like JavaScript keywords so we want to make a deck that's all about quizzing Us in JavaScript keywords and what we could do is we could bring in react router react router is pretty popular so let's try to look at the documentation and figure that out again everything I do is live so let's figure out how to get this going um let's go to examples I'm able to tell us nope let's go to tutorial I'm able to tell us so there's a lot of text here but really it's a lot easier than we we they should have explained this in a much easier way like a getting started guide really you just need to install react router Dom I believe so if I go ahead and go to my my client let me open this up so you can see it go to my client I'm gonna install react router down and we're going to read through their examples of how to get this going so very similar to the back end where we have different endpoints that do different things you can do the same approach on the front end where different URLs will show different things um we're going to follow this approach so all the code in green he's saying go to main.jsx so mean.jsx and we're going to go ahead and put that stuff there and we're going to go ahead and grab that as well the create browser router and we're going to put this here okay so instead of having app displayed here we are actually going to put app here and then whenever someone goes to the Slash URL it should display your app so let's make sure this works I'm gonna go ahead and rerun the uh this code and hopefully this works I'm gonna go ahead and just refresh the page we skip the same stuff but I want to verify that if I were to make a new page such as the deck okay so like for example let's say we wanted the ability for someone to go to the path next slash uh deck ID I'll have to go and read their docs about how to like get this stuff set up but let's say we want to display a new page called like deck and in this case I'm gonna go ahead and make a new component here called deck.tsx and it's going to export default function deck like this and this is going to return div that says hello world or something something super super basic that we can actually just verify this is working and then again Auto Import what you what you want so now the idea if I go to dx123 it says hello world so now we have two pages that the user can actually navigate to on the react app and we can display different information based on what page they're on so to kind of connect it all together when they click on this JavaScript keywords we want to redirect them to that new page we just added in which I don't remember how to do so let's just go through figure that out now usually there's like a link component you can use which it looks like you do this let me go ahead and just import this link component and if I go back to app TSX we're going to go to our cards and where we have title here I'm actually going to add a link to Dex and then I'm going to put deck underscore ID so that'll actually redirect us to the correct page when they click on the card and again if stuff's highlighted in red here make sure you Auto Import it from wherever they tell you to do it which I guess it's here I'll go ahead and do that and we don't need Outlet so let's just go ahead and import that and see what happens so now if I go back to the main page and click on JavaScript keywords notice that we are redirected to the right page and we can actually use our browser's back button to kind of navigate between those pages pretty easy to get set up that's pretty awesome right um now I as I keep looking through this code this code could be cleaned up a little bit we have different fetch requests which are getting hit by hard-coded URLs in different places and if we decide that we wanted this to be on a different port we'd have to go and update three different places in code which is a pain so often what we do in code is we find ways to dry things up and Abstract things away so I'm gonna make a folder called API and I'm gonna go ahead and just make methods that we can use for fetching data and deleting data so I'm going to say get dex.ts and we're going to take this code and we're going to abstract the fetch method away from the component and also the URL from the component so if I were to paste this code here I'll say export const git Dex is a function I shall say export function get Dex like this and that's going to do this now right now we're just doing some code cleanup and some refactoring but this is going to take in a title which will be a string and then we're going to return response.json like that and I think I copied the wrong thing because I was going too fast I copied the create so technically we could just rename this one to create deck how about that create deck and we're going to rename this the create deck okay that looks good same thing we're going to get one with the get decks and we're going to go ahead and just copy this one so just copy all that code in like so and then we're going to make sure that we return response Json here and it doesn't need a title we don't need a title we don't need to call it git deck we need to call it or sorry we don't need to call it create deck we need to call it git Dex and then finally that last method which was deleting so let's go ahead and copy this as well and I will make one called delete deck and then export function delete deck and then this needs to take in a deck ID which is a stream okay so that all looks pretty good now some people like to have a single file called Dex dot TS and then they'd have these methods inside them I like having all my methods separated because I don't know I just like it that way you don't have to follow my advice you can do your own thing I I invite you to find your own path of like how you like the code and don't just blindly follow other people if you like doing something a certain way then do it that way I think it's good to have confidence in your own opinion of how like code should be set up so I'm gonna go ahead and call that delete deck uh function now and this is going to keep this code void from the fetch keyword you don't want your components to know how stuff is being fetched from the back end or where it's been fetched you just want them to call methods that do stuff and behind the scenes those methods are abstracting away the mechanism for persisting and fetching data so down here we are also fetching the decks so I can go ahead and say get decks like this Auto Import that and uh this one I probably need to type a little bit so if I were to go ahead and make sure that this thing is returning a t deck array like this remember that we defined some tdeck data here I'm gonna go ahead and just export it and in fact I'm going to put this inside of the get Dex file here so that this is more coupled to the data itself oh let me do a promise here this needs to be a promise this this t-deck type is more coupled to the data in the back end so like it makes more sense to live in the API folder in my opinion than it does in the app folder so let's make sure we import that and now let's see why is this complaining oh this is complaining because I need to wait on it yeah and now the last method here this was for creating the deck so I'm gonna go ahead and just say await create deck pass the title and I will delete uh yeah I'll delete all this code and import that so now the app component is actually a lot cleaner this is much cleaner code because it doesn't know about fetch it doesn't know about the API endpoints but unfortunately this code is now really dirty because we have this hard-coded URL everywhere the one thing that you could potentially do is you can make a config file like this and inside the config file I could say export const API URL is equal to localhost 5000. okay and what we're going to do is inside of all these little other methods that we created I'm going to go ahead and just interpolate that URL that comes from a single place so we're drawing up our code and we're making it easier to manage we're going to do the same approach here um this one's already interpolated so I have to delete some extra quotes like this we'll do it here make sure we Auto Import that and then we're also going to do it in git decks so again like let's go ahead and delete this and go ahead and Auto Import that so let's make sure everything works we did a lot of refactoring I'm going to refresh the page make sure I can create stuff make sure I can delete stuff make sure I can go to stuff and that all looks pretty good and as I mentioned before every time you make a lot of changes we have 11 file changes we're starting to get pretty big let's go ahead and say adding the [Music] um actually what did we add we added the ability to delete the deck so adding the ability to delete the decks and refactoring code for Theory okay go ahead and add all that play commit go ahead and push it up cool so now when we go into the deck itself we want to be able to create cards and delete cards and fetch all the cards that belong to a deck um now when it comes to there's different ways you can do this you could have the cards be nested in the deck object itself which might be approach we want to do or you can have them be a separate collection is a nosql document store so if the cards do not relate to other decks like if you can't share cards between decks and you can't share cards between other users of your system then it probably makes a lot of sense to just have it be a nested array on the deck object itself it all really boils down to your your business use cases and performance right so again you're beginner so just do whatever works and refactor it if you find that it's not a good solution after you run into real issues I think a lot of people get caught up with like trying to read what are the best practices for X Y and Z and they do all these things that they don't even understand what the purpose of any of these things are I would rather run into an issue myself personally where I'm seeing performance issues or I'm seeing some type of maintainability issues in my project and then I will go fix the issue alright so I'm going to go ahead and um we have the ability to go to this Dex page and the next thing we should probably do is a very similar approach where we have the ability to create cards that belong to the deck okay let's open up the deck TSX because this is going to be our react component and then let's go ahead and load up the server index again and at this point the server is becoming a little bit unmanageable what some people like to do is they'll make a routes directory on their API like this and for every collection what you can do is you could add a DEX route [Music] um there's different ways you can do this I like just um I'll show you the way I like doing it you can say I'm dumb for doing it this way but I like making a routes file actually you know what I changed my mind I'm going to show you the way that I would typically do stuff I would make a controller's directory and make sure you put that in the right folder and the controllers are going to hold the code for all this so I'm gonna go ahead and make a new one for delete deck dot TS and then also I like to pre add a suffix of controller here so delete deck controller I like to make one called git deck controller TS and then I like to make one called create deck controller dot TS now you might ask okay why are we doing all this what I'm going to do is I'm going to pull out the logic for all this so this is going to be our get decks and I will say export const or export function get Dex controller is going to be a function that looks like this bear with me let me just clean this up a little bit and I want to make sure I import all the right things so let's go back and I'm going to go ahead and figure out what needs to be pulled in so first of all we need to request a response and we need the deck so I'm going to pull this stuff out and I'm going to put this at the top of this file like this and I think we just need to make sure we go up a level like this that doesn't complain and we got some syntax errors by the way if you're watching me code usually wait until like the code looks all non-red and then that's when you really pay attention but when I'm live coding like there's stuff I have to fix along the way so all we do is we took that function out and we pull it out into a separate file and that makes your code a little bit more manageable in my opinion so instead of calling this inline function here you want to pass in your controller like that and we're going to do the same approach for the grading the deck I'll open up crate Dex controller I'll say export function Inc async function create deck controller is a function that does this stuff so we need those arguments then we have to delete some of the stuff and again we can pull in some of the same shared responsibilities that we need to import foreign and there you have it so make sure you import this thing over here like this and then finally we're going to do the same thing for the delete Dex controller so delete the x controller export async function delete deck controller um go ahead and paste this in grab the arguments like so and also make sure that the Imports are pulled in from the other file and then finally delete deck controller so once you get into this habit of like this is how you're going to set up your files it makes it a little bit more manageable because now you have a single place you can just look at your routes and your endpoints and then they actually see the controller that's handling that request you can just go and dive into a single file that shows you that code now when you make refactorings like that like make sure you go and double check you didn't break anything so I'll create stuff I'll click stuff I'll delete stuff and it still looks good so that's what I would recommend doing if you want to keep your coat a little bit cleaner now there's different ways you can set up your Express app just do whatever you find the best way um okay so what I'm going to do now is we want to make some controllers for handling the cards and again like I mentioned with mongodb there's different ways you can do this and there's different performant ways to do it and what I'm actually going to do is I'm going to try to Nest the cards onto the deck themselves okay so I'm going to make a new controller called create card or deck controller might be a little bit verbose but hey that's fine and we're going to go ahead and copy this method over here and paste it in so create dark card for deck controller and what this is going to do is we need to actually find the deck that was requested there's actually two things I'm gonna I'm gonna do real quick so I'm gonna make a new endpoint and I'm going to go ahead and just say app post Dex Yak ID and then I want to say cards now I want to say create card for deck controller now again like I mentioned there's different ways to do this you could have potentially made it in point that was for post at like I put it in the app.post cards like this and then you could hit that endpoint to basically save new cards but cards is going to be a nested resource of Dex so it doesn't make sense in my head to do that so I'm going to go ahead and just make a create card for deck controller and inside of this controller we want to first get the deck ID which again we kind of saw before you can get that from rec.params dot deck ID and then we want to fetch the deck from right so I can say const DEC is equal to deck dot find by ID and I'll pass in the deck ID and now what we want to do is when someone tries to create a card that card information is going to be on the body so I can say rec.body and then what we could go ahead and do is inside the deck model which we haven't set up yet we want to basically add some cards here and that could be an array of in our case we'll just keep them strings I think that should be fine in fact I don't know how to do that Mongoose so I'm going to say Mongoose how to set up a collection actually I'm saying Mongoose how to set up model with array introduction to Mongoose arrays so it looks like you just do this that's interesting so you need to say it's an array of string we're going to keep this super simple okay so when we create a card I could just call it card text I guess would make more sense actually we're going to pretend like the the payload requires an object that has text in it so the card text will come over and the the post request in a card property and we're going to say deck Dot and we're going to say cards dot push I believe we can just pass it in that text array and then finally we want to save this so I'm going to say deck of save and then I'll wait on that and then I believe I could just return back the deck or in this case we could yeah let's return back the deck it should be fine um make sure you await on this because you need the weight to get the deck and this one it's saying deck is potentially null so to make this more proper in typescript I could say if there is no deck I could return uh res dot status of 400. dot send no deck of this ID exists so we're getting kind of like error handling with the API endpoint where basically if you try to request this or do this function on a deck ID that doesn't exist you the back end is going to throw an error but let's try this all out I mean I think this should work we basically find the deck by deck ID it doesn't exist we throw an error and then we get the body the text that's in the body payload we push that into the cards array we save the deck and then we send back the deck again it's always good to test your code after you write it because it doesn't always work the first time so the first thing I'm going to do is I'm going to go ahead and just do a request to get the get the decks and then I'm going to go ahead and get the ID and I'm going to say Dex Dot cards and I want to do a post request here and make sure in the body we're going to send some Json that says text is what is up so now if I do a send request every time I do this we actually are injecting Cards into this this data structure which is pretty cool and what we could do is we could try to display that in the UI or we could try to hit this API endpoint from the UI so again let's go to that ESX component that we created called car.tsx our deck.tsx I mean and let's just slow down a little bit because I think I'm getting ahead of myself okay so what do we want to do we want to basically give the user a way to create cards and put them on this deck well we just created an endpoint that allows us to do that so now let's kind of follow the same approach we use for app.tsx in this API directory and we're going to copy most of this code and we're going to delete the stuff we don't want so let me go ahead and just copy all that code and I'm going to go ahead and copy most of this code as well and the great thing about typescript is it's going to yell at you if you don't need some stuff so we do want to keep the handle create and the use effect will probably come later actually all this stuff is going to be used we're going to do the same approach for a lot of this stuff and we could find a way to dry this code up in a little bit but I know this might be a little bit overwhelming if you're a beginner and they're like okay I'm copying all this code over and commenting out but I know we're going to use this code in the future so I rather just start with like very similar stuff and we can change it up as needed okay so we have Johnny decks I'm like also comment out the decks and all this stuff so what is different between this page and the last page well we're dealing with text right instead of titles we're dealing with text and set text but we can go here and we can kind of call very similar methods I just wanted to match like the actual card model that we set up and instead of calling create card we probably need to or instead of calling create deck we probably want to call a method called createcard.ts and this could be a very similar method to create deck or a card and this is going to take in a a deck ID and then some text okay so like we did the API we have to then call Dex slash deck ID slash cards we need to do a post request we need to send over some text and then that should hopefully create the card and send us back the deck okay so if you want to get really really into typescript like this would return a t deck an array of yeah it's a return to tdac I believe which oh this will actually be a promise of tdac and again T deck we added something called cards which is an array of strings so make sure you update that uh type definition and let's try this out so if we in the front end if we call create card instead of create deck whenever the user tries to submit it it's going to send the text over that they entered into the input box and it's going to persist that but this thing is complaining because we also need the card ID which we don't know but if you're using a react router you go to the docs they'll tell you how to get that so if I go ahead and just search for like use params I believe this is how you can get that card ID I'm sorry the deck ID so I'm gonna go ahead and say deck ID is use params and this one needs to be imported from react router Doms so I'm going to go ahead and put it here and I want to make sure that the deck ID is actually passed in here make this cons as well and if it should be defined so I'm just going to go ahead and force it to be exclamation mark and that should make it work so let's test this out there's a lot of stuff going on here I know like half this code's commenting out commented out but it's literally the same code that we just did and we will bring it back slowly so let's refresh the page and there's some text that we need to change like instead of it saying deck title like we should probably call it card text this should be like guard text and uh there'll probably be some CSS that we can kind of update so I'm gonna go ahead and just say like Hello World here and I want to make sure that in the network tab this does a request and sends the right thing it doesn't crash so if I click create card it did a request to cards we got back the new deck and what we can actually do is like remember that the back ends returning the new array of cards what we could do is we could just update our collection of cards using what was returned and we could simply just keep track of that here so I'll go ahead and just bring that bring this thing back and instead I'm gonna call this cards and set cards and this is going to be array of strings and when we get back our request data remember that this will send us back some cards like this I'm going to rename this so there's not like a naming Collision I'm going to say like server cards and I'm going to go ahead and say set cards of cards and server cards oh wait yeah let's do this I'll just set it equal to whatever comes back from the server simple enough so now we actually want to render out those cards so if I were to undo this UL instead of saying Dex here I'll say cards this will be card uh card will just be ring and this will be a link to nothing we probably still want to delete button but this will just be the cart text so let's make sure this actually renders something out um and it probably won't enter any render anything until you actually create the card and then you get back all these cards that show up for you all right um and then also what we want to do is add back the ability to delete which I mean we'll do in a second um all right so what we also want to do is like we did in the first page when this component mounts we want to fetch all the information that was related to this individual deck but like we've been working we want to do the back and end point first so I'm going to go to the back end and I'm going to make a new method called git deck okay so I'm gonna go ahead and make an app.get then I'm going to say get deck controller which is different from git Dex because we just want to get one deck so let's go and create a controller here called get deck controller TS and it's going to follow a very similar approach for the get Dex controller so it's okay to copy that stuff in delete the s and what we want to do is we want to get the deck ID so I'll say deck ID equals rect.params and we want to find a single deck signed by ID using that deck ID and go ahead and return that individual deck by the ID so at this point like adding new endpoints it should be kind of familiar like we've already done fine by ID we've already know how to create a controller we already know how to set up that controller as a route in our express application um don't know why this is complaining it can't seem to Auto Import this file for some reason so let me just do it annually like so um but now we have a new endpoint that we can call when this deck component loads so I'm going to just call this but we don't have a method for getting a single deck so I'll make a new one called git deck inside of this API folder I'm going to follow a very similar Convention of get decks probably like this make sure you import T deck that's just going to return one t deck and I'm gonna call it get deck and I'm going to say deck ID is a string and we need to make sure that we call the right endpoint so I'm going to say deck ID do a fetch request and we'll return the date the data so now in the component itself instead of get Dex we will call it get deck and I will go ahead and use that deck ID that was originally set up here okay so fetch the deck ID and then I'm going to say new new deck uh set deck you deck now I don't think we're keeping track of the deck which we probably should right we might want to display what the title of the deck is at the very top of the page so I'm going to say const deck and set deck like this equals use State that's a t deck and that's going to be an empty object to start off okay and what we're going to do actually I'm gonna make it null to begin with and this could be nullable or undefined you could do that as well and when the component mounts again we're going to use that use a fetch or use effect and then we're going to fetch the deck and then we're going to call git deck using the deck ID which for some reason it could potentially be undefined um so really we should probably put deck ID down here in the use effect and then we can say if there is no deck ID we can return so this is the first time we saw an instance of like putting something in the dependency array and what this is going to do is the use effect is going to rerun anytime the deck ID changes and we probably need that but if it's not defined like we don't actually want to fetch the deck but in our case um we can actually put it down here let's just do that so it stops complaining all right so I know a lot of stuff just went on right there and I kind of rushed through it so I should probably slow down but now what we could do is since cards was a separate array which is probably fine what we should do is when we get the deck back we can also say set cards is equal to new deck Dot cards okay so now when the page loads if I refresh the page we get back all the cards and we display them to the page so now we have the ability to create cards batch the cards and now we should probably add the ability to delete the cards which again it's going to be just copy and paste a lot of code and we're almost there so let's just go ahead and add a new delete request here to a card ID or you could do a card index it really it is really up to you again we're storing like strings so maybe it makes more sense to put like the index of what we're trying to delete and I'm gonna go ahead and say delete card on Deck controller and we can go ahead and see if we can implement this so we'll go ahead and rename this the delete card on Deck controller and go ahead and rename this one to delete card on Deck controller go ahead and fix my phone my battery is getting low and same thing like we need to get the deck ID and we also need to get the card um ID I guess we call it the index right yeah we called the index so I'm going to call this index and I'm going to get that from index and then basically we find the deck if there's no deck we throw an error and then what we're going to do is we're going to basically set the cards array and I'm going to splice out uh the card that's equal to the index so I could just say index one and this is going to be a string so I do believe we need the Pars in this thing and then we could save the deck and return the deck so all we're doing is allowing an API endpoint to basically delete the index from the collection now there's different ways to do this I'm just doing the first way that works but this will work as well but you could probably find a way to just update the deck and splice out something from the uh the underlying collection if you want to so let's Auto Import this method here and make sure that we can call this from the front end I'm gonna go back to the deck.tsx and we have all this delete functionality that we can just bring back and I'll call it handle delete hard and then this will take an index which again would be a number and we're going to go ahead and call delete card which takes in a deck ID and index and we don't have that method so let's go to the API I'm going to make one called delete card TS and we're going to go ahead and copy the delete deck functionality like this so it's very similar delete card and as you notice like at this point it just becomes a tedious thing of like you're literally copying pasting code doing the same approach over and over and over again um but once you've gotten a hang of like the first couple of endpoints that's literally what web development becomes you make new endpoints these endpoints do a little bit different things you maybe interact with third-party services um but for the most part like that's just how it works in this industry okay so again like we have a method called delete card and we have to pass in cards and then also the index here um same idea we do a delete method and that's going to hit the endpoint that we just created and we'll verify if it works using the UI instead of ThunderClan at this point but going back to the UI let's just go ahead and import that and we could also do some optimistic um updates if you want to just delete the cards directly from the list like you could say set cards is equal to Dot cards and then I could probably say splice index one Maybe and then also like when you click on the button here let's just go ahead and make sure that we have the index so I'll just go ahead and do index here and this could be the index and again typically in a react you don't want to use like the indexes um because the way like sorting can work and stuff but yeah so now when you click on the X it should delete the card from that array and then also make the backend AP request so let's see if this works I'm gonna go ahead and click what is up and it actually deletes it looks like I deleted a lot more than one uh which might be problematic let's go to the API and figure out what do we just do so splice is supposed to remove one element starting at this index and then it should say that so I don't know if maybe the UI is just doing something kind of funky which I think it might be uh let's go back to deck and we're basically taking all the cards we currently have in our in our array we are going to splice out the index that we kind of wanted it to and that should be it [Music] um I think it makes more sense I think the issue is that this key here like you need to make sure you set this to the index and not the card string because we had different cards that had the same string on them and it might make more sense to also just add a unique identifier to every card but now I think we can let me refresh the page okay let me check something real quick if I click the X it should only make a request to delete index 0. and then we should get back a new cards array here so technically maybe we don't need to do optimistic updates what we could do is like we get the new deck back right so I could say like new deck and I could just say set cards of new deck Dot cards and then deleting a card will return a promise card let's make sure this works well I guess this would just be a deck do the same thing response and they'll say um return response.json that should hopefully make it work a little bit better Let me refresh the page there's something definitely going on here if I click on this one is it now working if I make different cards with the same AAA and then delete this one yeah cool so now like the idea of like this whole application is I can go ahead and say like proxy a way to uh listen for object changing properties and run some side effects when those change cool now there needs to be some styling and stuff like that but overall I mean like we have the basic foundations of like adding endpoints adding pages we kind of looked at react router we looked at how to do some typical crud methods we saw how to create a collection and inside the collection it can have [Music] um inside that collection we can have a nested array of hard strings I will add a little bit of padding to the the top of this I believe we have a we should call this probably cards instead of decks um yeah we'll call it cards and then I think we're importing a CSS file called app here I think I should import one called deck.css which technically could have a lot of the same styling of app CSS but we're going to rename decks to cards just so it's a little bit different um and I'll call this deck and then this one could be called deck instead of app and this one could be cards cards text yeah is this it looks like it's a little bit broken or it's cards cards let's see what do we call the the grid we call it deck and this is a UL of cards oh I know what's going on I need to import the right deck.css and also like all these grayed out variables like delete those you want to make sure your code is pretty clean and let's go back so now we got the the card here probably add a little bit of Origins at the top I don't know 20 pixels just so the button is not like in your face I think I put on the wrong thing um I need to put it inside of the LI so I guess that would be padding top of 20 pixels right or even 30 pixels to 30 pixels all right so it looks a little bit better um so I think we have a lot of the major functionality kind of implemented and there's things we could do to maybe change it up or refactor to make it more user friendly um but let's see if we can just add a couple things to like add some finishing touches to this like such as a top header maybe that'd be cool to add in so going back to our app you go to main.tsx remember the router provider is is defined here so if you wanted to make a header that exists on every single page then you probably need to put the header somewhere here right so I'm gonna make a header component and I'm going to go ahead and just make a new file here called header.tsx and I can say export function header is something that's going to return some just a diff right now and then make sure we of course import that and I'll make this a self-closing tag so what we should see here in the header if we actually style this a little bit or put some text here I'll just say hello we should see the header pop up now I think we have some styling that's kind of applied to like the root which is centering everything which is not what we really want so let's go to the root so if I go to like index CSS and find root we don't want the sintering which you know maybe it's not on the root I think this this display Flex in place item Center I think this is causing it to be a little bit all centered which is again not what we want and then if you look here the root has a bunch of green stuff which is padding so 32 padding we don't want so let's try to figure out where that's defined so root is there any padding defined here okay so in app CSS this is where like the roots defined and also index CSS there's a root Define I believe so I think it'd make more sense to like just delete both of those and see how the app looks there you go all right so again we're trying to build a header so how do we do that well let's go to our header component and let's try to style it a little bit and the best way to do that is probably making a header CSS file and I would just go ahead and style my header like this and let's go ahead and add a class name to the header this I'll say header and that gives us some scoping that we can just apply to the header directly so if I want to give this a height of like 80 80 pixels and a background of maybe white or something that should do it but I need to make sure I import it here so make sure you import from header.css so that the Styles will be applied when that header is loaded in so I have a set to 80 pixels but I am zoomed in like almost 150 percent so it looks a little weird um I guess I'll keep it zoomed in so you all can see and I'll just kind of change the size of it a little bit I'll put like 50 that looks a little bit better and then we probably want to put some spacing between the header and these things which I think if you just were to go to main.tsx I could just wrap this whole thing in some type of container or like a I don't know a page component and the reason I'm doing that is so that inside of index CSS we can style the page I'll say page and I'll say this is display Flex Flex Direction column and then I'll say gap of 20 pixels and that'll put a space between the header and the actual content of every page which is good now on the header itself we should probably um put some type of content in here so again we're building like an application typically on the left side you have like a logo so if I were to go ahead and just put like a span or div that has like a logo and typically it should be like an a a link so I'm gonna go ahead and just put a link here and we have that link component that we can use from react router right so I'm gonna say import link from react router Dom and then I'm going to go ahead and say two and I believe I can just go to slash right so whenever someone clicks on this link take them to the home page I want to make sure this works real quick um it actually is crashing oh um I can't actually do that because this has to be the link has to be inside of react router so if you look at Main TSX I can't do that because it has to be something that's inside of the uh the router provider so now that I'm thinking about this maybe it make more sense to have the header just kind of put onto every page explicitly or for right now I mean I could just do this simple thing and just make this an a tag and say href is that okay I mean this will work for now but ultimately you probably don't want to have to have it refresh the page when you click on the navigation um but it's probably okay we'll refactor that in a bit so we have the logo that should be over here and then on the right we should probably have some links are in the middle we should have some links so how do you do some links then on the right typically we have like a login logout button I'm not going to do authentication in this video but if we were to make a div here and put like a login like so that will kind of give us a login button and I'm just going to put three divs here like this and then I have three main sections so we'll have like the logo on the left we'll have some links in the middle that and then we will have the login on the right so how do you space these things all out well if you look at the header class um we can basically give this a display of flex and then give it a justify content tween now this should space them all out I think I might just have to give this thing a width of like 100 percent let's go ahead and look at this justify contents so I don't think whenever you look at the dev tools and it's Crossing something out it means you have it either misspelled or it's not right justify content which is weird because I'm pretty sure justify content is proper maybe it's called space between I think I'm thinking about this wrong there we go you know sometimes I usually get like intellisense that tells me like hints when I'm typing CSS I don't know where that went I don't know if it got turned off or something but it's kind of frustrating that I can't get intellisense when I'm doing my CSS I need to go find my extension that helped me out with that you also notice that there's like it'll be cool if this was contained in the center of the page I believe our container is like 600 pixels or 800 so if I were to give this a width um so in the header itself if I were to wrap all this stuff that the header is like you know so I have like a container I could just do like class name I'll just say container here and I will just go ahead and put that here and I think if we were to put um inside of here if I do like header dot container I could say the width is 800 pixels and this is where I could put some of these these flexbox things so I don't need this width thing I could do Flex here um and this should hopefully make it look a little bit better now I should probably also on here give it a margin zero Auto which will Center this on the page and then we also want to align items thinner and that'll kind of Center the the logos and stuff I believe um I think we might need to give this a height of 100 there we go I will I will say that CSS is my weakest link in terms of my web development I mean I know how to get stuff done I know how to figure it out but I I don't really know the best practices honestly so now you can you know click on these different things they don't actually do anything because they don't have a login page and we're not going to add one but it just looks a little nicer when there's an actual like login header and instead of logo like we should probably actually name this like flash hard stage or something there we go and I might even add some more padding between these things so like if I go back to header or index CSS and GAP I'll do like 30 or 40 how about that looks a little bit better and then usually every page you want an H1 if you wanted to have that page be proper in terms of like accessibility every page should probably have an H1 somewhere on it or an H2 I'm technically an H1 so if I go to the the app component let's go ahead and inside of this I'm gonna put H1 I'm gonna say you're X okay so now we have an H1 that says your decks here which looks good but we're gonna have to actually put this thing in a container because it's like all the way to the left here so we might need to do a little bit of refactoring I think app should probably be in some type of container um if I were to go to app CSS this is display Flex display Direction and column so I'm gonna make a just a generic container here that we can use on different pages I'll say container and I'll say width of 800 pixels margin zero our margin zero Auto and again like if you're using bootstrap or some existing Library like it'll probably be better to do that so I'm gonna go ahead and just put this whole thing in a container like this just so this thing is centered a little bit and the H1 is a little large in this example I think it's also because I'm just zoomed in so I would probably want to reduce some of the height and stuff so if I go to the app and go to um in this particular example I'm just going to reduce the font size by 24 pixels and uh okay maybe that's a little bit too much 32. and maybe make more sense to center it yeah probably so text the line in the center I guess that looks okay I don't really know all right so now we have our ability to view our decks and dive into them we can add new cards and we can delete some cards I think it'd be nice if this had more padding to it like notice how close they are to the edge here so if we go to deck CSS and we find the card we could give this some padding of eight pixels and that should hopefully bring some stuff in maybe even more um but I do believe I had some padding top here so I want to make sure that the padding top comes after the padding let the button doesn't um it obscured the text doesn't get obscured by the button all right so the idea is that like uh oh we should probably also display the actual deck that we have selected so when you go back to your decks and you click on JavaScript keywords there's no feedback to know like what deck do you currently have selected right so on the deck page we need to display the name of the deck now we have deck already set here notice that it's grayed out we can use this in displaying H1 and we could say deck dot title okay so now the deck is displayed here and same idea like this H1 is super huge we could do some more styling for this uh if you go to deck CSS we're going to follow kind of what we did for the other one so deck CSS I'm gonna go ahead and just put deck here and here we go looks a little bit better somebody and then anymore let's see here decks JavaScript keywords so at this point like there's different ways you could have done this like you could have had like legit flash cards where they have two sides to the cards a title and then you flip it over and you get the definition or description or you can just do what we're doing here where you have a bunch of cards that you can scroll through and read through this is the point on your application where you have to kind of play around with the best usability what design are you guys going for what is the best feature that the users need to use and then you have to make decisions about like okay should this thing be at the bottom of the page should it be at the top of the page should it be like a floating button over here and that's where you have to like go around and play around with different designs and try to figure out like what works best for your application but in our situation like I was just trying to show you how you can kind of get the ground running with a mernstack how you can actually get data persisted and retrieved from the database and how to get that all displayed in the UI those are the kind of the most fundamental parts of building out a full stack application and The Styling in the design and the usability that's all that's kind of separate that needs to be considered but it's not something that I'm trying to teach as a full stack developer right now and again as you get more experience like you're not going to be doing all this CSS by hand you're probably going to be using an existing framework like main time or material UI or something else that gives you all these components out of the box and you can just focus on like building out the functionality and the reason I didn't choose an existing framework or library is because I do think it is beneficial to know how to do CSS by hand like a lot of people just grab tail and CSS and they start using it and they don't even understand like what is half the things that Tailwind is doing really Tailwind is just an abstraction away from CSS so like it just shortens these these properties so that you don't have to write them all by hand so it's good to understand CSS because at some point you're gonna have to come through and manually change some things and if you don't know CSS you're going to get stuck and then additionally there's also error handling what happens if you create a car that has no text in it well you should probably not a lot of the happen you should probably make this red show an alert and these are things that at some point you'd probably want to come back through and add in but that's kind of beyond the scope of this tutorial so at this point what I'm trying to do is I'm going to commit my changes and then we're going to try to get this deployed out to hostinger services let's just go ahead and commit and I will say working on a header and styling some more so I'm actually going to start with the VPS because I think setting up this API on a VPS is going to be the most challenging part and by challenging I mean like it won't be too hard but we'll have to set up maybe some type of service like caddy so that we can get https set up so let's go to hostinger real quick so I'm gonna go to hostinger I'm gonna go find my uh API flashcardstage.com I'm gonna click manage and we're going to go ahead and dive into that VPS and I'm going to get that IP address here so so remember this is an Ubuntu box so if we want to set up the Ubuntu box to be able to handle running our application we have to SSH into it so I'm going to say SSH into the box and I'll say root at this IP I'll say yes and then I have a password on my clipboard that I'm going to paste in and now we're actually inside the machine so we are literally in a machine that's across um somewhere in the world that's not my computer and we can start actually installing some things okay so we are in a root folder and let's see what things we have we probably don't have git we probably don't have node we probably don't have npm so those are the main things that we're going to install let's go to Ubuntu setup npm and let's figure out how to do this I don't know what version of Ubuntu I'm using but all right so now that we have the Ubuntu box set up and we Association to it I'm gonna go ahead and follow this tutorial where it tells you how you can kind of set up node I'm gonna go ahead and change this to setup 16. uh actually let's check what version we have locally um if I don't have 16 I do have 16. okay so I'm going to set up 16. and that'll this command is going to basically allow my Ubuntu box to set up a registry and then I'm going to go ahead and just install node.js like this and then after it's installing or after it's installed make sure you have the right versions of everything okay so npm is at eight nodes at 16 that looks good and at that point well I think what we can do is we can also install git I'm going to say apt install git and git again is just the ability to like Fetch and clone our rotation okay so we installed node npm and git now what we want to do is we want to go to our repo is over here and I'm gonna go ahead and just clone this with https I'm going to say git clone and just go ahead and pull that over and if I do an LS it'll print out the project that we just worked on I'm a CD into that folder and then I'm going to say npm install and that's going to set up all of the necessary node modules that we'll need for running the server so that hopefully should be good make sure there's a node modules directory um so let's just try running this real quick I think if I were to just do an npm run Dev this should host the application again this isn't like a production ready host but I do want to make sure that um everything works so this is crashing because it could not connect to the Mongoose instance so remember you need a DOT EnV file to successfully connect to the database so what I'm going to do is I'm going to make dot EMB file in the server directory go ahead and just copy that same one that we're using locally and I can just go ahead and npm run Dev and now this should start a service on Port uh I think we're using what 5000 and if everything works okay what we should be able to do is we should be able to hit this endpoint at I think Port 5000 and go to Dex and uh actually I don't know what what port we were using yeah it's Port 5000. all right we are getting another error and I just want to say that like you're going to run to a bunch of Errors when you try to go from local development into production unless you're using something in like easier like Docker you're going to run to errors after errors because you're forgetting to set up different things so when we set up the mongodb cluster um we had to kind of specify what IP we're allowing this role to access now I had to figure out where that's set up oh it's under it's under network access so I'm going to go ahead and add in another one I'm gonna add in the IP address of our VPS this is a dedicated IP or it should be so I could just add in this IP and I could say um post Dinger VPS oh this needs to be an actual that and the comment I can say hostinger oh Stinger VPS go ahead and click confirm so now we have that IP and that should allow our API to connect okay so now this is active and what we should be able to do is just go ahead and run this again and see if this will fully set up okay so now this is listing at Port 5000 I think we should be good so if I go here and go to Dex we get back some information so I think this is good the notice that we are accessing our VPS on this IP and we can hit slash deck so that's that's awesome um now again it's not good to run node mon on your production server what you should probably do instead is I'm going to install a package called dm2 so I'll say npm install globally pm2 and when that's installed you can actually start your server uh using pm2 and that'll kind of make sure that's always running so we've tested that everything works the proper way to run this in production is I believe you actually want to compile your stuff down so I'm going to do MPX TSC hyphen hyphen and knit and this should set up a es config Json which we see over here and we can also kind of specify um some various things I think out of the box we should be able to just try to compile this so let's look for outdoor so outdoor I'm going to specify like a build directory here okay so this will basically when we compile the typescript it'll put all the compiled things in a build directory you could also change this to dist or something and in the package Json I'm going to go ahead and make a build command which is just going to run TSX over my project and then the start command potentially could just do a node on let's see build JavaScript you want to see what happens so now if I were to run npm run build npm run build it should load in that TS config it should compile all of our typescript into JavaScript and notice here we have all of our JavaScript files and now if it's the npm Run start that should start our application on Port 5000 it's already running so it won't work but I think this is a step in the right direction and what we're going to do is we want to also emit this build directory so go into git ignore I'm going to go ahead and say build we don't want to commit that to the repo so I added a few commands I'm going to commit those um adding more commands for building our API these are some things I forgot to do so when you go to production there's a couple more steps that you have to do and now that we committed that I'm gonna go back to the box that we're SSH into I'm going to do a git pull I'll just hit pool and that'll pull in those changes and then I can say npm run build that'll compile and make a build folder and then I can say npm run Dev or sorry and then I'll say npm Run start okay so that'll run the application production mode now again like we want this to automatically restart if something were to go wrong so I think I can just use the pm2 thing we set up so I'm going to say pm2 start uh npm I have to go figure out how to use pm2 for this I actually I think I can just do this I can say um em2 start build index.js okay so that's going to actually set up a process that's going to run on the machine and I can go ahead and just see this thing running and if it were to crash it should restart it automatically I believe cool so now we have to set up some type of like https to get this working so what I'm going to do is I'm going to go ahead and take this IP and I'm going to go to hostinger and I'm gonna go to domains and I'm going to set up a subdomain to point flashcard Sage or Point API dot flashcard Sage to the box so I'm going to go to DNS name server and I'll do an a record and then this will point to that IP and then I'm going to say API so that should set up a subdomain that points to that box now it may take a little while to propagate but at this point what we also need to do is we need to set up https on this machine so there's a a program called caddy you can set up that'll kind of get all this thing going and I do believe I did this on a similar project all right so I'm going to be using something called caddy to set up the https stuff I'm going to have to basically copy a lot of these commands I might have to do these commands one by one maybe I messed something up so I'll do that one and I'm gonna do this one I'll do this one I'm gonna do this one and setting up server sun and then finally we'll do install caddy all right so let's try it again caddy help all right so caddy is set up and we can basically try to use it now so I do have another project that I worked on where I kind of set up caddy where basically you can make a file you can make a caddy file in this directory here so I'm going to go ahead and do Vim set up my caddy file and it's already here actually so I think we just need to change a little bit what we can do is we can just put um a reverse proxy inside that file so I think let's look at this real quick what's in this file I'm gonna go ahead and delete everything and just put API and then I'm going to go ahead and say Flash cardstage.com and then we're going to reverse proxy the port 5000. so what this is doing is basically going to set up a proxy between my caddy service in my locally running API and put it behind https let me do a candy start let's see if this will work um okay so it looks like it set that up so I don't know let's see if this works I haven't done like lower level server stuff in a while but it's always fun to play around with this stuff let's try API flashcardstage.com and I'm gonna say Dex and let's see if this actually works so I think I think Apache might be set up on this thing yeah so the machine has Apache on it I don't really want to patch you right now I'm gonna go ahead and like system control stop Apache 2. I'm gonna do candy start hyphen hyphen config and then I'm gonna go ahead and put this location here and that should set up caddy that's the reverse proxy now if I go to over here and refresh the page notice that I can access the decks so we have fully set up the API to allow requests and now the next step is how do you set up the UI okay so let's go back to the clients and I do believe we have in the client it's like hard-coded to do a certain um a certain URL so if remember we go here this is hard coded for localhost which is not really what we want so what I'm gonna do instead is I'm just going to change this to API flash card stage dot com right now but you could also do a vconfig so like if I do Veet how to get environment variables um and I go over here I can basically import an environment variable like this and I believe if it's on the front end it has to be a prefix with Veet so I can just do this like so and I believe I can say use API URL or I could fall back on localhost 5000. let's try this so what I want to do is in the my local laptop I'm going to go ahead and try building this so I'm going to say let's look at the package Json and the client and we are going to try to see if there's a build command which there is and I want to go ahead and just make a DOT eav file I believe and I'm going to dot EnV here inside the client folder I'll do EnV I'm a duvite API URL is equal to https API flash card sage.com and I should be able to do an npm run build and that should use that environment variable and put it in my actual like compiled JavaScript so just to verify that I want to go ahead and search this entire file for that URL and notice that it actually is in the code base so now the next step is how do we deploy our UI to hostinger well if we go back to hostinger I have a bunch of stuff open let me close all these things if I go back to hosinger we set up the domain we set up the API we set up https using caddy now if I go to hosting and go to the premium at shared hosting this one I'll go ahead and click oh this one flashcardstage.com I'll click manage and we're going to go into the file manager so we can actually deploy this thing out so now that we're in the file manager I'm going to click public HTML and I'm going to go ahead and try to upload which I believe is probably this button I'm gonna upload an entire directory here so let's see if I can do this properly I'm going to go to my workspace I'm going to go to my project which I call flashcard Sage client dist and I'm going to go ahead and select um I don't know if I want to do files if I do upload disks I think I might just upload the entire disk folder let's try it out and see what happens but this might not be the right way to do it let's try it out okay so we are going to upload the disk folder and I need to move this disk folder up a level so I'm gonna go ahead and just copy all these and say move file and I'm going to move them to up level just go ahead and click move and then I can kind of delete this old one and now we should have our beat application set up on flashcardstage.com if I go to it notice that everything is deployed and we actually see the data that's um being fetched from the API so if I go to the network tab you will see if I go into here it's actually making requests to our flashcard Sage API this is all secured over https and I can actually start using this application Live and start adding new things like for Loop some something I don't know well so we fully created a mernstack application we got it all set up all integrated we got it deployed to hosinger's premium shared hosting and then also set up our API on a hostinger VPS and sending me the VPS again was the more challenging part the premium shared hosting is really easy you just basically copy over your built Veet application your compiled a react application and you're good to go I mean everything else is already set up for you just make sure you have the index in the main public HTML file folder and everything will just be hosted for you when you go to your app and then if you wanted to make changes and do more deploys you basically just re-run your build copy those over if you want to and same with the API you'd have to kind of commit your changes and go estimation to the box and do a get pull and restart your pm2 service so that about wraps up this tutorial if you guys learned something be sure to give me a thumbs up leave a comment below if there's something that I could work on to better explain what I'm doing and feel free to join me Discord if you want to talk to me directly again if you want to do anything with hosinger be sure to check out the description there is a link in a code you can use to set up and sign up for any of these services that you saw really fun to use really easy to use and really affordable to use as well so definitely be sure to check those out if you're looking for hosting in the future and like always I have a Discord Channel if you want to go and talk to me directly or just go and try to get some help with whatever you're trying to learn in programming in JavaScript this code will all be hosted at this git repo which I'll also put in the URL so be sure to check that out if you want to kind of see how I did any of this and like always have a good day and happy coding
Info
Channel: Web Dev Cody
Views: 69,669
Rating: undefined out of 5
Keywords: web development, programming, coding, code, learn to code, tutorial, software engineering
Id: G_XyAfcLeqI
Channel Id: undefined
Length: 192min 2sec (11522 seconds)
Published: Mon Nov 14 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.