I've been seeing a trend online lately of people needing to create full stack applications and having end to end type safety this approach is hugely popular and it makes writing full stack applications that much easier so today I want to explore with you guys how to create a full stack application with end to end type safety using the new amplify Gen 2 so we're going to look at a next js14 application we're going to use AWS Amplify but we're also going to use AWS appsync and we're going to see how easy it is to share
types between the back end and fern end and then we're going to create an application that has a many toone relationship and also we're going to take a look at kind of how to put this all together I really think this is a great way to create full stack applications and it's just really quick so let's dive in a little bit more so let me show you the application we're Going to create today so it's pretty simple let's assume that you're creating an application that allows you to track titles that maybe you're creating a blog
posts or pieces of content and you want a central place to uh save all your titles but it also allows you to leave comments to it so it's kind of like a blog post uh in some ways so here's a list of titles that I've created I can click on any of them and then I can list see a list of comments that people have Left on it if I want to I can sign in to an account so it's protected and and authorized now if I'm logged in if it's a post that I created
I can actually delete it I can add additional comment to additional comments and they'll appear I can delete any of them I can only delete them if I'm logged in this ad title only shows if I'm logged in so this is just a basic application that kind of shows you what you could create in a full stack application this is all This data is being saved in our managed graphql service backed by Dynamo DP and if I go to amplify documentation here you could see this is the new AWS amplify new code first DX so
I work at AWS so I'm a little biased but I think this is one of the most straightforward simpler ways to create a full stack application and the way we did it is it uses cdk which is cloud development kit constructs in the background so you can it's very straightforward to create your Application especially for author data right now and then if you like to layer on more backend code to provision more of your backend then you can also kind of drop down to the cdk layer and do that and then on top of that
we have this new data model that allows you to use this schema and then share this types between the back end and in front end and it all works together really well and so that's what I'm going to show you today in this application we're Going to start absolutely from scratch and then we're going to build up this application I can show you how flexible it is and how straightforward is so let's take a look for this application we're creating today we have 12 different steps that we're going to go through and and I am
going to have timestamps you can check in the description below so you can jump in between different parts here but we'll just start from the beginning so we have A good idea of how this works so let's go ahead and set up the app and install the dependencies uh I'm using visual studio code the latest version I'm just using the terminal inside here and yeah let's create it so mpm create next app latest and I'm going to choose most of the defaults but I'm going to call this our code first app we're going to use
typescript eslint Tailwind we'll leave the source directory we'll use the app router I won't do any customizations so This just take a moment okay it's installed so let's go ahead and change into it change directories into it so now I'm to my code first app let's open up in the same window okay so we are in a basic next app and we haven't done any changes to it so let's install a few libraries and so we'll do an mpm install AWS amplify AWS amplify UI react and AWS amplify adapter nextjs and so what these These
are AWS amplify is our JavaScript library that we're going to be using in This project the UI react library is to add in our authenticator and the adapter nextjs is going to add in some special functionality we can use to be able to talk to next with serers side rendering with our ads app sync all right so they're all installed and let's just make sure everything is running out of the box we haven't really changed anything here so it's running in Local Host 3001 and we'll just go to 3001 all right great so now we
have our next app here we haven't really changed anything but let's say we go into the pages app here I always like to clean this up a little bit before I do anything so I'm going to delete delete it all oh no I'll put in a hello world and then I'll go into the CSS and I'll clean this up to let's go back here make sure it's saved all right so we see hello world one down so we really need to now is set up the amplify Sandbox so let's take a look at that now
so what we're doing in this application is we're setting up amplify Gen 2 and Gen 2 is kind of a different way of setting up your amplify app so we're going to set it all up in code kind of infrastructure as code and then we're going to have some type safety between the back end and the front end and you can follow the get starting guide if you go to docs. amplify AWS it gives you some Clues on what you need to do but Basically we're going to run this npm create Amplified latest to do
it uh and if you don't already have it sign up for a free AWS account it's well worth it and you get hundreds of hours but most of the things that we're doing in this tutorial today are on demand so you only get charged when you're using it so it's not like you have to worry about getting charged monthly cost cuz you're provisioning ec2 instance or something like that so you don't get charged that Way at all all right so if we come back here we'll do mpm create amplify at latest and what this will
do is it asks a few questions yep we're going to have it in the root directory it's going install dependencies and this will just take a second while it's doing this if you are completely brand new to AWS amplify Gen 2 you have to configure your AWS account I'm going to skip this step but basically run this one right here npx amplify configure profile D- name And the value and this will allow you to it'll open up a screen here and it'll ask you to enter your details it'll create a user that will then add
a file into your local system into your uh AWS in your root folder uh I've already did that here so I'm not I'm going to skip the step but this something you'll have to do if you're completely brand new to this so it said it's done and what that did is it created a new folder here called amplify and it has uh a couple of Configurations in here and out of the box it comes up with this resources so this essentially creates a Cognito user pool and identity provider for you and so this is the
way we're going to be logging in and out of our application with Cognito and it's it's all code but if we wanted to we can add in like if we want to do a Federated login through Amazon or Google you can add it in here you can Add additional user attributes by the way user attributes can only be added when you first create your app so this is this is a configuration that you have for off for data it comes with this configuration so it comes with a basic to-do app and this is where the
type safe works for in your advantage and in the front end the back end so you create a schema and this will essentially create an AWS manage graphql service called Appsync in the back end and each one of these schemas you create will be tied to a separate Dynamo DB table and this will create one called to-do it only has one field called content and then you can add authorization rules like allow owner public to read and we'll add our our own in here in a second but I just kind of show you what this
looks like so to get this up and running like I said you have to have an AWS account but as long as you have the account you'll have this Folder in your AWS you'll have a new AWS file and you have some credential files in there I won't show you for obvious reasons but if that all set up you can run npx amplify sandbox and what this will do is it basically creates it'll deploy this to your back end by the way if the first time you run this itaz it might have to run a
bootstrap command so it may ask you to log in to your AWS Account once again I already did that before this video but it will go ahead and bootstrap your ads account and then what it's doing here is it's creating the this AAL environments creating the user pull and it's also creating the app AWS appsync account and this is an environment that will only last as long as you keep it running and it's not used for a production later on at the end of this video I'll show you guys how you can take this code
and then create a Production environment that you can use this is kind of interesting way of doing this too as this is provisioning if you look at the documentation This Cloud you have this and the idea really I'll zoom in here is that every single user will have their own sandbox environment so me as Eric I'll I'll have my own sandbox environment but Jim or Renee or Joseph will have their sandbox environments and the sandbox environments can match what It looks like in production so this environment you can quickly load spin up run it and
use it and what you could do as well if you didn't want every single user to have their own sandbox environment you can share sandbox environments too there's an amplify configuration file that's created you can share it with multiple users so maybe you have one sandbox environment that has a bunch of data in there there you want to share you could do that uh You can also set up scripts and other ways to load data into your sandbox environment because obviously it'll be empty when it soon it run soon as it runs but yeah we've
been trying to think of like what's a really good developer experience and that's what we have come up with so while this is running this will take a few minutes to to to bring it up to speed we do have set up all our routers and routes and folders so let's see here the way I'm kind of thinking About this app is we're going to have we're going to use all the next 13 14 features with the app router well we're going to use obviously app the app router and use our server components uh we're
also going to use a server actions so let's see if we can set this up I want to create a new folder here all right so what we're going to do is we're going to create a folder here so I'm going to create one called underscore actions and then actions L TS so this is Going to be where I'm put all my actions it's also underscore actions so it doesn't actually add a route for this app route we could put it in the source folder too I know I kind of go back and forth on
it all right so I added in a components folder which is empty an amplify UTS folder which will add some information in an app folder so now we have an ADD and a signin route so that should be it for our different routes all right so let's set up authentication So we're going going to create a new file and we're going to create an O folder and inside that it's going to be o. TSX great and so inside this off TSX file we'll go ahead and add in let's do a little bit of configuration here
so first this is going to be a client and we're going to import in amplify from AWS amplify and then we're going to import in config so we could check back back at our app here and you can see we Have this brand new ephemeral environment we have all these outputs and it's done you can tell it's done because it has this little check mark here and the deployment is done and we're going to import config from this folder here so it's going to be one lower and I believe it's called amplify configuration uh Json
and then we'll have to import in some Styles and this is all in the document mentation but I have it Memorized CSS and then we'll Import in this component this AWS amplify UI react and then we need to run this command amplify doc configure and we'll pass in that and then we'll put this SSR true option in here and what we want to do here is we'll actually have the whole app surrounded by this app this is also where you can put other providers if you had some others in your app we don't in this
case this going to be do react and We'll do react. react node and then for our app we're just going to return this authenticator provider and this kind of gives us access to the authenticator all over and we'll have this children and that should be it and what I'm going to do here is I'm going to go into the we'll go to the layout TSX and I'm going to change this title we're going to call it title listing list all titles and comments app and I'll leave to all the Rest this I'm not going to
change any fonts or anything I'm just going to leave it very simple but right here where it says children now we're going to surround the whole app by off and if I did this right we should be able to Auto Import this in I think I'm just going to import in the other way from slash components slash off slash off and it's a default import so not any import all right so now we have this Au in here and it really hasn't changed Much so if we look at our app okay so if you run
npm run Dev here it's running in Local Host 3001 we look go to Local Host 3001 or it's already here and reload it it doesn't really change anything but now we have this new provider working in the background so I think what we should do next is see if we can get the we have the signin route and let's see if we can get the signin to work correctly so I'm going to go to the signin route and let's see here Basically that's a snippet I'm using and really here and we'll call this sign in
we don't want to we want to use the authenticator component so if you come back here to the AWS documentation and you click on UI Library you can see that we have this thing called the connected component and this authenticator and what this is going to do is it allows us to really quick add in a way for users to sign in and create accounts and we want to be able To do this without with a minimum amount of code and boiler plate and things like that and this works correctly in the the whole AWS
amplify ecosystem we could definitely do this with the JavaScript V6 Library if we wanted to the JavaScript library I had installed earlier but I think this will be the easiest way to do it this is a client component though so we these are server components so that's obviously going to be an issue so what I think what I want To do oops is we're going to create a new file and so I'm going to call it sign in we'll go off client. TSX probably not the greatest name then we'll save that inside our components folder
inside our off folder perhaps and so this file will will be a client so I'm going to use client here and to import in the Authenticator from AWS amplify UI react and we'll call this it's basically sign in or sign up so we'll just call it auth client and this Will return the authenticator and we'll just self close it see here cuz we don't really anything else and then we'll export default sign in we'll call it offine actually and let's see here it's giving me a little squiggling line here I think I just need to
reload let's try to reload the window for a second sometimes when I get red squiggly lines I have to do that and while that's reloading I'm going to go back into the Signin page and then I'm going to just import it in so instead of doing sign in here we're going to do the off client and save it and now let's see if this works so just going to come back here and we'll just go to sign in our new signin route and our server is still running cool so here it is now we have
our sign in page we don't really have a way to sign out or do anything yet but we know at least we have the signin page so I think what we want to do next is See if we can set up all the routers and folders and then we'll come or we'll set up the nav and then we'll come back to the sandbox here in a sec but let's see if we can set up like a navigation so let's create a new file and we're going to call it bar and we'll save that inside our
components yeah we'll just call it right here because this is going to be also another client component we're going to call it use and what this Navar is going To do it's going to allow us to quickly show all our routes now this Navar is pretty big so let me kind of copy and paste some of it in so that way we can save a little bit of time okay so here is our Navar and let me explain what we're doing here so first first we have this is signed in prop that we're passing in
so later on we want to track if a user is signed in or not and we'll need to we'll have a prop that kind of helps do that so we'll have this use State here we have this off check to see if someone is signed in or not and we'll just default it to this prop that's this Boolean that's passed in and then we're using react router which is this use well it's this navigation next router that is and then we're using use effect and we're using something called Hub now Hub if we look in
the Like official documentation if we go back to outside of this Gen 2 let's see here we go back here and look up Hub so Hub is a way It's a utility that helps you figure out if a user if certain actions have happened so like for example we can look for off and then see if a user signed in or signed out and then do something so since this is a nav are we want to show if a user is signed in or not and then either show a signin button or a sign out
button so we're going to use this Hub to listen for off events and then every time it's signed in we're going to set this state this use state to true And then we're also going to navigate them to the route and then also for the sign out so we're if someone clicks the sign out button we're going to do that as well and then we have this Hub listener cancel button that just to help clean up this subscription once you move if if at any time you this this component gets destroyed and then I have
the sign out check which if we go to the code this is a button so as soon as you click this button it's going to check to See if the user is signed in or signed out if they are signed in then it's going to sign out and this sign out is directly being pulled from our Javas script Library this aw amplify slof otherwise it moves them to the signin route and then I just have two routes here basically a home and add title and this add title is how you're going to add titles later
on and then I'm filtering right here I add this logged in true so I wanted to make sure that if A user's not logged in that they don't see this add a route because it wouldn't work because you can only add titles when you're logged in and then I'm using these Flex components which are all from the UI react Library most of the time in this app I'm using Tailwind but we do since we're using UI react I thought I would use it then this just shows all the different routes by using this map and
then I have this button that signs out and then I have the text see says Sign out or sign in so let's see if this will work so this needs to be in our layout and what we'll do is we'll write above of the off we'll add this Navar bar now it's kind of complaining because we had that is signed in so we'll just default it to right now to false and then we can test it out so let's see if we did this right another thing too in our page TSX I have this main
I think what I want to do here is I'll you know what I'll leave it like this I suppose Maybe I'll make it with2 and then M Auto to have it kind of in the middle let's see what it looks like all right cool so now we have a Hello World still but now we have this big big beautiful nav bar at the top that says sign in if we click sign in it goes to the page that shows this sign in awesome so let's see if it works so this should change to sign out
soon as we log in since this is the first time doing this We'll have to create an account and like I said this is backed by Cognito we could actually even look at this Cognito user pool and ads console if we want we'll look at that later but for now let's see if I can create an account so I'm just use an old email address I have here I'm going to call test oops and then I'm going to log in and not going to save it so on my phone I'm going to look at this
email so now I should have an email here it is and by the way Sometimes it shows up in your spam folder so keep that in mind 79 769 764 click confirm cool now it says sign out at the the top so now I have essentially an add title showed up now we don't have anything in this route yet that's great now one thing that we do have a problem with so if I click sign out here this works if I click sign in I go back to sign in now I have this new account
I just created and by the way I did add in some cookies to keep the JWT tokens for This user when I log in but if I refresh the page if I kind of just refresh it it's back to sign in even though technically we're actually signed in already so if I go into the inspect and I look at the application and then I look at cookies so we already have the Cognito cookies already here but we're technically it still says sign in here so that obviously that's a problem because now we go to the
sign in we don't see anything the authenticator Thinks we're already logged in so we're in a kind of a weird State now to get out of this weird State I can go into storage here and just like clear the site data and then refresh it and now it's back and go back home so that's not good so where that comes from really is if we go back to our layout we don't have any way as soon as the app loads for it to know if the user signed in or not the easiest way to fix
that is we're going to use server components to take Care of this so for Server components uh I always look back at the documentation so I'm going to go back to the docs documentation and if I go into server side rendering it says we installed this adapter we did at the beginning of our app but now we have this way of to do things through this run with amplifi server context Runner and what this is used for is when you're on the server you can basically surround all your server calls inside This Server Runner and
then it'll protect it these API calls so you don't have any chance of accidentally leaking it out to the front end I it's it's actually pretty straightforward so let's set that up to do that I'm going to create a new file I think I actually already created it so it's called amplify UTS it's in the UTS folder and we're going to create a new create server Runner so I'm going to be lazy I'm just going to copy this and I'm Going to paste it and one thing with this config it's that amplify configuration so I
believe it's at the root since we have this run with amplify server context we actually want to run some commands and you can see here if you scroll down that says you can do authentication with nextjs Ser side Runner you can do it through middleware but what I'm going to do instead of using with middleware I'm Going to use this kind of same kind of concept they're doing here but put it in this utility file and then import it into any component I need server component I need to where I need to check to see
if a user is logged in or not if you want to do this for all routes you put this in your middleware file but I just want to do it for some routes you can see here is a few other examples of ways to do it and if you look look at the bottom it tells you Different functions that you can use so there's server functions and client functions so we can use uh in this case get current user which would be uh on the server and and on the client so we're going to use
the server version of get so I'm going to create a cons called is authenticated and that's going to be asnc component and what this is going to do is we're going to wait run with amplify server context that's that's what we extracted Before we're going to do next server context and then we're going to pass in some cookies now we haven't imported these cookies in yet I don't think yet so to do that you'll have to import in cookies cookies from next headers but we'll do async operation here and then we'll do contest spec and
then this is going to be brought in a try catch so error and that there's an error will return false and then we're going to run user await And this is where we're going to do the get current user so I'm going to import in get current user and it looks like it already saw it okay so it's an AWS /of wait and also this is the client version so if you want to use a server version It's slash server so keep that in mind it's really easy to get these confused so this is the
server version of it all right so now that we have this get so wait user we're going to pass in that contents and then we're just going to do This to see if it's a user if it's true or false if this fails it'll go to false they eventally throw but if it's fine it'll just return the user now I there is some user information we might want so you can see here if you user there's signin details user ID and username we don't really collect much information like username when you're log in so I'm
just going to leave this the way it is great so now we have this is authenticated we should be able to use This in our servers to be able to check to see if something's authenticated and you see from our Navar we need to send and is signed in over so let's see if we can get this working so I'm going to go to the layout and in here I could just await it inside here instead of doing this false I'm going to do wait is authenticated now it's complaining here about this a wait cuz
we don't have this async so we'll do async there it is this since we're running this in the root Layout so it'll have to run through this authentication anytime the app loads you can make this is probably fine for our scenario but you may want to test on different devices and how if this affects the speed and loading of the website and go back to our app so if we refresh it I think we logged out so it still says log out we'll click sign in we'll click sign in and we'll try and sign in
again cool so now if I refresh it it still says sign out so it's not Like switching to sign in real quickly and showing sign out it's calling the calling this amplify utils it's seeing that it's signed in and then it's it's displaying and also I have this console log which I'll delete so yep so working expected if I click sign out then it's signed out and it redirected back to the root page great so now we have a really rudimentary login system so we really want to be able to add and list titles that's
number five and six on our list Here we haven't set up anything up on that so if we go back to our app and we look this data we we left it kind of all defaulted so all we have is this to-do model which doesn't really make sense since we're not doing to-dos so what we want to do is add in a better way of doing this with a post and comments and things like that with our titles I'm going to delete I'm just going to delete all this and I'm going to start over all
right let's add in a post now I can call This a title but I'm just going to go ahead and call it a post just kind of give the idea of we we have posts and comments and we have an A and I'm going to use a model here and a model as it says here is a data model that creates a matching am Amazon Dynamo DB table and provides create read update delete and subscription API so it basically adds in all the appsync resolvers for you so you don't have to do that yourself and
then we can add in fields and I really like This typescript it tells exactly what to do here so I'm going to add one called title and then I'm going to use this a again string and then it's going to be required so that means you'll definitely have to have this as as when you create any of these posts I'm going to add comments I'll come back to this comments in a second and then also want owner authorization I'll show you how that works in a second as well but I think it Makes more sense
right now if I add in this authorization so this is really neat you can add authorization for your app so only certain users or certain people can make updates or changes to it so this is a an array so I'm going to allow public I'll move this mouse you can see better so this means uh any public users can read so I can do like this but I really don't want public users to like update or Delete anything because that wouldn't make sense and so also on top of this I also want to allow owners
basically people who have created it to we'll do a. allow. owner and you can see here this is the type of authorization access an owner has basically anybody that who's logged in who actually creates it will have updates will able to update and change it and so here are the two types of authorization so I want all public users to be able to read it and Then allow owners to make create read update and delete changes to it and just to make sure that owners don't have too much power they're they have this owner field
which gets added added on since we're using this type of authorization and what we can do is only allow owners to read and delete there we go so now owners should be able to read and delete but they're not able to reassign so they're not going to be able to take their posts and reassign it to someone Else or so that because that' be annoying obviously if someone was able to resign their own post to someone else's name so that's our post and then we want also a comment and we want a relationship between these
so in our comment we're going to also have a here and we'll have to have a comma here so this a. model and then in this model here we'll have we'll we'll make one called content so this will be whatever is inside here you can also notice post I only have a title I don't have any content just for the sake of this maybe we're just creating titles to save for social media posts so we'll have it string here we'll make it required and then we'll make a post and we'll have it belongs to post
so this what this is doing is we can have relationships we can have has many is belongs to so this will set up the uh relationship for us and then we'll also have owner as well and I'm just going to Copy and paste the same thing here and then we'll have also basically the same authorization rules to allow users to read but only owners to change now we have a belongs to here but we don't have a has many so let's add that in I'm going to add comments and you can see here we can
do has many has one we'll do has many relationship to comment and now when we're querying we should be able to query the comments and the post so when You're inside a post you can get the comments that you need which will be very very helpful to us so I'm going to say save that and if you look here now I've stopped and restarted this a few times but we'll need to restart our sandbox we'll do amplify sandbox if it was running it would automatically detect the changes that I just did and it'll update the
back end for us so we'll just give it a second while it updates the back end for us other than That if you look down here this is all defaulted what it's saying is that our default authorization mode will be API key and that'll need to be changed every 3 days the API key will is going to be inside the amplify configuration Json file if we need it it also has a URL and a bunch of other things this is kind of interesting so what this means is that this API key will expire in 30
days you can set up inside the Amazon console or anytime you push you can have it Increase the expire days or basically reactivate it so it won't expire in 30 days you can also set this up to 365 days and the reason we set this in production and everywhere else is just to keep an idea that you probably should be rotating your API keys in case someone steals it and starts sending a bunch of stuff to your endpoint now you know that you're protected by the key actually expiring after a while all right so we
have our posts Contents now we want to be able to see if we can list it so we'll do that I also want to mention real quick that this example is pretty straightforward but just between a post and comments you can do relationships like I said it handles all the resolvers and everything for you because we're using this dot model but there are other cases where you might need to do more additional API level changes and we do have quite a things a Few things to support that so if you go to the data category
if you go back to the doc site there is adding custom business logic so if you wanted to create your own custom queries you can connect this directly up to a Lambda resolver if you wanted to we also have the capabilities you can also add much more complicated authorization rules and you know I mentioned before there was that owner and private this gives you the explanation of what those are if you Want to kind of dig deeper into it and this is also how you can add in customizations to each record field level authorization roles
and you can also connect to like open ID and a whole bunch of other things and we have ways too of actually dropping down to the cdk level so there is examples of like adding in storage which would allow you which would require you to install AWS cdk live and then you can create your own Stack and then add in storage but for the sake of this video I'm just going to keep it straightforward and just have this post and comment model and we'll go from there so to for the next thing we need to
do is to add in a way to list all the different posts and so right now I want to basically listed on the front page here so instead of saying hello world I'm going to put in a list of all titles cuz really if we look at our schema really have we have comments and Titles we don't really have any post we don't have the the middle piece the content part we just want to list the titles and we'll do a little bit of Tailwind work here we'll make it I'll make this a little bigger
we'll put a little padding at the bottom and now we want to go in list all the posts so first we need to figure out how do we even grab posts and this is where I want to go back into my amplify utils and add in a very handy util for the server so There's a couple of different ways you can connect to our AWS Apps sync server one is you can do it on the client side with something called generate client so if we go back to our docs here this is the way to
do this on the client side there's generate client and this is a part of the this part of the JavaScript V6 Library if you're in here in Gen 2 and you're on the server since we're using the this the server way we have this plug-in that we installed this Adapter there's something called generate server and we have that in our serers side docs so if we do generate server client cookies there's two of them there's using rack response and using cookies and I keep printing accidentally hitting print instead of control K and we have more
examples of this too in the docs come back over here you can see the different types so if you're using like route handlers you probably want to use this generate Client using cookies if you using middleware using this since we're using servers server components we want to use this generate server client using cookies and there's a pretty good example of how to set this up so right here we have this command so I'm just going to copy some of these in here and we have this example here so I'm going to add this to the
top and this config here we already have the config imported in it's just from that Json file and we Already have the cookies now one thing you'll notice here there's this schema so if we go back to this resource TS file we have this Con schema here right at the bottom we're doing this export type schema client schema type of schema so this is going to allow us to have type safety from the front end and in the back end because as we create our backend code here creating the schema and by the way if
you look here it's already done and now we can see we have All our configuration it's already updated the the the Json file but we want to essentially grab the schema and have it available here and that way when we use this cookie based client in our app it's going to be typed correctly so if I hit control out dot here I'm going to import it in from not data store but this data resources so now we have this new cookie based client and and we want to be able to list it out so I'm
going to come back over here and we're going To now have it available so let's see here we're going to const and we're going to await and we'll have to make sure this is async async await and we'll do cookie based client see it already imported it in and really nice thing is I can hit dot here and I can see I can get models and I can get post and then I can list and I can also do updates and creates and deletes things like that and one thing nice thing is you know through
graphql one of The advantages of it other than having this language that makes it easier to map your backend to your front end is that you can specify exactly what you want so I'm going to create a selection set which is right here if I'll try that again selection set and I can then say exactly what I want in here now it shows comments because we are connected comments because it has that relationship if I just go title I don't really want the comments right the Second and ID are the only two things I want
and if we come back here too right now these two are running essentially on the client side so kind of what I like to do here is when I run this I want to set the default off mode so I'm going to add that to user pool that means you have to be logged in to run this and then I'm going to overwrite it here because many of my other times I'm using this API I'll probably want off mode but sometimes I want API key but since this Is a public remember we we set this
to allow read public we need to change the off mode again and I'll set it back to API key and now I should be able to run this posts into our app so uh if we look here we have data errors extensions I'm not going to worry about errors right now and I'm going to rename this to posts and I should be able to just kind of show I'm going to just do a map through it so well first what I can do is I'm Just going to console log posts to see what it looks
like and it's running on the server so we'll need to make sure we have the right one open and we stopped the server so let me start it again and we're just going to make sure that it works all right so the server is running I'm going to go back to my title listing app okay so it says list of all titles here all right cool so we have an empty array here there's nothing in here which makes sense since we haven't added Anything but let's assuming when we do add something so I'm going to
do posts. map we're going to do async Post index to have something here so right now we know we only have a couple things in here so we'll just put in we'll add a key in key and this will equal the index and then we'll create a div and then we'll create post dot yeah we see ID and so maybe I just have Title Here There we go and we'll just need a to fix the wickly brackets cuz we need a closing Div here all right so once again we're not going to see any change
cuz we don't have anything in here but let's see if we can add a way to add something and we'll create it to the add route all right so we need to add a post and if you remember we created at the beginning a new add so this will probably be where we want to do this at we're going to use our react server component and we're going to call this probably I don't know Add post and since this is a server component we're going to try to use server actions here to get what we
need to get now we also have a server actions folder which will in a second add a new server action so we can use it so let's add some HTML here I'm going to create a form and the form is going to have an action called well we'll call it create post We'll add that in there in a second we don't have it yet and I'll add some class name names onto this class name We'll make it just uh using some Flex box here to Center everything to add a few gaps and then we'll have
input and we'll have an input of type it's going to be type text and then we'll call this title title and we'll need to have the ID title too I like to add a few other things we're going to add a placeholder we're going to call it title and then we'll have some a class name here with some class I'm just going to copy and paste this for my other Screen save there we go and then we're going to have a button so button it's going to be type submit and once again we'll have a
few class names here we'll do text white background till 600 rounded P4 and we'll just call that submit okay I like this yeah let's see we don't have this create post yet let's create this post so in my actions I'm going to create a new one called create post so I don't know if I need to add this in there I Think I'll add a use server at the top just to make it explicit so we'll do export async function create post that's going to have some form data in there just type form data and
then we're going to use our cookie based client again so let's close this cookie client there it is and then we'll do models and once again this is really nice we have uh typescript so we can autocomplete it here so we'll do Post. create and inside here it's going to ask us what we want to create so we're going to have a title it's going to automatically generate some of the other things for us like the ID so we'll do formate data. git and we're going to grab the title and we'll have a two string
here and if it's nothing we'll just put in nothing there and then also after someone adds something we want to redirect them so I'm going to add in a redirect and this is just a nextjs Redirect and it it already added it in nicely in there it's actually I think that's the wrong oh yeah this is the wrong so we're going to go next navigation there it is that's the correct one yep yeah so now it'll we can do something here if we want to we have a data and errors maybe we'll just console log
the data create post data for now and now we should be able to use this in here now the create post I just added in I can just import it in I suppose Import in create post from and this should be in our where did I put this this is in our actions which I put in app say more and more I think maybe I should have put the actions in the same level as the components but I don't know actions cool so this will automatically add the title and then redirect back over I'll click
sign in I'll log in and we have list all nav click add Title Here There we are so now we can add in a title so let me add The title as this is the first title I'll submit it cool so now we have this this is the first title now I don't like the way it's in there I think it's because I have this Minh screen here I could delete this cool this is the first title so now I have the first title listed and with this first title I probably should have a way
to delete that title as well so let's take a look at that next let's take a look at a way to delete posts from right here you see This lists all the posts but what I'm thinking on this page here is we'll have a little x button and then you click it and it deletes it but we also have to make sure because if we go back to our resource file you should only be able to be the owner only the owners will be able to delete I think in a future future iteration of this
I'd also add in groups one thing really cool about this is I can do a. allow defined in which allows me to have group ownership of This so if I have like an admin group any admin owners can go in and delete posts or titles but for this example we won't do that looks like we still have everything running oh since I saved it it's going to rerun this it actually does hot deploy so if there or hot swap deploy so if there's just minimal changes it'll just uh do the change quickly so so this
shouldn't take like 10 minutes every time you change something the way I want to approach This is this is great we're using it on the server side but typically when we starting to get into more advanced use cases doing everything on the server side is not fun so what I probably want to do is create a a client and this client will be a new file that we'll create that will pass in that pass in everything we want for the sake of time I'll go ahead and create a post client which I'll pass everything in
so in the components let's create a new file call It post. TSX let me just copy and paste everything in and I'll explain what it's doing so obviously it's a client component so you have use client at the top I'm using router navigation now I'm passing a few things in you can see here the typescript definition I'm doing a pick or a post and the reason I'm doing this just the title and ID is because if we look back at here I'm just doing title and selection set title and ID and I can grab the
schema here and use this As a type from that data resources I can use this pick and this just says in typescript just grab these two values so that's what we're going to do this post I have an on delete which will be a action a server action that we're going to pass in we also have an index and an is signed in Number the idea would be if we go back to our page TSX file we're going to not include the posts I kind of went back and forth in this do we want to
do the map inside the component or Outside the component I wanted the component be really generic so in that case we're just going to do it outside the component and then we're going to pass in the index and is signed in we might even need to pass index in I'll have to play around with it we we'll look we'll see and then we'll have this new route so if you remember at the beginning I created a few routes and one of them right here was well I haven't created it yet I want To create also
a route that will be for the comments so we we'll create one called posts and then inside here we'll create a new folder called ID and then we'll have a new file there called page. TSX and so this will be a way to go directly into the post or the title and look at the comments that's why we have this on detail here I have just have a button anytime you click on it it'll go to the route and then we're just going to show the post title and then here This interesting is that we
don't want everybody to be able to click the delete button we only want logged in users to be able to see it so we don't want logged in people that are not logged in to click the delete button and that's why I have this is otherwise they see null and this is signed in it's also being passed in so that looks pretty good I think and now we have to do a few things so first I think what we want to do is we want to create the on delete Post in our actions so I'm
going to go into our actions here we already have this create post so let's do that async function on delete post I don't really like the naming here I could change it but we'll leave it as is and we're going to use our weight again this cookie based client models post. delete and then we just need to pass in the ID which we'll pass in right here and then we could do console log data deleted and obviously we probably want to do the Errors say data and errors I guess we can put in the errors
too you see here we also have errors and then lastly we'll revalidate and this is a nextjs feature that allows you to to like refresh a certain path because we're actually once you delete it we're on the same route we just want it to refresh I'll have to import that in from next cache great so that's all we need to do here for this delete and now we can of kind of figure out inside this this file Here how we're going to pass everything in so we have this posttop map let's see here so let's
comment all this out well let's delete it and now we have this post we'll self close it and let's see here if I could get it to yep there it is component I did the uh options period there but it needs a few things a few missing props that are required so first the idx we'll pass in the index the on delete we'll pass in on delete which will automatically get imported in here We need the post which is just going to be the post that we sent in I don't know why wonder do we
need key and index yeah I think we could do this I'm going to delete this index here I'm going to save this I'm going to put key equals index here delete this I think that makes sense and then is signed in yeah still thinks we need to get rid of this here there we go I think that okay and is signed in remember we created that really nice utility action this one Right here yeah this is authenticated so we can use this here too to see if a user is signed in so we'll go back
here we'll do is signed in equals A8 is authenticated authenticated there we go awesome so now we have this new post and the reason we submit the is authentic is signed in because then we want only users who are signed in to be able to delete it so let's take a look at this all right cool so you can see right here list of all Titles this is the first title I have little X there if I click sign out I'm going to sign in come back here let's see here if I hit sign out
yeah it seems like there's a bug here that it's not automatically removing this here so let's let me double check something okay so I found a little bug and I think it's just caused by the way server components do revalidation but there's this there's this thing called use Transition which kind of be used with the server components and if I use this router. push and a router. refresh in the start transition it fixes it so every time you sign in and sign out it should refresh the fight correctly so here it is I'm signed out
I come back in here now it now looks okay I have the X but if I sign out it's disappeared so I can't click on it again and so let's take a look what happens when I try to delete Click the x button here cool so it disappeared it's deleted I can go back here add another one so add title some other title hit enter it redirects and looks like it's working correctly so the next thing we need to worry about is comments All right so let's take a look at this post and we want
a way for this post when you click on it it goes to this route so basically shows details for this post so I went ahead and just started that process behind the camera Here just to speed up the process a little bit so here if you look in here we have this posts route and this ID right here is a dynamic route so anything after the posts in the URL will be a dynamic route so now here's the pages so this is what I just added in let me explain what it does so first we
have this post here we have this is signed in not using this yet I just added it in and then just like we did earlier with this cookie based Client Post. List I just basically did the same thing but with a git and then I passed in the ID which is the pam. ID now the way this works since we're using a dynamic route in next in between the basically there's a prop called pams that looks like this has prams ID string this is built into next and we can then use that to grab the
ID and so this would be the slug that we're going to use to grab the ID and this ID is being passed in from the Post component so if we look here this post ID is the same one and we'll do a look up on there this git we'll just grab one record we'll use it the a mode API key once again this is a public API if we look back at our resource file from data we know that comments both can read publicly and then we're also going to do a selection set so we
only grab the ID and title and then just like we did earlier on the main page where we did the post. map we're doing the same Thing essentially here but well we don't have a map anymore we just had the values and if you look at post you have an ID and title and so we're just showing the title and then we're going to add comments in here in a second so if we do this refresh it now we have this title the some other title ad if you click on it you can see it
goes to the correct route and the route has the your the that ID number is in the route and looks good so let's see if We can now add comments and it's going to be really similar to what we did with posts so let's see that right down here let's see if we can just grab the data and once again we don't have any comments so we're going to list the comments first even though we don't have any and then add a way to add them to get comments we're going to once again use our
cookie based client since we're on the server we'll do models. comment list once just Like we had before we can do create delete get L get delete all the cred options but we'll do list and we'll do off mode API key and then we'll do a selection set and really we want to grab the content we want to grab the post we'll need that in uh a little bit later and we'll grab an ID now you're probably thinking that this is gonna grab all comments for everyone for all time and you're right so it's grabbing
a whole bunch of content so we don't need every Single one of these comments we just need a a small set of them so we're going to do data all comments and we're just going do a con we're going to do a filter here there is a filter here but as of this recording I wasn't able to get it working to filter just for that post ID it wasn't working properly so this works just as fine maybe once you scale to like millions of comments you may want to be more specific on your comment list
and filter only for the Comments that match this user but for now this is fine so we'll do all comments filter we're going to grab a comment here and we're going to check if the comment. post. ID right here equal equals the pam. ID because we only want the comments that are associated with this ID for this parameter and we'll need to make sure that when we create our comments that they're linked correctly to this basically post and now we should be able to just map through All the different comments so I'm going to come
down here and I think well let's see here we'll go comments. map we'll have a comment and index and I think what I'm going to do is I'm just going to copy and paste what I have here and this is going to save us a little bit of time okay so I have it all copy and pasted in here so here's our comments map it's going to go through all of them I just got some Tailwind CSS in here I'm grabbing the content of the comment I'm Also having this form this is another server action
we're going to do this in a moment but I also want a way to delete comments and then we also have this isign signed in we're finally using it so we also don't want to allow people to to delete comments unless they're signed in and this is going to check to make sure that they're signed in we're also obviously protected by the AWS appsync authorization rules we already added but this is a clear way to make sure that It's going to work so if we save this we come back here and refresh it we still
have nothing so let's let's take a look to see if we can add a way to add a comment for adding a comment I think the best thing to do to start with is probably right above here we'll add a box so this will be a box that adds comments and then right underneath there you'll actually see the comments I think that's the way we want to do it so to do that correctly I we need to create a new Add component component it's G to be a client one client component so I already did
that beforehand once again to speed things up a little bit and I'll explain what's in here so this add comment component takes three props an add comment which is essentially it's a server action that we're going to pass directly in here it's going to create it's going to take a post which is that scheme of post and a prams ID which is type string so this is probably a little Bit I don't love the way I structured this component let me know in the comments if you guys know of a better way we probably could
refactor this the Cod will be available in the description as well but essentially what we're doing is we have this add function that we have a submit function that prevents the default sets comments to nothing and then runs this add comment server action that we're passing in and it's a it's a pretty straightforward form we have it On submit where we pass that ad once again probably not great name maybe we could call it like onsubmit on submit ad nevertheless we have this input here on change we have the values to comment one thing I
wanted to make sure is that once you submit this form that it clears the it clears the input and that's really a lot more difficult when you're using server components so I thought this would make make more sense and then just has submit Here so this looks pretty good let's this add comment let's see if we can add this in as a server action real quickly too so we're going to go back to our actions and then from here we need to add in this this we call it add comment I suppose let's do that
let's do it back from the top export async function add comment and we notice it does take a few props or a few arguments here so cont content let's type string post we're going to use schema and that's going to Have the post in here and then the pams ID type string and then we need to make sure that we import it in from this data resource and then from here if you look at the official nextjs documentation they have an example of using server actions and then using Zod to do some formatting and clearing
and checking and validation for you I did a whole video on Zod if you guys are interested you can look at my channel I'm just going to use just really simple Validation here I'm just going to trim the input that comes in make sure it doesn't equal zero and if it does return I probably should do more validation but just for this I'm not going to I'm going to do wait cookie base client. models comment create and then we have post and content remember one thing that's going to tie this comment to the post is
you have to pass in the post itself self so that's why we're passing it in here and then we can just conso log. comment and Then I always like to do this data comment rename it there comment and then you going do revalidate path so we want to revalidate the path but this is a little tricky because if you come here we have this path right here that has this big posts so that's why we pass in the pams ID so we can re basically revalidate that URL that path so we going do path and
then pams ID and that should be it for our add comment all right we're getting Closer now what we need to do is add in that add comment box into our posts route so I think right above here is where we want to add it so first we have this is signed in that we added earlier might as well use it then we're going to have this add comment that's the server action but we also need to import in the component add component add comment from SL components SL add comment okay so now we have
ADD comment here so it should be complaining that we Need all these props yeah add comment so now we can pass in that server action there and we'll go prams ID which will equal I think it's Pam ps. ID and then we'll need the post and that's this will be the post now I was getting a little error here that it doesn't like it cuz it's not exactly the same cuz so I can just long as it's very similar it'll work here here so I'll do as post and then I just need to make Sure
this gets imported in okay I think that looks good and then this will be null all right so now I have an add comment here here so let's see if this works cool so now I have this add comment box and let's add a comment so here is a comment hit enter great and here it is here is a comment now we have this x here but it doesn't do anything so we haven't figured that out yet but we at least have the comment showing up here is a comment so let's do the delete As
well and if we go back to down here we kind of started that right here with this server action where we have this use server and then we have re validate path but we're not doing anything so we probably should go into the actions and actually add in a action for delete comment so let's add it at to the top export async function delete comment and this is going to be like a normal one that just has form data in it and then we're going to do form data. git and Then we'll have to run
two string on it and if not ID return so if there's something weird about it or didn't they didn't submit it then it it'll just return here and then then you just this is probably becoming familiar to you but use use Kook based client. models do comment. delete and then we just need to pass in the ID which is right there and then we can console log deleted data deleted comment deleted comment delete deleted deleted there we go so now what This will do is it'll delete the comment and it should work here you may
be thinking why didn't you do something like this add comment pass in the prams ID I this form data way of doing it and this is all a server component so I had to if we go back to here since this is a a server component I'm not using a client component here I could have refactored this whole comments this whole delete button situation Into a client component but since I was using server components I thought this was easier just a different way to do it it's basically same thing server actions that we're doing and
then I just add the revalidate path here instead of inside the actions because then I would have to somehow pass I I just felt it was maybe a little bit easier doing it this way I didn't have to pass the pam. ID all right so let's see if that works oh first of course we have to probably call It right so to call it in here we'll need to justwait delete comment and then we'll pass in the form data and it automattic imported delete commented save it refresh all right and if I click here cool
it disappeared so I can another comment two comment number three comment misspelled and each one of each one of them I I can just delete each one and it shouldn't have this x here if I log out so I can click the sign out button okay Redirected back to this front page I click here I could still see the comment and I don't see the X so I can't delete it it's all working as I thought perfect so the last part we want to do is see if we can get this into a production environment
get this website deployed and to do that we're going to use amplify hosting and the New Gen 2 console if you take a look here we've been using this ephemeral environment but really you don't want to use this Per production doesn't make sense this is just for testing locally so what you need to do is log into your AWS console and then you can type in AWS amplify here and this will bring up your your AWS console and what's nice too it has this manage sandboxes button so if for some reason you accidentally you're in
the screen you hit contrl C you press no and it didn't delete the backend you need to delete it later on you can go to here and there it is I can click on it Uh and click delete selected but for now I want to create a new app so I'm going to click new app I'm going to click build an app Gen 2 you can also says public preview right now so as of this recording is public preview and then you can choose option two choose GitHub and what I did before is I actually
put this whole app on GitHub so make sure you push up your repository it's a public repository could be private too if you wanted and now we should be able to Select it so inside the screen here I'm going click next and it's going to ask me to log into GitHub so I'm going to do that really quickly you might have to click gith update GitHub permissions I did that I had to make sure that my pop-ups working but now I should I can click the drop down here and I click this code first type
safety example it's going to ask me which branch to use I only have one main but you can support monor repos and other things there's More advanced configuration if you need I'm going to click next and it should automatically detect everything I need here nextjs amplify deploy here it's going to create a new service role if this here right here if I need to add in any special environmental variables line packages now for build images this since I'm using nex1 14 I have to add in something specific here so to put in this build image
it's amplify colon Al 2023 you can do this after you deploy But it's probably a good idea to do it beforehand and in the future this will be autodetected but since next 14 just came out we have to put in a special build image I'm going to leave everything else defaulted click next and it should have everything else fine here I'm just going to click save and deploy all right so it's deployed you can see here we can take a little bit of a look around cck this little arrow here we can see that it
took about 10 minutes to deploy usually the first deployment does take a little bit of time if you saw any errors here we could go into like the build and look at the logs to see what happened one nice thing is we can click deployed backend resources so if you want to get directly to the Identity or the Cognito user pools you can click right here you can also look the IM rules the Lambda functions anything with the a with the appsync ser service all the links are in This big table of all the resources
that were created it also gives us this domain right now this domain you can take a look here you can click API playground and this will bring you directly to the appsync playground for this so you can start running queries and try it out which is great it also has this authentication uh it has like a little bit of user management so I can add a user here uh gives me some setup instructions a lot of useful information That you might need to use you can also redeploy now each one of these deployments are based
on a branch so this is obviously the main branch but if I wanted to I could connect like a development Branch up all I need to do that would be to go back into my code and create a development branch and then I can connect it here so then every time I push to the development Branch it would create a new deployment that it's really handy that way one thing we can Also do some access controls and hosting we can do environmental variables right now we can't do custom domains but that is coming soon and
there is actually if you guys are interested there is a work around to do custom domains using the AWS CLI if that is a really important feature that you need to look at right now but for the most part this is developer preview so we just really want developers to take a look at it and in the future we'll go ga Which is more a general availability now if we click this link this will actually bring up the app you can see there's a little bit of an issue I notice like this button here isn't
here it's there but I can't see it so if I click on it some of these buttons are missing this is actually a bug and I don't know why it didn't show up locally but this is a weird issue if you are running our amplify UI library and Tailwind CSS at the same time there's an easy fix for it Though so if I go back into my Global CSS and I just copy and paste this code here basically what I'm doing is I'm changing the background color to the internal background color if I save this
and I'm going to go back to my command line get status get ad I'm going to commit it updated I'm going to push and so went ahead and pushed to our app and if we come back here you see it's deploying again so let's give this a couple minutes and see if that fixed That little visual bug we just saw okay so let's see if it's working now I redeployed it I'm going to click this button here let's open up a new window it's running SSR cool now we have our signin button It's Not Invisible
I click sign in let's create a new account and then I'm look on my phone to grab my code that was just emailed to me all right so I still have no titles I'm going to click add title add a new title cool so now I have our new title here I Can click X here and it's deleted click a new one add another title and click into it add a comment another comment all right and if I click here if I click sign out great so this all seems to work fine I hope you
guys learned something I think this is a really powerful tool to create your back ends and and your front ends it works great with the next ecosystem you can use all your AWS accounts one thing I didn't cover too much too was that we Just kind of touched the surface of what you can do with this new amplifi Gen 2 you can add in your own CD K directly in here so if you're already familiar with cdk you can essentially get access and create your own uh Stacks so if I do like let's see let's
call this back end and I look at here I can create a stack if I want to I can also get access to existing resources like here off and data so if I needed to make some changes to data or add some like a custom HTTP Data source I can do it so there's a lot of possibilities a lot of flexibilities here so hope you guys learned something leave a comment below let me know thanks