skip to content
Home

Use WordPress with Next.JS

with Colby Fayock

Colby Fayock will teach us how we can combine the great content editing experience of Word Press, the flexibility of developing with Next.js, and the power of deploying to Netlify!

Transcript

Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.

JASON: Hello everyone and welcome to another episode of Learn with Jason. I'm just happy to have you here. What a week, and to the folks in Texas, I'm so sorry for what you're going through. I hope you're staying warm. I know there's a very low likelihood that you're seeing this live, but if you're catching this on the repeat. My heart goes out to you. I'm real sorry.
Today on the show we've got Colby. Colby Fayock how are you doing man?

COLBY: I'm good, how about you?

JASON: I'm so good. I'm so happy to have you on the show. This is going to be so much fun. I've got to say, you have one of my favorite avatars that I've ever seen. Look at this photo. This is so good.

COLBY: It's a throw-back to my modeling career.

JASON: Is that an actual, you modeled that for like a toy or something?

COLBY: Yeah of course I wasn't actually a model. But I used to work for a company called Think Geek which they shot product shots I was known for being the hugger.

JASON: That's amazing. Hey, also, put it on your resume. You were in a product promotional shoot. You're a model. That's amazing. So cool.

COLBY: Flashing lights.

COLBY: Right now I'm a developer and advocate at Applitools. Before I that was a front-end engineer. Now I'm actually able to spend my full time helping with educational serials and with Applitools and all that great stuff.

JASON: Nice, very tool. This is I think really exciting. Applitools is very cool. We're not going to really talk about it today unless we wind up some extra time. We do have a whole extra tools, I get to work with one of my all-time favorite people Angie Jones. Angie has been on the show. I'm going to drop a link in the chat if you want to see Angie and Applitools. It's easily one of the most mind-blowing episodes because of how quickly we were able to do something that I thought was so hard, which is setting up visual regression testing for applications.

JASON: We're not talking about today unless we go real fast, which obviously given the stack is a possibility. So what are we going to talk about today?

COLBY: Sure. So we're going to talk about WordPress. Everybody's favorite CMS and Next.js which is probably realistically everybody's favorite web framework. We'll talk about some of the challenges between the two and how we can get up and running with sourcing content from WordPress.

JASON: Nice. WordPress I think is like one of the things that I love about WordPress is that it has adapted really well. And I think this is in large part due to the strength of the community. It has an amazing open source community and it powers a huge portion of the Internet. But it didn't seem to lose momentum when people started moving to this headless CMS model. And I think that's fascinating. Back in the monolithic app days, WordPress didn't really have competition. There were ways to build with a monolithic CMS they were all kind of niche. But when you think about it realistically, in terms of dominance on the Internet, WordPress was the option. When we moved to headless CMSs, that was not the case. Why do you think WordPress has been able to keep its relevance.

COLBY: I think it's interesting because just WordPress generally, I feel like there's so many big companies they're probably using WordPress as it intended it. They've had a rest API for a while to fit into that ecosystem where you can source that data. I don't know if that was originally the intent. I never looked up the history of the rest API and the thoughts about building that. But it would be interesting to see what their thought process was for building it out and where that kind of took. Now with WP graph QL it makes it nice to be able to query your WordPress data. Mixing those layers it helped keep the momentum. Generally speaking, I still think WordPress has one of the better editor experiences. I'm not talking bad about the other CMS options we had, there's so many of them great ones. I think WordPress has a nice and familiar editing experience for people.

JASON: Absolutely. And WP graph QL is maintained, created by a friend of the show. We learned all about WP Graph QL. If you want to see how we're doing what we're doing today but with Gatsby instead of Next, we've got an episode for that. You can go check that out. So what I think is really interesting about it too is WordPress has this -- it's been able to carve out this niche where people who don't want to learn how to build websites use WordPress. And they like WordPress. It's easy to log in and edit my content and take it live and I never have to think about the way that the code works. And originally I remember this kind of painful for me, because I was -- I was a PHP developer and I resisted WordPress for a long time because I didn't like the templating that it did and all these decisions that were kind of being forced upon me. I wanted to do my templating a different way. So I remember moving to the solutions that were really heavy. Did you ever use bedrock back in the day? Bedrock was this way of changing WordPress into I think what was our goal? We want to turn WordPress into a 12-factor app. And it was wild. It was completely wild. And it ended up being so hard that I never used it. Because it was like we've got Ansible in play right now. I don't remember how to use any of that stuff. So when I went to go maintain things, you couldn't use the plugin updates through the UI anymore. You had to do it through the server and there was all of these challenges. So it wasn't really practical. But then when headless WordPress came out, when it became practical, suddenly it was like, ooh. Now WordPress is super appealing because I love the editing experience of WordPress. But I don't like building front ends for it. Now I can build a front end that I like, and use this editing experience that I like. And everybody is happy. Everybody wins.

COLBY: Yeah. It really kind of brings the best of both worlds. It still rough around the edges. I don't know if anybody's solved it with the Gutenberg editor. But the core experience you're able to bring but the things like user management, things that are already layered right into WordPress, it makes it nice and easy.

JASON: I see you Kurt, thank you for the sub. Your fascinating. I appreciate you. I see a couple of people are actively are -- oozes pics is working on a Next.js project right now. Hopefully this is a very relevant episode. Because I feel at some point if you work in web dev long enough, there is an inevitability that you are going to end up working with WordPress. There's almost no chance that you can get through your whole career and not touch WordPress at least once. It's something that you're going to come into contact with. I love this idea of showing different ways to interact with it. Because the rest API is one model. WP graph QL is a graph QL API which is a different model and you've got the monolithic model which is more like use WordPress as one solution. All of them have strengths and weaknesses. I'm obviously biased because I don't particularly like writing front ends in PHP because I think there are more strengths to this decoupled model. I think it gives the right amount of control. As an editor I want the great WordPress experience as a developer I don't want the experience. That I think is a good expiration of concerns.

COLBY: It also helps alleviate a lot of concerns that people had with WordPress in the first place. One of the things people complain about are things like security where you have to be actively understanding what routes are available and prone to attack and you can kind of lock that infrastructure off from the rest of your site if you're pulling it in headless and things like plugin bloat if you're doing it at compile time, things like that, you don't have to worry about that as much. It never hits the user with the visitor of the website with those long load times.

JASON: Yeah. And that's -- I mean, plugin bloat, absolutely was almost a nightmare. I ran an agency for a long time and we built WordPress sites because there was no other way to get things out fast enough. But the problem that we have is somebody would bring us a site, they had 75 plugins installed. We didn't know which ones they were using, they didn't know which ones they were using, so the hardest part of the project was untangling the WordPress set-up. And this headless approach is really cool, because if you install a plugin, all you actually see on the dev side is output of those plugins. And so -- and the other thing you mentioned that I think is really interesting is this idea of separating the front end from the back end. And I talk about the jam stack a lot. It's something that I'm pretty convinced should be the default option is try to go jamstack first. The reason for that it does give us that opportunity. I can -- using WordPress as a headless CMS, if I'm generating like a fully compiled UI from WordPress, I can shut down my whole WordPress instance or put it inside of a VPN or like an air gap you've got to walk into a locked room and plug a USB into it. You can make your WordPress so secure and it doesn't matter because the front end doesn't actually talk to WordPress to operate. And that security is a big deal. Especially when you get into like -- if WordPress is over 30% of the Internet is powered by WordPress I think is the stat that we see. And if that's the case, the bot armies are looking for WordPress. If one in three sites they try to attack are probably running WordPress, of course they're going to get automated attacks. Of course they're going to try to exploit known security holes and that's a big risk. So I think being able to gap it entirely where you can't get to the WordPress instance from the production URL, that's beautiful. That's great.

COLBY: And like for kind of managed services, there's a lot of manage WordPress services where you can spin up an instance and they take care of all of the services and stuff. If someone is loading it on an EC2 instance or their own server, they might not be considering if there is a security concern, they might have access to just your WordPress instance.

JASON: Absolutely. So this is all fascinating. I want to make sure we have plenty of time to get through and build so I'm going switch us over to -- if I can find my mouse, there it is. I saw a meme, I'm going go off on tangent here. I saw a meme I should find it and share it. If I try to explain it it's going to be terrible. How about this, I'm going switch over to this view and then I'm going to find this meme so I can show you instead of me trying to describe a meme which I'm sure everybody would enjoy.

COLBY: Why not both?

JASON: Here's the meme. It's Gandolf looking to the left and looking to the right and then he says where is the cursor and it switches to Jurassic Park. That was me. I am Gandolf.

COLBY: I'm still getting used to the multi monitor thing, so I'm definitely feeling that pain right now.

JASON: I dropped links in the chat already, but this is the episode with Jason Ball on WPgraph QL. This is the episode on Applitools with Angie. If you want to learn more about WPGraph QL, Jason built it. Speaking of knowledge sources, follow Colby on Twitter. That's a fun follow o, lots of good information. And you get to look at this amazing avatar. Now I want to go work at Think Geek. Keep in mind all episodes with Learn with Jason is are live captioned. We have Nicole with us today. She is doing live captioning through White Coat Captioning so thank you so much Nicole for being here today. Captioning is made responsible by our sponsors. To make this show more accessible to more people which means a lot to me. Then today, we're talking about a few things. We're talking about WordPress. So here's WordPress. We've got Next.js. So here's Next.js. We're going to -- so we haven't talked about this yet. We're going to use Amazon Lightsail to set up our WordPress instances?

COLBY: The cool thing about Lightsail it's easy to spin up applications and WordPress is one of the ones they offer. I think the first month is free but after that the lowest one is $3.50 a month. And that's I think at least competitive in terms of WordPress pricing for services.

JASON: I don't think I've seen anything lower than $5.

COLBY: It's pretty cheap. And the nice thing is, at least the way that I've been using it is I compiled the site. You're not stressing the server.

JASON: Actually that's another thing that I think is really like powerful here is that when you're doing this compiled version, you don't have to worry about, like, accidentally getting DDOSed by becoming popular. One of the problems you would see with WordPress is I remember something would go to the front page of Dig and everybody would go to the website and it would go down. You know, it was a joke. It was like a great thing, hey we got taken down. People who had the -- the Dig effect. You got your site taken down by Dig. Hey good problems. But it's also a bad problem because if a bunch of people are excited to check a thing out and they can't load the website, so the static compiling, it removes that problem. It makes it so yeah, hit the front page of anything and start trending on Twitter, everybody goes to your website and you don't even notice unless you check analytics because this model doesn't stress the WordPress server. There's no server to get overwhelmed it's all on CDNs. That's a pretty nice thing. Also I see you trying to bait me into doing a photo shoot. I see it happening.

COLBY: I mean the Netlify swag and Learn with Jason swag needs somebody to show off.

JASON: We're just going to do this. Somebody screen shot this right now.

COLBY: That's fantastic.

JASON: That's going to be my new profile now. 2022 Jason calendar. No. Nobody wants that.
[ Laughter ] I know no one knows what Dig is anymore. Do you remember when -- okay. Am I dating myself? Do you remember Dig?

COLBY: I absolutely remember Dig and I remember they tried to relaunch it and it didn't really go that well. I was never like a huge Dig person. I never interacted with it much.

JASON: I remember Dig was so popular that people who worked at Dig became Internet celebrities. I remember when everybody knew who Kevin Rose was just because of Dig. I know that still happens. It was one of my first memories of somebody being famous for building a thing on the Internet. Kevin Rose and Zay Frank. What's her name did the video shorts of like D & D. Not relevant to what we're talking about. Me being nostalgic.

It was like Reddit before Reddit.

JASON: It really was. In addition to Amazon Lightsail we're going to use WP GraphQL. We're going to deploy the whole thing to Netlify. So that's a whole raft of resources here. With that being said, I think I'm finally ready to shut up and start coding. Are you ready to teach?

COLBY: I'm ready.

JASON: Let's do this.

COLBY: Cool. So we could either start off with the Next app or we can start off with WordPress. Either way it doesn't matter that order.

JASON: Let's start off with WordPress. Let's get that set up and running because then we can -- yeah. I think that works.

COLBY: Cool. Over at Lightsail then, let's see. We want to -- are you logged in? Yeah.

JASON: I think so.

COLBY: I think you want to go in and search -- or we can see if that link takes you there. Anyway, navigating to the Lightsail console.

JASON: Now it wants me to log in. I'm going move over here because I don't know what's in my account. So I'm going to do this off screen. So nobody look. Everybody close your eyes. Chat, you're on the honor system. So what is my Amazon? Okay. AWS here we go. It's been a long time since I've logged into an AWS account so we're going to find out if I remember how to do this. Yes. That's the right thing. Am I logged in? Everybody is going to have to hold on for a second while I do like a forgot password on AWS. Wait. AWS, why are you like this?

COLBY: We could always use WordPress.

JASON: We might have to. I'm doing the thing. I'm logging in. I'm still logging in. I need multifactor authentication. At least I set that up, eh? Now I've got to find where that is. I think it's in my authenticator app. This is how everybody wanted to spend their morning, right? AWS, I have it in my app. So --

COLBY: This is the first step of debugging. Right?

JASON: In order to build something on AWS, you have to remember how AWS works.

COLBY: If you're using your phone, you should check out the Auth E app it has a nice Mac app.

JASON: I've been slowly moving everything into -- I'm going to show you all this. I am on like step 5 of trying to log into my account. Okay. Let me open my email now. Here's a sign-in attempt. I'm going to approve or deny. I'm going to approve this. Thank you. Now I'm going to refresh this page. Why? Okay. So we're on the third go-round here. I'm remembering now why it's been so long since I've logged into my AWS account. Okay.

COLBY: Chris said it's easier to just create a new account.

JASON: It definitely might be easier to create a new account. I think you're on to something. Add a phone number. I will not. You leave me alone.

COLBY: We're in.

JASON: We're in, okay. Hold on, let me do that in my hacker voice. We're in.
So now I'm ready. I'm going to find Lightsail, is that right?

COLBY: Yeah.

JASON: English, that's the one I speak.

COLBY: I'm guessing that's going to do the same thing as create an instance so either way.

JASON: Okay.

COLBY: At this point we're going to -- so what it's essentially doing is it's spinning up an EC2 server but it's going to be managed for us we don't have to worry or think about that. We select a blueprint there's a ton available. WordPress is probably the most popular one, I would imagine. It's at the top of the list there. So we don't really need to change anything here and we can kind of keep going through.

JASON: Okay. So I'll click these buttons. This is -- I don't actually know what WordPress version we're on. Is 5.60 the latest?

COLBY: I actually don't know that myself. So Bitnami I guess is who manages the WordPress instances and the stuff that goes behind that. We can see the pricing model. I think it said it's free for the first month.

JASON: Let's check this out. First month free and then if I scale up, like you said, we're not going to hit this very hard, so we don't need any more than this unless we were going to somehow upload 30 gigabytes of images or something.

COLBY: Exactly.

JASON: It looks like it scales pretty reasonably. 40 bucks a month, for an individual site that is expensive. But on the scale of infrastructure pricing, that's not bad.

COLBY: I would imagine. You would need a lot of traffic in order to hit that 40. And especially if you're server side rendering your application with that.

JASON: Absolutely so I'm naming it. Do I need any of this?

COLBY: Only if you want to. It's typical Amazon tags, AWS tags. If you don't use tags, you probably don't need it.

JASON: I don't use tags on Amazon.

COLBY: Some people using it for identifying billing and those kinds of things.

JASON: The fun thing about this is I'm going to remember in 30 years that I've been paying Amazon $3.50 a month.

COLBY: You need some kind of bot reminder.

JASON: I know.

COLBY: That's going to take a second to spin up the server.

JASON: It's up. 561 is stable so it's pretty dang close to being latest and my guess is because it's managed, they have some kind of vetting process on like they're running 561 through the vetting process and they'll upgrade for us which is pretty slick.

COLBY: It says it's running, but we can actually see if it's -- once the server is running, it might take a second for WordPress to be spun up. We have that IP and if it is available we can hit the IP in the browser and we should be able to see the WordPress instance. Your typical set-up page. It might be still processing that start-up part. That is the same IP at the top of the page.

JASON: Public IP. That's where we are?

COLBY: Yeah.

JASON: Not yet. Okay. So maybe while we're waiting for that to propagate, we can get the basics of our repo up here. How do you want me to start this?

COLBY: Create next step. That we can show from scratch.

JASON: Create next and we'll call this WordPress Next. I don't think I've created one of those yet.

COLBY: Someone made a good point it might not be available on HTTPS. I don't know if that's the case.

JASON: Interesting. Let me get into this and I'm going to initialize. This will be our WordPress site. Or we do that, let's go check here. This is central security risk. I'm going to accept the risk and continue it says the service is unavailable.

COLBY: It's still trying to spin up.

JASON: There we go. Now we're in. And so that's fine we're not going to use this over the web, we're only going to use this as part of our build pipeline. I'm exposing this to the world, which is not great. But for the standard process here, this IP address is never going to get exposed. No one really needs to know about this unless we explicitly share. Then do I just get in like this?

COLBY: Yeah. And then so we need to figure out the password which we're going to need to SSH into -- they give the console inside of there. So it will give you an option there to connect using SSH. And I need to find -- they have a document that tells you the command to run. It's basically inside of the instance it will have a stored file that tells you what the password is.

JASON: Choose the default key pair.

COLBY: You shouldn't have to worry about anything with key pairs.

JASON: Download my default private key.

COLBY: If you scroll up a little bit, it has a button that will pop up a new window.

JASON: Oh, right here. Okay. I saw this one and I just stopped reading. Here I am inside of the shell here.

COLBY: There's going to be a file. I just need to find that file name. That you find the credentials. Do you want to do an LS in there and see. . .

JASON: Oh, is it the application password here?

COLBY: Yeah. We're looking for the default user name.

JASON: Okay. I'm going to pull this off screen, because I know exactly what happens if the chat sees that.

COLBY: Great point.

JASON: The application password, then that's the one I'm going to log into WordPress with?

COLBY: Yes. Did you find that already?

JASON: I did.

COLBY: There should be a link.

JASON: We're going to find out. I might be wrong. No. Is it admin? No. So there's another one in here called Bitnami credentials. Let me try that one. Here we go. There's a default user name and password. So let me copy this password. The user name is user. No one would ever guess.

COLBY: Extra secret. Yay.

JASON: This is going to be LWJ WordPress.

COLBY: The one trick spinning it up with Lightsail we don't get default email server attached to that. We don't necessarily need it for this demo but if you ever want to reset your password or those kinds of things, you'll have to have Amazon's email service or I think I use send grid to connect SMTP. It's not too hard but it doesn't come by default. We have a default WordPress installation but it's pretty basic but it's a good starting point.

JASON: We've got to posts, we've got some pages. I'm going to not do Jetpack. This is fun. Akismet, that's the classic anti-spam. We've got some SEO, something for WordPress migration. Amp, boo. AWS for WordPress. What's this one?

COLBY: They're not activated by default, they're just kind of sitting there in case people want to use them.

JASON: They're not activated.

COLBY: I think I actually use the Yoast SEO one. If anybody wants to get started with it. But so the plugin that we do want to add is currently we have access to the Rest API but we want GraphQL. It's fortunately now in the plugin ecosystem.

JASON: Beautiful. I do remember in this episode we had to like install it manually. We had to drag it into the plugins folder. This is nice that's no longer the ways. So that is now active. Right?

COLBY: Yep and in the left-hand side we have our GraphQL tab.

JASON: Here's the GraphQL tab.

COLBY: Graphical we can query our data.

JASON: Okay. So I am sending data to WP GraphQL because I am helping. This, by the way, the explorer is my favorite innovation in GraphQL in the last little while. What a game changer to be able to click things instead of having to read through the docs and figure it out.

COLBY: I'm by no means a Graph QL expert and this has helped me tremendously.

JASON: Absolutely. We're going into pages, we've got nodes. I'm going to get -- let's see the title seems like something I want.

COLBY: We can probably use the slug if we want so we can create dynamic pages. Recently I've been using the URI, because the URI contains the full path to it. So that includes any parents. That way if you're rendering the page, you'll have that full path.

JASON: Oh, this is nice, yeah. You know what? I like that. Because then somebody could control the hierarchy through WordPress. Like if I make a page a subpage, then my static site generator doesn't have to determine these relationships, which it would have to using slug. Instead it could say use the URI.

COLBY: Exactly. And it requires a bunch of queries if you do it the other way.

JASON: Yeah yeah. That's slick. I like that a lot. And really, this is like what we need. Because we've got a date. We've got the URI. I'm going to turn slug off because I don't even need it. Let's get less data. Nothing extra sent over the wire. Title, content. And content is just HTML which is beautiful.

COLBY: That will be the rendered HTML and inside the rack we'll use HTML. I know some people have tried to use HTML parsers. I haven't dug too far into that thing yet. It's something I eventually want to do to create witch components for some of the widgets.

JASON: Yeah. And this is slick, right? And you do have access if you want to, you can use this format raw if you want to get what's in WordPress, at which point you can drop it into a re-hype kind of process where you could parse it and do stuff and you could manage, like you said you can do these rich content experiences with MDX or whatever. But you don't have to. And I think that's --

COLBY: Exactly.

JASON: The best system is the one that's simple. I've been the last few days I've been talking a lot about simplicity and making sure that things have fewer moving parts and I've been screaming like complexity is a code smell because you don't have to make stuff hard.

COLBY: I wholeheartedly agree. Trying to make things clever, it might be impressive, but it's not going to help people long-term. Even yourself, going back to your code months later.

JASON: Absolutely. Absolutely.
So are we done?

COLBY: So we have WordPress. Yay.

JASON: Did we do it? Honestly though, I feel like this kind of puts us in a position where we're done, right? Because I can go --

COLBY: In terms of WordPress, yeah.

JASON: Yeah. And if I go to postman, and I -- where is it? It's going to be here.

COLBY: The only thing is if we wanted to do faker content but that's not necessary.

JASON: We've got some fake content here. Let's hit this URL. I've got a body, I'm going to send in raw body of like query and then I'm going to send this Graph QL query. I wonder if that's going to fail on me. It probably is, isn't it?

COLBY: I'm not totally sure.

JASON: I failed because it needs to be one --

COLBY: You use that Graph QL option or does it not work that way?

JASON: Oh, does it work? Beautiful. It does it for you? I didn't know they added that feature. That's brilliant. So then I'm going to take this. Put this in here and I'm going to go Graph QL and now from a completely different app, I am getting back data. Hurray!

COLBY: Ready to use it.

JASON: This, the first time I saw this, my developer security brain went wait, how is that secured? Can you talk a little about that?

COLBY: In terms of getting people's content?

JASON: Right. I was like wait, how come I can just hit this endpoint?

COLBY: It's a good question. I think most of the time a lot of the APIs are relatively public just for reading content, right?

JASON: Yes. And that was the part that like I was like wait a minute don't we have security problems. Then I realized you can go to the website and read this content. We're not getting privileged accessed. It's all data that we published. It's public.

COLBY: I thought you were leading me towards something I wasn't thinking of.

JASON: No I was trying to not do the thing where I ask a question and immediately answer. So I'm sorry if it felt like I was trying to corner you.

COLBY: There is authenticated routes to do more complicated things. I know previews is an example use case. If somebody wanted to query the previews of a post you can still do that and draft pages if you provide it authenticated.

JASON: Yeah, yeah. Martin is asking would you still rely on the automatic WordPress classes for CSS styling? You can. Like WordPress ships -- don't they ship for like what's it called Gutenberg they shipped an MPM package that's got the styling for their blocks.

COLBY: I didn't know that. But don't they have classes? They used to have classes. Maybe they don't have that anymore.

JASON: They do all have classes, and I think what we ended up doing with this, I think there's like -- there was a project that we did where we actually pulled in WordPress's styling for content blocks and it did the basics and we were able to extend that and kind of customize it to our theme. But yeah. When you get into any kind of secure stuff, if you want to get at -- I think if we even wanted to get the raw data. So if I add this, I think this will cause failure. I think it will tell me that I need authorization. It gives me a null. And then in my errors we don't have debugging active. So it won't give us errors. Because I tried to access privileged stuff, it says there is none. So it does do like access control. It's not letting anybody in the world seeing anything in your WordPress database. It's only public data, what they would be able to see by loading this page.

COLBY: I don't think many people want to read your Jason file to read your blog, right?

JASON: Exactly. So this then, I mean, the hardest part of that was logging into Amazon. That's kind of amazing.

COLBY: It's lovely how easy it is to spin up a new instance.

JASON: Yeah. So now we're ready to start doing stuff, right?

COLBY: Exactly.

JASON: We've got a stock Next site and we're ready to rock and roll. What should I do next?

COLBY: So the Graphic QL client that I typically use is Apollo. It's always worked really well for me so we could start off by installing Apollo or whatever your favorite is.

JASON: Can you remind me what the package name is for Apollo?

COLBY: I will look it up.

JASON: Let's look it up together. This is Apollo client and thank you, chat, for catching that brilliant pun. Next is such a good source of puns.

COLBY: It truly is. I need to be here. I only need Apollo client?

COLBY: I believe so. Because once you have that installed --

JASON: I need Graph QL. . This also is something that the Apollo team has done they've really simplified this process. Because a couple of versions back it was a lot of things you had to install to get Graph QL up and running. So the fact that it's now I'm installing one community package Graph QL and one Apollo package for the client and we're in business. Instead of like Apollo Boost and like transport layers and caching stuff and all these things that I would need to make it work, now it's like here just install this and it going to work.

COLBY: That is nice. Especially for someone like me who isn't super well versed with Graph QL. That makes it nice and easy.

JASON: For sure. Where should I actually put this? I've got it installed now. It's available to us.

COLBY: So I typically create a lib folder and create Apollo file where I can store the client that way we can cache that client and have it accessible from one place.

JASON: Okay. To do this, is it a named import?

COLBY: We're going to import the Apollo client. It's actually capital Apollo and then a capital C client. And also, their documentation has importing the in memory cache. I'm not 100% sure how that works. But like I get gist of it. But I'm not sure if it's a required default. I start off with what they have.

JASON: Yeah. I think the general gist of how the Apollo client works is that it's going to make queries and Ddupe if we make the same queries it's going to D duplicate that so we don't hammer on the API and it has to keep track of which queries are being made. And in the-memory cache helps. You can target a whole bunch of different things. Like you can do local storage or you could do -- if you're interested in that, you should dig into the Apollo docs. There's a lot of stuff you can do but it's out of scope for what you're doing today. So this the rest of what I need is just this here.

COLBY: It will create the client. I typically create a global variable out of it. And then create a function, an exported function to access the client. That way we can kind of cache it globally within the process.

JASON: That's it? I just point at this URI?

COLBY: I think so. And then we can use the client.

JASON: That is really cool. So when I go out here --

COLBY: Again I'm not an expert on the Apollo front. I know how to get started with the queries.

JASON: Okay. So when we're actually going to use this, is this -- are we wrapping the whole Next app with this?

COLBY: Yeah. And we can do that inside of the app file, inside of the page. If we go inside our next application, it should be there already. We'll want to import that provider there.

JASON: So let me save -- I'm just going to export -- we'll export this client. So now in the app, we can -- what's the right way to do this? We can import client from lib Apollo. And we need to impact the Apollo provider, is that what it's called?

COLBY: Yep.

JASON: Okay. And then we just wrap it around here, right?

COLBY: Yep. And then the prop is client that we pass in client.

JASON: Excellent. And wrapped. And that's the thing?

COLBY: That's that. So now we have -- we'll have that client accessible and ready to go throughout the entire Next application.

JASON: Unbelievable. Okay. That's really nice. Is this night owl? It is night owl. The font is operator mono. You can go to HTTPS Jason/uses to see all that good stuff.
If I have my app, I want to get something on the screen, to just show that it's working, I want to start this. I'm going to run Netlify dev and that will start our next site and it opened in this browser instead of the one I wanted to over here.

COLBY: I'm curious what does Netlify dev do. Does it spin it up with the Netlify Next.js package?

JASON: That's a great question. I don't think it does anything like that. What it does it starts the Next server, but it also looks for any serverless functions or anything that you're using. And it will pull environment variables. Like if you've set up environmental variables and it makes the whole process a little bit more friendly. I just kind of like it because it's the same for every framework. I don't have to remember is it Gatsby start or Next dev. It's just Netlify dev and it works every time because we've got framework detection in there.

COLBY: That's pretty cool.

JASON: Let's dump some of this stuff out. I'm going to move this to the left.

COLBY: In terms of querying our data, we have two options. We can either -- three options, really. We can either query this data on the server. So either statically, with get static props which is what I typically do, or get service side props or we can do a client side using their hub. I personally recommend getting the static props since there's nothing dynamic about the content.

JASON: I think that makes sense. So on our home page, we have the ability to control here and we can start cleaning up all the things that we're not using. We're not using this footer anymore. That's basically it. That's our whole site. Boom, right there. Dead center. Here we go. So when we're using get static props, are we trying to pull from the home page here?

COLBY: So, it depends kind of where we want to put the content. If we want to show how it works, or if we want to show our blog posts on the home page, or even the home page page page.

JASON: So let's actually let's do both of those things. Let's show, to start, because we have some posts, let's create like a list of blog posts and then we'll go create a home page and we'll use that instead of this hard-coded stuff.

COLBY: That sounds good. Cool. So if we're going use get static props, we can use -- instead of using the hook, use query which would be like if inside a rack component -- we're going to import the client and the graph QL, GQL from Apollo. So the client gets imported from our package, actually, instead of Apollo. And then yeah. GQL.

COLBY: It will be client.query and we'll passing an object into that and we'll probably want to erase that request.

JASON: There's probably some.

COLBY: Yeah.

JASON: Let's not and say we did.

COLBY: Exactly.

JASON: So we've got a query here.

COLBY: That will be the query property.

JASON: That's going to be like GQL.

COLBY: We have a paste in our query.

JASON: We can grab our query. I'm going drop it right in the middle and for the sake of -- I'm going to just name these so we know what we're doing. So we'll call this get WordPress post. And I'm going to go back to WordPress and I want to switch this up to be post instead.

COLBY: It should be the same.

JASON: I think you are exactly right. Effectively exactly the same thing, and we can see here, this is kind of interesting. WordPress is setting our custom URLs for us. If we didn't want that, and I think we won't. But let's worry about that later. I'm going to start here. This bit of the query and I'm going to swap it out here. So we've got our posts. Now is that it? Like --

COLBY: Yeah. So what I like to do, I usually like to console log out the result here. I like to show that if you open up your terminal after doing that and refresh the page, you can actually see that data inside your terminal because it's happening on node.

JASON: Oh, this terminal.

COLBY: Well, you should.

JASON: Didn't like something.

COLBY: It's because return -- when you return the new objects with the props key and we could pass an empty object.

JASON: Here we go. Now we've got data and it's got posts and our posts are nodes and then the nodes is an array. Perfect. That's what we want.

COLBY: At this point we have our array of posts and we can now construct those into the post data that we want to pass into our page component.

JASON: So I can go result.data.posts?

COLBY: Exactly.

JASON: Dot nodes.

COLBY: Yes.

JASON: And out here what we'll get is posts. And then let's just log that. And we'll do posts and format it a bit. Ta-da!

COLBY: Awesome. And we have our data.

JASON: We've got data. So then, instead of doing this, we can do like a posts.map and we'll get the posts. Actually why don't we destructure this. We'll get the title, content, URI and date. And then we'll loop on through that and create -- let's do a list item. So we'll make an unordered list out here. And wrap that. Then I'm going to take the key and we'll put the URI is our key because that's going to be unique.

COLBY: That's fair.

JASON: And then we probably need like the link --

COLBY: Yeah. We need to also import that, yeah.

JASON: I was hoping it was going to auto import it for me. No. Only when I want it to do cool stuff. So I've got my link.

COLBY: We'll need to come back to that as you were alluding to a little bit earlier there.

JASON: Then we'll do our title and I'm realizing now -- I'm not going to use the content either. We can actually simplify this now. We're not going to use the content and we're not going to use the date. Should I show the date? What do you think?

COLBY: Are you going digital garden approach or are you going typical blog approach?

JASON: I don't know. Joel was on the show earlier this week and he would be appalled that I'm about to put dates in something but I'll just include it. Why not. So we'll just stick the date in here and save there we go. Why don't my links look like links though? I don't know. But it's linking. The page doesn't exist. We're going to have to figure out how to step that up. This is pretty good. I'm already mentioning. I can already tell I don't like the date string so I want to change that. I mean in the URL.

COLBY: The interesting thing that I was finding out is between the differences between pages and posts the URI is a little easier to use and reflect in pathing for pages. Because it's standard parent slug followed by the child slug but with the posts, you have that kind of different pattern matching. Depending how somebody is set in their settings, it might reflect differently for those posts. For there, we'll want to do something like slash posts slash slug, we can probably query for the slug and we can use that to reflect our URL.

JASON: I see what you're saying. That makes sense. Let's do that. I'm going to change this out for slug then. And then these will all also change to slug. When I save, what does that mean? Hey, look at that. So that's close but not exactly what we want. So instead why don't we -- I don't think it does come with a slug. That's incorrect. That's not how we want that to work.

COLBY: We probably want to prefix it.

JASON: Let's put under post or blog. How about blog. It goes to hello world but if we click it doesn't actually exist yet. So how do we get those posts to actually exist?

COLBY: Now we're going to create a dynamic page or dynamic routes rather where we can start off by creating a new directory under pages called blog, which is where our file will live. Or can you put that? I think it does it. And inside there we're going to want to create the dynamic pattern matching. The brackets with the slug.

JASON: Rubber duck done the reason we're changing from URI to slug we don't want WordPress's date all that in the URL. So instead we're going to set up our blog post as slash blog slash the slug. So using the slug in the query means that we just get to do that, as opposed to having to kind of reconfigure WordPress to change the way that slugs are written for posts. Which was what I was about to go do. And Colby reminded me we didn't have to. Let's keep it simple. Here if we export a function and I guess at the beginning if we say hello I am a blog.

COLBY: Make sure to name your function.

JASON: Oh, that's right. I'm mixing all my stuff because I'm a doofus. Now that I'm being less of a doofus, default expert is not a React component. That is a lie! That is a lie, it is.
You've got a lot of opinions, Internet. So cool. We've got the blog here, we've got this page. Now, how does this home page, does it have like a layout. I'm not going to -- should I worry about it or should we ship it ugly?

COLBY: Let's ship it ugly.

JASON: If we've got time we'll go back and do more. What do I get here? Now I'm able to navigate here, right? I get to this home page, and I click this and we get to a blog. But this is hard coded. So how do I actually connect that link to the content?

COLBY: So we're what we're doing with that dynamic slug we're telling Next.js we want it to be part of the dynamic URL. And inside that dynamic piece and inside of the get static paths function that we can define inside of that page, we'll have access to that value as a parameter, which we can use to create the paths that we need for the blog posts.

JASON: We've got get static path. This is what you just said. We're exporting a function called that. For that one we're doing another Graph QL query, right?

COLBY: Yes. At this point we're inside of -- are we? Yeah. So at this point when we're creating the paths, we want to query for all the posts. So that we can tell Next JS these are the posts we want to have a route for.

JASON: I need to go back one. All right. Now that I've got that, I'll make this async so we can do this query again. I'm going to get this result, but instead of did I miss a piece? I did. All I actually need is the slug now though, right?

COLBY: Right.

JASON: So I get my result, and down here when I'm returning -- I'm going to get rid of this console log. What I'm returning this one is get static props. So we're returning something different in get static paths, which is has an array, right?

COLBY: Exactly.

JASON: And we want that array to be each unique slug or full URL?

COLBY: We want each of the -- I believe we want each of the params. Inside of the paths there will be an object for each of the pages or posts, sorry, and each of those objects should have the params property inside of it which it will define what the params will be. In our case the params will have a slug params which will reflect the post slug.

JASON: So it's going to be like -- I'm going to do this long form. So we're going to return params slug like that?

COLBY: Yes.

JASON: To clarify what I just did because I did a whole lot in one line of code. We're getting the result of this query. The result has data, which is the actual -- you get dot data and dot errors from the query. Then we go into the query itself into post, into nodes, and this is an array, so we're mapping over that and getting the slug out of the middle here. And we're returning a new object for each one of the so now what paths is, is an array of objects that look like this.

COLBY: Now Next.js knows we're going to have all those paths that have that parameter that's unique to each post. So with that, we can now create our get static props function, which is going to access those parameters.

JASON: That's probably going to be async again. Function get static props is it like this or do I get like params?

COLBY: I think that's going to be params there, yeah. And this point we actually want to query for that param. I'm double-checking but if I remember correctly you can't actually query by slug so you've got to kind of do it the hard way. Let me confirm that. I might be wrong on that. So there's post by a top level query and we can select by slug.

JASON: Let's keep it simple. We'll get the title and content. That's what we want. So I'm going to copy this over. And our query is going to be GQL.

COLBY: It's just another reminder of how nice graphical is for setting this stuff up.

JASON: I'm naming these more out of trying to explain to my future self. Like this is actually optional we can delete it if we want it. It's nice to tell everybody who reads this later what's actually happening here.

COLBY: Does it show in the logs or something, like error logs? Is it useful?

JASON: If your have your graph QL it becomes more important. As your sites get more complex being able to differentiate, it can affect caching. There's a handful of things. So it's -- it won't matter until it does, but it's also pretty cheap to add it so I think it's nice to just kind of add it.
So I see a challenge here, which is I don't think I'm allowed to just do this, right? This is not okay in Graph QL land?

COLBY: I think you can, but you need to include the quotes still around it. Because you're essentially doing a template literal tag there, you can still place your variables inside of that. Let me double-check myself.

JASON: Even if that technically works, I don't think that's -- that's not the Graph QL way. Instead what we want to do is we want to include a variable, like a Graph QL variable. And we're going to set this as a required string. And this client here gives us the ability to set variables and we set it here. So the reason for this is that Graph QL is designed to accept queries in a cacheable, D-dupable sort of way. And when we supply it like this, it can do things it can statically analyze. When we start manipulating queries in javascript it gets difficult keeping things where. It won't matter until it does, but when it matters, it matters a lot. If you can keep things separate like that, it will make your life a little bit easier. And now we're back in here. So we're going to send back props. Props is one of these and so we can do -- we just want post and that's result.data.post by. Is that giving us just a straight result?

COLBY: Did you see that it added the await? I think that's because there's no await on the client query. That's interesting.

JASON: Silly bucket over here. That would have worked. That's like my favorite form of fetch when people wrap awaits in parentheses it's like await, await. It hurts me. This is cool. So now when we've got this, we should have a prop called post. And when we come up here we should be able to access that. I'm in the wrong place. Let's go up to the actual component. There we go. That's the right place. And here I should be able do like post.title. And wrap this thing in a div and also add a div with dangerously set inner HTML.

JASON: Here's the reason why this works. We are trusting our WordPress site to sanitize HTML for us. That is the only reason that we are using dangerously set inner HTML. Because we control the source of data. If we didn't, we shouldn't do this.

COLBY: I don't think WordPress will even let you -- like its interface won't let you input anything that could manipulate it, right? Like you can't put scripts in line instead of a WordPress editor, right?

JASON: I would guess if you were motivated you could do any terrible thing you wanted to in WordPress. What did I miss, chat? What did I screw up here?
Post singular, post singular. What have I done? Are we getting anything out here? Let's look. Post is not defined. I've missed something. Let's log this. Is that doing what we want?

COLBY: We need to fall back on it.

JASON: Oh, oh.

COLBY: I always forget about that.

JASON: Let's just say this one here. This one we're going to say fallback false. Because if we don't have a page, we're not going to try to do anything magic, we're just going to 404. So if we go to not a thing, it should 404.

COLBY: I'm curious why they don't have a default for that.

JASON: I feel like I could make an argument in both directions. I feel like having somebody explicitly choose whether they want a 404 or not is probably -- it's not the worst thing in the world to ask somebody to know, but it also like I would expect that if I provide an array of things, that it would just 404 if I didn't give that path. I don't know. Maybe the next team will do that. Anyways, it works. Yay. This is a WordPress page. So if I go back in here and I go to my posts and let's edit this and I'm like oh, hello, block editor.

COLBY: The same thing too, it's like the theme inside the Gutenberg editor, I think they take the theme -- the editor theme is the theme of the site I believe, at least that's what it looks like. So it's kind of like a weird editing experience. But there's also WordPress themes, like a headless WordPress theme or a minimal, that way it's just like, you know.

JASON: Yeah. But yeah. So this is -- this is pretty cool stuff. And I am happy. All right. So then if we take this and go back to -- let's maybe add a little bit more -- we'll have like a link. Then we'll do an href of home and we'll say back to home. Let's use HTML entities, left arrow.

COLBY: If we create a new post it should just work.

JASON: I don't like --

COLBY: Do we want to try that out?

JASON: Create a new post? Yeah we do. This button? No.

COLBY: I think we actually have to go back to the WordPress editor.

JASON: How do I leave?

COLBY: I think you can click the logo at the top left.

JASON: Got it. Cool. So I'm going to add a new post. And we'll say. . . High quality information. And I'm going to post it and we're going to come back out here and I'm going refresh the page.

COLBY: You might have to restart the server to -- because the query would probably be cached, right? Wouldn't you have to redo that query?

JASON: It shouldn't be, because when you're in dev mode, this should just fire. Did I forget something? Let's see. Something Boopful is now live. Let's stop and restart it -- oh, wait. It doesn't like something. It's just log is fine. Logging is fine. So let's stop and restart and see if maybe it did cache.

COLBY: Hey.

JASON: I'm not exactly sure to not be the case. But I mean, what do I know? I'm not a WordPress expert. Okay. So that's a thing that will have to happen. And really in like in practical purposes, that's completely acceptable, right?

COLBY: Exactly.

JASON: That's what you would expect. We've got 15 minutes left and I want to get two more things done. First, I want to pull for my pages, for this home page content here, and then I want to get this thing deployed to Netlify. Let's go to pages and I want to make this one my home page. My permalink. If I just make this nothing, will it work?

COLBY: I think you probably -- I'm actually not too sure about that one.

JASON: I want it to be home. You know what I think I have to do? I think I have to do like this site is built with Next and WordPress.
So I'm going to update this and then I think we have to go into the WordPress stuff. Because here, reading, the home page is a static page, ta-da. So now I'm pretty sure if we go back to the editor here --

COLBY: The only thing I don't know is how you query by front page. Maybe you know how.

JASON: I think what will happen is it's going to use the slug. So if I go -- actually let's do page by URI slash and then I'm going to get the title and let's find out. So here's my title. All of you go away. Tada! So when we set it to the home page it changes it to the URI that's what I was changing in the settings there.

COLBY: That makes sense.

JASON: Let's at the content. There we go.

COLBY: Yay!

JASON: Now when I go to my index here, I can -- check this out. This is why I love Graph QL. I can just. . . Get WordPress on page and posts. So then I can do like title will be result.data.postby.title and then we'll do the same thing. This is ugly but I want to make sure we get done. We'll get the content. And then up here I can do like posts title content -- thank you for the sub-Irish Beets I appreciate it. Welcome to the Boop Crew. Make sure you abuse that emoji. Add a div -- there are those boops. We'll add some HTML, put the content in here, and I think nothing up our sleeve. It's broken. I think we need to --

COLBY: That query again.

JASON: Restart. Maybe the home page gets queried specially or something. I'm not going to lie, I'm a little bit confused by that. But it's probably -- no it doesn't like that at all. I'm doing something wrong. Page by, title. Oh, page by, not post by. I am very good at computers. There we go. There it is. There's our site. Look at that, y'all. We've been able now to build a site and if I go in here and I edit this a little bit more, I go to my pages and I'm going to edit. Let's change this out. And we can say like oh dang, all of this is managed in a WordPress headless CMS. And then I can just start cleaning up the rest of this, because I don't want it anymore. Bye. There we go. Update. Then when I refresh, it is cached, but that's okay because we know how that works. We can stop and restart. So the next thing that I can do then is I am going to -- I mean, let's just like make this thing work. So I've got my we're built here, I'm going to create a Netlify or do I even need one? I don't, do I?

COLBY: The only thing -- so the only thing I'll say is if we're deploying the Netlify, unless it does it like -- just does it, quote, the next on Netlify, we will need to export it statically. That's the only thing we might want to consider doing.

JASON: Yeah. Here's what I'm going to do. I have this repo, let me GitHub repo create Learn with Jason WordPress next.

COLBY: I need to install that ES.

JASON: It's the git CLI. It's very nice. Now I have a public repo. Now I'm going to git add everything and did we add anything I didn't mean to? That all looks good. So I'm going to git commit and we'll say feature headless WordPress site. And then we'll git push origin main. Great. And then I'm going to set this up with Netlify. So I'm going to do a Netlify init and it's going to create a new site, which is what I want to do. I'm going put it into my team. We'll call this WordPress Next. I bet this is taken. What? Amazing! Okay. So then I can do an NPM run build. I think this part is all going to take over by Next on Netlify. Find the functions folder we're not using yet. Sure, I'll create a Netlify.toml. So now I'm going to open this, and it's going to open my browser, take me to Netlify. And we're going to do a plugin.
So I'm going to go to the plugins and I'm going to search for Next. And I want Next on Netlify. So let's install that on this one. And what this is doing is it's just adding support for like really we don't need this. Like with what we've built we could run Next export and it would be fine. If we want to add things for support for the fallback true or API routes the Next on Netlify is going to make that work

COLBY: Does it even work for get server side props?

JASON: I think so. It changes the next target to serverless, which means we can support all the features. There are some things that won't work. And this is the one that built without. This one, I think is built with. Let's see if it's going to tell us stuff. So I don't think we have to change anything. I think if we just put on Next on Netlify here, it's just going to work. Let's watch what happens. The plugin will start talking to it shortly.

COLBY: I usually try to get a static first until I need to reach for the server side stuff. I like having a little bit of extra sanity with it.

JASON: Here comes the plugin. It's building, it's doing things. Creating an optimized production build. Warnings are fine. I'm mostly worried -- here's Next on Netlify. It does all this work for us. It builds all the copy and all the things that we need to do. It sets up API end points, Netlify functions all the things we wanted now work. It just works.

COLBY: That's really cool.

JASON: It's very, very handy. So then it's going to do the function bits. Deploy. And we're live. Hey! Look at us go. And that is a deployed to production WordPress site running off of Next and Netlify. And when we click through, these things work. Everything does what we want. It is magical, y'all. I mean I really like this workflow. And what I like about it is it lets us do so much. When we're looking in here, this path of being able to say like I'm going to query whatever API, and the data that I get back I can drop in as props. And here's the thing that I think is really cool. If we look at this now, let's look at what happens in the network tab when we refresh this page. So if we look around, we will not see a query to WordPress. What we will see is our home page manifest somewhere in here. Maybe it doesn't show -- oh. So this one is generated to static HTML so we don't have to load the manifest. Hello world here is set up where we get a response. This is the props. So these are the props that we got. So we have our title, our content, all that stuff. So that when we click through to hello world, it loads instantly. Despite the fact that we didn't actually have to hit the API.

COLBY: It's beautiful.

JASON: We're sending very little content around, and this is with very little optimization or anything like that. What a great flow. If we want to shut down that WordPress instance, we can. Why would I keep this live? It's kind of this power of this model when I shut down WordPress, this site will stay forever until I take it up or try to rebuild it when WordPress is broken. But that is extremely, extremely cool.

COLBY: One question is about --

JASON: Were you going to talk about images?

COLBY: I was going to talk about deploy but images is interesting too.

JASON: We have like 4 minutes left.

COLBY: Since Netifly has the hooks, there's WordPress plugins that will trigger the play hook any time you update changes. If you find that plugin, and I can find it later, you just hit that build hook every time that content changes and it will click up a Netlify build and you have your updated site.

JASON: The way I like to do images with this plugin that I built so you don't hammer your nonasset services for assets. It will also optimize and make them smaller. All that good stuff. If you can just plug this into Next. If you want to see it in action, I think we'll use it on the explorer site. If we don't use it on the explorer site, we use it on Jason.af. The source for both of these sites is on GitHub. Hold on. We need to wrap up. I want to make sure we don't go over time. And Colby I want to make sure you get a chance to tell people where should somebody go if they want to learn more from you or learn more about this?

COLBY: You can go to my Twitter and I link out to everything. I have a YouTube channel where I do weekly tutorials. I also recently put out a course on egghead. So definitely check that out.

JASON: Nice. So good check out Colby. This is a really great kind of central hub here. Go follow him. And if we go to your website we can find all of these things? You've got the newsletter and it looks like we've got all sorts of good stuff here.

COLBY: I also have a -- yeah.

JASON: This is also amazing. I love that.

COLBY: I'll have to send you some stickers.

JASON: Please do. Let's do another shout out to White Coat Captioning we had Nicole diligently transcribing all of the nonsense that I pour out of my face. Thank you so much for putting up with me. That is made possible by White Coat Captioning and the generous support of our sponsors. Netlify, Fauna, Auth0, Hasura, thank you for making it accessible. Make sure you check the schedule. We've got so much fun stuff coming up. We've got century air tracking serverless functions. Then we're going to do state machines and Kubernetes. State machines I know, Kubernetes I know nothing about. I've maybe used Kubernetes once or twice in my career. That's going to be an adventure. Abbi is going to be frustrated with me. We're going to have Ben back on, Vue3, Sunil is joining we're going to talk about esbuild. Jennifer is coming to talk about Angular and building forms. So much good stuff is coming so please, please, please make sure you go to the schedule page and click this add Google calendar. If you want you can even set reminders. I think that's everything. Colby? Any parting words?

COLBY: You can go and enjoy WordPress if that's your favorite thing because now you can use it with jamstack.

JASON: If you build stuff show us what you're building. We're going to find somebody to raid. Colby thank you so much for spending time with us today. We'll see you next time.

COLBY: Thank you. See everybody.