Realtime Chat App with NextJS, GraphQL, NodeJS, MongoDB, Prisma, TypeScript (iMessage Clone) 💬🔥 | P1

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what is going on everyone my name is Shady and today we are going to be building an iMessage clone using next.js graphql node.js mongodb Prisma as well as chakra UI and we are also going to be using next Dot and Google Cloud platform for authentication and this entire application is going to be written in typescript and for those of you that do not know what iMessage is it is Apple's text messaging application that is used on both iPhone and MacBook devices it is basically just a real-time chat application and we are going to be building a web application that looks and feels like iMessage so it has been a while since I have posted so I am super excited to be bringing you this tutorial series I wanted to take this project Beyond just a normal basic chat application so that I can teach you as much as I possibly can so I worked really hard to include a bunch of complex full stack features that I'm going to be demoing in a second here and these features are really going to allow us to very deeply explore all of the technologies that we're going to be using so on the front end we are going to be taking a dive into react and xjs and we're going to be learning about things like server side rendering client-side routing and we're going to be using pretty much all of the react hooks that come out of the box with react and we are also going to be implementing authentication using next dot in combination with Google cloud provider and also on the front end we are going to be working very heavily with the Apollo graphql client library and we're going to learn exactly what graphql is why it is useful and we're going to become very familiar with all of the graphql terminology like queries mutations and subscriptions and we're going to learn how to write our own custom queries mutations and subscriptions and use them with the Apollo client react hooks so that we can actually send requests to our graphql API and we're also going to be learning how to implement real-time features using graphql subscriptions and websockets now on the back end we're going to be learning how to create a graphql API completely from scratch using node.js and the Apollo graphql server Library we are going to learn how to create a graphql schema as well as how to write query mutation and subscription resolver function so that we can actually respond to requests from our front end and again don't worry if you don't know what these words mean and also on our back end we are going to be learning how to set up a mongodb database and we're going to be using Prisma to communicate with that database and Prisma is honestly hands down one of my favorite libraries to ever exist so there is an absolutely incredible amount of stuff that we are going to learn throughout this tutorial and my main goal in building this project was to give you enough information so that you could build pretty much any application you want using these Technologies so that is enough talking let's go through what we're actually going to be building all right so to demo the real-time functionality of our app I have three different browsers open here and we are going to have a different user logged into each one and as you can see in the top two browsers we already have users logged in in this top left hand side browser we have Mr Elon Musk and on the right hand side we have Dua Lipa herself and in this bottom window here we are going to be creating a brand new messenger ql user and to demonstrate all of the of our app we are going to be facilitating communication between these three users so let's go ahead and create an account with Google here click continue with Google and I'm going to choose this email here so we're going to authenticate with Google and the first thing that the application is going to ask us is to create a custom username so the username I'm going to create is going to be Chad Mary this is going to be me and I'm going to click save perfect so we get brought to this Opening screen here where it is saying let's get started and is asking us to create a conversation because we currently do not have any all right so let's go ahead and create a conversation here so I'm going to click on this and this modal is going to pop up and we are going to be able to search for users by username so we can create a conversation so to start off I'm going to create two separate conversations with each of these above users here Elon and Dua so I'm going to search Elon and the search results are going to be all of the registered users with our search term in their username now since I am super tight with Elon Musk I know that this one at the bottom here is the real Elon so I'm going to click select because I want to create a conversation with him and I'm going to click create conversation so that is going to create a brand new conversation with Elon Musk and myself and you'll notice that at the top here in real time Elon was updated with the new conversation from Chad Mary there is no message yet so let's go ahead and send Elon a message hey Elon hope your doing well smiley face I said that and you'll notice in the top left here in real time elon's conversation updates and since I am such good friends with Dua Lipa I also want to create a conversation with her so I'm going to click on this button here that says find or start a conversation and that is going to open up the create conversation model once again but this time I'm going to search for duo so I'm going to click on select and do the same thing create conversation now notice up in do a screen She is again given that update so I'm going to send a Dua a message here that says love your latest track with the heart eyes send that and turn your attention up here and you'll see that Duart receives that notification up here so as Dua Lipa let's reply to Chad Mary so I'm going to click on this conversation and notice that the conversation is marked as red now let's reply to Shady that's it thanks Shady nice to hear from you with the super cool emoji with the glasses send that and notice how messages appear in real time I'm such a big fan and that appears in real time on do a screen Here and Now Elon sees Shady's message and goes oh Shady texted me I want to reply to him hey Chad when are you coming to the valley and chatty is going to receive that message in real time and you'll notice the conversation is marked as unread because we have not clicked on it yet so the application knows which conversations we have and have not read which is pretty cool and then when I click on it you can see that it is marked as red all right so I have a conversation going with Elon Musk and I also have another conversation going with Dua Lipa but what if I wanted to create a group conversation with both Elon and Dua well we can do that as well so if I open up the create conversation model again our duoliba search results are there so I'm just going to add Dua to the conversation and I also want to add Elon Musk so I'm going to search Elon once again and we want to add Elon Musk to the conversation so now we have two people in this conversation and now before I click create conversation turn your eyes up to Elon and Duo screens up here and we're going to see this new conversation up here for both of them because they are both included it's another create conversation and notice how the new conversation appears for both Dua and Elon okay so as Shady I'm going to send the first message in this group conversation I'm going to say hey guys I wanted to create HR Group and send that message and you'll notice that Dua and Elon both get that update so let's go into this conversation from do a screen and let's go into it from Elon screen awesome so now they're all viewing group chat now what about if after the group is created we actually want to add another person into the group well we can do that as well if I right click on this conversation I can edit this conversation to add another user alright so let's say we want to add Drake to our conversation so I'm going to search Drake and Drizzy Drake is going to pop up here so let's select him add him to the conversation and I'm going to click update conversation so I click update conversation notice how all three users are hit with that update you can see that the conversation participants are updated here as well as here in real time and I think that's really cool all right so let's get Dua to send a message here so she's going to say hey how are you guys and put the smiley face send that both Chad and Elon get that message in real time now let's say Elon Musk does not want to be in this conversation he's like oh my God I'm already in so many group chats I do not want to be in a group chat with Chad and Dua Lipa that's the last thing I want to be doing Elon can actually leave the conversation if he wants if Elon right clicks on this conversation and he clicks on leave the conversation is removed from his list and you'll notice that undo screen Elon was removed from the participants list same and same on Shady screen Elon is no longer there and Duo is going to be like oh my God Elon left Chinese gonna get that message and he's going to say it's okay I'll add him back now just to annoy Elon I am going to add him back to this conversation so if I right click on this conversation and I click edit I'm going to add Elon back in search for Elon again select Elon Musk and update the conversation now Elon is going to receive that conversation appear in his conversation list again and he's gonna be like oh my God they added me back so he's going to send a message saying stop and he is going to leave this conversation once again and now Dua is kind of like okay well Elon obviously doesn't want to be here so I don't want to be here either what is the point of this conversation so Dua decides to leave as well so do the leaves so the conversation has updated on Shady screen and he's realized that he is only in a conversation with Drizzy Drake and he does not really want to talk to Jersey Drake so he's just going to delete the conversation so he's gonna delete the conversation conversation is deleted and shady is back to just having two private messages with Elon as well as Dua okay so that was kind of a silly demo but it was kind of fun to do um but I wanted to show all of the features of this app so basically our users can create custom usernames they can search for users to create conversations they can create private one-on-one conversations or they can create group conversations with as many people as they would like users are also aware of which conversations they have opened and which ones they have not based on this dot indicator here and as you saw users can both leave conversations as well as delete conversations so there is actually a lot of really cool functionality going on here my favorite feature of this app is the group conversations as well as the ability to edit the user participants in a particular conversation to either add or remove users I think that's pretty cool and it was super fun to build so we have a really solid feature list here and they all have varying levels of complexity and in building these features we are going to become very comfortable with all the technologies that we are using so that is it for the product demo let's actually get into the build all right you guys welcome to the tutorial let's get building so on the left hand side of the screen here I have my terminal open to the directory that we're going to place the brand new project in and on the right hand side I have my browser open and throughout the tutorial I'm going to have my code editor open on the left hand side and the browser showing the app in real time as we build it on the right hand side and one last thing I want to say before we start building if at any point along the video you do get stuck or have a question about anything please do leave a comment I responded to 100 of my comments and also I have a Discord server where you can gain direct access to me and there is about 150 people in there now who are willing to help you out as well so please do join that I would love to see you in there all right so the first thing we need to do is create our brand new nexjs typescript boilerplate application so what I'm going to do is search up create next app go to the create next app docs here and grab this command with the typescript flag from the documentation and I'm going to paste it into the terminal here okay so the way I'm going to set up the folders for this project is I'm going to have the main project folder as iMessage graphql and inside of here I'm going to have both a front-end folder and a backend folder in the same repository so that we can work with them in the same editor but I'm going to deploy them separately at the end of the tutorial so what I'm going to do is place the brand new nexgs project into the front end folder of our project so I'm going to press enter and just click yes to all these questions all right so once that is done we will have a front-end folder inside of our iMessage graphql folder and I'm going to also just create the empty backend folder all right so now we basically have a front end and a back end and we're not going to touch the back end for a little bit we're going to start off with the front end with the whole next.js part and the back end will come in a little bit later but for now I'll just create the empty folder okay so what I'm going to do is open this up in vs code and see what we have here so like I said we have this main top level iMessage graphql folder and inside of here we have a front end and a back end and the back end is just completely empty right now but the front end has our brand new next.js project that we are going to fire up here in just a second and this is just a personal preference of mine to have this sort of mono repo with the back end and the front end in it so I only need one repository and one vs code window open if you had them separate you need two repositories as well as two vs code windows open at the same time so that is my personal preference however I do with the folders as you wish I'm just going to shrink this down to be about half of the screen size all right so let's take a look at our front-end folder here and let's go into the very root of our next JS application and that is going to be inside of pages and then the app.tsx file this is the root of our next.js app here so what I'm going to do is open up a new terminal in vs code here and I'm going to CD into the front end and then I'm just going to run the command npm run Dev to fire up the next JS development server and once that has successfully compiled I should be able to go to localhost 3000 in my browser and see the Bare Bones next.js project all right so for those two that are new to nextgis I'm just going to briefly explain how the page routing Works in xjs versus a plain react application so next JS has client-side routing built into it which is super nice and we don't have to set up routing on our own using something like react router so how the next.js router works is that the file names inside of the pages folder correspond to the route that that page will be seen so for example if I go to the index page which is just the home page or the base domain URL like localhost 3000 this is the page we're actually looking at right now you can see this welcome to next.js here that's what we're looking at so the file name of any file that I create inside of the pages folder will correspond to the route that I would want to go to to actually see the component that is inside of that file and you can do nested routing with folders you could have a folder called posts and then inside of that folder you have a file called comments and then you would go to the route post slash comments so it's very straightforward and it's very nice and it comes out of the box with next.js okay so what I'm going to do just so I have a bit more room inside of the editor here because this is kind of a small area is I'm just going to actually shut off the development server close this terminal and run the server inside of my actual external terminal here npm run Dev perfect and now I have a bit more room I'm just going to close the Explorer here so now what we can do is just remove this entire div we do not need it and I'm just going to replace this with a div it says hello home page for now if I save that you can see that that appears here because we are on the home page at the index route we can remove all of these Imports that we're not going to need and we're going to clean out the folder and file structure here a little bit as well so we're not going to need this Styles folder at all we're going to be styling our application completely with chakra we do not need any CSS so I'm just going to delete this all right and also what I'm going to do is at the root of our front-end folder I'm going to create a source folder and this is where all of the code that we are going to write is going to go and I'm also going to move this Pages folder inside of here as well so I'm going to click move and all the Imports should update and we're going to see some some errors here but we'll just need to rebuild the application uh it's actually a very common practice to create a source folder in the root of your project stated in the next JS docs it is configured to allow for it it's just another preference in mind I just feel like it makes sense to put all of the core application code in the source folder and in order to get rid of these compiler errors here all we need to do is just simply rebuild the application so that next.js has a chance to recompile and go look into the source folder for the code that it needs to actually render the app so if I refresh this I should see Hello homepage once again on the browser it looks different though because we don't have any of the Styles provided by next.js we have just a blank web page with zero styling which is exactly what we want all right you guys so the next thing we're going to move into is going to be authentication and setting up next auth with a mongodb database using the Prisma adapter offered by nexod which is going to allow us to actually create user accounts and store them in our database and this is going to involve the expiration of three big new topics which are next auth mongodb and Prisma and all of these three things work together there to just make authentication with your app super easy Prisma and were together as a database solution but in combination with Nexa storing users in your database is it so easy so what we're going to do is just simply search for our next auth in Google and go to their docs I'm just going to go to the documentation here so what is next auth well as the name suggests it is an authentication solution built specifically for next.js so essentially it is designed to work with the server-side rendering patterns of next.js and they have custom built react hooks to work very smoothly with the server-side rendering functions provided by xgs which we are going to see in a little bit here once we start actually getting deeper into authentication but it essentially is a plug-and-play solution for authentication with next.js applications there are really only two main pages that we're going to be focused on here and that is going to be the Prisma adapter as well as the Google provider so if we go to this provider section here and we just click this down arrow you can see how many authentication providers they have it's honestly unbelievable there's some companies in here I haven't even heard of we're going to be using Google for for this application but feel free to add more if you desire because once you do one you can kind of do them all they're very similar and Google is kind of the most popular one so I'm going to go to this Google page here there's going to be a link to the Google developer docs explaining how to create a new oauth web application within Google Cloud console what you're going to do in just a second and we're going to generate these Google client credentials that the Google Provider from nexoc is going to interact with to allow Google authentication so that's what we're going to do now actually so we can open up a new tab and we can search for Google Cloud console here and it should just be the first thing that comes up console.cloud.google.com I am already signed in so I'm going to sign out and just sign in with a different Google account that will have no projects inside of it so that I can show you what this process looks like completely scratch in case this is your first time using the Google Cloud console so what I'm going to do is just use a test account here and I'm going to log in okay so once you sign into the Google Cloud console with your Google account you should see something like this this is the entire Google Cloud product and Google cloud is a ginormous product and there are so many services that they offer so it is a bit overwhelming to be in here but we are only going to be using the apis and services product and particularly this credentials one here so when you visit this page for the first time it is saying to view this page select a project and we have not created a project yet so what we're going to do is Click create project okay so you can name your project whatever you would like I'm just going to name mine iMessage graphql tutorial and no organization I'm just going to say no organization because we're not really part of an organization here and it's going to create the project for us so you can access all of your projects from within this drop down up here and you can switch into all of the projects that you might have and you can use this new project button to create new ones if you desire so as we just saw in the next auth documentation regarding the Google provider we do need to generate these two potentials here for Nexa to communicate successfully with the Google servers and perform the oauth flow so we want to do is click on here create credentials and the credentials that we're going to be creating are for a new oauth web app which is this oauth client ID one here so you can click on this okay so it's time to create an oauth client ID you must first configure your consent screen so let's click on configure consent screen so I'm going to select external because that is the only one we are able to select I'm going to click on create okay so I'm just going to make this a little bit bigger so we can see this right side section here so this is basically where we are registering our app and configuring the details of the consent screen and the consent screen is basically the form that users are going to see when they try to sign into our application using Google and it's basically telling the user that our application wants access to their Google account and we are asking for their consent to do that and it basically looks exactly like this these are the details that we are customizing here so our app name is going to be iMessage graphql okay you can set your user support email to be your Gmail email and you can also add your application logo here which is pretty cool so Google will show that to the users so you can actually brand the form a little bit okay now down here is a section on our apps domain and we currently do not have an app domain because we have not deployed this application yet we are only in development so we can just leave all this blank it is not required as of right now I'm just going to exit this off and it's in here developer contact information so basically this is a way for Google to get in touch with you regarding changes about your project so I'm just going to add my main Shad Mary at gmail.com account and I'm just going to click save and continue okay the scope section is a little bit outside of the scope of this tutorial so I'm just going to click save and continue as none of this is required test users is basically where you can have your app only accessible to a certain number of like hand selected users this is not applicable to us so we can just save and continue and all this stuff can be changed later after the app has been created as well so just to give you a summary here of all the details we inputted and so we can just go back to dashboard here so if we go back to the credentials section here we have completed our consent screen so we should be able to actually go ahead and create the credentials as before so again create credentials and oauth client ID so you're going to be prompted here to select an application type and we are building a web application so we can select that and we want to give this a name so I'm going to name this iMessage graphql tutorial I'm going to zoom in a bit actually sorry this is really small okay and there's two important sections down here there's authorized JavaScript Origins as well as authorized redirect Uris so the authorized JavaScript Origins is basically the domain of our application so we're basically telling this new Google project of ours what domains we want to allow requests from so for development purposes all we need to add is http localhost 3000 that is the client development server that is going to be making requests to our Google project now when we deploy this application we're going to add another URI there's going to be our production application but this one will suffice for development now the second section here authorize redirect URI is going to be a callback URL coming from next auth that we're going to add into here now this is coming from if we go back to the next auth Google provider docs you can see here that there is a section on authorized redirect Uris and it's basically saying for development this is the URL that we want to add and so we can just copy and paste this into this input here whoops I forgot the H on HTTP okay so I'm just going to click create and it should create those credentials for you so this modal is going to pop up and you will see that there are two values here there's the client ID as well as the client secret and if you go back to the documentation here those are the exact two values that we need to pass to our Google provider and as you can see here these are both environment variables so we're going to do the exact same thing we're going to put them in a DOT EnV file because they are supposed to be secure credentials that are not supposed to be shared with anyone but your development team which in this case is ourselves so what we're going to do is so let's create environment variables for both of these values here so I'm going to copy this client ID one here and come over to our file explorer and inside of our front-end directory I'm going to create a new file called dot env.local which is going to be our development environment variables which we will later put into production okay so I'm going to create this new one called Google underscore client underscore ID and set it equal to that value that I just copied from over here and I'm going to copy the second one here client secret and create Google client if I could type properly secret and set it equal to that one there okay now as I mentioned before these are secret credentials and we do not want to share these with anyone I do not mind that you are seeing mine because I'm going to delete this Google Cloud project immediately after posting this video but you would definitely want to keep the secret in a production application so I'm going to click OK here we don't need that modal anymore and here you can see our new oauth client ID I'm Mrs graphql so that actually wraps up everything we're going to need to do inside of the cloud console here we are not going to need to come back here until we add our production application URLs to the URL section of this client here so we can go ahead and close this okay so the next thing we want to do is actually allow next auth to communicate with a database that we're going to create which is going to be a database and then we're going to do that is using the Prisma adapter created by next auth so if you expand this adapter section here you'll see a bunch of different options here and these are basically just adapter is created for all of these different tools that allow you to really easily read and write users to your database of choice so let's go ahead and click on the Prisma option here so the very first thing we need to do is install a bunch of packages next to auth Prisma client and next stop prism adapter here so let's grab this first command here it's kind of tricky with this copy window so copy this so let's go over to the terminal here and let's paste this in the front-end directory make sure you're in the front end directory and not the iMessage react well where the front-end and back end are our front end and back end are going to have two separate package.json files and therefore two completely separate package bundles and we're going to have different packages installed on both the front and the back end so it's important that you install the right packages in the right directory and in this case we want to be in the front end so inside of the front end let's paste that npm command or yarn whatever you're using inside of the terminal here and we'll let that install it's pretty quick okay it and then the next one is just this Prisma package and it's going to be a development dependency cool okay so that is all done so the next thing we need to do is create this next auth file in our project here and that's going to be created at this path provided here which is Pages slash API slash auth and then the file name is going to be this square bracket.next auth and you may have noticed that out of the box and actually s gives us this API folder inside of the pages folder and so another really great feature of nexgs is this API folder because it allows you to really easily set up a back end in your application if you do need to write backend logic and in our case we do but we are going to be developing our backend completely separate so we're actually only going to have this auth route in our front end but if you were developing say like a rest API with the next yes app you might have a lot more API routes inside of here the routing works exactly the same as the page routing so out of the box it comes with this hello.ts file so there's an API route API slash hello and this is just provided to get you started developing your API routes but we are not going you need this so we can just delete this okay and inside of our API folder we want to create this endpoint here auth and then this file next auth here and that is the only API endpoint at our front end API is what you have because we're developing a graphql API completely separate however we do need to create this endpoint to allow next auth to successfully communicate with our next JS server so let's go ahead and do this so inside of the API folder let's create an auth folder and inside of the auth folder let's create this file and it's going to be dot dot next auth and we're going to give it the extension.ts.js so then we can do is literally copy all of this stuff from the docs here and just paste it in there and we're immediately going to see some typescript compiler errors here because it's saying that's type string or undefined is not assignable to type string and that is because the value of these two things must be of type string and there is a possibility that these are going to be undefined because our compiler does not actually know all of the environment variables that we have however we as developers do in order to fix these I'm just going to Typecast these two things to be strings and we can do that in typestrip using the as keyword you can say add string and add string now generally in typescript typecasting is not recommended it's not really a good practice because it's overriding the typescript compiler is just generally not a good practice because it defeats the purpose of using typescript in the first place sort of but in this case I think it's a safe bet and a good choice to use it because we do in fact know that these values are going to be strings and they're going to exist so it's safe to do it here but in general we will want to stay away from typecasting if we can so I can save this and we actually are going to need to recompile our front-end development server because we added those environment variables so whenever you add environment variables in your dot EnV folder in order to actually have access to them you do need to just rebuild the application so I'm just going to shut that off and re-run it and we're getting some other errors here oh okay so we're running into some styling file routes here so yeah let's uh delete every reference to a CSS file that came out of the box with max.js because we deleted all of the CSS files so did that fix that okay so that seemed to fix that so we go to localhost we should be able to refresh and things are working fine and the environment variables should be accessible Now by our next auth file here all right so the next thing we need to do now is actually create a database that next auth can communicate with via this Prisma adapter so Prisma is going to act as the middleman between our next.js application and our database which is going to be a database which we're going to create in just a few seconds here so if we go back to the Prisma docs and we keep scrolling down it goes through how to actually set up your Prisma schema to work with a database of choice so in the documentation the database that they're using is a postgres database we are going to be using and luckily they have a section on mongodb but no matter what database you're using it's pretty much the exact same setup with just a few minor tweaks so we go back to the create Prisma schema section the way Prisma works is that you have a schema that represents all of the entities in your database so you'll see here the keyword model and then we have a model called account a model called session and a model called user and each model has a bunch of fields that make up the structure of the model and each field has a type that we as developers can specify such as string integer or a custom type like a message or a conversation and so as we build out the logic of this application we're going to have different models like messages conversations conversation participants it's cetera and all of those Earth can just be represented by models in the Prisma schema that's the pattern of Prisma you create models for each entity in your database and so the models or entities that need to be created for next auth to work with the Prisma adapter are these three here account session end user and actually sorry this fourth one that verification tooken and honestly at first this schema looks a bit intimidating don't let it scare you away it's actually just a bunch of different models with fields that are already provided to us so we can literally just copy and paste this into our schema dot Prisma file and make a few minor adjustments to work with and we should be good to go we can use the functions provided by next auth and immediately just start easily creating users using Google authentication and it's honestly amazing so what we can do is copy this file here this entire thing and inside of our file structure here inside of source I'm going to create another folder called Prisma and this is where we're going to create the schema dot Prisma file in here so inside of the Prisma folder we can create schema dot Prisma now I can just paste this entire thing in here I'm just going to close my Explorer so we have a bit more room so the very first thing we see in this file here is actually the data source object that Prisma is going to read and write to and in this example they provided here they have a postgres database as the provider in our case we are going to be using so I'm going to change this to mongodb and for this URL this is actually going to be the URL that Prisma is going to use to connect to our database and that is going to be the URL of our new database which we're going to create in a second here and we can get rid of this Shadow database URL here because we do not need it now moving on to this client object here we don't need this preview of features it's saying you will not need this in Prisma 3 or higher and we are using Prisma 4.2.1 so we are well past 3 so we can just go ahead and get rid of this okay now depending on what computer you are currently using you may need to add a field called binary targets and this ensures that the Prisma client will work safely on your current operating system so for me specifically I am using an M1 MacBook Pro for those of you using an M1 you will need to add these two binary targets here which are going to be native as well as Darwin now for those of you who are not on a M1 MacBook say you're on an Intel MacBook or you're on Windows or Linux I think you should be fine completely leaving out the binary targets because I was originally developing this application on an Intel Mac and then I recently purchased a M1 and continued the development and I only then was I running into issues and had to do some research and figured out I needed to add this so if you're not using an M1 I think you should be okay sorry morning alarm went off I think you should be okay leaving this blank however if you do run into issues down the road let me know in the comments or join my Discord linked below shoot me a message and I will help you get it solved so for now only add this if you are using an M1 so you'll notice that we're getting a bunch of compiler errors here um and this has happened since we changed our database provider to be mongodb and it's basically just saying that these fields are not valid IDs and this is exactly what the mongodb section of the next auth Prisma adapter docs talks about is basically just saying we have to change the value of these to be valid IDs so that the ID fields are mapped correctly so we can do is just copy this and paste this in for the ID values for every single one of models and you'll notice that those red underlines slowly disappear and we'll also need to add an ID here to the verification token perfect okay okay and the only other thing we need to change here are these DB dot text values here it's just saying that the native type text is not supported for the mongodb connector so all we have to do here is grab the DB string value from the docs and paste that in here as a replacement and we should be good to go our schema.przma file is happy and green now the last thing we need to do in this file is just change the database URL and so now we're going to create our database get the URL put it in here and we should be good to go to start creating users so to create our new mongodb database let's head on over to mongodb.com and click on sign in in the nav bar here now I already have an account with mongodb so feel free to create one if you do not already have one you cannot think it using Google or GitHub or email and password I'm going to authenticate with a Google account that I have not used before just so I can show you guys what it looks like if you are a first time user so I'm going to use this shadimiri7 gmail.com because I know that I do not have a account with this email yet just so I can show you exactly what it looks like from the very beginning so accept the privacy policy in terms of service and it is going to start provisioning some resources for you and your new account and it's going to ask you a few questions just basically about what your development goals are and what you're building so um it's asking us what is your goal today I'm just going to zoom in a bit here and I'm just going to say build a new application what type of application are you building I'm just going to say other and I'm just going to say a chat app and prefer language for me is going to be JavaScript and I'm just going to click finish now it's going to give you a few different plan options in our case we're only going to be using the free database so we can just click create and it's going to give you a bunch of different options for where this database actually is located in the world geographically as well as what cloud provider you're using we're just going to go ahead with all of the default settings whatever those might be for you depending on where you are in the world and we just go ahead and click create cluster if you would like to change the name of your cluster go ahead however you cannot change it once it is named it says here one time only once your cluster is created you won't be able to change its name the cluster name isn't super important for learning purposes so I'm just going to leave it as cluster 0 and I'm just going to go ahead and click create cluster all right the next step is going to bring you to is going to be the security quick start section here and this is basically just going to ask you to create a user within this new project that we're creating to allow access to the databases that are created within this project so we can just go ahead and create a username and a password for me at Auto filled you must have pulled already from like browser history or something so I'm just going to go ahead and click create user so now I have a username Shad Mary and my password and your username and password are going to be included in the database URL and those are going to be used as authentication credentials when Prisma tries to access your database all right so the next section down here is asking us where we would to connect to our database from and so for now we're just going to click on my local environment and then there's a section down here where we can add IP addresses that will allow access to the databases that you create and so you can just go ahead and click add my current IP address because we really only need our own for right now and later when we deploy we are going to need to configure this a little bit but for now this should be okay so we can go ahead and click finish and close having go to databases so once your project and database cluster has been successfully created you will be brought to this screen here and this is the home page of this particular project it is called project Zero by default and you can from here create new projects if you desire and within each project you can create multiple databases let's say you want to have a development database and a production database completely separate within the same project you can do that from within here by creating a new cluster this is the cluster 0 that we just created and this is the one we're going to connect to in our application over here and if you want to edit this particular Project's name to give it a more meaningful name other than project zero you can click on these three dots here and go to Project settings and right where it says product name here you can edit it so I'm just going to change this to iMessage graphql tutorial and I'm just going to click save perfect okay so that's saved and we should be able to just go back did that did that update okay so I refreshed and got updated to iMessage graphql so if you go inside of this cluster here this is where you can see all of the data relating to this particular database cluster and you can also see all of your database analytics now the place you'd probably be spending most of your time will be in this collections tab here which we unfortunately cannot view yet so it's in this collections tab here we're going to see all of your entity Collections and all of the documents for each of those entities so basically all of the data inside of your database will be viewable from within this collections tab now this is a nice segue into a tool that I love to use that is called mongodb compass and mongodb Compass is essentially a desktop application that looks like this that allows you to do pretty much all of this stuff but from within a separate app I personally love using the mongodb compass app over the dashboard in here I just find it a lot more intuitive so for example if I were to go into this one here this particular cluster which is the demo application I built and I can just connect to it you can see all of your databases inside of here so if I were to go into this iMessage graphql section here I'd be able to see all of my entity collections as well as all of the documents inside of each of those collections now all of my collections have been wiped so there is no data but when there is data in here this is where you can see all of that data and it's super easy to navigate and you can also very easily manipulate and delete data which is super handy in development I really only use the website to create a databases and then once I have the connection URI which we can get via this connect button here I would then put that into mongodb Compass connect to my database from within here and do all of my database work from mongodb Compass now for those of you that are interested in mongodb compass all you have to do is just search for mongodb compass and it should be the first thing that pops up and if you go to download now you should just be able to select your operating system I would just choose whichever one it defaults to so then once you download it you just have to open it up and you would be brought to a screen that looks similar to what I'm about to show you you basically have this and then all you have to do is enter your new database URI that we're going to put in here from our new database on mongodb.com and click connect and we should be able to see all of the databases within our newly created cluster if you did happen to get mongodb compass and you're wondering how to connect to your database from mongodb Compass I'm going to show you how to do that right now so what you can do is you can go into the cluster here and click on connect and you'll see that the third option here is it says Connect using mongodb Compass so you can click on that and it's going to give you a connection URI and that is what we're going to paste into this input over here now if you remember from a few minutes ago I mentioned that the user that we created within our new project when we were creating our new cluster those credentials are going to be part of the connection URL and you can see them here so my username is here and there is a placeholder for my password which I'm going to put in as well and then at the very end here we have slash test and this is going to be the name of the database and we can make this whatever we would like so what I'm going to do is I'm going to copy this and I'm going to come over to mongodb Compass and paste it in here I'm just going to zoom in a bit because this is kind of small all right as for the database name which is the last parameter here in the URL after the forward slash I'm going to give our database name iMessage graphql all right now something important to note here is that when you put your password in to this URI you need to make sure that it is URL encoded now this is particularly important if your password has special characters in it so to make sure that you are using the correct value here you can just search up URL encoder on Google and go to this mayorweb.com I will link this in the description below you pretty much just paste in your password so let's see you had a password of this whatever this really ugly thing and you click encode it's basically just going to URL encode it for you so that can actually read it properly so whatever password you chose when you created your user in the security section of our new project paste it into here click encode and then grab that value and paste it into here okay so I'm going to paste my password in here just like this and yes do not include the less than or greater than signs then you go ahead and click connect [Music] okay so you should successfully connect to your brand new cluster and if you go to your database section here you'll see that that iMessage graphql database is actually not in here and it will appear as soon as we start creating data in the database so once we create our first user you'll see a new database called iMessage graphql and all of the collections inside of it alright so in order to actually start creating data in our database we need to connect our nexjs application to our database so if we go back to vs code inside of the schema.present file here we are going to allow Prisma to connect to our database very similarly to how we did it with mongodb Encompass we're going to provide a connection string URI that Prisma is going to use in the Prisma adapter and that is how it is going to connect so it's going to look very very similar there's just a few subtle differences here so if we go back to mongodb.com inside of our cluster and we go back to that connect button here the first option we did was Connect using a mongodb compass this time we're going to click on connect your application and basically this is going to ask you to pick your backend framework that you are using in our case we are using node.js and the version is 4.1 or later and then it gives you this connection string which is what Prisma is going to use over here to connect to our database and it looks very similar to the Compass URI except there's just a few added query parameters here so we can just copy this from over here and we're going to create an environment variable that Prisma can read from because you'll notice that there is this EnV function here so basically this is Prisma looking for an environment variable with this particular name so we're going to name our new environment variable DB underscore URI and then we can go into our DOT env.localfile and create that right now DB underscore URI and we can paste that link in here now we do need to add our database name just after the fours last year and before these two query parameters and our database name that we chose was iMessage [Music] graphql okay and just like the Compass URI we do need to add our users password into here as well just like you did with mongodb compass so I'm just going to paste mine in here save this and then we just need to recompile our front end next.js app so that the new environment variable is accessible to our application perfect okay so that is then compiling so now when we actually call the Prisma adapter through next auth to create our users Prisma is going to have a way to connect to our database and is going to be able to successfully create documents within our new database all right so let's actually write a react component that is going to allow us to actually submit a new user to the database via next auth so let's go ahead and do that so on our index page here we are just going to write out a very ugly react component that is going to create the user in our database and allow the user to log in and log out and once it is successfully implemented and the logic is there we're going to make it a lot prettier using chakra in a little bit but for now let's just focus on getting it working using some raw HTML and the functions from next auth okay so let's go back to our localhost 3000 here and I'm just going to open up the console so we can see what is going on because I'm going to put some logs in here that are going to be hopefully informative for you guys okay zoom in a bit all right so at the top here we're going to import a few things from the next auth slash react package and those two things are going to be signed in as well as use session so the sign in function is a function given to us by next auth that makes it extremely easy and I'm talking one line of code to create a brand new user using any oauth flow which in our case is going to be Google and the use session Hook is another extremely useful hook given to us by nextdoc that allows us to really easily access the currently authenticated user so anywhere in the code of our application we can access the currently signed in user via this use session hook it's absolutely mind-blowing how easy next auth makes it here okay so I'm just going to create a button in here that is going to say sign in and that is super small I'm going to zoom in a bunch here and don't worry when we get chakra going and make our UI super beautiful it's going to look so much better again we are not focusing on beauty right now the goal is to actually create users so let's get that working so all we need to do is add an on click to this button and pass it a callback function that is going to call that sign in function and this is what I was talking about when I said in a single line of code we can create users with Google via next thought it's absolutely mind-blowing so all we have to do is when we click this button called the sign in function from next Dot and pass it the provider we're using so you can see here typescript is so kindly showing us all the options here and this is the same list of oauth providers that we saw in the next author docs so in our case we are using Google so basically we're just saying sign us in with Google that is it that is all we need absolutely crazy so now let's use this use session hook to actually view that user after they have been successfully authenticated what we can do is we can call the use session hook just like this and the U session Hook is going to return an object that we're going to destructure so if I look at what this function is going to return here typescript is telling us that it's going to to return a data object as well as a status object and this data object is going to be the next auth session that is going to contain the authenticated user and just in case you're wondering a keyboard shortcut that I use for autocomplete is control spacebar on a Mac I'm actually not too sure what it is on Windows but on on Mac it is control spacebar and you can view the autocomplete that is provided by typescript so for example down here if I were to delete the Google here if I press Ctrl spacebar it would show me the list of autocomplete options here so that's pretty handy I use that very very often so again control spacebar and I can view that so let's log out what this data actually looks like here is that here is data you can log that out okay and you'll notice that as soon as we try to use the use session hook we got this bug saying that you session must be wrapped in the session provider so the session provider is another react component given to us by Max out that we must wrap our entire application in in order for us to use the next auth Hooks and where we're going to do that is going to be in our underscore app.tsx file so inside of here we're just going to modify the structure just a little bit so I'm just going to cut out this component which represents our entire application here and I'm just going to put it inside of here and I'm going to wrap this in the session provider coming from Nexon slash react so make sure that Imports up top and we can move the closing tag outside of here just like this so this session provider context takes a session as a prompt and we can get that session from the page props up here so what I'm going to do is destructure these page props here and I'm going to grab session from it and then we can just spread page props just like this and then we can pass this session as a prop to the session provider um hmm okay all right so I just saved it and I'm just getting this weird um Jason error here what is this what is happening is there something in our console here okay yes something very important I missed okay so let's quit our next GS development server for a second I'm just going to clear this and something that is very important that I miss actually I'm glad this came off because I can explain it here is we need to generate our Prisma client now what does that mean so the Prisma client sort of represents the interface between Prisma and our data source which in our case is a mongodb database now in order to generate this client Prisma requires you to run a command that is npx Prisma generate and so once we generate the Prisma client it is through that Prisma client that we are going to be able to read and write from our database and we're going to see this a lot more as we develop out the core logic of our application so when we create messages for example we're going to say Prisma Dot message dot create something like that and that Prisma thing that we are calling the dot create on is this Prisma client so basically what happens when when we run this command is we are sort of building this schema with all of these models and all of these fields and that is how Prisma knows what entities we have in our database and what Fields those entities have so that us as developers can do things with those entities they create them delete them modify them now if none of this is clear don't worry we're going to be using the Prisma client a lot in our graphql API on the back end when we're actually creating messages like I said before and next auth needs this Prisma client as well in order to communicate with our database properly and actually add users to the database via the pisma adapter so what we can do is we can just come over to our front-end command line here and just run MPX Prisma generate now this may not work for you so if you run this it is going to say the post install script automatically ran prism generate and did not find your Prisma schema.prismafile so basically when we run this command it looks for our schema.prisma file and it is going to build our schema so we need to provide a path to our schema file so as you can see here it says if you have a prison schema file and a custom path you will need to run Prisma generate exactly like we did but then with the flag schema and then the path to that file okay so we can say MPX Prisma generate dash dash schema and the relative path to our Prisma schema is going to be Source slash Prisma slash schema Dot Prisma okay so now if I run this you can see here that says that prismac schema was loaded and it does all this stuff and you can see that the Prisma client was generated and now if we go back to our next.js application and refresh hopefully we do not see an error we actually see nothing because I have not re-rounded the development server so let's let's run that um and refresh now okay perfect so we have no error in our console now and you can see that the data is undefined which is good because we do not have a user logged in so I'm glad we covered all this stuff I totally forgot about the prismat generate but that was a good time to bring it up and hopefully explain it again that the Prisma client stuff is a little bit unclear right now do not worry we're going to work with it so much on the back end it is going to be extremely clear by the time we're done so let's go back to our index file and back to this login authentication logic that we sort of got to Sidetrack from a bit there so okay just a little recap we are calling the use session hook to access the currently authenticated user when the user clicks on this sign in button we're going to call the sign in function that is going to use the Google provider to authenticate this user okay and then what we did was we wrapped our entire application in this session Provider from next auth and we are passing it the session as a props so that the session is globally accessible throughout our entire application perfect okay so we do not need this app case x file anymore so I'm just going to close it off and let's give this a go we have the Prisma client generated we have next auth all configurated so theoretically this should work so if I click sign in you can see that it brings us to the Google oauth page I'm just going to click on chat Mary gmail.com let it do its thing and boom in a few lines we just created a user with Google authentication so you can see here that the data is logging now and check this out if I go into Data dot user this is the user that was just authenticated with Google Now check this out if we go over back to our mongodb compass and we just click refresh you can see that the iMessage graphql database was created because Prisma actually communicated with it and wrote the new user to the database so if I click on this you can see that it created three collections here so if I click on user I'm just going to zoom in a bit you can see our new user is in there Shady Mary it pulled my name from my Google account pulled my image from my Google account super cool now the account and session are less important entities that we're going to be working with they're pretty much just part of the next thought authentication flow next auth uses them to verify that the user actually exists and has a valid non-expired session but the most important entity is this user document here and this is what we are able to access on our client which we can see right here now this is really really cool because now inside of the code here I could do something like data dot user dot name and my name is there and that is really really cool okay so let's take a look at how we can log users out so we can do is we create another button and this button is going to say sign out and this function is going to call a function called sign out and we do not need to pass it in argument okay and what I'm going to do is add a ternary operator here to only show one of these buttons because we don't need to show the sign in button if we are already signed in and we do not need to show the sign out button if we have not signed in so what I'm going to do is I'm going to add a condition here that says if there is a data dot user let's show our sign out button and if there is not a data.user so the the falsey of the ternary operator let's show the signed in button perfect okay so as you can see here I am currently signed in so it is showing me the sign out button so if I click sign out it signs me out like it's just honestly crazy how easy it is so then I can click sign in again sign in again Prisma is going to communicate with our database see that we already have a user created and it's going to block us in so I don't know about you but I think this is honestly pretty cool within just a few lines of code across a few different files we are able to create users using oauth alright so in your terminal you may have noticed that nexoth is throwing these two warnings here it's saying that there is no next auth URL and that there is no secret and these essentially are two environment variables that we need to set so in a development environment which we are currently in next auth just throws warnings if these two environment variables are missing however in production this would actually break the application and nexot just would not function without these two things so we can just quickly add these two environment variables they are really simple to add just to make These Warnings disappear and they're going to be important later in production anyway so you might as well just tackle them now so the next auth URL is essentially just our application domain which in this case is localhost 3000 in production it's going to be our our website domain which we're going to get from versl when we deploy our front end and the secret is just a random string that next auth uses to Hash its tokens and the email verification tokens that it gets when it communicates with these third-party oauth providers just so much that stuff that's happening behind the scenes that nexoc needs all right so let's handle the next auth URL environment variable first so if we go to our DOT env.localfile here at the top I'm going to create a new environment variable called nextdoth underscore URL and for a development we are just going to have this be HTTP and then our localhost 3000. and then right underneath that we can create our next auth secret and the value of this we can actually generate in our terminal using a command that is provided to us in the next auth documentation so if you actually visit this link here that next auth provides in the warning so it'll bring you to their warnings page here all the warnings that could potentially be thrown in the terminal I'm just going to click on this read more link here and it brings you to the options documentation particularly to the secret section and it basically says what the purpose of the next secret is and how we can quickly generate one so I'm saying you can quickly generate a good one using this command here so what you can do is just simply copy this and then come over to an empty terminal window here just open up a new terminal Tab and put that in there and you can remove this dollar sign here I don't know why it automatically paste that in there run this command and it generates this nice random string for you that is going to be our next auth secret so let me come over back to our EMT local file paste that in here and so now in order for nextdoc to actually use this next auth secret environment variable we can go back to our next auth.ts file here underneath providers here we can pass in a value for this secret parameter here and the value of this is going to be that environment variable and we can access that by doing process.env Dot next auth or Secret which matches the name that we gave it over here and we do not need to add the next auth URL in the code anywhere next month we'll look at our environment variables and then if we just recompile our development server so I'm just going to stop running it and then we compile so now if I come back to our application and I refresh you can see that we are no longer seeing those warnings that were previously thrown by next auth and I can even sign out and sign back in perfect and we're not seeing those warnings so when we deploy this application all we're going to need to do is change the value of our next auth URL to be the domain of our production application that versal generates for us so for now we are done with our environment variables and we can just close this and continue on with our application okay so now that we have next auth working I think it is time to improve what our UI looks like because I'm kind of sick and tired of looking at this really ugly UI and so it is now time to install chakra UI and get our application looking a lot better than it currently is so I'm just going to close some of these tabs that we don't really need for now and we're going to head on over to the chakra UI documentation so I'm just going to do a quick Google search for chakra UI and go to the home page here chakraui.com I'm just going to click on get started and the first thing that we're going to see here is the installation section for both npm and yarn and whatever package manager you are using copy that command and we're just going to come over to our terminal here in our front end again make sure you're in the front end and paste that in here so we are installing four important packages here chakra UI react and a bunch of dependencies that it needs which are emotion react emotion styled and framer motion just going to run this command here so once that is done if we come back to the documentation here I'm just going to zoom in a little bit it tells you how to actually use chakra in a react application here so you can see that they're wrapping the entire application in this chakra provider so that is essentially what we're going to do in order for us to use the chakra Library throughout our application so what we can do is come over to our app.tsx file whoops not that one and this is essentially the next JS version of what this is here in the documentation because this component component represents our entire application very similarly to what we did with the next auth session provider where we had to wrap our entire application we're going to do the exact same thing with the chakra provider so underneath the session provider I'm going to bring in the Shocker provider to make sure that imports from shockware UI react [Music] and we're going to put the closing tag down here so now we will have access to the entire chakra library and all the components throughout our entire application inside of any page or component that we Define so another really cool thing you can do with chakra and you can pretty much do this with all major UI component libraries is you can define a custom theme object that you can use throughout your entire application so go back to the docs here and we just go to this styled system section and come down to the theming section particularly the default Theme tab we can look at what a theme exactly is and why it is useful so as the documentation says here the theme object is basically a place where you can define basically all of the aesthetic parts of your application so the main benefit of using a theme is that it keeps the overall look of your application consistent throughout the entire thing so that you have this you know the same colors being used the same border radius is being used and it just looks really consistent from a branding perspective and that can actually prevent a lot of code duplication where you would have to define the same CSS Styles over and over again throughout the code base and you just sort of Define it in one place and then whenever you need these Styles throughout your app you just access the theme object our iMessage application has very basic colors in it there's really only about like three to five colors that we're going to be using but I want to create a very simple theme object to show you how to do it because I think it is extremely powerful and it can be really useful in really large applications at other developers might be working on as well and just makes your code a lot cleaner so what we're going to do is create a custom theme here so we can just come over to the customized theme section here and essentially it just gives you a small guide on what to actually do to create a custom theme so this is basically exactly what we're going to do we're just going to create this theme using this extend theme function provided by chakra and then pass it to our shocker provider here so that it is accessible throughout our entire application so we can do is come over to our directory here and inside of our source folder I'm going to create a new folder called chakra and inside of here I'm going to create a file called theme.ts and I'm going to copy these lines here from the documentation and paste it in here so we're just going to make a few minor modifications to this file the first of which is going to be exporting this theme object here so we can actually import it into that app.tsx file and I'm just going to remove these comments here because we don't really really need them so for our brand colors we're only going to have one brand color and that is going to be the iMessage blue color now the hex code for that is going to be 3D A4 F7 that is the iMessage blue that is going to be used throughout our app and our other application colors are going to come directly from the chakra dark mode color palette so underneath this colors object here I'm going to add a Styles object and instead of here we're going to apply a background color for the entire body of our application so the way to do that is inside of the Styles object here we can define a global value and this is going to be a callback function and inside of here we are going to set the color of our body and the color that we want to set in this case is going to be white Alpha dot 200 so that is a shade of the white Alpha color palette and if you're curious what all of these colors are you can actually come over to the default theme section of the documentation here and if you just scroll down there's every color that exists in the chakra Library which is really really cool they have a lot of nice colors and they have a bunch of shades of every color which is super nice so if you want to access blue 200 for example you would say blue dot 200. so white Alpha 200 is actually dark despite the name it looks like this so this is sort of the background color of our application it is a very nice dark mode color so black alpha and white Alpha are really popular dark mode colors so we're going to be using these a ton throughout our build so one last thing I'm going to do inside of this file is create some theme config options here and this is going to be of type theme config so we can import that from Chakra UI react and essentially what we're going to do inside of here is set the initial color mode so we want our initial color mode to be dark and secondly we want to set the value of this use system color mode value to be false just in case our operating system is in light mode for example we want to prevent that from overriding our chakra theme so we want to set that to false so that dark mode is always applied so to use these config options in our theme Here we can pass it as a first argument like so we can wrap in an object just like this save that and we should be good to go alright so now all we have to do is actually pass this theme object to our shocker provider over here in our app.ts x file so the value of the theme prop for the shock provider we want to set equal to the theme object that we just created in that theme.ts file so we want to import that from Chakra slash theme save that now we will have access to this theme throughout the entire application so now if we go back to our application we can see that the chakra theme is being applied and we no longer have that bland white color with the base HTML font we now have the chakra styling applied to our app and we can build on top of this okay so now that the Baseline of our UI is taken care of and we have a nexot set up we can now start to build the app's core features now the first feature that we're going to build is going to be custom username creation we're going to allow users to create a custom username upon signing up because when they sign up with next auth through the Google provider all that they are given is a name email and an image URL and these three values are coming from their Google account that's all they have just those three things that is the default session object given to us by next auth and I want to show you guys how to add custom properties to this session and particularly the username because I just think it's kind of cool and I think it makes sense in a chat app sort of like you know Discord where you can create a custom username so you don't have to use your actual name from your Google account so when a user successfully signs up with our application we're going to prompt them to create a custom username that is going to be added to their user document in the database as well as to the client next auth session so that we have access to it throughout the app and in order to create these custom usernames and actually update the user in the database we are going to need to build out the first part of our graphql API and so in building this username feature we're going to get our first Glimpse at graphql so we're going to learn a ton and get a really good introduction to graphql and building out our backend by building out this username feature all right so we're going to start off by focusing on the front end side of this feature so we're going to build out the UI and the actual input that users are going to input their custom username into and then we are going to build out the actual graphql mutation that is going to execute when the user saves their username now if you don't know what a graphql mutation is do not worry we are going to get into the weeds of that basically a mutation in the world of graphql is a request to our server that is modifying data of some kind so a create operation an update operation or a delete operation we're going to use a graphql mutation and then for reading data which would be a read operation we're going to use a query queries and mutations are two very popular words in the world of graphql and there are subscriptions as well which allow us to real-time data updates like a chat application which we are obviously going to get into because we need subscriptions to perform real-time chat alright so that is enough about graphql for now we're going to see a ton of this very shortly so let's put out our react components that are going to allow users to create this username and then we will dive into graphql very shortly so we're going to head over to our index page which is the home page of our application and this is where we're going to start building out a lot of this username logic so the first thing we're going to do to our index page is server side render this page because right now it is being rendered client-side which is totally fine but you'll notice that if we refresh this page here you'll notice that just for a split second there it says sign in and it does not pick up that we are signed in until after about I don't know 0.5 of a second you just get that brief flash so if you look at the console logs here you'll actually see that on the first render of the component data is actually undefined and then once the session is successfully loaded from the next auth server that is no longer undefined and it actually has the populated values but for the brief second that the session is undefined and is being fetched from the next auth server this is actually rendering because a data.user does not exist which is the reason we are seeing that flash of signed in which is not terrible but if you have a bunch of UI components that depend on a user being signed in this little flash can be not the best user experience it's not again it's not the end of the world but if you can solve the problem why not and the way we can solve that problem is by server side rendering this page which allows us to fetch and compute data and pre-render our react pages on the server and then send these pre-rendered pages to our clients so that they are already populated by the time they reach the browser so we are going to do exactly this with our session so that the first time the component renders if the user is signed in and the session exists the first render of the component will appear as though the user is signed in so index.js the way we can server side render a page is using a function called get server-side props now in order to use this function at the bottom of our component here we can export the function which is called get server-side props and so the way nexjs works is that when it builds the application it is going to look through all of our page files and it's going to check if we have a function called get server-side props being exported from each of these files and if it is being exported it is going to server side render that page and this function is executed on the next.js server so everything that we write inside of this function is actually not happening in the browser is happening on the nexjs server before the react component even renders in the browser so inside of this function here what we're going to do is basically fetch this session just like we're doing on the client here and then pass it to our client page component as a prop and once we do this you'll see the difference in behavior that I am talking about okay so what we're going to do is fetch the session here but we're going to use a function called get session rather than you session because we are on the server side now technically we do not have access to client-side hooks like you session so we're going to use get session and if you head over to the next documentation it will explain which function to use depending on whether you are on the client side or the server side and because everything inside of this function executes on the server side we're going to use our get session function okay now in order for this get session function to work we need to pass in a context and this context is going to come from the get server-side props function and this context is basically just going to contain the request and response objects that nexop needs in order to retrieve the user session and the type of this is going to be next page context so we can import this from next at the top here so make sure that that Imports so the way this session is going to make its way in to our client-side component which is this home page here we need to return an object with a key of props and whatever we put inside of this props object is going to be passed as props to our react component and so what we want to pass here is this session so now if you refresh this page you'll see that there is no longer that brief glimpse of the sign in before we see that the user is actually signed in so by us fetching this session on the server side and passing it as a prop to our page component the use session hook has immediate access to that prop and it does not need to actually make a request to the next auth server to fetch the session it will just have it right away on the first render you'll notice that we are no longer seeing that undefined state of the data now obviously if the user isn't signed out the data is going to be null but that is good we definitely want that this is more for if the user is signed in and then you know goes away from the application for a while and then refreshes we no longer have that brief undefined State all right so now that our index page has successfully been server side rendered let's actually start building out the structure of the HTML part of this component here so all we're going to do in the HTML part of our index page here is check if the user is signed in and if they have a username if they do we're going to direct them to the chat component which is going to be where they're going to see their conversations and their messages and if they are not signed in and if they do not have a username we are going to direct them to an auth component where they're going to create their account as well as their username and once these two things have successfully been done they will then be redirected to the chat component so that is the overall governing logic of the index page that we're going to right here so what I'm going to do is totally get rid of this entire div here and I'm going to create a box component and the Box component is coming from the chakra UI react Library so under the hood the chakra box is essentially just an HTML div however it varies because we can pass in any CSS property as a prop which allows us to very easily style our components so for example here if I say here is a box and I just say that it just appears as a normal div but I can easily style this by doing something like passing in the Border prop and saying one pixel solid red perfect or I could give this a background of green and you can do this with every chakra UI component boxes inputs text areas and it's super easy to style them by just passing in the CSS properties as props and we're going to see a ton of this throughout this entire build okay so I'm just going to get rid of these Styles here because they are pretty ugly and just get rid of this text as well now inside of this box we are going to have this ternary operator that I was mentioning before that's going to check if the user is signed in and has a username and we're going to show the user specific components depending on whether that is true or not so what we can do is we can take the data from the use session hook and check if a user exists inside of it meaning that they are signed in if they are signed in we're going to show them the chat component and if they are not signed in we're going to show them an auth component and we have not yet created these components but that is what we're going to do very shortly here and if you remember from before I mentioned that we're going to not only check that the user is signed in but we're also going to check if they have a username however typescript is not happy right now because we have not actually added the username property to our next auth session and we're going to do that shortly after we create this auth component and this is getting into that whole idea that I was talking about before where we can take this base user object offered by the next op session which has the email image and name and we can add our own custom properties to it which in our case is going to be username but you can really add anything you want to you can expand this infinitely which is super cool and I'm going to show you how to do that in a second here but for now I'm just going to leave this as user alright so once you save this it is going to get very angry at you because we have not defined these components here so that is what we are are going to do now so inside of our file directory here inside of our source folder I'm going to create a new folder called components and inside of here I'm going to create two new folders the first one is going to be chat and the second one is going to be auth whoops not if auth and just to give you an idea of what our folder structure is going to be for the chat because it might provide some clarity as for the entire structure of our application I'm just going to create two new folders inside of chat right now which is going to be conversations and the other one is going to be right because a chat is essentially just a list of conversations and then your feed for that specific conversation uh so all of our child components of these things are going to go into their respective folder they're going to be empty for right now but I want to create them in the meantime just to provide some context of where we are going okay so at the top level of the chat folder I'm going to create a file called index.tsx which is going to be sort of the entry point to this parent chat component and then all of the child components will be rendered as a child of this index file okay so when I create my react components I use a vs code extension that allows me to just use a keyboard shortcut to construct the boilerplate of a react component so I don't have to type out the whole structure of it every single time and so I actually don't have this one installed right now but one of my favorite ones is called typescript react code Snippets so if you just search that up in the um extensions tab here so this is the one here created by infang 303k downloads at the time of this recording it might have more depending on when you watch this um but there's there's a few very similar react extensions in vs code but this this is my favorite one here and if you scroll down a bit here it gives you a list of all of these trigger hotkeys that can build you different types of components depending on what you're looking for there's a pretty pretty giant list here so I'm just going to install this and it's going to make our lives just just a bit easier here okay so we can access off here once we install it and the command I'm going to use is going to be TS rsfc which is a react stateless functional component okay so I'm just going to close the directory here and we're going to change the structure a tiny bit we actually don't even need this react import so we're going to be getting rid of these every time we use this but this is super nice it gives us an interface it gives us the arrow function component as well as the default export which is exactly the way I like to declare my components so I'm just going to change the function component to react dot FC and I'm going to change all occurrences of app to be chat and for those of you that are wondering to change multiple occurrences of the same piece of text I can highlight one instance of it and then I can do command D and then command D again and again and it will just select the next instance of that piece of text and I can change them all to whatever I want super handy keyboard shortcut in vs code so yeah feel free to use that whenever you desire so I'm going to save this and for now I'm just going to return a div that says chat in all caps and then back here I am just going to import this okay so now that we have created the chat component let's create our auth component so inside of our alt folder I'm going to create our auth.tsx file and actually I'm going to rename this index file inside of chat to be chat dot PSX now typically in react projects it is very common to name the top level component of our particular directory index.tsx you would have multiple index files throughout the entire application so like I had before index.tsx sort of represented the entry point to this whole chat directory I could also name auth.tsx index.tsx however for the purpose of this build just to avoid confusion in case you're looking at my tabs here I want to avoid having like multiple index files up here and so I'm just going to give them a little bit more meaningful names for your convenience so hopefully that is helpful again in our auth component we're going to use our extension TS RS FC and I'm going to change all of the instances of app to be off perfect we can save this and I'm just going to return a div that says auth and save that and close the directory here and we can also get rid of our react import I have a feeling I'm going to forget to get to get rid of the react import a decent amount and then back in our index page here we can import this from that file here save just like that and we can actually remove these Imports here okay so another really handy shortcut that I do to clean up my imports in vs code is if you do command shift p and you search for organize Imports it's at the top here for me because I use it a lot if you type that in and just highlight it press enter it will just automatically get rid of unused Imports and that's super convenient so you don't have to go manually remove all the unused stuff and actually one thing I'm going to do is go into our chat component here and just add a temporary log out button so that we can log out if we are signed in so we can test out this this logic in the index page here this button is going to be moved elsewhere once we actually build out more of our components but for now I'll just put it in this chat component so we're going to import a button from Chakra UI react and I'm just going to make it say log out and all we're going to do on this button is added on click that's going to call that sign out function from next auth so make sure that imports from next solid react save this and I think I'm zoomed in a bunch here on my browser I'm just going to zoom out to 100 so we can actually see the real size of this thing so it's not super inflated uh perhaps I'll make it a bit bigger and I'm just going to click log out and you can see that since we are no longer signed in we are shown this auth component which is exactly what we want so now we can actually build out our login with Google button and then the whole username creation flow so now what we're going to do is add our custom username property to our user object on the next auth session so you'll notice that if I put a dot here typescript it will autocomplete email image and username because it knows that the type of data is a next auth session because that is what the use session hook returns and just for clarity I'm going to come to the top here and and from next auth I'm going to import the type session so what we're going to do is look at the actual structure of this type from the next auth module so if you do command click on this thing it will actually bring you in to the type declaration file you can actually inspect the types written by the creators of next auth which is super helpful a lot of the time so we can see here that this session interface extends the default session object provided by next auth so the extends keyword in typescript essentially allows us to build interfaces that build on top of existing interfaces so the session interface in this case is going to include all of the properties that default session has plus whatever we want to add to it ourselves when you're extending an interface whatever is put inside of these parentheses here would be added to the session interface so if I were to add say username and then string the session interface would have the property username plus all of the properties of the interface that we are extending which in this case is the default session so by default as we saw out of the box this is what the session looks like there's currently no Fields being added however it is built such that it extends the default session meaning that we can add properties to it so if I take a deeper dive and I command click on default session here hopefully this looks familiar to you because if you remember the data that was being logged from our you session hook it's not logging now because we're signed out but if you remember it had a user object with those three properties as well as the expires value which was just a date so I'm just going to put this over here for a second this is a very small workspace but just so we can see okay so to make this more clear I actually want to log in so we can see the fields here because I feel like it's you might not remember what it looks like but I'm going to go into this odd component here and just for a brief second add a another temporary button that says sign in and this is going to take an on click that is going to call our sign in function that is going to take in the Google string as a parameter and we're just going to import this from next auth react again I apologize for this very small workspace um this is only going to be temporary as I illustrate this structure of the type here so if I click on the sign in button and I sign in I just want to show you the structure of the type that is returned from you session awesome okay so you can see here that the session is logging and if we inspect this a little bit you can see that we have a user with properties name email and image which matches exactly this user name email image as well as this expires date string so again this is the default session that we are seeing and that is why typescript is mad when I try to access username on this object because it simply does not exist on this type all we need to do to satisfy typescript here is simply add the username property to our default session user object here however we are not going to modify the source code of the next auth Library we are going to create our own type declaration file that is going to extend upon the next auth Library so I'm going to show you how you can create a custom type declaration file that can take an interface from any library and build on top of it so that it can have any custom property that you desire so I'm going to do is just close this off here so the way to create a custom type declaration file is we can come into our source folder here and create a new folder called lib short for library and inside of here I'm going to create a file called Next auth dot d dot TS and the extension.d.ts means that it is a type declaration file and the next Dash auth prefix matches the name of the library that we are going to be modifying so the typescript compiler is going to recognize the matching Library names here so all of the types that we create inside of our next DOT type declaration file are going to be interpreted as actual types from the next auth Library itself so it sort of allows us to override and customize types directly from the next auth Library which is really cool I'm going to be super useful in our case of adding a custom username property to our session user object okay and this is sort of an advanced abstract typescript concept here so if it doesn't make a lot of sense don't worry just sort of try to follow along and hopefully it becomes more clear as we proceed but essentially this is going to be a very small file where we're basically just taking the default session type and adding a username to it that's essentially all it is going to be so at the very top here we are going to import next auth then underneath we are going to write declare module next auth and open up a set of curly brackets so by using the declare module keywords here we are able to add custom types and interfaces to the next auth library and modify types and interfaces that exist within the next auth Library okay so what we're going to do is create our custom user interface so this user interface that we created here is going to be sort of merged with the default user object from next auth we saw that the default one has email image and name and the properties that we want to add as custom ones are going to be an ID as well as a username so then above here we can make modifications to the session interface and we want to make the user of our session of type user which is this custom user not the default one so an important thing to note here is that the interfaces that we are creating in here so session and user are going to be combined with the existing session and user interfaces from the actual next auth library and that is the reason why we don't have to explicitly declare the expires keyword on our session and we don't have to explicitly declare the email or image or username on our user it's because they're going to be blended with the existing one so there's no need to Define them here so now if I go back to our index page here and just close this you'll see that typescript is actually no longer angry that we are trying to access the username on our user and now if I try to access properties on my user I can see the ID and the username are there and if I go back and I add another thing like LOL and it's at the type number and I come back here and I try to access Dot law you can see that it's there typescript knows that it is there because we declared it on our user interface here in our next auth module okay so again this is more of an advanced typescript topic and it's not critical that you know how to do these things if you're at the beginning of your typescript journey so if it doesn't make a lot of sense uh try not to worry too much just sort of accept it for now and hopefully it will become more clear over time but I did want to show you how to add custom properties to your user object in the next auth session because it was something I was wondering how to do for a long time and I finally figured it out so I wanted to share with you how to do it as well because I think it's super cool and I think it's a lot of fun to be able to extend the user Beyond just the email image and name that comes from the Google oauth provider so now that we have solved our custom username property from a typescript perspective we actually need to allow users to submit custom usernames that we are going to store in the database so that they actually exist on our user object although typescript is status fine and is expecting them to have username they actually do not because we have not let users actually create them yet and the auth component here is going to be responsible for having an input that takes in the user's custom username so let's go ahead and continue building this out and I'm just going to close this type declaration file here because we're not going to need it anymore okay so let's start off with the component interface and declare the props that this component is going to take in so our auth component is going to take in two props and the first one is going to be our session and this is going to be of type session from next auth and this can also be type null because if the user is signed out the session is going to be null and the second prop that this component is going to take in is going to be a callback function called reload session and we're going to revisit what this actually does in a few minutes here basically what this is going to do is refetch the session end user from the database after the user successfully creates a username so that we have access to the username on our client so we're going to come back to this in a little bit so for now you can just put there and ignore it and inside of our props here I'm just going to destructure the session and the reload session function here now let's come down to our HTML of this component and just remove this div completely and I'm going to replace that div with a center component from Chakra UI and the center component from Chakra is essentially just a div that already has flexbox applied to it such that the content within it is centered so I believe the three properties for that would be display Flex align items would be Center and Justified content would be Center out of the box the center component has those three CSS properties applied so we do not have to create a div or a box and manually apply them ourselves which is super handy so I'm going to make the height of this component equal to 100 viewport height that is what VH stands for viewport height and we're saying that we want the height of this to be 100 of the viewport height meaning that it is the entire viewport screen that we are seeing here so if I add a border to this just for clarity one pixel solid red borders in CSS are essentially like console logs in JavaScript they're extremely helpful to see uh the structure of your CSS so that is a good tip for you to use in your homework as well and as you can see here when I apply the Border it is applied to the entire viewport of the screen and so if I adjust the viewport it just sort of automatically adjust to the 100 of the height of the viewport which is exactly what we want so inside of the center component I'm going to add a stack component from shock drop and the stack component is a div with flexbox applied to it with but with the flex Direction being vertical rather than horizontal so we're going to align items in a vertical fashion then inside of this stack here I'm going to create a ternary operator that is going to check if the session exists and if it does exist we are going to want to prompt the user to create a username so I'm going to add a text component again text is coming from Chakra it's basically just a P tag and I'm going to make this text say create uh username okay and we're going to add some more to this in a little bit here but I'm going to come to the falsiness of this ternary and if there is no session we are going to create a fragment and inside of this fragment I'm going to add another piece of text that says just the app of the name which is going to be messenger ql and to apply a size to the text component we can use the font size CSS property font size and we can set this equal to a string and you can see here that typed grip has a bunch of autocomplete strings here and we're going to use 3XL which is about three times the extra large size as it's set by chakra and so you can see it's a little bit bigger here then underneath this text I'm going to add a button that is going to say continue with Google this is going to be our login with Google button and this is the button that we're going to add that on click2 that we've seen before that is going to ask the user to authenticate with Google so we're going to use our sign in function pass in the Google provider and a very cool thing about the button component from Chakra is that it can take in a prop called Left icon and the value of this is going to be a react component that is going to appear as the left icon of this button so for example if I put a div here that says LOL you can see that the left hand side icon is going to be that HTML component but we do not want the text law we actually want to put something valuable and meaningful in here so we're going to put in a image and this is going to be our Google logo and we want to import this from Chakra which is not automatically importing for some reason so let's come up here and do that okay and by the way the keyboard shortcut command period uh pops up this little window here and usually it will give you the import for this component right now it is not I don't know sometimes it just doesn't work it's kind of weird but usually it does um I am not too sure why it's not working here okay so we're going to give the height of this image 20 pixels and the source value is going to be a Google image and the actual image that we're going to put in this Source tag you can download from the GitHub repository for this project which will be linked in the description I'm just going to copy and paste it from my demo project here so I'm just going to copy this and what you can do is in your file directory here come into the public folder and create a file called images and we can just paste that in here this is what that looks like and I'll put a direct link to this image in the description so check it out down below for a link there and you can download it and make sure you do put it in this public folder it must be in the public folder in order for next.js to use it okay so we can access off and then come back to the source take here and the path is going to be relative to this public folder because that is what nextges is configured to do so the path to this image is going to be slash images and then Google logo dot PNG you can save that and you can see it appear on the screen over here I'm just going to close the directory here okay so as you can see this is a little bit off-centered so we want to Center this text so what we can do to solve that problem is come to our stack component here and pass in the Align prop and align is short for Align items which is a flexbox property and we want to set this equal to Center and that centered the text there I'm just going to get rid of this border actually also this stack component takes in a proc called spacing and this is basically how far apart you want your items to be vertically spaced out so for example if I put eight in here you can see that they are spread out a little bit more if I put 100 they're spread even more and so you can choose the value of this accordingly I'm going to use eight and I use the stack component a lot because I am often in the situation where I want to create a vertical container of items and I want them to be spaced out evenly and are in a certain fashion so I do use the stack quite a bit so that I don't have to manually create a box and apply flexbox to it so let's come up to the username part of this component and we want to actually add the input that the user is going to type their username into so import this from Chakra and we are going to give this a placeholder that says enter a username username why is this mad oh we just need to wrap this in a fragment just like that and we want this input to be controlled by state because it is going to be stateful because the user is going to be typing into it with a changing value so we can come up here and create that state and that state is going to be called username and the set function is going to be set username and we can bring in the use statehook from react and the initial value of our username is just going to be an empty strip so we can come back down here and make the value of this username and our on change function we want to update that username so what we can do is take the event and set our username to be the event.target dot value which is going to be the text that the user has typed in and then underneath this input you're going to have a button and this button is going to say save so this is what the user is going to click to actually submit their username to the back end and save it in the database so we are going to add it on click here and this is going to call an on submit function that we're going to create and we're going to create this on submit function right now so let's come up underneath our state here and create a function on submit and this is going to be an asynchronous function that is going to actually communicate with our back end and we are therefore going to need to use a graphql mutation because if you remember from before mutations are used to create update or delete resources and in this case we are updating the user resource by adding in a new username so we're going to need to create a graphql mutation which is going to be called create username so we are going to need to create our graphql server so that we can actually make a request to our back end so for now inside of this function I'm just going to create a try catch block so basically what's going to happen inside of our try block is we're going to I'm just going to create a comment here we are going to call our create username mutation to send our username to the graph ql API and we have not yet created our graphql API so I'm just going to leave this comment here for now and inside of the catch block I am going to just log the error I'm going to say on submit error log the error here so once we actually have our graphql API set up we're going to come back to enhance the error handling here to actually show a UI error component to the user if an error occurs when they create their username but we'll come back to that in a little bit so our user is currently logged in however we are still seeing our continuous Google button which is not correct we should be seeing this and the reason is because we are actually not yet passing in our session as a prop to this component and that is why this file is read over here typescript is mad and it is saying that session and reload session are missing from the prop tier so we can pass it in by saying session and we just want to set this equal to session and what we are going to do is I'm actually going to Alias the data coming from you session to be called session okay and I'm just going to change these logs here so it's going to say here a session and I'm going to change both of these things here to be session rather than data data is kind of vague so I like the Alias session and we need to pass in a function called reload session and I'm just going to actually create that here cons reload session and it's going to make it an empty Arrow function for right now and again we're going to come back to this function in a bit I'm going to explain the purpose of it but for now let's just pass in an empty function called reload session so now typescript is happy because we are passing in the correct props and you can see that we are actually being shown this input here to create the username so I'm just going to come back to this auth component here I want to make this text a little bigger I'm going to change this to font size 3XL so it's quite a bit larger and I want to make the button a little bit wider so I'm going to add a width property here I want to set this equal to 100 percent so that it matches the width of the input so as of right now what is happening is our user is logged in we do have a session however they do not yet have a username so this is not yet true so they're not going to be shown their chat they're still in the auth component here and inside of our auth component here it is picking up that the user is signed in and there is an existing session so it's going to prompt them to create a username and then once they create a username we are going to call that reload session function and that is going to fetch the username from the database and put it on the user object here which is going to make this true meaning that we are then going to be shown the chat so hopefully that makes sense so what we're going to do now is actually create our graphql server as well as this create username mutation so we can actually send our username to the backend and store it in the database so now it is time to get our hands dirty with the graphql we're going to start looking at Apollo graphql and set up both our client and server so that we can actually start having our front end and backend communicate with each other so I'm just going to head over to Google and search for Apollo graphql and just go to the home page here apolographql.com and take a look around if you would like so Apollo is a graphql client and we are going to use it to create our graphql server on our backend and we are also going to use it in our react application so we can actually use graphql to communicate with our graphql server okay so if you go over to the main docs page of Apollo and if you go up to this docs home Navigator here you can see that the library is separated into in sections we have Apollo client which is used in front-end Frameworks which in our case is going to be react and then we have our back end which is where we're going to build our Apollo graphql server and then there are things for the cloud and other specialized topics we're not going to be really touching these uh really we just need to think about these two things our client and our server on our backend so Apollo is going to give us these two things okay so the Apollo client library is going to be used in our react application and this is going to allow us to make queries mutations and subscriptions to our backend where our Apollo server is going to be set up so there are sort of two separate things both with their own documentation and setup so we're going to start off by setting up our Apollo client in our react application so I'm going to be walking through exactly how to set up our Apollo client but I wanted to show you where the documentation is just so that you can go to it if you come across questions so the first thing that we're going to need to do is install some packages here and so we're going to need two packages which are going to be Apollo client as well as graphql itself so I'm going to copy this and again we are installing these packages in our front end because we are working with a power level client not public server right now so make sure you are in the front end directory and let's install these two packages here okay so once those packages are done installing let's come on over to our Explorer here and inside of our front end and inside of source let's create a new folder called graphql and inside of here let's create a file called Apollo Dash client dot TS this is where we're going to instantiate our Apollo client instance so basically I'm just going to be doing the steps that are outlined in this documentation here with a few subtle differences so if you have any questions feel free to visit the documentation so I'm just going to close the directory here and we are going to import a bunch of things at the top and the first of which is going to be from the Apollo client Library so the things we're going to grab are going to be Apollo client HTTP link and the in memory cache and I'm going to explain what these things are as we get to them so then down here we're going to create a variable called HTTP link and this is going to be equal to a new instance of that HTTP link import from up top here and our HTTP link is going to be our graphql endpoint that is going to allow us to send HTTP requests to our server and later when we get to real-time data with subscriptions we are going to need to create a websocket link because for real-time data we are going to need to use websockets we're going to need both an HTTP link as well as a websocket link but we are going to just start off with HTTP for now and later when we get to real-time chat we're going to come back here and add our websocket link so inside of our HTTP link we want to pass in a property called the URI so we want to make the value of this the URI of our graphql server so that our graphql client knows where to send requests to and we do not yet have an Apollo server but the value is going to be at when we create it for development is going to be http localhost and it's going to be on Port 4000 and at the endpoint graphql and this is one of the key differences between a graphql API and a rest API so with the rest API they have multiple endpoints and you make requests to specific endpoints to get specific data whereas with graphql every single request that is made to our server is sent to this one graphql endpoint and at this endpoint in our back end we are going to Define what are called resolvers and don't worry if you do not know what a resolver is it is a graphql concept that we are going to cover very heavily once we start building out our backend essentially resolvers are just functions and they are functionally quite similar to endpoints in a rest API in the sense that each request that we make to our graphql API we'll call a particular resolver function to either get or store the appropriate data depending on the type of operation whether it is a query a mutation or a subscription and again do not worry if this is not clear right now we're going to get super experienced with this as we build out the graphql API but I did want to sort of explain that this is one of the main differences between graphql and a rest API and a second parameter that we're going to pass to our HTTP link which is going to be important for authorization and cores is going to be a value called credentials and we're going to set the value of this to be include and I'm going to talk a little bit more about this in a little bit but for now we can just put that in here so now all that is left to do is we need to just create our actual Apollo client instance so we can create a variable called client and this is going to be a new Apollo client and we're going to pass in a link and the value of link is going to be our HTTP link and a second property of our Apollo client is going to be our cache configuration and our cache is going to be a new instance of an in-memory cache from Apollo client and so one of the most amazing features of Apollo is that it has built-in caching so it caches the results of all of the queries that we make so that it does not perform unnecessary requests to our API and so here we're just basically telling Apollo that for our cache we're going to use an in-memory cache which is coming from Apollo client so now to actually use Apollo in our application as usual we want to come to our app.tsex file and wrap our entire thing in a provider and that provider is going to be our Apollo provider coming from Apollo client we're going to put this at the top level here and this needs to take in a client prop and this is going to be the client instance we just created in our file over here so let's import that from graphql Apollo client save this us so as far as our front end react application is concerned we are ready to start actually querying a graphql API however we have not yet created our graphql API so that is what we are going to do now alrighty we are now ready to start building out the back end of our application and set up our Apollo server so that our client actually has a server to make requests to okay so what I want to do is close this tab here and I'm just going to navigate to the Apollo server documentation in a new tab here so that we have a reference and we are essentially just going to be following along with this get started with Apollo server page here the Apollo documentation is honestly amazing pretty much any question you may have about anything Apollo client or server do check the documentation they do have some of the best documentation that I've seen out of every library that I have worked with highly recommend you check them out okay so currently our backend folder is completely empty we have not done any thing inside of it but now we're going to start filling it up and building out our backend logic and I'm going to open up the terminal here and I'm going to open up a new tab and navigate to our backend folder so I'm going to CD back to the iMessage graphql folder and going to CD into the backend directory here and we have absolutely nothing in here so now we are going to start building this out okay so the first thing we need to do is actually initialize our back end to be a node.js project and it talks about this in the docs here we just need to run a command npm init and this is going to create a new node project inside of this backend folder and I'm just going to add the flag Dash Y which is short for yes and it's essentially just going to answer yes to all of the questions that npm init would ask you so now we have a new node project initialized we have a package.json file so we can actually start installing node packages in here which is pretty cool okay so inside of our backend folder I'm going to create a source folder in here and similar to our front end our source folder is going to contain all of the core application logic of our backend and it's going to contain more and more folders as we build out our backend but the root or entry point of our node.js application is going to be in a index.ts file and they do the exact same thing in the documentation here they create an index file and they're going to put in all of the boilerplate Apollo server code so it is inside of this index file where we are going to actually initialize our Apollo server instance to create our Apollo server we are going to be using a package called Apollo Server Express if you go to this choose which package to use section of the documentation just under get started it basically says how Apollo server has a bunch of different packages that you can use for different web Frameworks and different project requirements in our case we are going to be using Apollo Server Express and the reason we are going to be using the Apollo Server Express package is because we are going to have subscriptions in our application so if I open up a new tab here and I just search for Apollo server subscriptions and I go to this page here subscriptions in Apollo server okay so somewhere in this page I believe it's down here a bit um yeah in the enabling subscription section it is saying that subscriptions are not supported out of the box by the base Apollo server package and to enable subscriptions we must swap to the Apollo Server Express package so that is the reason why we are using Apollo Server Express I just wanted to explain why because I was sort of confused I was developing this application which of these packages to use I was like why are there so many of these but when I dove deep into subscriptions I realized that Apollo Server Express is the one that we must use so similar to our front end for now we are just going to be focusing on HT P request we are not going to be writing about websockets and subscriptions right now we are going to come back to this in a bit when we actually get to the real-time features of our application I don't want to throw too much at you right now so that is why for now we're just going to start off by creating a base HTTP server using Apollo Server Express and our index.ts file is going to look pretty much exactly the same as this and when we go back to modify our server to enable subscriptions we're going to add a few things to this file from the enabling subscription section of this documentation here but again we will worry about that when that time comes so what I'm going to do is just copy this code here from your index file and paste it into ours and save this okay so I'm just going to close the directory here and it is getting extremely angry at us because we have not installed any of these packages yet our package.json file has absolutely no dependencies inside of it so we do need to go ahead and install all these packages in the documentation here there is an npm command that we can run that contains all of the packages that we're going to need so let's go ahead and copy this and come over to our terminal and again make sure you're in the back end because we are now installing packages for our back end we want to paste this in here so to create an instance of our Apollo server we are going to need the packages Apollo Server Express Apollo server core Express itself and graphql itself so we can install these and as I mentioned before when we go and enable subscriptions in our server we are going to need to install a few more packages to allow for that but we will worry about that later so now if you look at our package.json file you can see that those dependencies are showing up and if you go back to index.ts we are actually able to import things from those libraries all right so we are going to make some minor modifications to this file here but functionally it is going to be the exact same as this so the first change I'm going to make is I'm going to rename this function to be called main then at the very bottom here we are going to immediately invoke that main function so that it runs as soon as we start our server and I'm going to add a catch block and we are going to log any error that might occur inside of our server so we are essentially just wrapping our entire main script here in a catch block so that errors are caught and we can clearly see if any errors happen Okay so down here we are getting a compiler error because the main function is expecting two arguments typedefs and resolvers okay so both of these things are two very important graphql Concepts we just a few minutes ago talked about resolvers and their role in a graphql application but we're going to dive more deeply into them right now so when you are creating a graphql API the most important thing that you're going to need is a schema and if you just do a quick Google search for what is a graphql schema it will kind of explain more in depth what it is and the importance of it but basically a graphql schema is essentially just the structure of our graphql API inside of our schema we are going to Define all of the data types that our graphql API can send and receive to and from our client and also inside of our schema we are going to need to define the structure of all of our queries and mutation and subscription functions that are graphql API is able to do so long story short inside of our schema we are going to define the structure of all of our types both entity types like a user or a mess message or a conversation as well as operation types like queries mutations and subscriptions so the main purpose of a graphql schema is to ensure that our graphql API is type safe it is very similar to typescript in the sense that it ensures that all of the requests that we make to our API and all of the entities that are being sent to and returned from our API all match the appropriate structure so that our API is type safe and this is one of the main benefits of graphql is having these type save apis so using graphql in combination with typescript makes your entire code base pretty much bulletproof from a type safety perspective which is really really cool and comforting as a developer now circling back to these two things typedefs and resolvers we are essentially going to construct our graphql schema using our typedefs and resolvers so as you can see here on lines 13 and 14 our typedefs and resolvers are being passed to our follow server and Apollo is going to take both of these two things and construct our graphql schema so that Apollo knows exactly the structure of our API and all of the data that is coming to and going from it as well as all the operations that it is capable of doing so this is a lot of information and graphql is definitely not an easy concept it took me a while to become comfortable with graphql so if this does not make sense to you right now do not worry too much you're going to become a lot more comfortable as we actually start writing out our type definitions and resolvers and this should all become a lot more clear as we build out more of our API but for now if all you remember is that a graphql schema represents the structure of our graphql API and that it is made up of type definitions and resolvers that is all you really need to know as of right now so now that we have had a very brief introduction to schemas typedefs and resolvers let's go ahead and actually start building these things out so I'm going to show you guys how I like to structure my graphql projects because I find that it is very easy to become very and organized very fast in graphql projects if your typedefs and resolvers are not organized very nicely so I'm going to show you a good file structure technique to keep your graphql apis very clean and easy to manage so inside of our file director here inside of source what I'm going to do is create a folder called graphql and inside of here I'm going to create two folders one for our typed apps and one for our resolvers and inside of both of these folders I'm going to create and index.ts file so we're going to have a type defs index.ts and we're going to have a resolvers index dot TS and I'm going to explain the purpose of these so the way I like to structure my files for resolvers and typedefs is to have one folder for each one which we already have an index file for both which we just created and in each of these folders We are going to create a file for each of our entity types and in each of those files we're going to put in the related typedefs or resolvers depending on which folder we are in and then in these index files we are going to combine all of those entity type depths and resolvers and then put them into our schema in our main index.ts file and if that makes absolutely no sense bear with me because it should become more clear over the next few minutes okay so for example inside of both typedefs and resolvers we are going to have a file name for each of our equities so for example we could have user.ts in typedefs and in result offers the same thing user.ts and in this user.ts file in the type desk folder we are going to put in all of our type definitions that are related to a user and inside of user.ts in resolvers we are going to put in all of our user related resolvers and the same thing is going to go for conversation so we're going to have conversation dot TS in both of these two folders and then we're going to have messages and so on and the entity gets its own dedicated file and then inside of these index.ts files we are going to combine all of them into one so you're only going to have a single typedefs array and a single resolver's object that are going to consist of all of the entity resolvers and typedefs so to explain this further let's go into user.ts here so inside of our user.ts file let's create a variable called typedefs Now to create type definitions in graphql we are going to use what is called a graphql string and we can create a graphql string by using the gql package from Apollo server core so bring that in here like this and then we can add in a pair of backticks and it's inside of these back ticks where we are going to write all of our type definitions for our user entity so an example of a type definition that is user related that we must declare in our graphql schema is the user itself so the way we can declare an entity type in a graphql string is by using the keyword type followed by the name of the entity which in this case is going to be user and then we can open up a set of curly brackets here so then inside of these curly brackets we can declare all of the fields that the user is going to have as well as the types of those fields so for example we can say that the user is going to have an ID and the type of that is going to be string and we can also say that it's going to have a username and that is also going to be a type string and for those of you wondering how to get syntax highlighting in your graphql strings like you see on my screen here there are two vs code graphql extensions that you can install to get that I will link those down in the below and please note that you do need to install both of them so one important thing to note here is that although this looks very very similar to typescript this is not typescript that we are writing this is the graphql query language that we are writing you will notice that graphql types have a capital letter rather than a lowercase letter like it does in typescript and graphql pretty much has all of the same primitive types as typescript for example to declare Boolean we could have a field that that says whether or not this user is banned we could declare a Boolean like this with a capital b or we could have a followers field and this could be a number notice the capital letters on these types so this is how we can create an entity type in graphql so if you remember from before I mentioned that not only are we going to declare our entity types in here we are also going to declare our queries mutations and subscriptions in here as well so to declare a query in here what we can do is use the type keyword once again but this is going to be followed by the keyword query then inside of here we can put in the name of the query that we are declaring for example I can create a query called search users and very similar to a JavaScript function I can declare all of the arguments that need to be passed to this particular query so for example since we're going to be searching users by username I'm going to need a username input that we want to search users by and the type of this is going to be a string and very similar to typescript we can also specify the type that this particular query is going to return and our search users query is going to return an array of users so to declare that we can add a colon after the closing parentheses there and declare that we want to return an array of users and in our query language this is how we declare an array of a particular entity we wrap the entity type in square brackets okay so now that we have created a query let's go ahead and declare a mutation and it's going to look very similar however instead of the word query we're going to use the keyword mutation here we can open up square brackets and inside of here is going to be the exact same thing all we want to do is give a name to our mutation declare the arguments as well as the return type and just as a reminder a query is a operation where we are going to be reading data so in the case of search users we're not writing to the database at all we're not creating anything updating anything or deleting anything we are simply searching for users we're reading from the database mutations are write operations so creating something updating something or deleting something so I think that is a good time to remind you of this because the first mutation that we're going to create is going to be that create username mutation so let's write out the name here so create username and this is only going to take one argument and that argument is going to be the username that the user is trying to create so we can call that username and it's going to be up type string now as for the return type of this function we want to return an object with two Fields a success field and an error field the success field is just going to be a Boolean that indicates whether or not the creation of the username was successful or not and the error field is just going to allow us to send back custom error messages such as the username is taken try another or any other custom error message we want to send so to return an object of this structure we unfortunately cannot do something like this that we might be able to do in typescript where we say success is a Boolean and error is a string unfortunately graphql will not accept this and it will tell us that we need to define a type for the response so all we need to do is just create a new type that has this structure here and then we can declare that type as the return type for this mutation sorry that's a lot of a lot of types that I just said okay so how do we do that so what we can do is create a new type and we can call it create username response and this is essentially just going to have the exact same structure as this object over here so we can grab these two Fields paste them in here and we actually don't need this comma so it's going to look like this and then up here for a return type of this function we can now use that type create username response so in our graphql query language this is how we Define the structure of custom return types so these are pretty much all of our user related typedefs and at the bottom here what I'm going to do is just export default hypedex object on line three so now we have enough stuff going on in here where I can demonstrate the purpose of this index.ts file and I'm just going to open up the directory here for clarity to remind you that we are in the index file inside of typedefs so as a reminder this index file is going to serve as a place where we are going to combine all of our typedefs for all of our entities and then sort of package it into a single type depth array so this is how we are going to do that so at the top here we're going to be importing all of the typed apps from all of our individual entity files so our user type devs conversation type defs and message type defs for now we only have users so let's go ahead and import that user type defs from our user file there then down here we can create our Master type depths array and we're going to put inside of it our user typedefs and later this is going to look something like this we're going to have conversation type depths and message typed apps Etc all of our entity typed apps are going to go in here and we are creating a single typedex array that we are going to export out of this file export default typed apps I'm going to get rid of these because they are not existing yet and this is the type that's okay and this is the typedefs array that we're going to import in our main server file the index.ts so many so many index.ts files I hope that's that's not confusing and it is that main type that's array from the index type x file that is going to be passed to our Apollo server to create the schema and we are going to follow the exact same pattern for our resolvers so let's go ahead and do that right now so let's open up our directory here and let's go into user.ts inside of our resolvers folder so now I'm sure you can guess that it is in here we are going to create all of our user related resolvers so what I'm going to do is create an object that is called resolvers and as I mentioned before a resolver can be one of three things it can be a query resolver a mutation resolver or a subscription resolver so what we are going to do is structure this object into those three things so what do I mean by that so we're going to have a query section in here a mutation section in here as well as a subscription section in here so now inside of our query section we are going to put all of our user related query resolvers and inside of our mutation section we're going to put in all of our user related mutation resolvers bear with me as I try to explain the structure of this here so if you go back to our typed as file we saw that we created a query called search users and a mutation called create username now these are how these two things are going to be tied together inside of our user query section we are going to create a query resolver called search users and this is going to be a function that we're going to Define shortly here and inside of our mutation section here we are going to declare that create username mutation and again this is going to be a function that we're going to write out in a second and so this is what I was talking about before when I was saying how the type depths and resolvers combined represent the structure of our graphql API in our typed Sile we have a query called search users so what's going to happen is our react application is going to query our API with the search users query so when we make that request our graphql server is going to like oh okay I am receiving a request for the search user's query I need to resolve that request so in order to do that I am going to call the resolver with the same name that is defined inside of our type definitions the request comes in for search users then the search users query function and then the search queries resolver function is going to be defined do whatever it needs to do inside of here and return the result value which in the case of search users is an array of users back to our client let's repeat all of that but with the create username example so on our client when a user types something into your like Shad Mary and then they click save we are going to fire off a create username mutation request to our graphql API our API is going to be like oh I am receiving a request for the create username mutation I am going to call the create username resolver to resolve that request so our create username mutation resolver resolves that request by taking that username and updating the user document in the database you have that new username and it's going to return either success or failed back to our clients so that our react application knows that it worked or that it did not work so I hope that this is starting to become more clear now as to how typedefs and resolvers are the structure of our API which is the schema so as I mentioned before we are going to come back here and actually modify these functions to do the appropriate thing because now they do absolutely nothing they are just empty callback functions but I want to successfully create our graphql schema and then we'll come back here and update those so at the bottom here we are going to export our resolvers very similar to what we did with our typedefs and then inside of our index file of our resolvers folder we are going to import those so we can say import user resolvers from and then they are in the siblinguser.ts file then what we're going to do is create that Master resolvers object and put in all of the resolvers for all of our entities so we're going to put in our user resolvers and just like typedefs we are going to later have our conversation resolvers and our message resolvers Etc yeah I'm going to delete these because they don't exist but hopefully that makes sense um so we're going to have one major resolvers object that combines all of them then underneath here we're going to say export default resolvers and actually to successfully create this master resolvers object we are going to need to use a function from low Dash called merge and essentially what that's going to do is just successfully merge all our resolver objects into a single object and the reason we are going to be doing that is because all of our resolver objects are going to have repeated Keys query mutation and subscription and we want to ensure they are all merged properly and the way to do that is by using this merge function from low dash for those of you that don't know what lodash is it's essentially just a JavaScript utility library that has a bunch of really useful functions common operations that you would want to do in JavaScript like merging arrays and compare deeply comparing objects and stuff like that okay so we are only going to be using the merge function from lodash so we don't really have to install the entire Library if you just search up for npm low Dash merge and you can go to this page here it's kind of cool how you can install just single functions from certain libraries so if you run this command npm install low Dash merge and let's come over to our terminal make sure we are in our back end directory here and run that command okay then inside of this index resolvers file we can import merge from low Dash merge just like this and I think typescript is getting mad at us here because it cannot find the types for low Dash merge so yeah we also need to install the type so we need to run this command here so copy this come over to our backend terminal and run that Perfect Chaos come back to our file here and this should go away which it does so to use this merge function what we're going to do is just remove this object completely and we're going to see that resolvers is going to be equal to merge so the first argument that our merge function is going to take is just going to be an empty object and this empty object represents sort of the destination object where all of the objects that we are going to be merging are going to end up so we're starting off with an empty object and then all of the other arguments are going to be our entity resolver objects user resolvers and like before our conversation resolvers blah blah blah all of our resolvers are just going to be the following arguments and those are going to be merged and written into this object here and that is what the resulting resolvers object is going to be and that is what we're going to be exporting okay so once we save this we now have our actual resolvers object and we have our actual type depths array um which is in index.typedeps and so we can come back to our index.ts file I'm just going to close the directory here and we can actually import those two things because they actually exist so let's import that Master typed apps array so we can say import typed apps from graphql slash typedefs and we do not need to explicitly indicate index because it is going to just automatically look in the index file and the same thing goes for our resolvers we could say import resolvers from graphql slash resolvers and actually I'm just going to remove these two arguments here we don't really need them because we're just importing them up top and those two things are going to be passed to create our schema and another minor modification that we're going to make to this script here is that we are going to create our schema outside here as a separate variable because it's going to need to be used in two places both in our Apollo server as well as our websocket server which we're going to be creating later when we get into the real-time functionality of our app and since our schema is going to be needed in two places we are going to declare it as a variable out here and pass it to our Apollo server and websocket server separately so the way we are going to create our schema outside of here is by using a function called make executable schema and this is going to be coming from a library called graphql tools so if we just search that up npm graphql tools I'm going to go to the graphql tools slash schema here this is the package we are going to need to install to create our schema and you can see that it has 5.1 million weekly downloads so it's a very popular library and I say that to illustrate that what we are doing is not uncommon and it's actually exactly what Apollo does in the subscription section of their documentation so what we can do is grab this command here come over to our terminal and install this then we can come up here and import that function that I'm talking about so we can say import from graphql tools slash schema and the function we want is make executable schema then we can say that our schema is equal to make executable schema and all we need to create our schema are our typedefs and resolvers because as I mentioned before those two things in combination create our graphql schema so we can pass in our typedefs and our resolvers say that we now have a valid graphql schema then down here in our Apollo server rather than passing in the typedefs and resolvers we can just pass in our schema just like this okay so now that we have created a valid schema let's actually try to start up our Apollo server and see if we can get it running before we do that we're going to install a package called nodemon and actually create a start script so that we can run a script to actually start our server so for those of you that do not know what node mod is it's essentially just a tool that is used in the development of node applications that watches any changes that you make and then it just automatically restarts the server whenever you make a change so you don't have to restart your server every single time you make a change so it's super convenient so we're just going to quickly install a node mod and it's going to be a development dependency because we only need it in development to the command we want to use is npm install and then dash dash save Dash Dev short for development and then node mod so once that is done let's come over to the package.json file in our back end here and create an actual script that we can run to actually start up our server so inside of this scripts section here we are going to remove this test script and we are going to create our own custom development script which we're going to call Dev and the way to run any script inside of your script section is by running the command npm run and then the name of the script so in this case npm run Dev and that might sound familiar to you from the nexjs application because when you install next.js if we go look at package.json um in our front end you can see that out of the box there is a development script so just in case you did not know what ncam run Dev actually does when you type npm run Dev into your command line in an xjs application this is actually what it's running for those of you that do not know so in our back end we are essentially going to be doing the same thing but in our case we want to run our index source file because that is what is going to start up our server and for those of you that are using yarn as your package manager and not npm the command you would use to start up a script would be yarn Dev so it'd be yarn and then the name of the script which in this case is going to be Dev and later we are going to need to create a production command which is going to be used in production by whatever deployment tool we use to deploy the application that is actually going to be used to actually start up our production server but for now we only need a development script okay so that is that is enough talking I hope that that provides some insight though into what these actual script commands actually are doing so as I mentioned a few moments ago when we run our development script we want to run this file here this index.ts file in our source folder we want to run this file here source index.ts and the way to use nodemon is to just throw nodemon in front of the command here so now if we come over to our back end directory here and we run npm run Dev okay okay so it failed for a reason that I'll explain in a second here but as you can see if you take a look at this up here when we ran npm run Dev it tried to execute the file index.ts which is exactly what we wanted to do okay so we got an error here saying that the TS node command is not found and the reason that is is because our source file that we're trying to run is a typescript file and out of the box no it does not have a typescript engine so we need to install TS node okay so if we just do a quick Google search for npm TS node and just go to the npm page here you can see that it has 15 million weekly downloads so it's an extremely popular Library so let's go ahead and install this so let's copy the command here and just paste it into our backend directory here and let that install Okay so if we start our development server now let's see what happens npm run Dev and it's doing more than it did last time but it's still failing what is it saying here cannot find module typescript oh okay yes we forgot got to install typescript as a development dependency as well so we're going to need to install that so let's run the command npmi-save Dash Dev [Music] it's probably important that we install typescript because we're writing our entire graphql API in typescript so we probably need it okay now let's try this again npm run Dev okay so we are getting this error that's saying subscription is defined in resolvers but not in schema and I'm actually glad we came across this error because it's important and it's happened to me so many times and when I first encountered it I it took me a while to figure out so I'm kind of glad we're encountering it together so that I can help you streamline debugging this if you ever come across it okay so let's just start off by reading the error message so subscription is defined in resolvers button opt-in schema so if we go back to our index resolvers file here index.ts we can see that our resolvers object currently only contains our user resolvers okay whoops so if I go into user resolvers and if you recall we sectioned this object into three sections query mutation and subscription okay so we have all three of these things in here and you can see that for queries and mutations so for the search users query and for the create username mutation we defined those both of those two things in our user type definitions therefore they are successfully part of our schema however for our subscriptions as the error is saying we have defined subscription in our resolvers however we have not defined any subscriptions in our typedefs therefore there are no subscriptions in our schema and that is what this error is saying oh you have subscriptions declared in your resolvers but I don't see them in typedefs therefore the schema doesn't have them and that is what this error is saying so to solve this what we can do is just simply remove the Declaration of subscriptions here and thanks to nodemon it should just automatically restart the server and as you can see here the server has successfully started up and just to show you that this works completely from scratch if I just run npm run Dev once again it will successfully run our script and our server is successfully running on the port 4000 at the endpoint graphql and the reason it's port for a thousand in case you missed that or in case I did not explain that I apologize if I did not is because the boilerplate mode that we brought in from the Apollo docs declared 4000 as the port you can set this to whatever you want you can make it four thousand at one four thousand and two four thousand and ninety nine whatever you want I'm just going to leave it as four thousand because that is the standard and as I mentioned just a few moments ago this is the endpoint that our client is going to make requests to so if we go back just as a refresher and look at our Apollo client we declared the HTTP URI as exactly that URI that we're looking at here that our server is running on so in our react application whenever we make a query or mutation it is going to be sent to this URI here which is where our server is running and that is how our client and server are going to communicate all right so now that our Apollo server is actually up and running we can start making requests to it from our client application before we do that though I'm just going to quickly get rid of this super annoying 3000 pending changes in my source control here so I have a remote repository for this project that I am hosting on GitHub so if you do not have a remote repository ignore pretty much the next minute or so okay so inside of our backend folder here I'm just going to create a EnV file and I'm also going to create a git ignore file and inside of our git ignore I'm just going to ignore all of our node modules as well as all of the EnV files so I'm going to save that and you can see that this goes right down to 11 which is much better than 3000 plus okay so I'm going to quickly commit all of this and now normally I would do much smaller commits than all of this this is a ginormous commit and I recommend you to do much smaller commits um for the sake of this project though it's okay I'm just going to commit this as one giant commit and I'm going to have a very generic commit message that says initialize back end and I can click publish perfect yeah I just wanted to get rid of that annoying 3000 thing in the source control so I can close our git ignore I can close our DOT EnV we're going to be adding some stuff in here very shortly here when we start working with our database when we actually start writing the usernames to our users but for now I'm just going to close this so typically when I'm working on projects I do not work directly on master I typically create feature branches off of Master and then when those are ready I will merge them back into Master but for this tutorial I don't want to get too sidetracked with Git and Version Control so for the duration of these videos I'm just going to continue to develop on the master Branch okay so now we're going to do is head back on over to our front end and actually start writing out the logic that is going to be needed in order for our client to start firing off requests to our brand new graphql server so I'm going to close all of these folders here so we don't get too cluttered and I'm just going to collapse the backend folder here and I am going to go back into our auth.tsx file because if you remember from a while back we created this comment saying that this is where our create username mutation was actually going to fire to our graphql API and now that we actually have an API we can do that okay so now we're going to start talking very heavily about the Apollo client side of things for the last half an hour or so or however long that whole slew of video was where we just set up our entire server we saw a lot of Apollo server and then how to actually set up our graphql schema so that our Apollo server knows what type of requests it is capable of receiving and now we're going to switch Focus to Apollo client and start looking at how we can actually send these types of requests to our API from our react application so if we go back to the Apollo docs here in this second tab here that says getting started with Apollo server if you remember the Apollo docs is sort of separated into Apollo client and then the Apollo server so we're going to go into the react section of Apollo client and thankfully Apollo client is mainly built to work specifically with react and as a result there are a ton of extremely useful react hooks that Apollo client comes with out of the box that makes it extremely easy for our react application to communicate with our Apollo server so the main hooks that we are going to be using from Apollo client are going to be to execute queries mutations and subscriptions so let's go into the query section here and I'm just going to expand this out and zoom in a little bit so we can see here so if you scroll down a little bit here it actually discusses how to execute a query and send one off to our graphql API and this is one of the react hooks that I was just mentioning and we are going to be using this hook to execute our queries so it goes through a simple example here of how to create a query string and then how they use Query hook accepts that query string and how it's actually going to fire that off to our API and get data back so we are going to see this flow a ton as we build out the logic of our app but I'm just going to quickly discuss the anatomy of a query string as well as what's going on down here just to give a nice preface to what we're going to be doing so that when we see it in our own app it's not going to be completely unfamiliar so as I just mentioned the use Query hook takes in a query string and in this case they have provided an example of a query string called get dogs and this is the structure of that up here so as you can see here we are using the same graphql query language to write our client-side queries and how hopefully this looks familiar to you this is what we were using on our back end in our type definitions so as you can see here they have created this query called get dogs and inside of it they are querying the dogs query and this name here dogs matches the name of the query that is declared in the type depths on the back end this name here doesn't really matter it's more for just Clarity for the developer it is this name that is important here because this is the name that graphql is going to use to know which query to actually send a request to on our back end so somewhere on the back end of this example there must be a declared query called dogs in the type definitions and then the dogs query would call the dogs resolver and then the doctor's Opera would probably get all of the dogs from the database and then return an array of all of the dogs and in this particular query string example they're only querying for the ID and the breed of each dog and this is another key difference between a graphql API and a rest API with a graphql API you can query for only the fields that you want which in this case is ID and breed with the rest API you can't really do that you have to get the entire dog entity back so you might be over fetching a lot of the time whereas with graphql you can ask for just what you want and that is actually one of the main selling features of graphql over rest and it comes in handy a lot and the more you use graphql the more you see this benefit come to life alright so now looking at down here we can see that this get dogs query string is passed to our use Query hook and this hook returns an object with three important values inside of it loading error and data now this is another thing I really love about Apollo is that it automatically tracks your loading and error States so you do not have to manually create your own loading and error State and update it accordingly Apollo does that out of the box for you now the most interesting thing that this hook returns is the actual data because this is the data that we are querying our our API for so what is this data going to look like well based on this example here we were querying the dogs query and we were asking for the ID and breed of each dog so basically data is going to be an object and inside of that object there is going to be a key with the query name which in this case is dogs and inside of that is going to be the data that The resolver Returned which in this case is an array of dogs so they are mapping through that array and using the values that they queried for which are the ID and breed of the dog in this component here so let's go quickly look at the mutation section here so let's look at how to actually execute a mutation and it's very very similar to what we just saw with the query so as you can see here they are creating a query string however they are creating a mutation query stream and just as a reminder a mutation is a write operation so a create update or delete so you can see here they have a mutation called add to do which actually takes an input and they are asking for a few Fields back after the add to do resolver on the back end has successfully added that to do to the database or does whatever it's intended to do and just something interesting to note here is how to actually declare input variables to our mutations because usually with mutations you are going to be passing in an input like the new entity you are creating or the ID of the entity that you are deleting or updating all right now looking at the actual use mutation hook very similar to use Query it just takes in the query string now the values that this hook returns are slightly different than the values that the use Query hook returns but with the use Query hook we were only getting back data loading and error with these mutation hook we are getting those three things and also the actual mutation function that we can call in our typescript to actually execute that mutation and then down here you can see how to actually pass in the variables to that mutation so looking back at this query string they said that this particular mutation takes in a variable called type and you can see down here that in this variables object they are passing in a variable with the name type and so that name here type must match this name here because that is how they have declared it now the other hook that we are going to be using is for subscriptions it is called the use subscriptions but we're not going to really look at that right now we're going to get into that more later let's first focus on getting comfortable with queries and mutations and once you can do that picking up subscriptions isn't too bad as it is quite similar so again this is a lot of information to take in and if this isn't super clear right now don't worry too much we are going to be working with this stuff so much over the next while but I do hope that this is a nice preface all right that is enough going through the documentation let's actually go write out some of the stuff for ourselves because that is the best way to learn hands down so the first actual operation that we're going to build into our app is going to be the create username mutation we are jumping over queries and going straight to mutations and once you are comfortable with mutations going back to queries will be a breeze because queries are a bit simpler than mutations in my opinion okay so let's go back to the code here and I'm going to show you how I like to structure my client graphql query strings so I'm going to come up here and just collapse the back end here and inside of our front end inside of the graphql folder inside of source I am going to create another folder called operations now inside of this operations folder we are going to create a file for each of our entity types and in each of these files we are going to put in the query strings that are related to that specific entity very similar to what we're doing on the back end where each entity has its own dedicated file for example inside of operations the first file we're going to create is going to be for our user entity so let's create a file called user.ts now this is where we're going to put in all of our graphql query strings for our user entity so basically all of these things for our users so at the top here I'm going to import gql from Apollo client ql okay and in each one of these files I'm going to create an object that is going to have a queries mutation and subscription section similar to our backend so I'm just going to make the default export of this file an object and inside of this object we are going to have a query section A mutations section and a subscriptions section very similar structure to our back end now as I mentioned a few moments ago the first operation that we're going to be creating is going to be our create username mutation and we can use this example from the documentation as a guide as we write out our own okay so inside of these objects here we are going to have keys that match the names of our query strings so our first one is going to be our create username and this is going to map to an actual graphql query strings we can do gql and then the back text and inside of these back texts we can create our new mutation so since we are creating a mutation query string we want to use the keyword mutation and then following that we can give a name for our mutation which is going to be create username and inside of these parentheses here we want to declare all of the inputs that this particular mutation is going to have so to declare an input we want to use the dollar sign followed by the name of the input to which in our case is going to be username and the type of this input is going to be a string and we're also going to add the bang operator here to indicate to graph URL that this is a mandatory input to this particular mutation then we can open up a set of curly brackets here and this is where we're actually going to call the create username mutation on our API so to do that we need to use the exact same name that the mutation has on our API which is camel case create username and then we want to pass in the input and we want the value of this to be the username input that we declared up here and this is how we can pass the value of that input as the actual username input to our API so now we want to indicate what fields we actually want back from the response of our create username resolver and if you remember we want the two Fields success and error and that is how we declare those two things here and one thing I actually want to mention here relating to graphql query strings in vs code are a few extensions that you can get to actually get the syntax highlighting in graphql query string language I think I actually forgot to mention this um when we were writing out our typedefs on our API I might go back and add like a voice is over because it's really convenient to have the syntax highlighting so let's quickly find out what those two extensions are let me expand this out a bit okay yeah it's these two here so the graphql syntax highlighting by the graphql foundation and then the other one is graphql language feature support which is also by the graphql foundation now I believe you need both of these to get actual proper syntax highlighting like you're seeing in my files here so just go ahead and install both of these two things here and you should be good to go so once you install those two extensions you should have some nice syntax highlighting which is much more nice to look at than just a single color and it makes it way more readable so let's go back to our auth component here and see how we're actually going to pass this particular query string to the use mutation hook and this looks slightly difficult and this okay and what we're doing here is slightly different than what they're doing in the documentation in the docs here they are just declaring a query string just right in their component I prefer to have this object here on a per entity basis I just find it helps keep the project a lot more manageable than having to declare these query strings over your components okay so I'm just going to close my directory here to give us more room and let's come over to our auth component and at the top here underneath this username State let's call our use mutation hook so I'm just going to say that an empty array is equal to use mutation import that from Apollo client and the query string that we want to pass in is going to be this particular create username one that we just typed out so we were going to access that is we're going to come up to the top here we are going to import this object from our user.ts file and then access the one of Interest which is this one here so this is how we're going to do that so we can say import user operations from and then we need to go up two levels into our graphql folder here and into operations and then into the user file and for those of you that are wondering we can make this name whatever we want because inside of our user.ts file we just have a default export it is not a named export and therefore when we import it as the default export into other files the name we give it does not matter so I'm just going to call it user operations here okay so for our create username mutation we want to access user operations dot mutations dot create username because the value of this is a valid query string because it maps to this graphql string right here which is exactly what they're doing in the docs it just has a different structure in our case now as for the values that this Hook is going to return the first value in this array is going to be the actual mutation function that we're going to use in our typescript code the second one is going to be an object with those three important variables that we talked about before which were data loading and error and you can see that it is being Auto completed thanks to typescript and this is getting exciting because you're getting super close to actually communicating with our server here so now how do we actually want to use this create username function well down here you might remember our comment create username mutation this is what we are going to call to actually execute this mutation okay so let's delete this comment because we don't really need it anymore and we want to call our create username function and pass in the value that the user has typed in to the input let's actually go back to the app here and open up the console zoom in a bit so when a user types in to this input here whatever they're typing in that is the value of username and we want to pass that to our create username mutation function so our create username function is asynchronous because it is communicating with our API so we want to use the await keyword called the function create username and now we can pass in our variables then we need to send along with this mutation so to pass in variables to a mutation function we can open up a set of curly brackets here and set the value of variables to be an object with the variables that we said we were going to pass with this function and if we go back to our query string we said we're going to pass in a variable called username so the name of the variable we pass to our function must match this name here let's go back over here and pass in our username variable and due to these two things having the same name we are able to take advantage of javascript's shorthand notation for object values here so now I want to show you how to improve the typing of your queries and mutation and subscription calls when you're using these hooks from Apollo client so as of right now the way this is currently written typescript has absolutely no idea what the structure of the data that this function is going to return and it has absolutely no idea what variables this is supposed to take in now this is where it gets a little bit confusing as for the differences in types between graphql types and typescript types I think I mentioned this when we're writing out our type definitions when we are creating our server that the graphql query language looks similar to typescript you know you declare things as strings or numbers and in typescript you do the same thing however it is important to note that they are not the same thing and just because we declare a type in graphql does not mean typescript is aware of it all typescript is is a compile time language it's just a developer tool that helps us developers make our code more robust and Bug proof it has absolutely nothing to do with graphql typing and this was something I got confused about when I first started developing with graphql because I was like why are we declaring multiple types we have graphql types and we have typescript types why is this necessary and it's a little bit confusing at first but I want to hopefully explain the differences here that typescript is simply a developer tool it doesn't even exist in production it is literally just a development thing so typescript and graphql types are not the same thing and we need to create typescript types that model our graphql types so that our typescript slash JavaScript code is type safe to match our graphql types and just a few seconds ago I was saying how typescript has absolutely no idea what variables we are supposed to take in to our create username function and you might be saying well what do you mean it doesn't know didn't we just declare a username name as an input to our create username query string which is what we did here and this is the key distinction between graphql typing and typescript typing currently the way our code is written graphql only knows about this username input typescript does not and this is what I meant when I said we have to create typescript types to match our graphql types so that our JavaScript code is typesafe as defined by our graphql typing and this might not make complete sense to you at first you might just have to sit with it and work with it a little while but just know that we are creating typescript types to model our graphql types to improve our developer experience and make our code robust typescript has no idea about the graphql structure and the graphql structure has absolutely no idea about our typescript structure so as I just mentioned graphql currently knows that we are supposed to pass in a username so let's go back to our auth component here and make typescript null as well okay so here is how we can add typing to the use mutation hook and it's going to look very similar with the other hooks as well use the Q very unused subscription okay so what we want to do is add a set of angle brackets right in here and inside of these angle brackets we are going to put two types the first type is going to be the type of the data that we are going to get back from our create username function and the second type is going to be the type of the variables object that we are passing into variables here so let's go up here underneath our auth props and we're going to create two new interfaces the first one is going to represent the data we are going to get back from our create username function so let's create an interface called create username data and this interface is going to represent the structure of the data returned by the use mutation hook so when you use any of the Apollo react hooks the data that comes back is going to be an object of the following structure it's going to have the name of the query or mutation which in this case is create username and then inside of it it's going to have the actual data that your API returns and when we were looking at our query string here we are getting back a success Boolean and an error string so we can declare that here by saying success and this is going to be a Boolean and we're going to have an error which is going to be a string so when the use mutation hook successfully completes this is the structure of the data that we are going to get back now underneath here let's create another interface for the variables that we're going to pass to our create username mutation so let's create an interface called create username variables and the only variable that we're passing to this mutation is going to be our username and this is going to be of type string now to use these two interfaces with the use mutation hook as I mentioned before we can pass both of them to these angle brackets here so the first one is going to be the create username data and the second one is going to be the create username variables I'm going to save this and now Apollo knows the exact structure of all of the inputs that we're supposed to put in so if I just delete this and I press Ctrl p period to get autocomplete typescript is now expecting a username input if I were to come up here and say some other input and make it up type Boolean and I come down here and I do a control space you can see that typescript is expecting that because we created that interface and we passed it as a generic to our use mutation hook and so this is how typescript is aware of the variables that we're supposed to pass to this mutation so we can get rid of this some other input Pane and now you can see that typescript is mad because it's like property username is missing in type object it's saying that this particular object isn't missing the username so if we add that in there now typescript is happy and furthermore now typescript knows the structure of the data we're getting back so if I were to say data and now you can see that typescript is like oh okay well I'm expecting data to have an object with a create username key and if I go into create username and if I try to access a nested field there you can see that error and success are both there because we declared them here if I remove error down here now it's gone and only success is there so this is how we can declare data and variable interfaces and pass them to our hooks as generics to make our client queries type safe so let's delete this and for every single query mutation and subscription that we write we are going to create interfaces to define the structure of the data and the variables so you're going to get a lot of practice with this so if it's unclear right now don't worry it will become more clear with time and very quickly I'm actually going to move these interfaces to a utility file because it's going to help keep our code organized so inside of our source folder in the front end I'm going to create another folder called util and then inside of here I'm going to create a file called types types DOT type script and I am going to cut these interfaces out of our auth component here and paste them into our types and we are going to put all of our front end types in this file here and we need to export these because we're going to need to import them in this auth component here so now typescript is mad because it has no idea what these are so I'm going to press command period and add all missing Imports and it's going to automatically import those from that util folder and file that we just created perfect so we're going to be adding a bunch of stuff to this file as we build out this app so I'm just going to close this for now and just close the directory here and come back to this function here okay so now that we've added these interfaces and our mutation is typesafe I think we're actually ready to call this mutation and see what happens when we query our API so let's come back to our app here and I'm just going to open up the console move it to the bottom here okay zoom in a bit here let's see what happens when we actually fire this query off so do we have this button hooked up to this function uh where is our save button here okay so yes when I click the save button it is going to call our on submit function which is actually going to fire this off and actually at the very top of this on submit function here I'm going to add a quick check to make sure that the user has actually typed in some sort of string into the input we don't want to just send an MP string so I'm going to say if there is no username meaning that the string is empty let's just return and prevent doing anything so now if I try to record this button it does not do anything because there is no username in the input right now okay and also I'm just going to add a console log and say here is the data and log these three values here data loading and error so we can see what's going on in the console if these things happen so you can see that data is undefined loading is false because we haven't sent the request and there is no error so it's just undefined okay so let's actually give this a go so I'm going to type in hello and I'm going to click save and what happened looks like some some bad stuff happened so I we got an error here the thing failed to fetch okay so that's okay all right so typically when I get these errors with graphql I really like to go to the network tab in the dev tools and see what's going on yeah so you can see this request failed and we are getting the classic cores error if you've developed an app before of any kind you've probably come across core's issues before and it is just the Classic error that all developers absolutely love to deal with luckily for us it's actually not too challenging to solve all we need to do is go back to our server and add some cores configuration to our Apollo server and we should be good to go okay so let's quickly go back to our index file in our backend here which is where our Apollo server is being created so we're back on the back end and what we want to do is add some cores configuration to our server here through this apply middleware function so if you go so if you go inside of this object here and you just type chords you can see that it is built to accept some course configuration here so we're just going to create an object called cores options pass it to our appointment aware function and that should solve this problem okay so just underneath our schema here I'm going to create that object and I'm going to call it cores options and we need to add two things to this object here we need to add an origin which is going to represent the URL that our API is expecting requests from which for development is going to be localhost 3000 in production it's going to be our production client URL which we will configure later so we are going to put our origin URL in our EnV file and I actually don't know if we have created that for our backend okay so we have EnV but we have nothing in here so I think we need to install the dot EnV package in order to be able to access environment variables in our node application so let's come to our terminal here and in our back end let's go ahead and install dot EnV so npm install dot EnV and this is essentially just going to allow us to access environment variables in our node application so we need to come up to the top here and import that package so we can say import Star as dot EnV from dot e and V and then at the very top of our main function here we can just say dot env.config and then call that function just like this and then inside of EnV so we can create a variable here called client origin and again we're going to have one of these for both development and production but we only need development right now and that is going to be our localhost 3000 so we can type that as HTTP localhost 3000 just like this and then back in our index file we want to set that to the value of this origin key in this course options object so we can say process Dot env.client origin okay I'm just going to close my directory here and another value that we want to add to this course options object here is going to be a credentials parameter and we want to set this to be true and so the reason we are adding this credentials parameter here is so we can access the next auth user session on our Express server so that we can have access to the currently signed in user so basically when our client sends requests to our server next auth is going to package up authorization cookies in the headers of those requests and we are going to use those cookies to access the next auth session and we are going to do that later on when we create our Apollo server context and if you don't know what context is don't worry we will get to it but for now we're just going to add this credentials parameter here to the course options so that our server actually allows next auth to send those authorization headers along with the requests so now down here we can set cores equal to cores options we can save that let our server recompile make sure it runs okay perfect and now if we come back here let's go to our console let's clear this out and if I click save so we are not getting an error anymore and you can see that we are actually getting data back and so we are successfully communicating with our graphql API and it's not returning anything right now because if you remember if you go back to our user resolvers this is just an empty function it is not doing anything and so the data that we are going to see in here is going to be whatever data we return from this function but if I just add a console login here pay at the API and we fire off another request let's go to our backend terminal here and I click save you can see that we're actually reaching that resolver create username resolver hey at the API and so now that we have actually successfully hit our API and seen that we have actually made it inside of this create username resolver now we need to modify this function to actually take in that username input and add it to the user document in the database and then return that object with the structure success or error to indicate whether or not the update was successful or return some sort of error if it was not so that is what we are going to do now so now an important question that we must answer is how do we actually access that username input inside of our create username resolver so to answer this question let's head over to the documentation here so I'm just going to search AC Apollo resolvers and we want to go to this page here resolvers in Apollo graphql okay and somewhere in here there is a section on arguments that are resolver except here we go resolver arguments so out of the box all of our resolver functions are going to be passed four arguments as it says here parent args context and info and it says in that order which is going to be important now the two arguments that we're going to be most interested in for this project are going to be args and context so just a few moments ago when we were dealing with those course issues I briefly alluded to our Apollo server context so we are going to talk more about context when we get to that in a few moments here but I'll briefly just give you an introduction to it right now since we're on the topic here but essentially the context is just an object that we can put whatever we want into and this object is going to be accessible in every single one of our graphql resolvers and it comes in handy when there's particular information that we want access to in all of our resolvers so as the docs say here authentication information is a typical example so in our case we are going to put our user session inside of our context so that we can access the currently signed in user in every single one of our resolvers now this args argument here is what is going to contain all of the arguments that we pass to our resolvers so in the case of create username args is going to contain our input so that is how we're actually going to access it here okay so let's actually come over to the code here and see how we're going to work with these arguments now again these are the exact order in which we are going to receive these arguments in this function so the first argument this resolver is going to receive is going to be that parent argument and as I mentioned before we're not really going to be working with this argument so I'm just going to declare it as an underscore and give it a type of any because we don't really need to do anything with it and typically a common practice when functions have arguments that you don't really need you just can declare it as an underscore here to indicate that you're not really doing anything with it the second argument is going to be this args object so we can just call it args now the type of this is going to vary across every single one of our resolvers because it depends on what arguments we're passing to this particular resolver now in the case of the create username resolver the type of this is going to be an object with a username inside of it and the type of the username is going to be a string and the next argument we're going to receive is going to be that context object so we are going to create an interface shortly called graphql context when we actually create our context but for now I'm just going to leave it as type any and we'll come back to this and update the typing of that when we create the context and we're not going to really need this info argument here so we don't really need to declare it in our arguments here so now let's actually see how we can view this username argument here so we're going to destructure it from args so we can say that const username is equal to args and I'm going to add this username variable to the console log here so that we can actually see it show up in our console so let's come back to the app here and open up our back end console here and if I click save check that out we can actually see that text appearing there if I change this to whatever random text and I click save you can see that showing up here so now we actually have access to the username that the user is trying to create so now that we actually have access to the username inside of this function here what do we need to do with it well we need to access the currently signed in user and update that user's document in our database to store this username on it now in order to do that we need two more important things inside of this resolver here we need to know what user is currently signed in and as I mentioned before we can do that using the next auth session and we also need a way to communicate with our database now if you remember from way back when we were setting up our authentication with next auth we were communicating with our database through Prisma and we are going to be doing the exact same thing on the back end we are going to be creating another instance of our Prisma client and configuring it to communicate with the same database that next auth is communicating with which is our database and that way we're going to be able to communicate with our database from our backend okay so I was going to wait until after we wrote out this create username function to create our graphql context but I realized that in order to actually create the username we're going to need access to the currently signed in user which is going to come from the session object that we're going to store in our graphql context so we're actually going to go ahead right now and create our context okay so let's come back to our index.ts file and we are going to go down here and I'm going to show you how we can do that this Apollo server instance is configured to take in a value for context so if we just type the letter c you'll see that it is allowing us to define a context inside of our Apollo server now the value for our context is going to be a callback function that is going to be called when our client first communicates with our server and it's going to be in asynchronous callback so we can declare that like this and through this callback function that our client is going to send important information to our server so we can accept that information as arguments and it's going to be an object and that object is going to contain a request object as well as a response object and this request object is what we're interested in because it is going to contain those authorization headers that next auth is going to send to our server and we are going to use those headers to get access to the currently signed in user using a function called get session that we're going to get from the next auth library and if you remember from a few moments ago when we were doing cores that is the reason why we set this credentials to be true to allow our server to accept those authorization headers so inside of this callback function here whatever it is that we return from here is going to be the value of our graphql context that is going to be accessible inside of our resolvers so right now if I just return an object with say name and value is Shady that is what the value of context is going to be over here so for example if I add a log here and I just here is context and I logged out the context and we open up our server terminal here and I just send off a request you can see that here is the contacts which is being logged inside of this resolver has that name Shady in it because that is the value we returned from our context callback function here okay so this is not very useful information so we are going to put information inside of this object that we are going to need access to across all of our resolvers one of those things is going to be our user session another one of those things is going to be our Prisma client so that we can actually communicate with our database and the third thing is going to be a thing called Pub sub which is not super important right now it more has to do with subscription so we're going to come back to that but essentially this object is going to have three things session Prisma and Pub sub so for now I'm just going to put session in here and now we actually need to somehow get a value for the session and as I mentioned before we're going to use a function from an X auth so we are going to need to install that library in our backend repository so let's run npm install next Dash auth so now inside of here we can actually instantiate our session and this is going to come from an asynchronous function called get session and for some reason it doesn't want to Auto Import okay so we can come up to the top here and we want to import this function from our next hot package but specifically from the react folder so next slash react and this function is going to be get session perfect now this get session function is going to take in an object and inside of that object we are going to pass in our request object that is coming from our client and it's this request object that is going to contain those authorization headers that next auth is going to be sending to our server from our client and the get session function is going to use that information and return to us the current users session so let's go ahead and log this out and see what this looks like so we'll say contact session and when I save this if I come back to our app here and let's open up the logs if I run that request you can see that here is context and you can see that we have access to the current user session and this is the same exact session object that we are able to access on our client so now we have access to the currently signed in user on our server and this is really useful because if we want to secure our API routes and only let sign in users or certain types of users have access to particular resolver functions we can do that using this information because we know if a user is signed in and who that user is and so now our graphql context which we have access to in our resolvers is going to contain that information this session information here which is really really useful so we want to specify the type that this function is going to return and this is where we're going to create the interface for our graphql context so this is an asynchronous function so it's going to return a promise and that promise is going to contain an object that is is of type graphql context that we have not yet defined so where are we going to Define this inside of our source folder in our backend we are going to create another folder called util similar to our front end and inside of our util folder we are going to create a file called types dot TS and this is where we are going to put all of our backend types and while we're here we might as well create another util file that we're going to use and this is going to be called functions.ts and this is where we're just going to put a few utility helper functions and we're going to come back to this very shortly so for now I'm just going to close this off now inside of this types file I'm going to create the interface for our graphql context so we can say export interface graphql context so as I mentioned before this graphql context is going to contain three important things the first one is going to be our actual user session which is going to be of type session which is going to come from next auth and we're going to need to modify this type in a second here but we'll come back to that the second one is going to be our Prisma client and we haven't installed Prisma yet here so I'm just going to comment this out and the third one is going to be our Pub sub module which we also haven't dealt with so I'm just going to comment this out but this is going to be the entirety of our graphql context and we'll come back here to update these types when we get to those parts so I'm just going to save this and now we're going to make some minor modifications to our session object to include our username now if you remember we did the exact same thing on our client when we declared this next auth module here we're going to do the exact same thing and unfortunately since our front-end and back end are being developed as two separate applications that are being deployed separately we need to sort of repeat some typing across our front end and back end and this is a common typescript dilemma that developers face in the industry where they sometimes have to create duplicate types for their front-end and back-end but currently that's just sort of the way it is especially with graphql so we are literally going to do the exact same thing as we did on our client inside of our source folder we can create a lib folder and inside of here we can create that next auth module declaration file so next auth dot d dot TS and I'm going to come down here and literally copy this from our front-end file close it off and paste it in here just like that okay so I'm just going to close my directory here and so now inside of this session object we are going to have a user that is going to have a username on it which is exactly what we want and we can really add whatever we want to this thing I think the default session actually has an image on it as well so yeah perhaps we should add that as well we're not going to really use that on our back end but I guess to be correct from a type of perspective we might as well add it so we are done with this Nexus module declaration thing so we can just close that off and so now we can actually use this graphql context interface in our index.ts file here so let's come down here and I'm going to press command period and Auto Import that from the util types file now here this is saying uh type session or null is not assignable to type session now this is happening because the get session function doesn't always return a valid session if there's no currently signed in user it is going to return null so this is complaining because on our graphql context we have declared this as always being a session when it could be null if there is no signed in user so the way to fix that is we can just say or null using the pipe operator here so now if I come back here typescript is happy once again all right so now that we have the session successfully working I'm just going to remove this console log we are now going to install and set up Prisma now we saw a little bit of Prisma when we were setting up next auth because we were using the Prisma adapter but as we're setting it up on our back end here I'm going to do more of a formal I guess setup of Prisma so that you get a clear understanding of how have to do it from scratch because Prisma is a library that was created to communicate with our database so it's more of a back end package it's not really a front-end package the only reason we're using it on the front end was because it was a requirement of next auth but you can totally use Prisma without also using next auth so I want to show you the steps to set it up from scratch in a node application which is what our graphql API is so what we're going to do is come over to Google here and I'm just going to search up literally Prisma and I'm just going to go to the Prisma homepage prisma.io and we can go to Quick Start can I zoom in a bit here because it's a bit small so there are two guides here in the quick start documentation there is starting with Prisma from scratch as well as adding Prisma to an existing project so we are going to click on start with Prisma from scratch now in here it's asking you if you're using a relational database or mongodb now in our case we are using so let's click on that so we can scroll down here to the project setup section so the first thing we're going to need to do is actually install Prisma which probably makes sense so let's come over to our back end here and run the command npm install Prisma and this is going to be a development dependency so we can add the flag dash dash save Dash Dev and we already have all of these other packages that it's asking us to install here so that is why we just went ahead with Prisma alright so the next thing that is going to be of interest to us is going to be the section connect your database and this might look familiar to you because we have the exact same thing on our client so because our front end and back end are going to be deployed separately we are going to need to create another Prisma client on our back end and on our front end we created a Prisma client because it was part of the next auth configuration because the next dot needs it for the Prisma adapter and it was connecting to our database to store users and sessions in there but on the back end we're going to need to also create a prism client so that we can interact with our database from our backend application so it's going to be a little bit weird because we are going to need two Prisma schemas one in our front end and one in our back end and there is going to be some duplication between the two but our front end schema if we go back to look at that currently only contains models related to authentication so we have the session the user the verification token and the account Etc and on our back end we are also going to have these things so there is going to be some duplication but it is on our back end where we're going to add the additional models that our application needs like conversations messages Etc so our front end schema is going to remain exactly as it is we're not going to add anything else to it it only needs to contain entities for next auth to perform authorization which are the current models that are already defined our back end schema is going to be more representative of our actual database schema of our messaging application and I really was trying to find a way to only have a single schema schema but because we are deploying our front end and back end as two separate apps I couldn't really find a way around having two schemas but it's not terrible because as I mentioned the front end schema is more for just authorization and our backend schema is going to be more for our core application logic okay so let's come to our file directory here and inside of backend and inside of source we are going to create a folder called Prisma and inside of here we are going to create our backend schema and that file is going to be called schema dot Prisma and then so what we can do is copy absolutely everything inside of our front-end schema and paste it in our backend schema okay and then as I mentioned before it's going to be underneath here where we're going to add those additional models like messages and conversations and a few others and then we're going to modify these a little bit to start introducing some relationships between all of our models and we're going to need to create an environment variable for our mongodb URI and it's going to be the exact same one as our front end mongodb URI because they are communicating with the same database okay and again the reason we also need to create the Prisma instance on our back end is because the front end and back end are separately deployed and in production they would have absolutely no idea about each other so that is why we have both here so inside of our backend.env file let's go ahead and create that environment variable so it's going to be called mongodb underscore URI okay and we can go to our DOT env.localfile from our client and grab this value because it's going to be the exact same it's going to close this paste it in here and save that okay so I'm just going to close my directory here and let's go back to our backend schema Prisma and so now we will actually be able to communicate with our database using Prisma on our backend our client generator is going to be pretty much the exact same as well however we do need to add one more binary Target to this array here and this just has to do with apple M1 chips I was running into some issues trying to run the demo application a few days ago and it was complaining about something to do with my operating system and it was telling me to add this new Darwin arm64 to our to the binary targets array and that seemed to fix it so value pad is going to be Darwin Dash arm 64. now again this is explicitly for Mac M1 users I don't know if you will have this issue if you are using Windows or Linux I am not too sure I honestly do not know too much about what this is doing so I unfortunately don't know why these are necessary or what they're doing but the error message just told me to add this in here and that seemed to fix it so now we actually have a valid Prisma schema on our back end all right so let's keep moving through the docs here uh we don't really need to do any of this mongodb configuration with the URI because we've already done that so let's keep going through creating the Prisma schema and we have already done this as well we have pasted in the currently existing models that we need and later we're going to be adding more models so we don't really need to stop here let's go to the next section which is installing the Prisma client so this package we are going to need to install so let's copy this command come over to our back end and install that okay so that was easy let's go to the next section here querying the database so this section here shows you how to actually instantiate the Prisma client and use it to query your database so it is through this object here that we're going to be able to query our models in our database and this is the Prisma object that we're going to be adding to our graphql context so I'm going to close these schema.prismafiles for now I'm going to close the dot EnV so let's come back to our index.ts file and our backend and this is where we're going to create that Prisma client and add it to our context so just underneath our cores options here we are going to create our new Prisma client I'm going to say cons Prisma is equal to new Prisma client and I don't know why this doesn't want to Auto Import that's so interesting um let's come up to the top here and import that so import from at Prisma client so I don't know if I'm the only one that experiences this but Auto Import just sometimes doesn't want to work I don't really understand why it's kind of weird okay and so the thing we want from our Prisma client package is the Prisma client itself lots of Prisma clients going on here so Prisma client okay awesome so now come back down here this is all happy and I'm going to add a comment here that is going to say context diameters parameters and later on we are going to create our Pub sub instance but that's not important right now just ignore that I'm just going to add it in there so we can come back to it later and so now we can add our new Prisma client to our context object here so let's go back to our graphql context interface here in our types file and actually update this to include our new Prisma client so the type of our Prisma object is going to be up type Prisma client so we can again import that from the Prisma client package and for some reason in here it auto imported in the other file it did not I have no idea what's going on I can I can't explain that so let's save this and let's come back here and now typescript is mad because we are not passing Prisma to our context so next to our session here let's go ahead and pass in Prisma now typescript is happy and now our Prisma client is part of our server context and we will have access to it in every single one of our resolvers and that is how we're going to actually communicate with our database in our resolvers so that's pretty pretty cool and so now we can actually update the type of this from any to be that graphql context interface that we created in util types so import that make sure that Imports up top here and now that we have updated our contacts to be of type graphql context we can successfully destructure our user session as well as our Prisma client from our contacts and typescript is going to know that they are on there so if I say const empty object is equal to context and I come in here and I do control spacebar you can see that typescript knows that the session exists on this thing as well as the Prisma client and so now we have absolutely everything we need in order to actually update our user document in the database because we have the username that the user has submitted from the react app over here and we have the user session so we know which user to update and we have the Prisma client so we can actually communicate with our database and update the user to have this new username so before we start writing out the actual logic of our create username resolver from function let's specify the return type of this function and we also want to make this function asynchronous because it is going to be communicating with our database which is going to be an asynchronous operation and as for the return type of this function we can specify that here it is going to return a promise because it is an asynchronous function and the type of the data that is going to be inside of the returned promise if you remember is going to be an object with the success Boolean as well as the error string because if you remember I mentioned that we want to create typescript types to model our graphql schema and if we look at our user typedefs we said that the create username mutation is going to have a response of structure create username response and in our graphql schema we Define that as this as an object with a success Boolean and an error string and we also defined a typescript type of this structure as well on our front end when we were using the use mutation hook but we also need to Define one on our back end so that we can specify the return type of this create username resolver so what we can do is go in to our types file here and create that interface so this file is going to contain all of our backend types so I'm going to create comments for each entity so that it stays organized so we're going to put all of our user related interfaces here and then when we create other ones related to messages and conversations we will add those down there as well in their own little section so we are creating an interface that is going to represent the data being returned by the create username function so we can say export interface create username response and we just saw that this is going to have a success Boolean as well as an error string now when our create username resolver returns an object of this type only one of these things is going to be present because if the request was successful that means an error did not occur and therefore an error is not going to be present and if an error does occur we are going to return that error to our client and the success field will not be present so only one of these is going to be present so I'm going to make these optional to make it so they don't always have to be both present so let's go back to our resolver here and import that interface create username response now typescript is complaining typescript is saying well you're saying you're returning this but you're not currently returning anything so what the heck and so now we are ready to write out the logic of our function and actually return an object of this type okay so I'm just going to get rid of these console logs here now the first thing we're going to check is that the user is signed in and that there is a valid session present because we want to make this mutation secure so we can say if there is no session dot user we want to return an object and this would be the case where we are returning an error so we can add the error field and the error in this case is going to be not authorized so we are protecting this mutation against unauthenticated users so if the user is signed in and we successfully make it past that check we want to grab the ID off of the currently signed in users session so you can grab the ID um okay for some reason [Music] email image and name why isn't ID present here hmm what is happening because on the graphql contacts we said that this session is coming from next auth which we declared in our type declaration file but for some reason that is not working why is that so I'm not totally sure why our type declaration for next slot is not working with the user session here so what we're going to do instead is actually just manually declare the session and user types so we can do is come over to our types.ts file and we are going to define those in the user section here so we are going to manually declare our session interface we can say export interface session and this is going to have a user on it and we also need to create the type for that user and we're going to make it have the same structure as we intended it to have in our type declaration file here I'm just I'm not too sure why this isn't working but it's not super critical so we can just keep moving forward because we can just manually Define them so I'm going to copy that bring that over here and going to export this okay and we can see that the type of the user on our session is going to be of type user so we're basically doing the exact same thing as we were with the type declaration but we're just sort of doing it manually on our own and the session for next thought also has that expires date on it so we can add that and I believe the type of that is ISO date string which is coming from next auth and then we don't really need this session from next auth directly anymore because we have created our own here so I don't even think we need this type declaration file here so we can just go ahead and delete that I'm not too sure what's going on there but oh well okay then down here we now should be able to see that ID on the session user type so let's grab that ID and close the directory here and we can keep on moving so now we can actually use our Prisma client to update our user document in the database to have this new username so to handle the asynchronous operation of our database communication with Prisma we are going to use a try catch Block in case an error occurs so in the catch block I'm just going to log create username error now in the event an error occurs and we end up in this catch block we want to return that error to our front end so we can return our object and make the value of error the throne errors message so we can say that error we want to be error Dot message I'm going to add optional chaining here just like that now inside of the try block there are a few things we want to do because usernames in our app are going to be unique we need to check to make sure that the username that the user is trying to submit is not already taken by another user so let's add a comment that's going to say check that username is not taken if the username is already being used by another user we will return an error message to our front end saying that the username is already taken and to please try another if the username is indeed available though we want to update the user's documents to have that username so we want to say update user and after creating our Prisma schema I don't believe we have run the command to actually generate our Prisma client based off of the current state of the schema because every time we make changes to our schema we need to rerun that command and regenerate our Pismo client so that it knows what models are present in the database and what Fields those models have and what relationships exist between those models so that we can perform all of the operations that we want to on our database using the Prisma client and we did use this command on our front end as well if you do remember so let's come over to our terminal here and go into our backend directory and we want to run the command npx Prisma generate and we want to identify dash dash schema and we want to pass the relative path to our schema.prismafile and the path is going to be Source slash Prisma slash schema dot Prisma that is the path to that file so if we run this it is going to generate our Prisma client based off of the schema we have currently written so now when we use our Prisma client it is going to know what models currently exist in our database based off of our schema which we have defined here and as I mentioned before every single time we make a change to our schema we are going to need to rerun that command to update our Prisma client okay so let's come back to the code here and we can just close off our schema for now and now we can actually start using the Prisma client to communicate with our database so the first thing we need to do is check that the username is not taken so we can create a variable called existing user and we are going to use Prisma to query our database to see if there is a user with this username so the way we can do that is we can use the await keyword because this is going to be an asynchronous operation and we want to call our Prisma client and we want to query the user collection and let's backtrack a bit here if I just type Prisma and I press period you can see that it knows all of the models that exist in our database because we just ran that npx generate command in our command line if I were to go add a new model in our schema right now say messages and then re-run that command messages would also be included in here because Prisma would know that that model exists so hopefully that's starting to make more sense now so here we are wanting to query the user model and if we press period again you're going to see a bunch of functions come up that Prisma is able to perform on any one of our Collections and we are going to get to use a ton of these throughout the rest of our application on other models as well so if we just think about what we are doing now we are trying to find if there is any single user that already exists with this username that the current user is trying to create so the function we want to use is find unique because this is going to find a single entity in our database that matches a certain condition okay so how these functions work on the Prisma client is that inside of them we can pass an object with a bunch of different conditions inside of it and Prisma is going to convert all of the logic we write into a database query that is compatible with the current database we are using which in this case is but if you're using a relational database like postgres or something it would convert all this logic into a SQL statement and then query the database but in our case it is going to convert all of the logic we write into a query okay so we are trying to check if there is a user with the username that the user is trying to submit so we want to use the where property here and the value of this is going to be an object and inside of here we can tell Prisma which fields on the user model we want to match on so if I press Ctrl spacebar here you can see that Prisma is showing us what entities are present on the user model and it's asking us which of these fields we want to write a certain condition on so that it knows what user document from our database to grab now you'll notice that the username is not present here so typescript does not know that the user model on our Prisma client should have a username and the reason that is is because if we go back to our schema we actually have not yet added the username field to our user model so as of right now our Prisma user is only going to have these properties on it it is not going to have a username and the reason that only ID and email are showing up here and not the other ones is because we are using the find unique function and Prisma knows that currently the only unique fields on our user are the email as well as the ID because if a field is not unique like in the case of name here the Prisma find unique function is not going to work on that particular field so what we need to do is add the username to our user model and make it unique because our usernames are going to be unique as I mentioned before so just underneath email here let's create a new field called username and this is going to be up type string and we can make it optional because it's not always going to be present and we want to add the unique keyword here and in a prism schema this is how we declare a field to be unique we say at unique so now if we save this schema Prisma we need to regenerate our Prisma client to have this update on it so let's go back to our command line here in the backend and just simply rerun this command okay so now our Prisma client should have those updates so if I come back here and I check typescript again you'll see that the username is there so now we can actually search for entities on the username field and this is all we need to do to check if there is an existing user with that particular username and we are just using JavaScript shorthand notation here the value of this is going to be the value of this username here and since they have the exact same name we don't need to explicitly declare that JavaScript automatically knows that this is going to be this so now we need to check if Prisma actually found this existing user if Prisma did find a user with that username it is going to return that user and that is going to be what the value of existing user is going to be if it did not find a user matching this query existing user is just going to be not so we can say is we can say if there is an existing user with that username we want to return an error to our client saying that that username is already taken so we can make the value of our Arrow key username already taken try another so then if we make it past this if statement and we don't return that error that means the username is available and we can update the user to have that username so to update our user we can say await Prisma dot user dot update and again we're going to pass this an object the user we want to update is going to be the user that has an ID that matches the user ID coming from this session here so what I'm going to do is actually Alias this to be user ID just so that it is a bit more readable so we want to update the user where the ID matches the user ID coming from the session now when we are performing an update the second parameter we need to pass in here is going to be called Theta and the data object is going to contain the actual updates that we are making to the user and the field we are updating is going to be the username field and again due to JavaScript shorthand notation the value of this is going to be the value of the username coming from the argument then after successfully updating the user in the database we just need to return an object with the success parameter being true and then our front end is going to use this information to call a function called reload session which is going to get next auth to refetch the updated user session so that we then have the updated user with the username on our client so we don't really need to return the updated user here because next dot is going to do that for us on our front end after receiving a successful response so now that we have written out this logic I think we can actually try to perform this query from our front end and see how our new resolver actually performs and if it does what it is supposed to do and actually update the user so in order to do that we do need to start up our backend server once again so let's give that a go npm run Dev and the server has crashed and some stuff is going on here so what is happening all right so we are getting a typescript error inside of our index file it's saying that the session types of property user are in edible okay let's go to our index file so I think this is happening because this get session function from next auth is returning a session and this is going to be of type session or null and this session here is a next auth session and not the custom session interface that we defined in our types file and because we are declaring our own session interface here with our own custom user there's essentially just a type conflict going on here because typescript is detecting a difference between the user on the next session interface and the user on our custom session interface so typescript is not wrong but typescript also does not know that the user in our database is going to have the username property which means that the get session function is actually going to return a session of the structure that we defined and not that next auth fine and so the way we are going to get around this is by typecasting the return type of the get session function to be of type session but the one we defined not the session from x dot the one from the util slash types so once we do that you can see that that texture of error disappears and actually if we go back and look at our custom session interface here and actually right over here in our client console we can see the structure of the default session user it has these three properties here email image and name and these two Fields here ID and username are the custom fields that we are adding to our session user and they're really the only two that we are going to use in any of the backend logic of our application we're never really going to use email image and name any of the core backend logic but to be more correct we should probably add these three Fields into here for completeness especially since we are typecasting here we want the type of this session to be as accurate as possible so what we're going to do is just simply add those three fields just want to say email is going to be a string image is going to be string and name is going to be string so if I were to log out what the current value of this session object would be it actually would not have the ID and user properties on it because it would still have the same structure as our default session from next auth which is being shown over here and so we've added these custom properties to our user in typescript so typescript knows about these custom properties but next auth currently does not it is still just using the default session and so we want to make the two match and so how do we do that and this is where I'm going to show you how we can add these custom properties to the actual next odd session and in order to do that we need to go back to the file we have not seen in a long time this next auth API endpoint in our front-end repository because this is where all of our configuration for next auth is going to go and this is where we're going to be able to add those custom properties to our next auth session so in addition to these other three property that we specified in our next object here there is also a section called callbacks so if I just press Ctrl spacebar here you can see that there are a bunch of different options for different callbacks that we can declare inside of this object so what I'm going to do is I'm just going to search for next auth callbacks and I'm going to come to this section of the database here and this section of the documentation is specifically regarding this callbacks object inside of the next Health configuration here so we don't really need to dive too deep into what these functions are actually doing but essentially these are just functions that fire at different points of time throughout the authentication flow that nexos performs when a user assigns in and authenticates and which ones of these you are interested in is going to depend on the type of authentication you are doing in your app in our app we are doing database authentication using the Prisma adapter if you remember we are storing the sessions in our database and that is how nexoth is going to work with Prisma to verify that the user has a valid session so the callback that we are going to be interested in is going to be this session callback so if you just scroll down to that section of the docs here basically it's just saying that this function is going to fire every time a session is checked so when a user signs in with next auth next auth is going to try to receive that user session from the database and when that happens this function is going to fire and it is inside of this callback function that we can actually modify the session to have a particular structure that we desire so that the session that we are using throughout our application has the structure that we wanted to have and has the information on it that we want to have and so to tie this back to our conversation before about adding custom properties to our session if we look at the current structure of the session just as a reminder specifically the user we have email image and name and this is just the default session that we get from next auth and out of the box these are the only three properties that are going to exist on the session user regardless of what the structure of our user is in the database so our user in the database could have like 100 other properties like username and last visit and anything any other custom property that we add to the user in our app in our case we are adding a username to the user in the database and we want that to be present on our session here and so it's in this callback where we can actually do that you'll notice that the three properties that this callback receives is the session itself a token as well as the user and this user object is going to be the user that next auth pulls from our database and that is where the username is going to be so all we have to do is take those properties from our user and add them to our session and then they will be available to us in this session here using the use session hook on our front end as well as the get session function on our back end okay so this is a lot of information I hope I'm explaining this clearly it's kind of a mouthful but um to illustrate this a bit further let me let me um try to do an example here so if I just copy this code and paste it over here let's add a console log here let's say inside of the session callback so let's save that and we are not using access tokens so we can just get rid of this so since this log would be on the next auth server they're going to appear in the console here so you can see here inside of the session callback so every single time the authenticated user session is fetched from the database that function is going to fire so if I refresh this page that request is going to fire because nextoff needs to get that session from the database and you can see that that log is happening so now let me show you how we can actually add custom properties to our session so what I'm going to do to add a custom property is I'm going to instead of returning just the session I'm going to return the entire session object but then I'm going to add a custom property called custom property and it's going to be my name so if I save this and then I refresh this page let's take a look at what the session looks like now you can see that that custom property is there so whatever object we return from the session callback is going to be the value of the next auth session and so hopefully this is all starting to piece together because now we can take any property we want from our user and put it on our session object and then return that object so that we have access to those properties on our session okay so let's delete this return value here and instead let's return an object now the value of our session what we want to do is sort of blend the existing session and we want to modify the value of user on our session and so for the value of user we essentially want to create an object that is a blend of the session user as well as the database user and so the way we can do that is we can see that the user is going to be an object and we can spread the session.user and we can spread our database user just like this and so now the value of user is going to have all of the Blended properties from both of these two objects if I refresh now let's take a look at what this looks like go into here a session and we expand the user you can see that it is no longer just those default original Three we have information from the database user here we like the ID and the email verified flag and when we save the username onto the user document in the database that username will also appear here and on our back end because we are using this get session function from next auth this session object is going to have the same information that our client session has because they are both pulling from the next auth server okay and actually one last thing we have to add to our user type here is this email verified Boolean just to make this type completely correct so just under email here I'm just going to add email verified and this is going to be a Boolean and we can come back to our index file okay so I think we just spent the last 10 minutes or so talking about typescript and sessions and sort of stuff that is not as interesting as the actual core application logic but I am glad we got all that sorted out and I hope you found that insightful and interesting adding custom properties to the session was something that I struggled with for a while so once I figured it out I wanted to incorporate it into this application and show you guys how to do it as well so that you didn't have to struggle with it like I did so now that our session is all set up properly and our types all match we can actually go ahead and test out this create username resolver to see if it functions like it is supposed to so what I'm going to do is I'm going to open up our mongodb Compass here which we have not done for a while and I'm going to go into our database iMessage graphql and open up our user collection here so currently there is only one user in there and that is me shadmare here at gmail.com and this is the current structure of our user and you can see that it does indeed match our session user now which is super nice as it is right now there is no username here after running this create username mutation if all goes well and it functions as it is expected to we should be able to see the username on our user document here so let's go ahead and give this a go now I think our back end is actually turned off so I'm going to reboot it up npm run Dev okay and our server crash again which is super sick um what is it going on now typescript error message okay you know what this is this is this is a simple one this is the only going to take like 30 seconds so if you go into our user resolver function here it's basically just complaining about the type of this error here now I don't know why the typescript compiler is not picking it up here I don't know why there's no red underline but that is strange oh well hopefully you guys are seeing your red engine on here I don't know why I'm not but basically typescript is just saying that message does not exist on the current type of our error so we just have to update the type of our error here now unfortunately typing errors is kind of strange and if you try to type this using the typescript default error interface it complains and it's basically complaining that the type of this must be any or unknown if we are specifying an error in our catch Clause I am not too sure why this occurs this is what I typically do with errors and if we try to recompile our server typescript should no longer complain so yeah the server did recompile successfully but I'm going to clear our console because that ugly error node message was kind of ugly so I'm just going to get rid of it and have our clean console here with a successfully started up server so our server is up and running our client is up and running we should theoretically be able to send off a mutation and see what happens okay so what I want to do is clear the console and we're just going to go ahead and see what happens here so I'm going to say Shad Mary that's going to be my username and let's click save okay so loading went true for a sec so it actually contacted the network it seemed there's a ton of logs here because the component re-renders every time I type a character but anyway let's look at the data that came back here is data so inside of data we can see that the create username returned this object with success being true so I think it actually worked and the error is null so I think it actually works so let's go to our database here and refresh okay yeah so look at that the username is successfully appearing on our user document so the resolver seems to have worked we got a success message of true the error did not occur now there is some work to be done on the front end here to do some sort of action depending on what response we get back from our create username mutation and if you want to test this out with a bunch of different usernames you can just try this out click save and look at the response success is true so if I come back to the database refresh this you can see that the username does indeed update so now that our user has a username let's refresh our page here and see if that username appears on the session so let's open this up and it is not there so even though the username exists in the database it is not showing up on this user object here on our next odd session so the issue lies right here so this object that we're looking on the right here in our console is this object here which is a blend of the default session and the user from the database okay so if we take a look at this we are obviously getting data from the database because the ID and email verified are coming directly from the database document so why isn't the username there and so the reason that the username is missing on this user object here is because we are fetching the user from the database using Prisma and we have not yet added the username field to our Prisma schema on our front end so Prisma actually does not even know that the username is there and therefore it is not going to be able to fetch it from our database even though it exists so we need to go back to our schema in our front end and all we need to do is just add the username to our user model here similar to what we did in our backend we just need to update our front end hematol because that is the schema that the Prisma adapter is using to do all of this authentication flow so underneath our email here we can add the username property it's going to be an optional string and we want to flag it as unique so now that we save this we need to regenerate our front-end Prisma client because remember after every schema update we need to regenerate the Prisma client so that Prisma has the latest schema updates so the command is npx Prisma generate dash dash schema and the path to our schema file is Source slash Prisma slash schema dot Prisma run that is going to generate the new Prisma client and so now Prisma along with the Prisma adapter are going to be aware of the new username field so when I refresh this page now we should theoretically have the username so let's see if that's the case if I refresh nothing happens because we have not started our front-end development server it's probably needed to use the front end so that's up and running let's refresh and if we take a look at this user here now we can see that the username is there so we have successfully put the username on our session and we have access to it in our client throughout our entire front-end application and you can see that the react app is actually picking up that we have a valid username map because it brought us to the chat component here so our logic is working and our chat component is very non-progressed to say the least this is what this is what our chat app looks like right now but we have solved the problem of getting the user's username in the next hot session now one last thing we need to do with our next odd session is use that reload session function that I have been sort of alluding to this whole time this reload session function to re-fetch the session after the user successfully updates their username because right now if the user updates their username they would have to refresh the page in order for next auth to go and get that newly updated user document from the database we don't want that behavior we want to just automatically refetch that session end user from our database after successfully calling the create username mutation and to do that all we need to do is somehow trigger this session callback function to fire after successfully updating our user because once again that's what the session callback does it goes and gets the session and the user from the database and returns that as the session that the U session Hook is going to return us so we just have to make this function fire and it is through this reload session function that we are going to trigger this session callback to fire again okay now to demonstrate this whole flow again I'm going to go to the database here and just delete this username off of our user so that our app doesn't think we have one and so if I refresh this now it's going to bring us back to the create username view because we do not have a username anymore okay so what we want to do is inside of our on submit function after getting a successful response from our create username function we want to call that reload session function but right now the reload session function I believe is just empty if you go back to where it's defined in our index page here it's just doing nothing so we just need to write out this function very quickly and it's only about two or three lines so it's going to be very very quick okay so I'm just going to copy and paste these two lines from My Demo project here inside of this function and this was the solution I found online after searching through a bunch of GitHub issues and talking to people in Discord about how to get this behavior of automatically refetching the session after a user update and this seemed to be what the community had suggested to do and it does work so we are going to roll with it so we're passing in the reload session function to our auth component here I'm going to move this tab to the left of auth so it's in the proper order so down here in our on submit function we want to read the data that comes back from our create username function and if the response shows that it was successful meaning that the success value in the return object is true and there is no error we want to call that reload session function now the data that comes back from our create username function is going to be this data object up here from the use mutation hook because that is how the user mutation hook works it gives you a mutation function and then whatever data is returned from that function is accessible in this data object here but another way we can access this same data object from our mutation function is to come down here here to the line where we're actually calling the function and do this this function is going to return an object and inside of this object we can access that data and this is going to be the same data that this is up here and since we are going to be reading from this data down here we actually don't even need this data up here anymore so we just don't really need to declare it and I'm just going to delete this console log here because we know the function is working and now we can actually do some stuff with this data here now the first thing we want to do is check that the data that our create username function returned is actually valid and if it is not we want to throw an error so we can say if there is no data dot create username we want to throw an error so we're just going to do that and this is going to be caught in our catch block down here and in a little bit we are going to be adding some nice UI error components here to indicate to the user that an error occurred but we'll do that in a little bit here okay so if we make it past this if statement and actual valid data came back from our hook we want to check if that data contains an error message so we can say if data.create username dot error meaning that there is an error string present in The Returned object we are going to destructure the error message off of our data so we can say create username and then on create username we want to grab the error and we're going to throw a new error where that error message from our API is the message string and we're going to again catch that down here and do something meaningful with it on the UI in a little bit so if we make it down here past these two if statements that means it was a successful response and this is where we want to call that reload session function because we only want to call this function if this create username mutation was successful so I'm just going to add a comment here that is describing what this function is doing so it's going to be reload session to obtain new username so now that we have added this reload session function when we create the username the session callback is going to fire and refetch the session and the user from the database and recreate the session that is going to have the updated user on it and the user will not have to refresh the page for this Behavior to occur so just as a reminder we removed the username from our user in our database so we are starting from a clean slate so if I refresh this page here and we take a look at this user here we can see that the username is currently null because it does not exist in the database so if I update the username now to Chad Mary what should happen is that the session should be refetched the username will be detected and it should automatically take me to the chat component so let's see and it does exactly that and you can see that the session has logged a few more times here and if you look at the latest one and we go into the user you can see that the username is there so the user did not have to refresh the page and their brand new username was automatically fetched from the database and updated to be inside of the session and so all that is left to do with this whole create username flow is to just add some nice UI components if an error occurs to tell the user to try another username and we're also going to add a success UI component as well and to do that we are going to be using a library called react toast and if you have not heard of a react toast before it is essentially just a really nice library that makes it super easy to display notifications to your user so if we just search up react host oh sorry it's called react hot toast um they have a ton of really nice just like notification messages here like error messages success messages and you can configure where they appear in your screen so you can see that if I set it to bottom center they come up here lots of cool stuff you can do here and this is a really popular library and it is extremely easy to set up and use and it is what we are going to be using throughout our application to display notification components to our user so let's go ahead and install this so I'm just going to open up a new terminal here in our front end directory and I'm just going to run npm install react hot toast now to use react hot toast in our application we have to come over to our app.tsx file and just simply add this toaster component from react hot toast and the component is literally called toaster so import that from react.host we just have to add that here and now we will have access to the toast Library throughout our application and we can invoke it by doing something as simple as this toast.error toast dot success and put in whatever message we want super super easy to use so thank you react hot toast for being so awesome all right and let's come back to our app here and let's just quickly add a few toast messages here throughout this on submit function okay so we're going to add both a success toast and an error toast so after the user successfully updates their username we are going to display a success host so I'm going to import toast from react hot toast and I'm going to call the success function because that is going to make it green and look like a success message and we're going to make it say username successfully is there two s's and successfully I'm honestly forgetting the spelling of successfully I am kind of embarrassed that I have to look that up successfully there is okay there are three doubles in that word C S and L okay user username successfully created um with an exclamation point and the rocket because why not let's be extra like that okay and then in our catch block we want to display an error toast so we can say toast.error and inside of our toast here you want to put the message from our error so I'm going to say error Dot message and just as before I'm going to declare this as type any now let's go back to our database and just delete the username off of our user so we can test this out update that so if I refresh this we should be brought back to our create username function so if I create the username that works this should say username successfully created so it's kind of a nice it's a nice UI Edition and it redirects us to the chat portion of our app I like that I think it's a it's a nice user experience and to demonstrate an error message what I'm going to do is create another user and try to create the same username because if we try to create a username that is already taken it should return an error to us and this error should appear on our front end here in the UI component so we can test out this existing user functionality so I'm going to log out and I'm going to continue with Google and I'm going to sign up one of my test accounts Shady Mary 7 gmail.com I think I remember the password to this okay looks like I do nice okay so we authenticate with Google um that user is in the database now and looking at our database if I refresh this we can see that the name we can see that the username Shad man is taken so if I try to create that username let's see what happens boom okay we get that error username already taken try another so our error message from our back end is successfully being relayed and caught on our front end and displayed to the user and so I think that's pretty cool so this is how you can do some nice error handling with graphql if I try that again username already taken try another we can spam our server until it blows up cool okay so the error is obviously working so now I'm going to create a nice username for this person LOL dude law dude okay yeah username successfully created if I go to the database refresh that username is there and the username should be on the session here LOL dude nice okay so the username flow is working we have reacto successfully setup so we have some good ux going on there and so the cool thing about having access to our users username on our front end is that we can actually display it on our UI wherever we want so if I go back to the index page here not the back end but the front end index page so the username is going to be available to us on the session so I can display that anywhere I want on our UI so if I just want to put it here for example I could say session dot user dot user I say that you can see that the user's username is there and having access to this username is going to be a lot of fun when we start building out the actual track components of our app because we can put the username in a bunch of different places on our UI all right you guys I think I'm going to leave it there for part one we have covered a ton of Concepts in this video we have set up our entire authentication system using next Dot and the Google cloud provider and we have set up our mongodb database and have learned the fundamentals of Prisma by creating our Prisma client and connecting it to our database we have seen how to create custom usernames for our users and we have learned the fundamentals of graphql and Apollo by creating our own custom queries and mutations and we learned how to set up a brand new Apollo graphql server using Apollo Server Express in a node.js environment basically in this part we covered all of the fundamental information and we are now really nicely set up to start developing the core chat features of our app which we're going to do in the next part and I am planning to release part two sometime over the next week or so thank you guys so much for watching I really really appreciate it if you have any questions or feedback please do leave a comment and I will 100 respond to you I respond to all of my comments and also please do join my Discord server I am very active on there and would love to lend a helping hand if you are stuck in anything or if you just want to chat I would love to do that as well the link for that is in the description thank you guys again so much for watching and I will see you in the next one
Info
Channel: Shadee Merhi
Views: 43,986
Rating: undefined out of 5
Keywords:
Id: mj_Qe2jBYS4
Channel Id: undefined
Length: 246min 32sec (14792 seconds)
Published: Tue Sep 27 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.