GraphCMS, GraphQL, and Nextjs - Let's Build A Static Site

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
i think it's about time for me to try out a new headless cm mess so in this video i'm going to check out graph cms and combine it with next.js to build a static website for my learning quick streams let's get into it what's up everyone if you're new to the channel my name is james quick and i do weekly videos on web development related topics and i spend lots of time in the jam stack using headless cmss using static site generators or dynamic page generators or a combination of both with something like next.js i like react and in this video i'm going to try out a new headless cms in graph cms now this is a sponsored video by graph cms but i'm really excited to check this out and create some data inside of their dashboard create schemas and then consume that in a graphql format inside of an xjs application to build out a static site for the details associated with my learning quick streams did i mention that i'm on twitch at james quick every friday check it out all right so let's go ahead and head into the dashboard so we can get started all right so i'm on the landing page for graph cms and uh sure you can have the cookies so let me go ahead and log in and i have already logged in with my github account so it's just going to kind of take me here and i've got a couple of test projects in here from testing this stuff out as you might imagine and uh let's go ahead and create a new project that's going to be blank and we'll call this jqlq for learning quick and this is my learning quick space whatever and then i am on the east coast in the united states so i'll use the us east and north virginia and go ahead and create this project now while this is loading up i'll show you a little bit of what i'm actually talking about so on my the current version of my site which is going to be getting updated sometime soon on the streams you can see like these are all the episodes of learning quick so there's a uh another one coming up actually tomorrow after creating this with jessica chan and then i'm talking about super bass and careers and passion and all sorts of what i consider to be really fun stuff so back inside of graph cms we're trying to kind of replicate that data so that we can consume it in xgs so i'm going to choose a free tier here there's plenty of plenty of plenty of freeness in the free tier for me to use so 5 000 content entries i don't i only have like 50 content entries um 100 megabyte or 100 gigabytes of asset traffic um 1 million api calls i'm not planning on getting anywhere near that so this free forever should work perfectly well for me kind of cool here that they have uh invites for team members so this is kind of something you'll find in some headless cmss for free and some not so it's kind of cool here i don't need to invite anyone so i'll start here and they kind of walk you through like what to do to get started so the first thing is probably what you would expect is to actually set up the schema so i'm going to set up the schema for the actual stream so if i look at a model let's go ahead and create one and this is going to be a learning quick stream and then the id on here we'll just call this stream and then the pluralized version of this would be streams i guess we need to capitalize that like this all right so this is this is a collection of a collection is that a thing collection of learning quick stream details i don't know whatever so go ahead and create that model and now we're going to need to add data so what's the what's the data that we're going to need in here well we're going to need a title for the stream we'll need a date with a time for the stream we'll need a cover image we'll need the guest name and then a description like just a kind of a block of text to write whatever we want to about this now right now this these details are stored inside of air table so when i have someone fill out a form for coming on to a little behind the scenes stuff there for my streams it sends me this record and they send me all the details that i need about them so we'll use a couple of these as an example so let's go back over to grassley mess the first thing we'll do is a single line of text so we'll just go over here and click these fields i really like that this is a nice gui for adding the fields to your schema so we'll call this uh title this is the i don't think we need a description it's pretty self-explanatory we'll use this as the title of the field this is going to display uh this field's value instead of the id in relationships that way it gives you a little bit under better understanding of what record it's actually pointing to cool thing in here they've got validation so uh yes we want this to be required yeah we probably want it to be uh unique we don't need to necessarily limit the character count or anything like that and uh we don't need to set an initial value so we'll just go ahead and uh create that and then we'll want a date field so i'm going to scroll down to date and time because i want to have the time of the stream not just the date that's important so we'll call this stream date again pretty self-explanatory we'll also mark this as required those could probably be unique as well because i can't stream two places at one time i'm pretty good at streaming but i'm not quite that good whatever all right and then a cool thing that we can add in here is an asset picker and this is going to be for the cover image so we'll add the cover image in here we'll have validation to make sure this is required and we'll be able to pick an asset from the stuff that's inside of inside of graph cms that stores our assets for us pretty neat and the last two things we'll need a regular field here as well for a single text this will be guest name and we'll make this required as well and then lastly we will have a description now this will be in the format of the rich text this is a text editor with format text editor with formatting if i can speak english so this will be uh this will be just a description and we'll mark this field as required as well which is nice all right so with uh when that finishes now we have our model now we can actually create a couple of pieces of data so let's start with uh one of these we'll do like two of these i won't waste a bunch of your time just typing in information uh this first one is like going full time with content creation with jessica chan for example um oh i just realized the other thing we might need is a slug we'll come back to that uh this is gonna be friday the third and then they also have the time picker in here so this is gonna be at 11 it's kind of an interesting time picker 11 a.m we'll add a cover image so i'm gonna go and grab the cover image from the site will it let me paste this in at existing cover image i will need to upload can i paste it in here not quite looks like the paste didn't work all right so let me go and save this image i'll call this content creation in our downloads folder and then we'll go and upload this thing inside of graph cms so inside of our downloads folder we'll go to content creation and we'll upload that file now notice when that's finished this image is marked as a draft so the image itself has to be published as well we'll come back to that in a second uh so jessica chan here and then inside of the text now we can add whatever whatever sort of description we want and i'll give the coder coder you should go check her out on youtube and twitter but i'll go ahead and grab her twitter handle her link and we can add kind of the basic things you would expect inside of this formatted text uh thing i can say jessica chan is joining joining to talk about content creation and then i could do like a header uh header two and say social media and follow jessica chan on twitter and uh inside of here i could do a link maybe to her twitter now this doesn't get this doesn't need to be like um oh tooltips that's nice uh this doesn't need to be like super in-depth just so you've got the basic things here of you could do list items you could do uh images the basic stuff that you're used to in like formatted text inside of some sort of editor so we'll want to make sure that we save and publish this this is going to ask us hey this image is not yet published so we want to check that as well so we'll publish the image which will allow us to publish the record and now this data would be live and i'm not going to go through and like enter a bunch of these things i think that's good just for like demo purposes just show you what's there the one thing we did mention though is we might want a slug property so this is a url friendly version that we're going to use for the paths of our streams the individual landing pages so we'll call this the slug description and we'll say generate slug from template yes and then we'll get this from the oh this is kind of cool where you can do this uh this little string interpolation in here so we'll do this as the title oh it gives you intellisense that's nice so yeah this is just going to be the title and a sluggified version those titles should be unique which should make this slug or should let this lug work out really well all right so that is created we've got our model the only one that we need and then we've got our one piece of data and now we can go to the api playground and i'm kind of curious here this is graph cms this is based on graphql which means i could write in a query here and i could say all stream or if i just say stream sorry just the pluralized version of that and then if i wanted to query the title here i could get the title and if i wanted i'm not sure exactly what the format is for the slug will this is it a property directly looks like the slug isn't defined that's because i haven't added it so this is a great test let's go back to our content inside of this record let's edit this and let us generate this slug so regenerate button right there nice and easy save and publish that cool cool so we've got that slug set up for that and we should be good to go so if we go back to our playground if we run this query again we'll see that that slug is showing up so that's perfect so we're able to query the information about it uh the other pieces of information that we'll want is the stream date and the cover image i wonder what sort of format those things will be in uh it's making me query the id here for the cover image and what's cool is if i hold down command and click on this cover image it will show me the uh schema here for that asset and with that pulled up we can see this is a type of asset and if i go into there i can see all the different fields and things that i can work with including there should be a property down here of url so i can query not the id of the image i don't really care about that but the url which is what i want to be able to display the image so there's that actual image there so is there any other i guess we'll also need and one of the things tips here is you can just type a and now you get all these different things pre-populated for you to show you what's there so we want to make sure that we get the guest name we have the stream date we have the title slug stream date and lastly we want the description and uh description is going to take some sort of field so we'll take the raw here it's kind of cool that you can also get markdown out of that as well but this raw stuff we'll be able to use to generate html on our end as well so you could do either the markdown or the raw here and we'll see that in a second all right so that looks good now we can move over to next.js and start to put all this stuff together in our next.js application but the last thing we'll have to do before we do that is go into our project and find out what the url is to make these graphql requests let's go into our endpoints and here is the content api so we'll want to make sure that we use this content api to be able to query that data so that's what we're going to do so i've got a new next.js project created here there's not going to be anything in it now the one thing i'm going to use to make graphql queries is apollo client so let's look at this on apollo client npm i'm curious what other packages you may use for doing graphql so let me know that in the comments below but uh this is the one that i'm going to start with so i will install npm install and i think this is at apollo and then uh client so we'll go ahead and install that package while this is installing i can go ahead and set up a little bit of helper so i'm just going to copy in something over here what we'll do is we'll create a new file called apollo client js and what this is going to do is just configure a new apollo client and we're going to paste in that url for the graphql endpoint from graph cms let's go and grab that again to make sure we have it so this content api will click to copy that and then we'll throw it into this api and now we have graphql kind of ready to display so let's go into our index page in graphql i'm not going to worry about all the details of in here we're not going to worry about making this super pretty either so we'll say this is uh content this is going to be learning quick streams that stuff doesn't really matter and then we'll put an h1 that says learning quick we don't need image here and then we're also not going to use any of the styles that come with us in nextgen so we'll just have learning quick and now what we want to do is on the home page basically create landing or links to the individual pages for the items let's do an npm run dev here to get this started uh is port 3000 is already in use maybe i should kill the existing stuff that i have all right so now i can run the npm run dev that should start this thing up and we'll just see a basic a basic next gs project starting here all right so there is our learning quick now let's start to actually query this stuff inside of our home page so with this home page what we want to do is to be able to use the get static props from next.js to be able to query all this information and statically pull it in at build time and display it on this page so we'll do export async function i get static props and then inside of here we want to actually go and get those streams so let's go back to our graphql api and let's just copy this query and then we're going to use our client to be able to query this stuff so we want to pull in gql which comes from that apollo client and then we also want to pull in the client that we created ourselves so if we look at these auto imports uh yes i know it's kind of fancy i cheated it did it for me but it pulls in graphql from apollo client and then it pulls in the client thingy that we just created that represents our connection to the uh the graphql api in graph cms all right so this thing will return to us something that has data inside of it hopefully and we will await we'll say client.query and then inside of that what are we going to pass well we're going to pass a query parameter which uses gql and then these template literal tags so inside of these template literal tags now we can actually write that query which means i can now copy in this query that we got from graph cms this is going to do any auto formatting for me maybe not so let's tab this over twice and so what we're doing is saying from streams we're going to query the title slug stream date cover image guest name and description and we're going to get all that information so hopefully that is all the data that we need let's go ahead and log out that data here and then lastly from here we need to return this data as props to the component that we're on which in this case is the home page we're going to return an object that has an object of props inside of that object we're going to have this data which i will rename or alias as streams so we'll rename that to streams we'll rename it there we'll pass this in as our props so that will pass into streams which then means inside of the component above we can now destructure streams and hopefully log this out on the front end as well that was a lot of code fingers crossed that any of that works we'll take a look at this in a second so let's go to the home page that we have let's just do a refresh and see what happens cannot find module graphql well that's because we forgot to install one additional dependency which is graphql so let's do an npm install of graphql we'll let that run we'll restart it and hopefully now we'll be able to see some data coming through all right we'll start this back up all right now we're getting this error that's saying not allowed so we need to make sure that graph cms is configured dog so we need to make sure graph cms is configured to be able to accept public request in this case all right so if i come back to the settings tab here there's a public content api here and we'll need to set this for us to be able to access these uh the this data publicly without making or these are going to be unauthenticated requests they're not going to be authenticated so they've got a button here to initialize defaults i say we just do that hopefully this will take care of it for us and then we'll be able to make our queries on this data ourselves all right so hopefully this will allow all read access or read on all models which should be good for the published stage so we've published that thing let's now try can we do a refresh on this page will it re-start that hopefully it did now that it's configured if we go into the console do we see the data coming back we see streams and then we see the actual information that we want so that's looking good so this comes back as uh inside of here i think i renamed data to streams actually what we want to do is since this query here is called or we're querying streams it's going to come back as a property called streams on data so we can then say constrains equals data we can destructure that from our data and in this case we should basically get the exact same thing all right so if we log this out now we get an array with all the information that we want inside of those streams so if we were to uh inside of here if we were to do an unordered list and then we wanted to iterate through each one of these streams and create a link to each one we could use our streams streams.map and that means we'll take each stream and what are we going to return in here well we will return a list item and that item will be an anchor tag and that anchor tag will have a text of stream.title we'll have an h ref of stream dot slug all right and then i will need a key in here for each one of these so we can kind of cheat and use the index of the array so if we grab the i parameter now we can do key equals i and that should get rid of that warning let's see what we got if we do that refresh this page so there's our list item this is a link and if you look at what it links to it links directly to localhost 3000 slash and then the name of the article which is the sluggified version with the dashes and stuff now the one other thing we can do in here is instead of just linking directly to slash and then the slug we may want to prefix this with something so we could do if we use es6 template literals here we could use this as a variable and then just prefix this with slash streams so this would now link to slash stream slash and then where we want to go so this is really kind of small in the bottom there but in the bottom corner you can see this is linking to actually i can just pull it up it's linking just live stream slash going full time with content creation with jessica chan now you notice that this page also doesn't exist so we need to figure that out so what we're going to do is we will create a inside of our pages directory we'll create a folder for streams and then we'll create a dynamic route so this dynamic route says it goes in brackets with kind of a spread operator here and we're going to say we need a property inside of here called the slug so all of these pages that we're going to create are going to be built on top of the slug so that's going to be the url that we're accessing this thing at so i just had a a little snippet here to generate a react snippet and we'll call this the stream page and then we'll have two functions and this one that we're going to need to uh work with we're going to have git static paths so let's export async function git static paths and this is the thing that we're going to use to go and get all the different paths for the different posts and then when we have each of those then we'll be able to use export async function git static props and what git git static props will do is query the information for that given stream based on the slug to then pass those properties into the page to be able to display the information on the page all statically at build time it's pretty cool stuff all right so this query in here is gonna look actually very similar to what we did on this index page i'm gonna go ahead and copy all of this so we'll copy this over into our git static paths and we really don't care about all this information really all we care about inside of here is the slug so we'll just grab the slug for each one of the streams and then we want to use the streams that are in there and we want to convert that to an array of objects that have a params property that then has a slug property all right so what this is going to look like is we'll say that our path is going to be we'll take our streams we'll do a map we'll get an reference to each one and then we want to return an object that object will have one key which is params which will point to another object and that thing will have a property of slug which comes from the stream dot slug all right and then lastly we want to return we want to return paths and not have a fallback so we'll set that to false so this path is basically going to be an array of objects that has a parameter called params and then we'll pass in a key of slug notice that matches what this dynamic parameter is here in the route with that dot dot syntax which means we're going to create a page at slash stream slug for each one of these different streams that we have all right let's try to log out our paths all right and let's just see if that is working so let's try to refresh this page we see a weight did we not mark this function as async no we didn't import all of our stuff so we'll need to import the client again we'll also need to import the graphql all right now let's give this a refresh and see if we're able to get those paths all right so now the thing all right so that is pulling in the information correctly you see we've got an array of objects with a property param that has the slug and we have the slug inside of there so now it's giving us an issue though of formatting inside of here that we want this property this stream.slug to be in an array so we can just wrap this in an array syntax so now we're saying we're going to take that slug and put it directly inside of an array and we'll see now if it's okay with those paths okay so it looks like it's good with the get static path so we're able to figure out each one of those paths now based on that path we want to go and actually get the individual stream to pass all those details in the component so this is for generating the individual page urls this is for getting the information for the individual pages for those streams all right little bit tricky here in xjs but it's kind of cool how this all works so i'm going to uh let's actually copy again let's copy if i have this in my clipboard let's go ahead and query this stream one more time so we're going to query streams but now we're going to do this slightly differently and i'm going to get some more room on the screen here all right so make this a little bit bigger we're going to query stream here but we're going to query it by the actual slug so if we look inside of our git static props it's going to take in a params parameter that params if we do this correctly that params parameter will basically be what was up here so it will have a slug property which means we can grab the slug from params and then we want to use that slug to actually make that query and since this was an array if you remember we'll do uh params.slug of 0 and then we'll just get rid of the destructure syntax in here and we'll open this up all right a little bit better formatting so we're going to query this data and we want to query where this property is matching the slug that we just got so we can do that by passing in a property of variables after this query so after this query we'll pass in a variables and this thing will be our slug all right so that we're going to pass in there and then we'll define our query which is for stream we're going to find that to take in a parameter of what we'll call slug and then it will be of type string and it's required so we'll want to make sure that we're passing that in there and then lastly as we make the streams now we're going to say this is going to be where the slug property the slug property that we're looking for is going to equal the slug property that we pass in all right so we're passing in an object of variables that has a key value pair of slug that comes from the params for this page we pass that into our query we say that we can also call this stream by slug or something just to give this a better name so this is going to take in a property of slug which is of type string and it's required and then under streams we're going to pass that in so we want to query the streams where the slug property of a given stream has to equal the slug property that we're actually passing in all right and hopefully what this will return to us is that individual stream so if we destructure the stream here we could log this out and then we can even get and we may be better off well we can do it like this and we can also say that uh the stream is streams at zero so we'll get that first stream and we can log out streams and stream probably just need one if that will work and then lastly just like we would in our previous example of git static props we need to return this back to the component so we'll say return props and then we'll pass in the key value pair of stream now if you haven't seen this before i haven't clarified this is a little syntax here that is a shorthand for this so if the key and the value are the same name you can just pass in the key like this all right so we've able to get all the paths up here we pass that in to get static props now we grab that slug and hopefully this query will query graphql for that specific one it looks like we might have some red over here so let's give this a shot all right so we've got an error here that comes back from apollo all right so let's take a look and see if we can figure out what's going on there and after a little bit of stumbling around i realized that uh we can just do a direct string comparison here uh for slug so we don't need that equal so we want to say the slug equals that string directly since it's just the string it's a little bit simpler here so let's actually try to refresh this page now hopefully we're able to query this data do we see it logged on here we do which means it should be passed into this page so we can get this at the stream and then inside of here we can have an h1 for the stream dot title alright so let's take a look at that so there is the title then we can have the image and we can use the next.js and we can use just an image tag here and say the source is going to come from stream dot cover image dot url and then the alt will be cover [Music] stream.title cover image let's see if that shows us an image here alright so there's the image that's really big we could use the next.js uh image component which is what it's asking us to do here we could do that but we'd have to uh set up a little bit of configuration to be able to pull these images from grassy mess not something i think we need to cover today but it's able to pull that information appropriately i'm going to comment that out for now the last thing we want to do is uh use the raw uh stuff from the stream um description so if we take string stream description and then take raw let's just see what this outputs objects are not a valid uh or not valid as a react child that's because this is actually an object of all the different components and things that are inside of that raw so we need some way to convert this raw stuff that comes from graph graph cms into our project that we can display so i found this article working with graph cms rich text field i'll put a link to this in the description so you can look at some more details but it gets down into if you're querying text you can actually get the raw which is what we've done or you could get html directly let's actually take a look at if we were to query this html directly from the description we could get the html and if we wanted to render the html in here we could do this but if we come over i think react is going to give us an issue because we're not setting this stuff oh there we go actually it just inputs this stuff as a string so if we wanted this to be inside or actually displayed as html instead of just an html string there we could use dangerously set in our html in react and i never know the syntax of this right off hand so let's go ahead and take a look at what this is basically what this is saying is like do you do you trust that this component uh that you are this html that you're going to render is actually valid and safe and in this case we'll just assume that we do so this is going to be coming from that same thing that we just did so this is going to be stream dot description dot html so this should now allow us to render that raw html onto our page and it actually takes uh one little bit of formatting so inside of here you'll have an html property that our html key that then has the string as its associated property so we'll have to make sure we match that format so now let's go back and you see that this is able to display all the stuff including the link to twitter so it's got the twitter link here it's got the h2 so this is a way that you can take that raw html right out of the input from graph cms and use it that way you can also if we scroll down here there's a couple of different options you could grab markdown so if you had some sort of markdown transformer you could do that so you could get html markdown you could get just regular text which is probably not very helpful and then you can also if you grab that raw stuff you can customize the way these things are displayed so if you were to build a serializer for the different pieces of information you could say hey this render element function for these different types of children if it's a quote if it's a link generate them in this way so that way you can have full control over how you display that stuff but in this case we just took the raw html and displayed that directly to the page so if we go back to the home page we can see if we go back to home page right here and we click on one of these this should now take us to that secondary page that's pretty cool so that works also one of the things we could have done is inside of this home page instead of doing an anchor tag we could have used the next.js link tag so we'll need to import this import link from next link so this would be a little bit more optimal if we go back to the homepage it's basically going to do like some preloading on this page and this should load faster now without having to do a full refresh of the page so that's cool and then just to show how this would work if we were to come back into our data into our content and can we duplicate one of these let's see if we can duplicate this looks like we can't duplicate so let's actually just do another one of these let's pull this upcoming one with superbase i'm going to download this image all right and then we'll create a new record inside of here so we'll create a new item we'll say this is going to be super base stuff this is going to be at some point in the future that time is fine we'll add a cover image in here so we'll upload a new one we'll need to make sure we publish that as well so there's the new image guest name is john myers john is super cool whatever uh notice this slug is already uh specified for us so that's kind of cool uh did this looks like it didn't take our date time maybe because we didn't choose a time so we'll just say okay all right there we go and then we'll publish this and we'll publish the asset along with it and what is cool is from here now if we were to refresh our home page on our next js app we should now see if we do i don't know if we need to restart the server we may need to kill it so it'll query everything again because it's already kind of up and running so let's rerun this again all of that static stuff happens at build time so this needs to run through one additional build process to be able to get this updated information hopefully we see two uh two links here which takes me to the right page and you see this html is being displayed appropriately which is pretty neat so that is graph cms connected to next.js creating static pages and pulling in data with graphql and apollo client i think it all works pretty well i'm curious what you think of graph cms let me know in the comments below if you enjoyed it if you want to check it out appreciate you watching the video and i'll catch you next time
Info
Channel: James Q Quick
Views: 2,478
Rating: 4.9032259 out of 5
Keywords: graphcms, graphql, headless cms, jamstack, nextjs, nextjs static website, nextjs getStaticProps, apollo query, how to query graphql in nextjs, web development tutorial, headless cms tutorial, nextjs tutorial, headless cms react, web development, javascript, react, react and graphql, next js tutorial for beginners, next js tutorial 2021, how to build a static site, how to setup graphcms
Id: oUZLx79AN1A
Channel Id: undefined
Length: 36min 16sec (2176 seconds)
Published: Thu Sep 09 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.