In this workshop, you’ll learn how to build a Next.js app that uses Apollo Client to fetch data from a headless WordPress backend and use it to render the pages of your app. You’ll learn when you should consider a headless WordPress architecture, how to turn a WordPress backend into a GraphQL server, how to compose queries using the GraphiQL IDE, how to colocate GraphQL fragments with your components, and more.
Build a Headless WordPress App with Next.js and WPGraphQL
- Welcome and introduction3 minutes
- When to consider a headless WordPress architecture21 minutes
- Tour of the finished app we will build16 minutes
- Turn a WordPress site into a GraphQL server with the WPGraphQL plugin4 minutes
- Configure Apollo Client to point to WordPress’ GraphQL endpoint13 minutes
- Compose a GraphQL query using the GraphiQL IDE / Implement blog index page26 minutes
- Implement single blog post page / single category page / search pageabout 1 hour
- Leverage GraphQL Fragments27 minutes
AI Generated Video Summary
Let's get started with the workshop on building a Headless WordPress app with Next.js and WP GraphQL. We'll cover the benefits and drawbacks of a headless approach, explore the finished application and blog page, and implement features like search and single blog post pages. We'll also learn how to turn WordPress into a GraphQL server, set up Apollo Client, compose GraphQL queries, and use fragments. The workshop discusses caching, cache invalidation, and the use of Next.js as a static site generator. Various CMS options are compared, including WordPress, Contentful, Sanity, Prismic, and Strapi.
1. Introduction to Headless WordPress
Let's get started with the workshop on building a Headless WordPress app with Next.js and WP GraphQL. We'll cover topics like what is Headless WordPress and why you might want to consider it. Then we'll dive into the live coding workshop where you'll clone a Next.js application and connect it to a WordPress backend using GraphQL. We'll also discuss the benefits of a headless architecture and why you might choose it over traditional WordPress. So let's get started!
So yeah, let's get started then since we're a few minutes past the hour. So thank you, first and foremost, for being here, for tuning in for this workshop. I'm really excited about it.
The title of this workshop, as you're well aware already, is Build a Headless WordPress app with Next.js and WP GraphQL. So what we'll do is, I have a few slides to go over. I'll share my slides, introduce myself, and then go through a few topics, such as what is Headless WordPress, why might you want to consider it.
And after we get through those slides, then we'll dive into the live coding workshop part you actually clone down a Next.js application, get that up and running on your local machine, and then we'll see how we can get that hooked up to a WordPress backend so that we're pulling data from that WordPress backend via GraphQL, then using it to render the pages of our Next.js app. And we'll walk through a few different types of pages and see how each one is built. So I hope you really enjoy it and get a lot out of it.
All right. So let's build a headless WordPress app with Next.js and WP GraphQL. All right. So to start off, I'll introduce myself. So my name is Kellan Mace. I work at a company called WP Engine, which is one of the most popular hosting platforms on the web for WordPress sites, specifically. And it's relevant to this audience and this talk is the fact that WP Engine recently, we launched this new hosting platform called Atlas, which is geared toward headless WordPress WordPress sites even.
I know I start with just a kind of disambiguating or calling, drawing attention to the differences between traditional WordPress and then Headless, and why you might wanna go one way versus the other, as I said. So let's do that.
Oh yeah, before we do that, just one slide here, and that is clone the app repo. I wanted to put this right at the top of the slide deck here, just because it might take a minute depending on your internet connection. But for you to clone down this repository, and then you can follow the steps in the readme there. They'll tell you to CD inside of the directory of this project, and then run npm install to get the dependencies installed, and so on. So if you do that now, that'll save you a minute once you get to the live coding portion later. Then you won't have to wait for the dependencies to be installed and so on. So you can go ahead and grab that that link in the slide on this slide.
All right, so with that, let's talk about traditional or monolithic WordPress. So as many of you on the call probably already know WordPress has been around for a while. So we're world's most popular content management system. At this point the statistic is pretty mind blowing. It's like WordPress has achieved about 43% market share on the internet. That's the percentage of sites online that are running that which is just just mind boggling to think about.
In traditional WordPress, WordPress has a lot of jobs, it's responsible for providing the admin interface that your content creators log into, when they create and edit and manage their content, it's responsible for saving the data to the database. And then when requests come in from, you know, website visitors WordPress is also responsible for pulling the data out of the database, and then templating it out using its theme API, as HTML, and finally responding to that request. So it wears quite a few hats and does a lot of jobs. And in many cases on the web, this is a great setup and works really well.
One way to do that is to use the REST API that's just built into native WordPress. I would argue though that a better choice these days is WPGraphQL. So that's the logo that you see here at the bottom. WPGraphQL is a free open source plugin for WordPress that turns any WordPress site into a GraphQL API, which is very powerful. So then you get all the benefits of GraphQL. In REST API architecture, if you wanted to query for blog posts and users and categories and something else, you might have to hit multiple REST API endpoints just to aggregate, you know, just to get all the data that you need, which can be time-consuming and cause a performance hit. But with WPGraphQL, you have the benefits of GraphQL where you can enter your WordPress data graph at any point and then from there, query however you want. You can say, I want the first 10 blog posts, and for each of those authors, I want their name and other posts they've written. And for each of those, I want the categories and kind of compose these nested queries and get all of that data back in a single network request, which is very powerful. And it has other benefits, too, but that's I would say one of the main ones. This is what kind of a decoupled architecture looks like. And this is the thing that we'll actually be building today.
2. Headless WordPress: Benefits and Drawbacks
When using a headless approach, you can choose a front-end framework to build in components and have a nice developer experience. However, there are drawbacks, such as additional complexity, the need to recreate some built-in WordPress features, the inability to use WordPress plugins for visual elements, and the inability to use the new full site editing features. Let's now dive into the workshop content, starting with the setup portion. We'll explore the pages of the finished app, turn WordPress into a GraphQL server, set up for local development, and configure Apollo Client. Then, we'll move on to the build features portion, where we'll cover topics like composing a GraphQL query, implementing specific pages, and leveraging GraphQL fragments if time permits.
I would argue, you know, these days, many of us in the web development community are really, really appreciate and like to build in a component-based architecture. So, since you're at the React Summit, I'm going to assume you, you know, like React and like building in a component architecture and you get all of that, right? If you go for a headless approach, then you can choose a front-end framework to make things easy and then build in components and have, you know, a really nice developer experience, which can be another perk.
All right, drawbacks. Go through this slide, and then I'm going to check the chat here and see if we have any questions. One is additional complexity. So, you do have a few more moving pieces. Instead of just WordPress, now you have the WordPress site, which serves up data. And then you have your front-end application, which consumes that data. So, a few more, you know, moving pieces there to manage.
Next, drawback would be, it requires recreating some built-in WordPress features. So, some examples here would be user authentication and post previews. In traditional WordPress, a content creator can create a new draft blog and a post, type a little bit of content, and then click a button to preview that post and see what it would look like on the front-end if it were published. So, that kind of thing, you don't get for free. If you decouple your front-end from your back-end, now you don't have a way of authenticating the user and knowing if they're allowed to view an unpublished draft of a post, for example. There are some pre-built solutions people have created in WordPress to bring that functionality to Headless. But just know that it's not something that is kind of out of the box, you know, that you have to put a little thought into how am I going to, you know, add this feature to my decoupled architecture.
This may not be a con or a drawback, though, depending on your project, you know, many times you don't want the client themselves adding all kinds of visual elements to the page all the time and potentially tanking performance and that kind of thing, so this could be seen as a pro as well because you have things more tightly locked down and controlled as far as what gets rendered.
Alright, so let me pause for a moment and I'll pop open the chat and see what we have. Alright. Reading through the comments here. Yeah, I can absolutely pop the GitHub link in there so, let me just do this. Ah, alright, so I popped the link to the Github project in the chat. You shouldn't need that direct link though because you should be able to open the slides that I had shared at 10.05, my time, 10.05 in the chat. But let me copy that one again as well. The link to the slides, there we go. So I put the link to the slides in the chat as well if that's helpful to anyone. Let's see, oh I see a few of you shared the Github link as well, thank you for doing that. Saved me the trouble, okay. Alright, let's continue with this. Then I just have a, yeah a couple more. So that was really it for the slides as far as how Headless WordPress is different from traditional WordPress and then the benefits and drawbacks, I'll resume this slideshow now. The next thing after the benefits and drawbacks here was let's code. So at this point we can actually dive into our workshop and talk about what we're going to build together today. All right, so this is what we'll cover. So here's workshop content, I'm calling this the setup portion. So what we'll do is we'll crack open our finished application and get it up and running in a browser. And we'll look at both the pages that it has as well as the code that powers each of those pages. So for number one, we'll take a tour of the pages of our finished app. Number two, I will see how we can turn WordPress into a GraphQL server with the WP GraphQL plugin. Number three is get setup for local development. Some of you who clone down the project and follow those steps in the readme have done some of that work already, so that'll save you some time once you get to that step. Number four is configure Apollo Client. That's the GraphQL client that we're gonna use in our next JS app to pull data from our WordPress backend. So once we're done with this stuff, our setup portion, then we'll get into the build features portion. So we'll cover these things here. So number five on the list is compose a GraphQL query using the graphical IDE. So I'll show you how you can do that. And then six through nine, here are all about implementing specific pages of our application. So we have the blog index page or blog landing page, we have this single blog post page. Number eight, we have a single category page. Number nine will be a fun one, that's our search page, where people, rather than pre-rendering a static page ahead of time, like we could with some of these other pages, the search one will be rendered on the fly. So as the user types something in and hits a button, will fire off a request in real-time to our back end to find matching blog posts, and then re-render the page to show the matching blog posts. So we'll see how we can do that. And then number 10, if we have time, if we get to it, we'll see how to leverage GraphQL fragments. This way, we can reduce boilerplate, and having parts of our GraphQL queries disassociated with the components that actually use them. So with GraphQL fragment, that allows us to have a single React component and co-locate the data that it needs with the component itself. So it makes your code base very nice and organized. So we'll see how we can do that if we, again, if we have time to get to step nine. If not, though, if we did, or step 10. If not, though, if we just get through step nine, I think it'll still be hugely beneficial in a helpful workshop to see how you build out each of the pages that we'll cover here. All right, and after that, the very last slide on this deck is just helpful links. So as we go through the workshop, I'll reference these things. So number one I've already referenced, right? That's the nextjs app repo. But the numbers two through seven here are things. As we go, I'll just reference the links on this page so you can click these to open them. To dive into things here, what we'll do first is clone down that repo as I said. So hopefully most of you have done that already, but if not, you can click the link to open this code repository. And we'll need to just follow the steps in this readme here. So clone down the repo, you'll cd into that directory and run npm install to install the dependencies. And actually the rest I'll do with you here. So let's dive in. So on the command line here, you can see that I've cloned down this project myself right here to my desktop, and now I'll run npm install just to make sure all the project dependencies are installed, okay? And then once they are, we'll continue with the rest of the steps here. So it's just says, create a new.env.local file in the root folder with this as its contents. Okay, so let's do that. So open up our project in a VS Code window. Let me just resize this for us. There we go, okay. So following the directions here, I'll right click over here and just go to new file. I'll name it.env.local. And inside of this, we're gonna put an environment variable. So I'll copy this right there and then paste that into this file.
3. Tour of Finished Application and Blog Page
The GraphQL endpoint is used by our Next.js app to pull data from a WordPress backend site. If you already use WordPress, you can pull data from your own site by pointing the Next.js app to a local WordPress install. Make sure you have WP GraphQL installed and activated if you choose this option. To run the app locally, use npm run dev and open localhost 3000. You can host the front end and WordPress backend on different hosts, such as WP Engine's Atlas, Netlify, Vercell, or other providers. Tour the finished app, starting with the homepage and the blog page, which displays a grid of linked blog posts. The blog page uses dummy data, but we'll replace it with actual data from a WordPress backend. The blog post page pulls posts from a dummy data file and renders them using components like post list and post card. Our task is to fetch actual data from a WordPress backend and use it to render the list of posts. Let's continue with a tour of the single blog post page.
So this points to the GraphQL endpoint that our Next.js app is gonna use when it pulls data from a WordPress backend site. All right, we'll talk more about that in a little bit. There's an alternative here if you're somebody who already uses WordPress and would wanna pull data in from your own site, you could do that. So if it says, I want to point the Next.js app to a local WordPress install, swap out that with the domain for your local WordPress site. So you can do that, either now or later on your own, if you wanna swap it out and see what it looks like to pull data from a different WordPress site. This is the only thing that you would need to change here.
All right, let's see. If you do choose to use a local WordPress install, make sure you have WP GraphQL installed and activated. All right, and then you run npm run dev to get the app up and running at localhost 3000. And then you can stop it at any time by hitting Control C. All right, so let's see how we can do that. So back on the command line, I'll do npm run dev, there we are. And then I'll just click this link here to open localhost 3000. We'll see our application in all of its glory. So here we go, headless WP app. All right, so this is what we'll explore here. Head back to our sequence of events.
So I'll open up pages in the code editor and then go to blog here, and this is what that page looks like. Cool, thanks for the thumbs up. All right, so here's the blog page. You can see right now we're cheating. None of this is real data here all right, it's dummy data. So what we're doing in this file is we have this directory right here, let me bump up the size actually. We have this directory here called dummy data with an index file inside of it. You can see it just has a bunch of hard coded you know, posts data here. So it mimics the structure of the data. We'll get back later when we do actual GraphQL queries, but for now you see this is just hard coded dummy data. So what our blog page does is it pulls out the posts from that dummy data file and then instead of get static props we tell Next.js, hey, at build time when you're building out this page send through a prop to the component called posts and here's where you should get the data from this, you know, these posts that we imported from our dummy data. And if you look at the component here it does just that, right? It receives the props, destructures that to pull out the posts, then it renders this post list component and that's the one responsible for, you know showing our posts on a list here. So I'll control click through to that so we can see that. So post lists is pretty simple it's just a UL here and then we map over each of the posts and, you know, put one of each one of those an LI with a post card inside of it. And I'll click through to post card and likewise, it's pretty simple too. Right? Just destructures the posts, prop it gets to pull out title excerpt URI, featured image and then it just has an article tag and renders some of the content, you know, of that blog post like that. So that's how the blog post is written here. All right. So our job is to change. This is to rip out this dummy data right here and fetch actual data from a WordPress backend and then use that actual data to render the list of posts. So we'll see these change instead of the Latin titles here. You'll see this page re-render. Once we get it working, with the actual blog post data from our WordPress backend. So that'll be pretty cool to get that up and running. All right. So we've looked at the blog page now. Let's take a quick tour through the single blog post page. So I'll click on one of those and we'll see an individual blog post page here. So our front end app. That would be inside of pages. I'll go to this dot dot dot URI.
4. Exploring Search and Single Blog Post Pages
In this part, we explore the search page and the single blog post page. The search page is currently broken as it relies on dummy data. We discuss how to handle XSS protection when rendering HTML content from a CMS like WordPress. React escapes HTML on its own, but there are considerations when dealing with a CMS. We explain the options for handling HTML content, such as using dangerously set inner HTML or using a library like HTML React Parser.
js file here as well. If you're not sure what this is, like why the brackets are here with the dot dot dot, this is just the Next.js convention. So back in our slides, on the link page here, you could see their documentation. So like number six here, if you're wondering like why we created that dot env dot local file and I said that we were storing an environment variable inside of that, if you're wondering where'd that come from, why are we doing that, this is the answer here. Number six shows you in the next docs how to create environment variables. And likewise, if you're wondering how the file-based routing here works, like with this catch-all route, you could check out the next yes docs to see how that all works. But basically this just is a catch-all route that tells Next.js anything that doesn't match one of the other ones, like slash blog or slash search. If it's something else, use this as kind of a catch all to render our other pages. So we're using that ourselves to render our single post page. So back in our frontend application, what it does is very similar to the last page. So you can see that we're importing post from our dummy data. And then down below, inside of get static props, we're passing in that single post as the props that our component should receive. And inside a component, we're destructuring post to pull out date, title, content, author, and so on. And then using that to render our list here. So with layout component, which just gives the page a bit of margin and padding and a max width and so on. And inside of that, we should have an article tag with all this stuff. So you can see that, you know, here's the title of the blog post. Here's, you know, the, the author's name on, and then a formatted date says where we get this kind of meta information here. Below that, we have the content of the blog posts. You know, all of this HTML gets rendered out. And then at the very bottom, we say, if we have categories, then display a categorized as heading. Let me scroll down here, categories as, and then, you know, map of each of the categories and just display those on the list. That's how the single blog post page is written. And I'll keep on cruising here. In the chat, let me know if any of this is confusing or, you know, needs a little more explanation.
5. Turning WordPress into a GraphQL Server
To turn WordPress into a GraphQL server, enable the WPGraphQL plugin. It provides a GraphQL endpoint for your decoupled front end to hit. The GraphQL endpoint can be customized, but the convention is to use '/graphql'. WPGraphQL can leverage existing caching solutions like Redis or memcached to speed up GraphQL responses. A feature called persisted queries is being developed, which will allow caching responses on a CDN.
So don't try to escape it and just render it. All right, cool. Cool, yeah, excellent question there.
All right, so let's keep going, then. So we just got through with our tour of the finished application, right? So let's dive in deeper now. The next step on our list of things to cover is turn WordPress into a GraphQL server with WPGraphQL. So I'll show you all how to do that. But you won't actually need to run a WordPress site yourself on your machine. Instead we'll just use, we'll just connect to a WordPress site that's live on the internet.
So you can see here I'm using a free app here called local for running WordPress sites locally on my machine, and I will just start up one of these sites and then go to the WordPress admin screen. So let me log in to this site and I'll just show you a couple of things. All right, so here we're in the WordPress admin. How to turn your WordPress backend into a GraphQL API is by enabling that WPGraphQL plugin I mentioned. So that's here. If you don't have this on your site, you can just click add new right here and go ahead and search the WordPress plugin directory for WPGraphQL and then just find it on the list. So there it is, WPGraphQL. So you'd install and then activate that and then you'd see that on your plugins list right here, all right?
Once you've done that, that gives your site a GraphQL endpoint that your decoupled front end can hit. So if you're wondering, well, what is it? Where is that GraphQL endpoint, right? What you could do is in the sidebar here, you can go to GraphQL and then on the settings page right at the top, it just shows you what the GraphQL endpoint is. You could customize it but the convention is just use slash GraphQL here. One note too, anybody who's, if you're jotting some notes and you wanna do this on your own WordPress site, one thing I would make sure to do on this page is on your local environment is to enable GraphQL debug mode here. This is hugely helpful where in your front end application, if some queries you're trying to fire off are failing, instead of getting very opaque, unhelpful debug messages coming back, if you enable this and you'll get much more helpful with debug messages. So just a note there if you're running WordPress site and doing this kind of thing, definitely enable debug mode and it'll help you out on your local.
So let's look at this endpoint then. I will go ahead and command click on this to open it in a new tab. You'll see I just get a JSON response back if I try to visit this directly in a web browser, it just says GraphQL requests must include at least one of these parameters, query or query ID or whatever. And that's because I haven't provided a query, right? All I did is send a get request in a browser to this endpoint, we didn't provide any data. So this is the expected output there.
So that's how you would do this on your own WordPress site. For us though, we're going to use a pre-defined GraphQL endpoint. So let's see, I'm gonna close this stuff, we don't need to look at that anymore. What we're gonna use instead is this endpoint here, so this would be number five on the list of links. If you go ahead and open that in a new tab. Oh, there we go. So that should send you to this content,.wpgraphql.com slash GraphQL. So this is the endpoint we're going to use so that you don't have to worry about running your own local WordPress site. And if you notice, this is the same one that we had popped into our.env.local file here. That's where this came from. So we'll go ahead and use this for the rest of the workshop as the site to pull our WordPress data from. All right.
So that was number two that's how to turn WordPress into a GraphQL server with the WPGraphQL plugin. So I'll pause here and check out the chat and see if there are any questions here. Let's see. So is it safer to avoid dangerously set innerHTML and instead use a parser library? In most cases, no. If you look at some popular like parser libraries that are out there, including the one we're using in this project, they themselves use dangerously set innerHTML actually. So if you look under the hood at the source code of those, they might try to, depending on what the HTML looks like, they might try to render it another way, but as like a last resort or a fallback for rendering the content, they themselves would use dangerously set innerHTML to achieve the same thing. So, no, I wouldn't say it's more or less safe. A parser can be helpful if you wanna swap things out. So let me do, show you a quick detour here. So I maintained this site with my team at work, developers.wpengine.com. We used to have like lots of resources, articles, videos and all kinds of stuff on doing this kind of thing, doing headless WordPress. So one of the articles that I wrote recently is on working with Gutenberg data and it kind of speaks to this question that we're talking about right now. So it's this blog post I wrote, Gutenberg and Headless WordPress colon render blocks as HTML. So if I open up this blog post page, I'll show you one. Oh yeah, our syntax highlighting is actually broken at the moment. This is a bad demo, I'm sorry. But anyways, this is the section I was thinking of. So use a parser to convert some blocks to components. So this is something that you might be interested in. So like in Next.js, you know, you wanna use the Next.js link component for instance, so that you get the client side navigation for any internal links, but out-of-the-box, what WordPress will give you, if you have any internal links inside of your content, it'll give you just a regular anchor tag. So the result is in your front-end application, if someone's in the middle of reading a blog post, and then they click something that's an internal link, if that's just an anchor tag, then they'll get a full page reload, right? It'll still work, it'll still send them to the next page, but it defeats the purpose of using a single page app framework like Next.js. That's capable of doing the really quick client-side navigation. So in this blog post, I go through how to swap out, you know, those anchor tags for your internal links, how to swap those out with a link component, so that you get the nice, quick client-side navigation. So that would be one example of when you would wanna use a parser beyond just escaping HTML like we're doing here. I'll put this blog post in the chat in case any of you are interested in what I'm talking about. You know, this post can be helpful. Yeah, I'll just put this site there as well if you're interested in any of our walkthrough videos and so on.
So M has another question. Does this endpoint cache queries? This is an excellent question as well. So wp-graphql that we're using here, this is what we're using for our API layer, right? To allow WordPress to talk back and forth through our ConnectedJS front end. It, I want to think of how to phrase this. It can leverage any existing caching solutions that you can use on the WordPress back end, such as Redis or memcached. If either of those are used, like an object cache, then wp-graphql will also see speed gains from that. So if you have a certain query that, every user who hits a certain page of your site, if you have a certain query that's always run, then what Redis would do is, it would see that database query and then cache it in memory so that the next time a request comes in, it would serve up, you know, the response to that from memory. So it'd be much, much quicker. So, yeah, you can use, you know, existing caching database, caching solutions like Redis or memcached, those would work to cache and speed up your GraphQL responses. I'll go a step further though. One really exciting thing is Jason Ball, who's the creator and maintainer of wp-graphql, and another guy, Mark, they're working on a feature called persisted queries right now for wp-graphql. And this is going to take the caching story to the next level. What this looks like is a request comes in for a query, and then after it gets resolved, that gets saved in some kind of, it could be saved in memory cache like Redis or memcached, but beyond that, the JSON response is stored, can be stored like on a CDN. So that means you could distribute, you know, the responses to your GraphQL queries, you could distribute them all over the world at data centers using a CDN. So that means some user who's in Tokyo in Japan or something, if they're trying to visit your site and fire enough of GraphQL query, that query would hit their local data center within Japan, see that, oh, we have a cache response for this query that's still valid and immediately return that. So this round trip, going to the origin server wouldn't even be necessary anymore. Just serve up the responses right from the nearest CDN data center. So that's where WP GraphQL is headed, which is very exciting to me. This would be what I'm describing is similar to other solutions, like GraphCDN is a popular product that does this kind of thing where it takes GraphQL responses and then caches them like across the globe in a CDN. But pretty soon native support for that, that kind of thing, persisted queries will come to WP GraphQL. So I'm really excited about that. That'll make, like I said, take the caching game like to the next level.
6. Setting Up Apollo Client and Checkpoints
We've covered the setup steps, including turning WordPress into a GraphQL server using the WP GraphQL plugin and setting up for local development. Checkpoints are available in case you fall behind. We recommend using Apollo Client for a real-world project to enable in-memory caching of queries on the client. The Apollo Client configuration involves installing the necessary packages, initializing the client with the GraphQL backend URI and cache type, and connecting the client to React using the Apollo Provider. TypeScript is not necessary for this simple project, but it can be beneficial for larger, more complex projects.
So I'm really excited about that. That'll make, like I said, take the caching game like to the next level. So stay tuned for that if you're interested, you could, follow the blog here or follow the Twitter account for updates.
Alright, okay, I think that's it for questions so let's keep rolling on the conference. These are excellent questions, so thank you so much. Let me know if you have more.
Alright, so what have we done? We did a tour of our app. We've seen how you can turn WordPress into a GraphQL server by using the WP GraphQL plugin, next Git set up for local development. So some of these steps we've done already, that would be these steps here in the readme, so we walked through these already. Yeah, so we're good there. One more thing I'll mention though is this bottom section here, checkpoints. So this is very important for our workshop. Let me blow up the text a bit. So this says, you can check out these commits in Git to get caught up if you fall behind at any point. Alright, so as we dive into the code and you're actually, you know, meshing on the keyboards, making these updates to the site, trying to get things to work. If you fall behind at any point and the group is, you know, done with one, done implementing one page and we're ready to move on to the next one and you feel like you're kind of falling behind, it's not a problem at all. What you can do is just run on the command line run, Git checkout, and then just paste in this commit hash right here, and that will get you up to date. So the first one here would be, and just remember that this is the commit after we create the blog index page, this is the commit for after we create the single blog post page, and so on. So if at any point, you know, you're feeling like you're falling behind, just don't feel bad at all, just go ahead and check out this commit and that'll get you caught up with the rest of the group. Alright, but if everybody followed the steps, you know, you have your env.local file there and you ran npm run dev, you should be, you know, in the same spot I am here looking at the front end application. Can anybody in the chat, can you give me like a thumbs down or something if it's broken and you weren't able to boot up this application? Just let me know, I'll stay tuned for those.
7. Using Apollo Client
We'll be using Apollo Client to fetch data instead of using dummy data. Let's continue with the workshop.
So this app does use it, or will use it as soon as we wire it up. So that's kind of our job. So instead of blog right here, you can see I'm importing two things that we're not using yet. So like on our blog page on this site, I'm importing GQL from Apollo Client. And also importing the client that we had created inside of this Lib folder right here, this thing that we saw, I'm importing both of these. But if you notice, we're not using these yet at the moment. And that's because our data is just coming from this dummy data file. So our job will be to rip these lines out so that we're not using dummy data and actually use Apollo Client to do the data fetching. So I hope that's helpful. So yeah, that's where we're headed. We will be using Apollo Client for this project. Great, I think that's about it for the chat then. So let's keep rolling.
8. Composing GraphQL Queries with the GraphQL IDE
To compose a GraphQL query using the GraphQL IDE, you can use the graphical app. It provides a nice IDE environment where you can compose queries by selecting the desired data fields. As you select the fields, the query is automatically composed for you. Once the query is complete, you can execute it and see the data that your front-end app would receive. This is a helpful tool for building queries and getting a preview of the data that will be returned.
So remember this, you know, WordPress site that I had started up earlier just to show you what it would look like to install and activate the WP GraphQL plugin. If I go back to the WordPress admin, it actually provides a GraphQL IDE for you right in the WordPress admin. So if you do this on your WordPress site, what you would be able to do is hover on GraphQL, go to graphical IDE, and it gives you this really nice IDE environment that you can use the composer queries. And it's going a little slow here. This is not a great demo. What is happening? Okay, I don't know why it took a long time at that time to load up, I'm not sure why, but this is what a graphical looks like. So it's a really helpful app for composing queries so you can do stuff like this.
9. Composing GraphQL Queries with the Graphical IDE
In this part, we'll compose a GraphQL query using the graphical IDE. We'll start by checking the boxes to build the query for the most recent blog posts. We'll include fields like database ID, title, excerpt, URI, and featured image. This will allow us to get the necessary data for our blog page. Let's dive in and start coding!
So let's do that. I'll hit the play button and there we go. So here are the post nodes that I get back. So you can see each of these objects is, here's the date, here's the content of the blog post, here's the title of that post. So this is super handy. You can keep modifying this and keep checking boxes until your query looks good and the data coming back is what you need for this particular page or component of your front-end app. So once you're happy with it, then you can just highlight all of this, this query that you have had written and paste it into your front-end app. And that's what you tell Apollo to fire off. And then you know the shape of the data that you can expect to come back. This is super handy. So this is one example of the graphical IDE that the wp-graphical plugin gives you. So you can use it here right inside of the WordPress admin. For us though, we're gonna use a free hosted version of GraphQL to build our queries. So, back on our links page, that would be number seven here. So if you click on number seven on the links page, open this up, that'll send you to this page. So that's graphicalonline.com. This is a cool little free hosted version of GraphQL that you can use. So for us, who can guess what are we gonna use for a GraphQL endpoint URL here? If you guessed the one from our EMV file, you win, you are correct. So let's do that. We'll copy this whole thing from the.emv.local file. That's the GraphQL endpoint we're gonna use. And we'll paste that here and then hit this button. All right, and you can see it looks pretty similar to what I showed you in the WordPress admin. We still have the query explorer. We still have this area to compose our queries and in this area to see the results of those. And you have some other options like to add headers or whatever, if you'd like to. All right, so we're set up now to use that endpoint to this content site. And if you're curious, this is what the WordPress actually looks like. So if we try to just go to this domain, you can see that it's a WPGraphQL WordPress site. It looks like this. If you let WordPress handle the rendering using a particular theme, I think this is like the 2022 theme or something like that. Then this is what it would look like. But instead what we're doing is saying we wanna hit the GraphQL endpoint to get just raw JSON back because we're gonna handle all the rendering in our Next.js app. So that's kind of where that came from. All right, so back in the hosted graphical here, let me know if you all were able to go to this link and then paste in this GraphQL endpoint because we're gonna be spending some time here composing our queries. Can we give me a thumbs up, if you made it to that point in the chat and you're here? All right, cool. I'm seeing some thumbs up. All right, so let's figure out what we need here. So going back to our to-do list, where were we here? All right, so compose a GraphQL query using the graphical IDE. So let's actually do that, right? We'll dive in now and do some coding. So as I showed you before, you could check some boxes here to compose these queries. So you can go to posts, starts building the queries for us, or I'll show you how there's another autocomplete feature. So everybody, let's try to do this, just this together here. So everybody open the Explorer. If it's not already open, you can hit this button here to open the GraphQL Explorer. And once that's open, scroll down until you see posts right there and then click to expand posts. And then we're going to click again on nodes because we're interested in getting each of the individual post nodes. So click again there. So you should see this, the queries, it starts composing the query for you, and we're going to get a few pieces of data. So just pause, bear with me one second here. Sorry. All right, so let's start getting the data that we will need for our blog page. Give me a moment, just like a minute setup here. Okay, I think we're ready. All right, so back here, we were going to do posts and then nodes. And then inside of there, we're going to need some pieces of data. I'm sorry, one, I checked out the wrong. I admit I'm a finished app that has the fields. I'm using a cheat sheet here. There it is, okay. So now I know which fields to tell us to query. All right, so the query we're going to try to compose here is the one we need for our blog post page. So as a reminder, that's this one, right? We're going to compose a query to tell Apollo client and ultimately tell WPGraphQL that the query we want to run is for the most recent blog posts here. So let's see how we can build that. All right, so we'll need posts, nodes. And then inside of this, we're going to check some boxes. So we'll do, the first one we'll do is database ID. So inside of nodes, if you scroll down and find to the Ds, click database ID, you'll see that it pops that into the list. Next we'll get the title. So scroll down to the Ts and click for title, right? If you like this workflow of clicking the boxes or checking the boxes, you know, this works great. Another trick is you can use control space. So I use this a lot. So for example, if you're like nested, if your cursor is nested like this, you can just scroll somewhere inside of your query. So I'll just hit enter to get a new line. And then from here, if I hit control space, I get auto-complete here. So you can see I can using the arrow keys, I can go up and down. And then as I type, this list will get shorter and shorter and I'll try to auto-complete the thing I'm typing. So the next thing we're going to get is excerpt. So I'll try to type that. So if I type ex, you can see already it's narrowed the list down to excerpt. It thinks it knows what I'm trying to type. And if the highlighted one is correct, that that's the one you want. And if you'd enter, you see it pops in excerpt for you. So this can be a quick way, I find that if you're somebody who doesn't, if you feel like you don't know what the GraphQL schema looks like very well, that WordPress gives you, then the check boxes are really handy because you can visually see all of them. Otherwise, if you've done this kind of thing before and you're somewhat familiar with the GraphQL schema, that's when doing, you know, this auto-complete to just drill down to the thing that you want quickly, that's when it is more helpful, I think. So we'll get excerpt. The next thing is URI. So U-R-I, that's the URI or the URL of the blog post, for example. The next thing we'll get is featured image. So this one, it will have some nested fields inside of that.
10. Querying Featured Image in GraphQL
Here's how to query the featured image in GraphQL. You can get the source URL and alt text of the image. Remember to handle cases where the featured image is null. GraphQL provides explicit information about the possible types of values, allowing you to know exactly what to expect in your Front-End JS App.
So this is our first time seeing this. So here's featured image in the Explorer, and you can see that it has a dropdown here. So if I expand this, here's featured image. It tells me it's going to throw an error saying, oh, you need a selection of subfields inside of this to tell GraphQL which fields you want. So in our case, we'll just get a few of them on the featured image node. So featured image, and now click on node, like that. So you should be at this point. And then inside of node, we're just gonna get two fields. So the first is source URL. So there you go, so let's scroll down to the S's and then check source URL. So that's the URL where this image actually lives, this actually, you know, JPEG or PNG or whatever, that's the URL to it. And then for accessibility reasons, we need our alt text as well. So I'll scroll up and click the checkbox next to alt text. Just like that. And this is really it for our query here. Yeah, I can show you, we'll pop in maybe one variable just to specify the number of pages. But for now, if you've built this up, go ahead and click the play button to execute this and then see what you get on the other side. You should be looking at something like this where you have each of the post nodes and then inside of there you have, what is the database ID? What's the title? What's the excerpt URI? A featured image for some of these you might notice is null, right? You might think, oh, is this a mistake? Is it a bug or something? But it's not. All that means is this particular blog post doesn't have one. There is no featured image attached. So we'll need to account for that in our front-end JS app, we'll need to say, is there a front-end, is there a featured image? If so, then go ahead and render to the page. Otherwise, if there isn't one, then don't attempt to render it. So have to account for that. All right, and GraphQL is super cool because it is very explicit about what every single value could possibly be. So if I hold down command, I'm on a max, if I hold down command and then click on featured image, right here, it pops up in the schema documentation and you can see what the type of this thing is. So the type of node right here for featured images is this media item, type in GraphQL. If I click through to that, you can see all of the fields that it has. So here's like Alt Text, all the types that Alt Text could possibly be, so it's always a string, for example, but other things in here, you may see that, well, it could be Null sometimes, other times it could be a string, and so on. So it's very handy for the fact that it's so explicit so you can know exactly what the possible types are in your Front-End JS App.
11. Composing the Query and Setting Pagination
Let's pass in a variable for how many posts we want to retrieve. By default, it's set to 10, but we can increase it to get more. For example, we can select the first 18 posts by specifying 'first: 18' in our query. If we want to start from a specific post, we can use the 'after' parameter. In this case, we're starting from the most recent post by setting 'after: null'. This way, we'll get the first 18 posts from the beginning of the list.
All right, so this is it for composing our first query with one exception. Like I mentioned, let's pass in one variable here for how many posts. So the default is 10, I believe. So this will give us 10 blog posts. Let's say we want a few more on our Front-End App, what we can do is pop open some parentheses here. So after posts, pop open some parentheses, and you can see our options at this point are after, before, first, last, where, so you do some like pagination and some filtering options if you want to only get certain posts. So in our case, let's select first, and we'll say we want the first 18 posts. So instead of just the first 10, which is the default, we'll just bump it up a little bit. So you want the first 18 posts. If we were doing pagination, we could say after and say get the first 18 after the one on page three or whatever further on down the list, but just to be explicit, we can say after null, meaning start at the beginning with the most recent post. So we'll leave it at that just to be extra explicit, we'll say after null. So we're getting a post, the first 18 of them after null, so we're starting at the beginning of the list. So now if we fire that off, we should get 18 or however many there are, if there are only two blog posts, then you might only see two on this list, but we're getting all of them up to a max of 18 there.
12. Fetching Real GraphQL Data
Let's define the query we need in our front-end app to fetch real GraphQL data. We'll use the gql tagged template literal from Apollo Client. We'll define the query, name it 'get posts', and pass it through gql. Next, we'll use the query const we've defined to fetch data from the WordPress backend using Apollo Client's query method. Once we get the response, we'll drill down to the blog posts and pass them as a prop to our component. Finally, we'll save the file and see the live data displayed on our front-end app.
All right, so let's, I'll go to the chat again, let me know how you're doing. Can I get some thumbs up, I'll do a dividing line in the chat. There we go. I get some thumbs up if you're able to compose this query and then check the box to execute it and see the results on the other side. All right, cool. Great. Yeah, so this is the query that we need in our front end app and that we're gonna use to fetch our data. So this is exciting. Let's actually make use of that now. So pop back open VS Code or whatever code editor you're using, and like I've said a few times, our job is to rip out the dummy data and get this actually working with real GraphQL data. So let's do just that.
So our front end page, bye-bye front end page, you're gonna break as soon as we do this, right? So I'll have you highlight these lines with the dummy data and delete them and then as soon as they save that, your front end app will crash and burn if we try to reload it here since it doesn't have the data it expects. So let's fix this by giving it the actual data from the WordPress backend. So I'll show you how to do that now. So what we need to do is use this gql. This is a tagged template literal is what it is from Apollo Client and inside of that, we're gonna define what our query is. So let's do this. Right above where the blog component is, type this. We'll do const and then get posts and all caps just like that equals gql and then two backticks just like that and then a semicolon after it. So if you read through the documentation on Apollo Client, you'll see this convention you use. It tells you to use this gql tagged template literal and then pass inside of the backticks the query that you'd like to run. So that's where this is coming from. So inside of these backticks, I'll just hit enter twice to make a little space. And what we'll do is we're gonna return to graphical and copy this whole thing that we had composed right here. I'll copy that and then paste it between these backticks like this. I'm getting syntax highlighting here because I have a certain VS Code extension installed. I have this one, Apollo GraphQL. So if you like working with GraphQL and Apollo and want the syntax highlighting within these GQL tag type of literals and other features, then you could install that if you want the Apollo GraphQL, but otherwise, if you're just seeing a solid text here, if it's all white or whatever, that's still fine. It'll still work just great. All right, so we've defined the query that we want here. Maybe one other change, instead of just calling it my query, I like to be a little more explicit. So we'll just call this like get posts like that. So then if in the browser console, Apollo Client is like throwing errors or whatever, it's referencing a certain query that's broken, there's the name that we'll see. It'll say the name of the query that failed is get posts. So we'll know which one that is. That's why we give it a name there. All right, so this is it for defining our query. By creating this query, passing it through GQL, that'll turn it into what's called an AST Abstract Syntax Tree. That's ultimately what Apollo Client, you know, expects to receive and can use to process the query. So that we actually use this const we've defined here, right, so that would be the next step. So let's do that. We'll scroll down a bit. So go to get static props here. And anybody who's not super familiar with Next.js, get static props is an next jazz convention that they give you. They say that if you export an async function from your component file called get static props, then anything inside of this, Next.js will run at build time. So it'll effect, do any data fetching and anything you want to do build time and then pass these props through to the component when it renders on the Next.js server. So this is not something that the site visitor would ever have to wait for. This is done ahead of time when the page builds. So this is a perfect spot for us to do our data fetching. So we're going to make use of our client that we had created then. So at the top of the file, remember we had imported this client from lib, Apollo client, just like that, that's the thing we're gonna use. So at the top of this, we'll just hit enter a couple times and then we'll define another constant. So we do const response, we type that. Equals. We'll await the response of this. So we'll await client.query. All right, so I'll start with just that. So this means we're taking the Apollo client instance we had created, and then calling the.query method on that. And we're going to pass in info about the query that we would like Apollo to run. And then we'll get the response back. So inside of these parens, then we're going to pass in an object. So go ahead and open some curly braces like that, hit Enter, and then we're going to say query colon. And this is where we pass in the query. So for us, that was getposts, all caps, just like that. So that passes in this query that we had built up at the top. All right. So once we get the response back from that, we have to actually make use of it. So instead of this postposts thing, so delete that. And then instead we're going to drill down to our blog posts. We're going to do response.data.posts.nodes. Just like that, I give you a second to type all that. So if you're wondering in your app, how you would know to drill down that far, GraphQL is really cool in that how you structure, the levels of nesting here, how you structure your query, the response that comes back will match that, which is very cool. So if you look at here, we had query, posts, nodes, and then the fields, the response is data, post, nodes, and then the fields. So if we drill down that far, and then the fields, right? So it follows that same structure. So that's where this posts and the nodes comes from. It comes from our own query. Cause we said, we'll add posts and then nodes, right? And that's where our posts would live. All right, so we're trying to drill down to each of our individual post nodes. And we're passing that as a prop, called posts into our component. Our component then is destructuring, and pulling out that list of posts, and trying to render our list of posts on the page. So I will save this file, and then return to the front end, and we'll cross our fingers. Shazam, there it is. It's working. So you can see no more Latin. We had the Latin titles, you know, with our dummy data. No more Latin titles. This is the actual live data coming from a real WordPress site. So this is super cool, right? You can see we have the titles and excerpts being displayed here. And these are linked. So if I click on one of these, it'll try to send me to, you know, the single page for the blog posts that I had clicked.
13. Implementing the Single Blog Post Page
We specified a max of 18 as well. If you get more advanced, you can do pagination stuff. If you're getting a type error, try console logging the response. Make sure Apollo client is configured properly. If you're still having issues, use the provided checkpoint. We're done implementing the blog index page. Let's move on to implementing the single blog post page. We'll build a query to use instead of dummy data. We'll use the URI to look up the blog post. Create a new query to get a single blog post. Let's go to the GraphQL Explorer and find 'posts singular'. Let's create a query that gets the title and date fields. Leave the ID blank for now. Your query should look like this.
And we specified a max of 18 as well. So if you count these up, there should be, you know, 18 of these. Once you get more advanced, you can do pagination stuff, where you could either do infinite scroll where you just load more in right away when the user scrolls down, or have a load more button and load more. But for us, we'll just stop here and display the 18.
Alright, so check the chat real quick. So Vaka, I see. So type error, cannot read property data of undefined. Okay. So it sounds like that's coming from this point in the code, right? Saying that you're trying to drill down to data, but response, this thing is undefined. All right. Let's see. I don't know why that would be. One of the first things I would try is just console logging. This I'd probably just do console log, the response here, save that. And then if you open the terminal, you should see that data printing out. I'll try to reload my blog page and we'll see if it prints out. Yeah, it does. So if I try to reload my blog page with that console log statement in place, you can see that this is what it prints out for me. So you have any data posts, and inside of that there's my array of nodes, and then a few other things, loading false, network status seven. So this is what is expected in that response. If you're getting something different, then it must be an issue with Apollo client, you know, not being configured properly. So I would just do some checks, make sure on the repo here, make sure you did all of these steps just right and you're defining this environment variable inside of the.env file just like this, it has to look exactly like that. Yeah, and this is typed as it should be, just like that. So hopefully that's enough, if you're not able to get it working, then you can always use this checkpoint here. So we're done, implementing the blog index page. So Vacha in the chat or anybody else, if you were struggling here and had issues getting the blog post page working, at this point you could run git checkout and then paste in this commit hash and that should get you back up to speed. So you should be able to... I would try git checkout with that commit hash and maybe doing command C or sorry, control C just to kill the Next.js server and then npm run dev again to get that backup and running. And at that point, you should see the blog page working like this. Alright, oh, amazing, fixed. Good, happy to hear it. Cool okay, we'll keep rolling then. So hopefully you're all having fun. So number five was, we saw how we could compose a query using GraphiQL and we've accomplished number six as well, implement the blog index page. By using that query we had composed, we told Next.js to run that at build time and then pipe that as props into our component and use that to render the page, right? So onto number seven now, so implement the single blog post page. So as a reminder, let's, oh, let me get rid of my debugging lines there real quick. Okay, so as a reminder, let's just take a look at our single blog post page. So that was this dot dot dot uri catch-all route here. So if you go back to that, we will see, yeah we'll just remind ourselves what this looks like. So again, we're pulling out the dummy data, you know, called post and inside of get static props, we're just sending post through, you know, as the props and that's what we're using to render the content. So it's just dummy data at this point. So here we'll follow that same pattern where we're going to, you know, rip out our dummy data and then go build a query to use instead. I'll go ahead and delete that dummy data and let's head back to our hosted graphical instance here to build another query. So one cool thing I'll show you is you can define multiple queries here that's allowed as long as each one is named. So like this one, we had called our getPosts query like that. And you could have multiple here as long as they each have a unique name. So you can do query get Post singular and then have inside of here, have another query. And then when you go to execute it, GraphiQL will ask you, well, which one. You'll use this dropdown and say, do you wanna execute usePosts or usePosts? And you could tell it which one you want to run. So that's one cool way. If you don't wanna delete, the thing you had worked on building the first time, if you wanna kind of leave it in place or you're testing or whatever, it's okay to have multiple as long as they have unique names and they can run them, each of them. For us though, let's just delete these and start from a clean slate. So this one will be a fun one because this will be our first GraphQL query that accepts a variable. So in the last one we just said, give us the first 18 blog posts and that's it. I guess technically we had a variable because we said the number 18 is how many we want, but this one will be a real variable where we'll pass in the slug, the URL slug the user is visiting. We'll use that to look up the particular blog post that's the correct one, whose data we need, if that makes sense. Let me show you. I'll just, let me just put the data back for a second so I can show you what I mean. So what happens is if somebody is on the blog page here and then they try to click through to one of these posts, this is the URL structure, it sends them to... You know, we have like the date here and then adding end to end test to WordPress. We have this whole thing, which is called the slug in WordPress. So we have like this date structure and then the slug after it, and this whole thing, all of this, the date plus the slug, all of that is called the URI. And that's the thing we're gonna actually use to look up the blog post. We're gonna tell WordPress, hey, find the blog post that has this whole thing as its URI. WordPress will find it in the database and then provide the title content, you know, all the data that we asked for. So this is what we're gonna use as our variable that we send in to our query that we're gonna build here. Alright, so let's do it. Okay. So here, let's create a new query to get a single blog post then. So over in the GraphQL Explorer, let's go down to the P's, element of P and find posts singular. So click on that. And already, you know, just like last time, it'll start building the query for us. And it even knows that post requires an ID because it asks, oh, well, which post do you want? So we'll have to address that here. So for the ID, yeah, you could, if you want, for testing purposes, you could pop in a value here. Even if you type a value, then that's the thing that would use as the ID. For us though, we want this to be dynamic. So it'll pass in a different, you know, it'll give you a value variable for each blog post. So I'll just leave that off for right now. I'll show you how to turn that into a variable. Or actually I guess we could just use this one. Let's see if we can get that working for demo purposes. Alright, so if I say that's the ID and I have curly braces and say get the title, does that actually work? Yeah, it doesn't, the ID isn't. So let's not attempt to do that right here. I'll leave ID blank for now. We'll just focus on the fields that we need. So your query should look like this. We can rename it though instead of my query, you could do, you know, get post. For instance, I think I called it Get Post by Slug in our project. Yeah, okay, so let's continue with the fields then. So inside of this, we wanna get the date as the first field.
14. Composing the Query and Selecting Fields
To get the content of the blog post, check the box for Content. For the author's name, select AuthorNode Name. For the categories, select the slug and name for each category node.
So if you scroll down to the Ds, we'll click on Date right there, oh, and I still have, yeah, so we'll need Title and Date. So both of those, so title, I clicked on one of those, we'll leave that and then grab the date as well. We want the content of this blog post. So in the Cs, we'll check the box for Content like that. We want the author and here again, then we see that this is not a checkbox, but it has a dropdown. So we'll need some nested fields inside of this. So click the Author dropdown and then Node. And for that AuthorNode, we're just gonna get that person's name so that we can display who wrote it. So I'll scroll down to Name and I'll click that checkbox. So there we are, AuthorNode Name, looking good. The last thing we need is the categories for the blog post. So scroll up to the Cs and then what we have is the Cs. Where am I? I'm still inside of Authors. Oh crap, my mistake. Okay, so it'd be Cs on this list. The nesting levels are confusing me. There we go. So here's the categories I'm looking for. Inside of this, we're gonna go for the nodes. So for each of those category nodes, we're just gonna select two things. The slug and the name. So inside of this one now, so you can check the boxes for slug and name, or again if you're somebody who, you know, using the keyboard likes autocomplete, what you could do instead at this point is pop open a curly braces and do command space, slug, enter, command space, name, enter. To autocomplete those fields as well. Either way, you know, it works great.
15. Dynamic Query with URI Variable
To make the query dynamic, we need to accept a variable for the URI. We define the variable in the query variables section and pass it to the query. We specify the type of the URI variable as an ID. We can then use this dynamic query to fetch different blog posts based on the URI passed in. We define the getPost constant using gql tagged template literal and paste the query inside it. Finally, we get the URI from Next.js context and pass it to the query to fetch the corresponding blog post.
All right. Instead of My Query, get post by slug. And our app is what we called it, and here's our composed query. So if we attempt to fire this off, it will crash and burn because we don't have an ID. It says the ID input is invalid. Since we're passing just an empty string here, need to give it something valid. So we should be able to get this working using this. Oh, I think I forgot a slash. Let me just attempt this once, and if it works, I'll pop it into the chat and you can use it too. So I'll try to pass this for the ID like that, and then we need to tell it what ID type as well. So I'll do comma and then Control space, and you can see that in addition to the ID, one of the other variables I could provide is the type of ID. And that's because there are multiple ways that WordPress could identify a blog post. You can use its database ID, you can use its URI, you can use its slug, there are a few different identifiers. The default is the, what's called the global ID in GraphQL land. But instead, we're gonna look it up by its URI. So I'll do for ID type, getting a little crowded, I know. But for ID type here, I'll do Control space again and here's my options. So this is a GraphQL union it's called, where it just has these four options only. And you have to choose one of these or an enum rather, this is an enum. So are we gonna look at a database ID, or its ID, or it's slug or its URI? So in our case, we're saying, URI is the one we want. So I'll hit Enter and that will add URI. All right, so that should be it. We're saying, here's the ID to use and the type of ID is URI. So let me just try this once and then I'll paste it to you if it works. All right, so I'll hit the button and we'll try to execute this. Shazam, there it is. All right, this works. Because you see right now we're hard coding this. So if we were to highlight this entire thing and go paste it into our app, that's a problem, right? Since every single page we just pull from this particular blog post. We need to make this dynamic here by accepting a variable. So that's what we can work on next here. So to accept a variable, we can do it, like using this section down below. So see query variables here. If we, if you click down there, if it's collapsed like that, if you should be able to click on it and drag it upward like that. Inside of query variables, you can pop open some curly brackets here and it'll type in our variables. So let me get rid of these from here. And if I do ID colon, what we'll need to do afterwards to make this dynamic is to use a variable with a dollar sign. So the ID that we're gonna pass in is our URI. So we'll do it like this. So for the ID, pass in this variable called URI, comma, and then our ID type. This thing we can hard-code, right? Since we're always gonna look it up by its ID. So that part of it, I'm comfortable, you know, hard-coding, but not this URI here. So it's saying the variable URI, not defined by this operation here. It's saying, you're not accepting this variable. So we need to go ahead and do that now. So at the end of this line, you need to add some parentheses to say, you can see already my error, squiggly lines are going away. So at this point we can say, you're going to expect a variable and the variable you're going to accept is URI. And in GraphQL we have to be very explicit about the type, the type of argument we pass in. So we'll do URI colon, and then we have to tell it the type is an ID with an exclamation point. So if you go, you can go dig into the GraphQL specification if you want to see like all the supported types and things like that. But this ID is one type that's been defined for us and then the exclamation point means it's required. So it can be, you know, in some GraphQL queries you can have an optional argument where like you could pass it in, but you don't have to. In our case though, we are adding the exclamation point because this is always required for our query to be able to run. All right, so now we have our query defined, it's expecting URI, and then when it runs the query, it's going to pass in that variable at this point. It's going to use it as, you know, this ID to pass in to the post. So now down in query variables, if I pop up on my curly braces and do control space, you can see here, yet again, I get auto-completed. It, looking at my query, it knows that, oh, it looks like you've defined a variable called URI. So that's probably the one you want to, you know, define in this query variable section, and it's right. Right, so I'll highlight URI and just hit enter, and then it'll pop in URI here. And again, at this point, we can try using this long string. So let me just put this in quotes like that, and we'll try to fire that off. So this simulates, you know, a query variable being passed into the query and then used. So let me try this out now. So I'll hit play. There we go. It worked again. Yeah, so we're still getting the data back. And this gives us a nice, flexible, you know, and dynamic query to use where you can just throw any URI at it, and it'll, you know, look up a different post depending on which URI was posted, it was passed in. So this is good. This is everything that we need for our single blog post page. So let's go ahead and use this now. All right, so back in your code editor, go ahead and open up URI right here, and we will follow our same pattern from before. So we're gonna delete these dummy data lines. We don't need those anymore. And we need to define our query. So this time, instead of defining our query like right above the component, we can do it maybe further down so it's closer to where we actually use it. Yeah, like right above getStaticProps. Let's do that, so it'll be easier to see, you'll be able to see the component here and then see where we use it right below as well. All right, so at this point, right above getStaticProps, we're going to define a constant again, so do const, and then getPost. Go ahead and type that in. And just like last time, we're going to set that equal to this gql, taggedTemplateLiteral, and with a colon at the end of it. Tagged Template Literals, if you're not familiar, you could like Google that and find the Mozilla docs on what those are, but they're kind of like a type of function that expects a string. So, you can think of gql as a function and it's passing in the string that's inside of these back ticks and then using that as its argument. All right, so inside of that, this is where we're going to paste our query. So, I'll go back to graphical and this whole query we had composed, copy that, and that is what we're going to paste in at this point. So, getPost, is what we're calling it. All right, we have to actually make use of this. So, one thing we're doing here is we're getting the URI from Next.js. And Next.js has this context argument that gets passed in here and we're drilling down. We're saying for the current page context, we wanna drill down to the params, drill down to the URI, and then join those together with a slash.
16. Implementing the Single Category Page
To retrieve the URI, we use Apollo Client to query the object. If the post is received, we check if it was successfully retrieved. If it is undefined, we return 'not found true'. Otherwise, we pass the retrieved post as a prop to our component. We have successfully implemented a GraphQL query that accepts an argument and renders the individual blog post pages. Next, we need to implement the single category page. In the category file, we define the 'git category' query, passing the slug ID and slug name as variables. We test the query and confirm that both variables are necessary. We then proceed to compose the query and retrieve the dummy data, passing it through 'git static props' to our component.
I just, cause by default it separates all of these. it sees the slashes here and tries to break them up. So, what we're going to do is just join them so that we have, we're left with just a single string to work with. That's how the join is there.
17. Implementing the Single Category Page
We're going to include slug ID and then slug name. We're going to do get category. We're going to pass in just just the slug ID like this and then for the slug ID, we'll pass in tutorials. We need to get the posts within this category as well. We're creating for a category, getting the name of that category, and then saying, and for the posts associated with this category, here's all the data that we need about them. Let's attempt that. This is working out really well. We have the name of the tutorial that we'll use to display at the top of the page there to tell people this is which category. And then we also get our array of nodes back with the info that we asked for here. Cool. I think this will work well. Let's check in the chat. Everyone's doing well. Let me know if you're having any trouble with this. If you're able to compose this query though, then that should be exactly what we need. So let's head back to our category and then slug.js page here. And we will make use of this. First step, just like last time, we will last two times, I will rip out the dummy data. You don't need that anymore. And then down right above git static props here, this is where we'll define our query. So the drill by this point we'll do const git category. We'll call it all caps like that. And then GQL with our back ticks. So start with that. And then inside of our back ticks, that's where we're going to paste this whole thing. And next we need to actually make use of it. Now, we need to use that to look up our category. Right below this, I'll do const response equals await client.query, like we've done several times before. And then inside of this, we're gonna pop open our curly braces, and for the query to use, we're gonna say use that query, and then we're gonna pass in the variable that it expects. So we'll say variables, and that'll be an object, the variable that it expects is the slug ID. So we'll pass slug ID, and the thing that we're gonna pass in is this slug that we had pulled out of the params. A better name, we could have chosen to call this just slug probably, might've been a better choice than it would match what we're pulling out of here, but naming is hard, and this will work great because what it actually maps to is passing as the ID field, input field in GraphQL. So anyways, this should work great for us. We're passing in the query here, and then for the variables, passing in the slug for the current page, all right? Just like last time, we need to check to see is this category valid? Were we able to find this page? So we'll do that, very similar to what we did last time. We'll do const category equals response.data.category. If we can't drill all the way down, we'll know that's invalid and render our 404 page. Otherwise, if it's not falsy, then we'll pass that through to our component as props. And that's what we'll actually render on the page. I think we're good with this one. So I will save that. And we'll see how we did. Yeah, it's working. So now when I visit slash category slash tutorials, I get a proper name for this category that the user's visiting. And then the posts within it are all ones that are in that category. Well, cool.
I see why I was doing it. All right. So we're going to go back to our to's because we have a nested query for posts. Anyways, okay. We're going to include slug ID and then slug name. Wait, I lied. Okay, I've changed my mind three times now. You think I'm crazy. I'm sorry. I think we can just use the one that's like a thought. So here's what we're going to do. We're going to do get category. We're going to pass in just just the slug ID like this and then for the slug ID, we'll pass in tutorials. Okay. So that that works for getting us the name back. And now we need to get the posts within this category as well. So at this point, if you start typing P O S, you'll see the auto complete pop-up. So you just hit enter and then we'll need a sub selection here. So some fields nested inside of posts. So I'll open up some curlies and inside of this, we need to post nodes. So we'll type nodes, open that up. I'll do control space again to get my auto complete and start taking database ID. That's the first one we need. Next one is the title of the post. Next one is the excerpt. There we go. Next one is the URI like that. And the next one we'll have yet another sub selection, that'll be our featured image. So if we start typing featured image there and then pop open some curlies inside of that, we'll say for the featured image node, we need two things, just the source URL and then the alt text. The same as the last time we tried this. Yeah, just alt text like that. All right, so this is pretty cool. So we're creating for a category, getting the name of that category, and then saying, and for the posts associated with this category, here's all the data that we need about them. So let's attempt that. There we are. Okay, all right. Sorry, I was waffling back and forth there trying to decide if we needed the second argument, but I think this'll work great for us. All right, so this is working out really well. So we have the name of the tutorial that we'll use to display at the top of the page there to tell people this is which category. And then we also get our array of nodes back with the info that we asked for here. Cool. I think this will work well. Let's check in the chat. Everyone's doing well. Okay. So let me know if you're having any trouble with this. If you're able to compose this query though, then that should be exactly what we need. So let's head back to our category and then slug.js page here. And we will make use of this. All right. So first step, just like last time, we will last two times, I will rip out the dummy data. You don't need that anymore. And then down right above git static props here, this is where we'll define our query. All right, so the drill by this point we'll do const git category. We'll call it all caps like that. And then GQL with our back ticks. So start with that. And then inside of our back ticks, that's where we're going to paste this whole thing. So we'll copy that whole query that we had composed and paste that inside of our back ticks. All right, and next we need to actually make use of it. So you can see here yet again, we're drilling down to contexts and then params and then slug to pull the slug out of the URL for the page that the user is currently on. Now, we need to use that to look up our category. All right, so right below this, I'll hit enter a couple of times, I'll do const response equals await client.query, like we've done several times before. And then inside of this, we're gonna pop open our curly braces, and I bet you can guess what we're gonna do next. For the query, we're gonna pass through this thing that we just built, right. So for the query to use, we're gonna say use that query, and then we're gonna hit enter and pass in the variable that it expects. So we'll say variables, and that'll be an object, the variable that it expects is the slug ID. so we'll pass slug ID, and the thing that we're gonna pass in is this slug that we had pulled out of the params. Yeah, okay, yeah. A better name, we could have chosen to call this just slug probably, might've been a better choice than it would match what we're pulling out of here, but naming is hard, and this will work great because what it actually maps to is passing as the ID field, input field in GraphQL. So anyways, this should work great for us. We're passing in the query here, and then for the variables, passing in the slug for the current page, all right? And just like last time, we need to check to see is this category valid? Were we able to find this page? So we'll do that, very similar to what we did last time. We'll do const category equals response.data.category. So try to type that out, but just in case it was invalid, some of these might be undefined. So like last time we'll use optional chaining. And we'll do a question mark, and then question mark right there. So if we can't drill all the way down, we'll know that's invalid and render our 404 page. Otherwise, if it's not falsy, then we'll pass that through to our component as props. All right, and that's what we'll actually render on the page. So I think we're good with this one. So I will save that. And we'll see how we did. All right, so I'll reload tutorials. There we go. Yeah, it's working. So now when I visit slash category slash tutorials, I get a proper name for this category that the user's visiting. And then the posts within it are all ones that are in that category. We do a little check, I guess, we can like open a post, scroll to the bottom and then, yup, sure enough. So all of these are within the tutorials category. Well, cool.
18. Implementing the Search Page
We'll now move on to the search page, which is our first page that involves client-side requests. Up until now, we've been making build-time requests on the Next.js server. However, for the search page, we need to make on-the-fly GraphQL requests from the browser to our WordPress backend. We'll start by composing our query in GraphiQL, specifying the search term and the fields we want to retrieve. Once the query is complete, we'll pass in the search term dynamically and make the request from the browser. We'll handle cases where the search term returns no results by displaying a corresponding message. Let's proceed to implement the query in the search.js file.
That was it for the tutorials page. How you feeling? Can I get some thumbs up, thumbs down everybody. Doing good. Thumbs up, thank you. All right, cool. Thank you. All right. I'm feeling good. We've accomplished a lot, right? In a, I don't know, two hour period or whatever, we've created our blog index page, our single post page, our single category page, we're not even done yet. Next is that search page. So this one should be fun, like I said, because this is our first page where we're doing client-side requests. So it's the first one, where we're doing client-side requests. Up to this point, we've just been doing build-time requests. So inside of, you know, Git static props here that Next.js provides, we've been firing off queries, you know, at build time on the Next.js server, when the page is being, you know, pre-rendered being built. That's when we've been firing off our data requests, but for the search page, we can't do that, right? We don't know what the user's gonna try to search for ahead of time. So we have to do on-the-fly GraphQL requests from the browser to hit our WordPress backend and then rerender the list. So this one should be cool to see how that works. All right, so our first page, our search page then, I'll close out of my open tabs here in VS Code. And then we'll, to remind ourselves, we'll head back to the search page, see what that looks like. So that's this page, and again, like we saw last time, it doesn't work currently. We try to submit the form. All this dumping data stays unchanged. So inside of pages, we'll open up search. Here that is. And we'll get this working. Let's compose our query first then. I think that'll be helpful. All right, so like we have before, let's head back over to GraphiQuel. So we can wipe out our query variables and our query here. So we won't need those anymore. Next we're gonna do a new one for searches. So let's do this. So type the word query and then do type search posts. Just like that. So query search posts. This one, we'll expect an argument, of course we need that user's search term that they wanna use. So I'll do dollar sign, search term, colon. And then the type of variable that we wanna accept here is a string. So do capital S, string, and we wanna say that it's required for this query to be able to run. So I'll pop on the exclamation point to tell GraphQL this must be passed in. All right, so with that, we'll open some curly braces and then on the next level, we will go ahead and query for posts and use that search term. So I'll start typing posts right here. And inside of those parentheses, we need to use our where argument. So there's some other options here for doing like pagination. Like I mentioned, you could do, gimme the first 10 after this other post or whatever, do cursor-based pagination. We're actually gonna make use of the where argument though, which is used for filtering posts and saying instead of all of them, filter down to just the post in this category or that match this search term or whatever. So we'll do that. Now we'll do where, colon, and then this is an object here. So instead of where, that expects an object. Inside of here, here are all the ways that you could filter, a post. So for us, we're gonna do it by a search. So if I start typing that, it'll autocomplete. Search, colon, and this is the point where we wanna make our query dynamic and pass in that search term that the user had given us. So for the search here, we'll pass in search term. All right? And then from there, we need some curly brackets after the posts. And here we'll drill down to the nodes. Open more curlies. At this point, we need a few of our fields. So database ID is the first one. Next one is title, so type title. Next one is excerpt. Next one is URI. Next one is featured image. And this has subselections, we'll do a curly, and then for the node on that featured image, just like last time, we'll do source URL and alt text. And just a side note here. You might be looking at these fields going, man, we've typed this so many times. This featured image thing that always has a node and always has source URL and alt text, we've typed that like three different times already, right? It seems like there's some repetition there. And you're right, there is. And that's where later in the workshop, we'll get into using GraphQL fragments. That's what they can help solve. It's where you have like part of a query, somewhere in your code base you've defined it as a fragment, and then you pull that in and inject it into the points within other queries where you wanna use them. So stay tuned for that to see how you can kind of reduce some of the repetition with your queries. All right, so this should do it for us I believe. If I try to fire this off though, is it gonna work? The answer is no, right? Because we haven't provided this search term that it expects here. So down in query variables, I will open up some curlies, do Control Space to get the autocomplete and it'll tell me that it thinks I want search term, which I do. And here, this is really free form, right? This is kind of fun because we can search for anything at this point. So the GraphQL endpoint we're using is for a WPGraphQL blog and they probably talk about cool headless WordPress topics like React, how about, right? So I'm gonna type react here, that's what we're gonna search for and fire this off. So there we go, look it, first post, build an app using React and the GraphQL AP plugin for WordPress, right? Just so happens to be a post written by me on the WPGraphQL blog. So this is cool. Our search works to find posts with React. You know, we can try to find edge cases like what if I just type a bunch of gibberish and attempt to search here. There we go. I still get a successful response, but the nodes that come back is just an empty array. So I have to keep that in mind on our front end and say, you know, if we ran the search and that nodes are empty, maybe fall back to just displaying a message saying, no results found, right? But for other topics, let's do like GraphQL or something like that. For other topics, it seems to work great to find the matches. So this is cool, that is exactly what we need. You could compose it like this if you like search being on a separate line or you could just put these on the same line if you prefer that look. But either way, this is the query that we need. So let's go make use of that then inside of search.js. So we'll rip out our dummy data as usual at the top here and we're gonna define our new query.
19. Implementing the Search Page
We're going to use the useQuery hook from Apollo client to run the query on the client side. We'll pass in the query and the necessary variables, such as the search term. The useQuery hook will handle the loading, error, and data states for us. We'll render the post list based on the data retrieved from the query. If there is an error, we'll display an error message. If no posts are found, we'll display a corresponding message. The user can submit the form to search for posts based on the entered search term. The useQuery hook will fetch the data based on the new search term and trigger a rerender of the post list. We have implemented a working search page that allows users to search for posts based on a specified term.
So we'll do const, we'll call it searchPost. Or posts, I mean, all caps like that equals GQL. You know the drill by this point and then inside of our back ticks is where we're gonna paste our query we built. So copy that, paste that in, there we go. And now we're gonna make use of this but we're not gonna do it at build time. Like I said, if you notice in this file there is no get static props. That's cause we don't need it. We're gonna run these queries on the fly from the client. So to do that we're gonna use a hook that Apollo client provides. So that's why at the top here we're pulling in this use query hook from Apollo client. They have their own docs. If you go look up the Apollo client docs they have use query, use lazy query, use mutation and all the documentation on how to use those hooks. On this, you know, in this workshop you'll get a feel for using the most common one which is the use query one for running client side GraphQL requests. So that's what we're gonna use. So I'll show you how instead of our component instead of having this dummy data, we were saying const loading is always false. Const error is always false. And then for the data we were passing in our dummy data, instead of all this we're gonna use actual, you know the real loading error and data values that the use query hook from Apollo gives us back. So we're gonna delete all of this stuff and instead use query. So, whoops, what happened there? Okay, so start by typing const and then we're going to destructure some things that we're gonna get from use query. So we're gonna do, we're gonna pull out that loading state, we're gonna pull out an error if there was one and then we're gonna try to access the data. So those three things are gonna destructure and pull out of the results of our call to the use query hook. Whoops, there we go, is like that. All right, and then use query accepts two arguments. The first one is the query and the second one is any options that you want to define. So for us, if we scroll up, our query is search posts, right? That's the names all copy the name of that const and I will paste it here. So I'll tell use query which query to run. And now we need to pass in the options array as well to tell it about our variables we need. So pop open some curly braces just like this and inside of there, we'll do variables, colon and open up an object inside of here. We need to provide the search term. So what we're gonna do is store that search term in react state like this. I'll show you how that works in just a minute but so I'll copy search term and that's the thing that we're gonna pass in to our query right there as the search term. One other thing we're gonna pop in here is this notify a network status change that comes with Apollo. That's a lot to type but if you start typing N-O-T it should pop up for you. We're gonna set that to true, all right. And the reason for that is if you don't set this to true, Apollo will only set loading to false the first time the query is run. I know that's weird, but that's just how it works. So if you run the query once, loading will be true while it's being resolved and then set to false. And then after that point if you rerun the same query and pass different variables, loading would just stay false unless you do this. Unless you say notify a network status change true then loading will toggle between true and false every time which is what we want. So I know it's kind of a weird quirk but that's why that is specified here. All right, so that's really it. So our use query hook will tell Apollo to run this query on the client and we're passing in the query and the variables we need and getting all this stuff back. All right, below this have posts line should still work just fine. You can see what we're doing here we're trying to drill down to data.posts.nodes.length and they were casting that to a Boolean. So if either the data was undefined at some point in here and that would be casted to false. So we don't have posts or if length is empty, right? Remember when I ran that query and I passed in a gibberish word where the nodes array was empty. If that's the case where post.nodes.length is a length of zero, then in that case have posts would also be false, right? Since we don't have any, otherwise if we drill down to this level and length is truthy when we cast it to a Boolean like it's one, two, three, or some other positive integer then have posts will be true there. And we see further down like where we're using that. So let's look at this actual page for a minute and see how this thing works. So you saw at the top already, we're using Reacts useState, it's passing an empty string. So we're saying when this component first loads, there is no search term, right? Just keep that empty. And then we're pulling out of that, the current search term and then the function we need to be able to set that. We're providing the user with this form here at the top of the page where they should be able to type something. And then when they click search, we have a submit handler here. We're saying when the person types something and then submits the form, we're providing the default form submission on the web. We're using this form data just built into the web platform here. We're just saying we want new form data for this particular element, or for this HTML element that was submitted, we're pulling the data out of that and then do object dot from entries to pull out each of the individual values for the inputs, which in our case was this one here the search input. And then once we've done that, we've pulled up the values. They were drilling down to the search term value and calling our set search term function here that we got from use state to set that now as the new search term value. As soon as we do that, as soon as this is set to the new value, React will rerender this component and the search term variable will be new, right? It will be updated and reflect this, the new search term. And then Apollo will see that in its new use query click here, it'll see all this search term value is this new value after the rerender happens, I better go ahead and fetch this data and then provide the new loading error and data states now. Yeah, so that's how that all works. The user submits the form, which sets search term to something new. And then the use query fires off a request using that new thing. And that triggers a rerender of our list of posts here. All right, and then below that, we just have for display purposes, we just have a few options, so we say, are we currently loading the display? A loading message, or do we currently have an error than to say an error has occurred? You could do more robust error handling here, of course, and should dig into like error.message and display the actual error that came back. For us, that we'll just say an error has occurred, frowny face. If we don't have posts, then we're saying no posts found, or finally, if we make it all the way down here, then we know we're not loading, there is no error and we do have posts, right? So if we make it all the way down here, we go ahead and try to render our post list and pass those in there. All right. So with all that talking out of the way, I will save this and hope for the best. Hooray. I think it's working. All right. So when this page first loads, so this is how it looks now with our working search page. So when this page first loads, you see, we get a momentary loading. And then the results pop in. You could do a few things there. You could like fetch the default list ahead of time on the server and show that until the user makes their first query and then swap it out with the results or something to avoid that momentary loading or just not show any results until they perform a search, right? Could do that a few different ways. But we have it set up right now. As soon as the component mounts, it fetches the posts using the current search term, which in our case is empty string, right? So it just searches like all posts. To hear results, so let's try to update this now. If I do, if I do the word React search loading, and there it is, I get the results back for React. That's cool. If I do my Jibberish string again, you know, something like that, search, no posts found as expected like that. So this is cool. We have our working search page now. All right, so I'll pause here and check the chat. See how we're doing. Oh, Patricia, yeah, absolutely. Sorry, you had to wait ages for this.
20. Apollo Client and Cache Policies
21. Caching, Cache Invalidation, and Fragments
Apollo Client offers options for cache control and cache invalidation. You can control caching with fetch policies and specify how long data should be cached. Cache invalidation can be done by refetching queries after a mutation. Next.js incremental static regeneration feature allows serving stale pages while regenerating them in the background. If WordPress is down, Next.js can fall back to serving cached pages. However, some dynamic features like search may not work in such cases. Fragments in GraphQL allow co-locating component data needs with the component itself, improving code organization and reusability.
So if you do this, and it basically tells Apollo never cache anything with the freshest data, you know, don't cache it at all. You can do that, no cache, or stand by. There are a few different options there. So this is how you can have some control over, you know, what it's caching, and so on, and for how long. There's some options for that.
Alright, yeah, I think we're good then. How are we doing for time? We can dig into our fragments if we still have time. I think we have 30 minutes remaining. Yeah, my pleasure Stefan, hopefully that was helpful. Their docs are really really good. I found Apollo's docs. If you see I dig into those, you can typically find your answer. All right, yeah, so at this point we could gig into some of the fragments stuff, unless I see in the chat that the group wants to go down to other rabbit holes that I'm happy to use it. I got a rabbit hole. Good, what happens when WordPress is down? This is an interesting question. Yeah, so if you're doing this decoupled architecture that looks like this, right? It's a good question. Like, well, what if Next.js tries to use this API layer to contact WordPress to get through data. WordPress has downtime, right? The server's not there. So this can be handled a couple of ways. One way is in Next.js, if you're using like it's incremental static regeneration feature to like regenerate your pages on a time interval, it will, if it fails to regenerate the page, it'll just keep serving up the stale page actually, which is a really cool feature. So you can tell Next.js, and if you're not familiar, if just Google Next.js incremental static regeneration. If you Google that, if you're not familiar that'll you know, explain kind of what that is. But it's basically tells Next.js, I want this to be a static page, but it should only last for a certain amount of time, you could specify and say, regenerated every 10 minutes, every hour, once per day, whatever you want. On that interval, Next.js will, it follows a stale while revalidate model, where it'll, if a request comes in and realizes the page is no longer valid, you know that time duration has elapsed. It'll still serve up that stale page to that one, you know, that one last user. But then in the background, it'll kick off the process to refetch the data and regenerate that page. As soon as that new page, new versions available, it swaps out the new one for the old one. So then any new visitors coming to the site would get that new version of the cache page. So to them, it's still a very quick, you know response times as though it's it's a static page, but you can add some dynamism there and like refresh on interval by using this feature. But anyways, if you're doing that kind of thing, Next.js will not swap out the old cache page for the new one if it fails to do any of the data fetching. So that'd be one solution to this. So if WordPress had downtime and Next.js is trying to, you know, reach out to WordPress and regenerate the page for a blog post or whatever, and it's unable to, it's fine. It would just keep serving up the stale page until, you know, at a later point when WordPress is back online and it tries again at that point, it would just, you know, start regenerating the pages again. So that's a really cool, robust solution where you can have your front end app just fall back to the cache pages, you know, whenever your data sources in our case, WordPress, like happened to be down. So that's one cool solution. It doesn't handle every case, of course, so like our search page, right? If somebody goes to the search page and tries to perform a search and the WordPress is down at that moment, like then of course, we can't, you know, we can't really do anything about that because we need the actual, you know, data from WordPress. So the best you can do there would just be to follow, to fail gracefully, right? Like on our search page, we just have, if an error happened, in our case, Apollo would call this like a network error, like it tried to send the request to the backend API and got, you know, either a 500 error or it was offline or whatever else. So you just fall back, you know, and fail gracefully and say, sorry, unable to perform searches at this time or whatever and just display a message like that. So yeah, definitely a real concern if WordPress goes down, but, yeah, doing the like the static rendering of pages can really save you sometimes from that being a problem. Yeah, good question there.
Okay. We can dig into some query or some fragment stuff for a little bit then. GraphQL fragments are really cool. Let me show you what they are at a high level. So let's say we, so we had this search post query that we had composed, right like that. What we're able to do with fragments is kind of break up some of this and define it other places. Let me show you what I mean. So if I can type fragment and we'll give it a name. So this will be, so fragment featured image. I'm probably gonna get the syntax wrong for this. Wanna get myself. Get my cheat sheet so I can look at my own app in the syntax here. Look at the post list, oh yeah. I had to refresh myself on the syntax. So featured image is a fragment where we're gonna define, and actually let's do a different one that we'll actually use in our app. So this kind of fictitious one I was gonna do on the search page, let's just dive right into it and we'll start with the real ones on the blog page, how about? Alright, this is the one where we got the first 18 posts and display them on a grid, right? This one, let's say like these nodes here, we don't want this data to live here because actually, if you look at this component, how much of that data does it care about? None, right? It just grabs the posts and sends them straight through the post list component. This component actually doesn't care about all of the fields that we're defining here. The only reason we're putting them in this file is because we need that data eventually downstream for the post list component. So one really powerful pattern is to co-locate your components data needs with the component itself. So what you could do is create some fragments so that this data lives and is defined maybe with this post list component, if it's the one that cares about that data or otherwise with this postcard component. Since it's the one that cares about some of that data, why not just define a fragment in the same file where we define the fields that we need and then immediately below it inside of the component, go ahead and destructure it and use those same fields. Like, wouldn't that be a nicer, more organized code base for us, right? And that's what fragments allow you to do. So we can do that, like, with the blog page and then post list and then post card. So I'll start with, like post card since that's the most granular, I guess. That's like the, it doesn't render anything else. It just gets rendered by post lists, which gets rendered in turn by blogs. So let's start with like post card. I'll show you what I mean by creating these fragments. This is what you would do like above this thing, you would do, so we'll export a constant from this file.
22. Creating Fragments in GraphQL
In this section, we'll learn how to create fragments in GraphQL. Fragments allow us to define the specific fields we need for a component's data requirements. We'll define a fragment called 'postcard fields' for the 'post' type, specifying the title, excerpt, URI, and featured image. By using fragments, we can organize our component's data needs in a separate file and easily make changes to the fields without leaving the file. We'll also explore how to use the fragment in a query by spreading the fields using the three dots syntax. This approach improves code organization and reusability.
23. Fragments and CMS Comparison