Tech Breakout Summit/2021: [Demo] Building Modern Experiences with Headless WordPress

Headless WordPress architectures use modern JavaScript frameworks like React to create experiences that push the envelope of what’s possible with WordPress. In the video below, find out how WP Engine is helping shape the future of WordPress.

Video: Building Modern Experiences with Headless WordPress

In this session, WP Engine Developer Relations Manager Matt Landers discusses:

  • Everything Atlas, starting with the code on WP Engine’s developer site for a demo of headless content delivery.
  • New tools like the Atlas Content Modeler and Content Engine, including demos of live sites using these powerful applications of headless.

I think this really changes the game for Headless WordPress. Having the ability to create custom content types in a nice headless-first way with a great user experience—for the developer creating the types and for the publisher who is going to enter the content—it’s crucial to making a great headless CMS.

Full text transcript

MATT LANDERS: Hello, Summit 2021. I’m Matt Landers, Head of Developer Relations at WP Engine. And in this session, we’re going to do a demo of everything Atlas. So, there’s no slides or anything like that, we’re just going to look at code, write some code, and then get a sneak peek of some things that are coming in the future.

So, the first thing that we’re going to do is we’re going to look at our Headless developer site. That’s at

We’re going to look into that code, see how we accomplish some of the things on that site. And then we’re going to take a look at a new tool that we have coming, the Atlas Content Modeler, and see how we could have done some things differently and build a little site with that tool.

After that, when we’re done, we’re going to get a sneak peek of Content Engine, which you should have heard a little bit about in the keynote. We’re going to see a live site running on that. And we’re going to talk a little bit about what could be coming in the future. So, let’s dive right in and look at the developer site.

All right. So this is the developer site. If you haven’t been out here, you should definitely check it out. It’s at

There’s links to where you can get in touch with me and my team. Like, our Discord server, definitely join that and get into our community and talk about everything related to Headless. There’s a podcast that we release every Monday, check that out, the Decode podcast. And we have a YouTube channel as well, where we post video tutorials, blogs, and everything else.

So, on the home page here, you’ll notice that we have some blogs. These are coming straight out of WordPress, just their posts. And then up here, we have links to some documentation. Now, all of this documentation actually lives in GitHub. So we have a repo, headless-docs, where a lot of our Headless docs are, that gets pulled into this site. So, it’s a data source for us.

So we have WordPress, GitHub, and then we also have videos down here, that we pull from YouTube. Now, these videos have a custom post type related to them as well, which is something that I want to talk about. And that’s what we’re going to use the Atlas Content Modeler to show how we would do this with it, rather than the way that we’re doing it now. So let’s dive a little bit into how we’re accomplishing these video tutorials right now.

So, if I go over to the WordPress side, you’ll notice that I have a custom post type here called Videos. So here are all of the videos. So these each have different fields related to them. They have the video URL, the publish date, and the title. So let’s look at one. Here’s one on custom content types. We also have SEO data in here as well.

And then we pull this data back with a query to WP GraphQL. So this is the query that we’re using in our code, and it pulls back a list of all these videos, straight out of that custom post type. This is really convenient to be able to create this nice data entry experience for our publishers, or whoever is going to edit this data, to be able to put things onto the site in a very structured way.

This is very common in a Headless set up. And the way that you have to accomplish it today is we need a few plugins. So the ones that we’re using here are Advanced Custom Fields, Custom Post Types UI, and then the WPGraphQL extension for advanced custom fields.

And what this allows us to do is create a custom content type in the form of a custom post type, and then add a field to that with advanced custom fields, and then query those through GraphQL.

So this is a really important piece of building a Headless site. This happens all the time. But the experience that we get when we use these plugins is not great right now. So, if I go to Custom Post Type UI, I have to come over here, I take my videos post type, have all of this extra data here that I don’t really care about, it doesn’t matter in a Headless world.

And then when I get down to the bottom, I can add it to GraphQL, I can name what I want that post type to be, and all of this stuff. So there’s like this disconnect between what a custom post type is traditionally used for in WordPress, and what I need it to do in a Headless scenario.

So then I have to go over to my Custom Fields and actually create a custom field group that is attached to my custom post type. So now I’m doing things in two different places. So you can see that this is somewhat of a disconnected experience. When really what I want to do is just create a data model for my custom post type and then have a nice way for me to enter that data.

So, this does work. And you can do this today. We use it on all of our Headless sites. Definitely recommend it. You can go check out some videos that we have on our site for how to create custom content types. And it walks you through all of the plugins that you need and does a demo of how to build a site from scratch using that. So, definitely check that out if you’re interested in how this works in detail.

But now, let’s go over to the site and see how this translates. So we end up with these video tutorials. This one pulls the top three for the home page. And if I click watch more or view more, I can see all of them. So now let’s go over to the code and check out how this is working.

So now I’m in the code for the developer site. And you can see that I’m on the Video page. So this shows me the list of videos. I have my query here, which is what we just ran in the graphical editor. And then I have my React component as where we’re pulling this data into.

And basically all that we have to do is, we’re using our Headless framework, and we get our Apollo client. We make that query here. And then we– Then that data will be available to us in our component, which is how we get right here. We make the same query on the client side, or inside the component. So this will happen server side as well.

So, the way that the framework works is that it will make that query on the server. We’ll get the videos back. We’ll save those to an Apollo cache and make sure that’s available on the client as well. We’ll restore that cache. So that whenever this component runs on a server, we make that call, we get the videos. And then on the client, we’ve already got the cached data, so it doesn’t actually make the call again. We only make that call once. And that’s something that you get with the Headless framework. So check that out as well.

All right. So you can see kind of how this process works. It’s just a React component pulling the data from WordPress. And we had to use the Custom Post Types and Advanced Custom Fields to make this happen.

So in the next part of this demo, let’s build a site that does something very similar but using our Atlas Content Modeler. And we’ll walk through what that is, how it works, and how you would implement it in your site.

I’ve got a little site up and running. I haven’t done much. I just started with our Headless framework starter template, and then I stripped it down a little bit, and just show a list of posts that come out of a local WordPress site that I’m running. So, let’s take a look at that.

I just have a local site here running. Not a whole lot to it right now. We do have some plugins installed, one of them is the Atlas Content Modeler, which we’re not actually using yet. We’re going to use that right now in this demo.

But I’m going to have the WP ENGINE Headless plugin, which is part of our Headless framework, and WP GraphQL. So, there’s not a lot here. And then I just have some posts.

So let’s look at Visual Studio. And here’s a catch-all route that I have. So I just have a catch-all route, and that’s JS. And it displays the page. And just has a layout component here, which we won’t dig into that. And then we just loop through posts and show them on the screen. And it’s pretty straightforward.

So, with the Headless framework, I’m not doing any custom query here. So you don’t see a GraphQL query or anything like that. We have these React quotes that you can use. And that pulls in the post based on the URL that you’re on, and shows them on the page.

All right. So, that’s working. But what we want to do is, we want to add in About page that shows a list of team members. So we’re going to build that right now.

The first thing that we need to do is create the About page. So, let’s go ahead and do that. So I’m going to go to my Pages folder here. Create an about.tsx. And I’ll just create a simple component to make sure this is up and running. So, let’s call it About. Just a simple React component.

So I’ll just do an h1 for now. Put About there. A little bigger. All right. And then we just need to export that.

Perfect. All right. So now let’s go back over to our site. And click the About page. And there it is. We lost our nav bar and our footer. So let’s go ahead and just make that work, since that’s pretty simple.

We have a layout component in the project already, so I’m going to use that.

All right. I need to import that component, and should be good. Save that. All right, there we go. Somehow ended up with a space.

All right. So, now we have our header and everything, so we can navigate around, which is great.

Perfect. OK. So, now what we want to do is we want to be able to create a custom content type. So, you saw in the developer site when we created those videos, we used the Advanced Custom Fields, Custom Post Type UI, and then an extension for WP GraphQL for Advanced Custom Fields.

And then the interface that we got to create that content type wasn’t that great, it had a lot of things in there that just don’t make sense in a Headless scenario. So what we wanted to do was create something that allows us to have a more streamlined Headless experience for creating custom content types. So let’s check that out in WordPress.

So, here we are. We’re in the Atlas Content Modeler, which you should be able to start playing around with right now. The version that you see might be slightly different, but the concept is the same. So, let’s check it out.

When I come in, the first thing that I see is that I just have a getting started button. It’s really nice UX, though. We spent some time with our designers to make this a good experience for creating these types.

So I click Get Started, and I’m ready. I’m just creating a new content type, or content model. We’re going to create– On that About page, we’re going to show a list of team members. So let’s just call this Team Member. That’s the type. And then the plural name will be Team Members.

And we’ll get what our API identifier is. So, this is what’s going to show up in the Rest and WP GraphQL API. And then we have a description. So, I’ll just call it DevRel Team Members. And we’ll create that.

Now when I create that, the first thing that you’re going to notice is that we get that showing up in the left hand side of the nav here. If I click on it, you can’t really do anything yet. So let’s go back.

I need to add some fields. So I’ll go in here and add our first field. So, we have a bunch of different fields here that we can choose from. The first one that we’re going to choose is just a regular text field. And we’re going to put our name in there. So we need to have the name of each of our team members. We’re going to make this field required.

And we want to use this as the entry title. I’ll show you what that means in just a second. And we’ll go ahead and create that.

So let’s go back over to our Team Members and add one. So now when we click Add, we see that we have the name field here. And we just fill it out. Put my name in. Publish that.

When I go to my list, I see Matt Landers in here. And that’s because I clicked that check box. Let’s check it out again.

So, If I go into that field, you’ll see that it says use this field as the entry title. That is the field that will show up in the list of all of the entries for that custom post type.

All right. So let’s add some more fields here. So, If I go over here, I can get this plus button. And then we have all of these different field types. So we used a regular text field. We have rich text, so that will allow you to do like bold, italic, whatever. So let’s use that for one of our fields.

We’ll create a bio.

All right. And then let’s also add a media element for our profile pic. We’ll make that required as well. And then we’ll go back over to our editor and we’ll add these in.

So, let’s say– Let’s add some text in here. I’ll say, Hi, this is Matt. But I’ll bold that, and I italicize the whole thing. And then we’ll pull that in on the front- end.

Also, I want to upload a pic. I already got one on here. And I’ll add my profile pic, and we will update this. All right, great.

So now I’m going to go Team Members. You see that I just have that. I can add my list. So, let’s add a couple of people in here.

Let’s add Will. And I’ll upload a picture here.

And there is Will. Perfect.

Publish that. And that’s all we need to do for now. Now, we’ll go add this in.

All right. So now we have our list. We have Will and Matt. And let’s go to the Content Modeler and look at something else that’s really cool. If I put the ellipses over here, I have an option to open in GraphQL. So I’m going to click that.

That automatically creates the query for me that I can run right away, that’s pulling everything back. So I can literally just copy this query into my code and start pulling back the team members. I don’t need all of this data, so let me get rid of some of it. I don’t need all this data about the profile pic. I just need the URL, really. And we’ll run that, make sure everything’s good. Perfect.

All right. I’m just going to copy this query over into Visual Studio. Pull that up. And we’re going to paste the query here. And we’ll just call it Team Members. And we’re going to make that a GQL query. I’m going to import this function.

Now we have our query, everything’s here. You’ll notice that it is– It’s under Team Members. So we need to remember this for whenever we’re pulling the data out. So we’ll have to drill down and get to our Team Member data.

All right. So let’s go ahead and do this.

So we’re just goint to use useQuery. We’ll do this all client side for this demo. This is more about the Content Modeler and pulling content types, not about static site generation. If you want to learn about that, we have plenty of videos on our site that show you how to do that. So, check it out.

All right. So we’re going to pull that data out using useQuery, which is an Apollo hook that allows us to make our GraphQL query.

All right. So, we have our data. And we want to put that in something nicer. And we’ll call it Team. And do data dot Team Members, because that’s what it was for that API identifier, and then nodes.

All right. And then we want to loop through these and show all the team members. So, let’s do it. So we just do team. I’m going to make sure that it’s there, because it won’t be there until the query happens. And then we’ll just do dot map. We’ll get a team member out of that.

I don’t have any typings for this, and I’m not going to worry about it for the demo purposes. But definitely would want to create some of those. And we’ll be helping you out with that in the framework here soon as well.

All right. So, let’s just show the name for now. So, I’ll just do member dot name. And should be good to go. Let’s go check it out.

Go to our site. And there they are. Matt and Will showing up. So that was really simple. I was able to go into the Content Modeler editor, create a new content model, add the fields that I need. And then pull them up really quickly, because I was able to just generate that query from the Atlas Content Modeler.

So, let’s go ahead and blow this out and make it look nicer. So I have an li. I need the name, which we’ll just put that in an h2, let’s say.

I also didn’t wrap this in a ul, I just realized. Wrap it. That way I don’t get the bullet.

All right. Make sure those go away. There we go. Looking great.

Now let’s bring our bio in. So, for our bio, we’re going to have to put that in a div, because it’s going to be HTML. So let’s pull that out using dangerously set HTML, which isn’t as dangerous as it sounds because we know where this data is coming from. If you had user entered data, you wouldn’t necessarily want to do this. But we know where this data is coming from and we trust it.

All right. So we’re going to do member dot bio. And then we’re also going to have our image. I’m not going to do a lot to format this image. I actually don’t know what it’s going to look like.

And the source is just going to be member dot profile pic dot media item URL, I think. Let’s see. Yeah. Media item URL. All right. Perfect. Save that. Go back over to our page. And there we are.

And you’ll see that we’re getting that formatting here from our rich text as well. So this is pretty cool. So, from the Content Modeler, we were able to do all that very quickly. If you’ve ever done this with ACF, or in Custom Post Types, and all that, the experience is not nearly as nice and fluid as this.

I mean, we just come in here. We can create another one. Call it whatever. We’ll just do a test one. Create that. And just so that we can see this again.

So, I mean, that quickly we’ve added this over here. We can add a number field. Like, let’s just create a Test Number field. You can have an integer or a decimal. Create that. A Boolean. See how that shows up.

Go over to Tests. Add a new one. And we’ll see that now we have this number field. So I can’t– It let me type in numbers, which is kind of odd. But I also have– There is a text box of type number. And then I can click that checkbox for the Boolean. And everything’s great.

So, this is cool. So what we’re going to be doing in the future is adding more field types, and just continuing to iterate on this to make the experience better. So, please go out and check this out, build some stuff with it, and give us some feedback in our Discord server. And let us know what you think.

I think this really changes the game for Headless WordPress. Having the ability to create custom content types in a nice headless-first way with a great user experience—for the developer creating the types and for the publisher who is going to enter the content—it’s crucial to making a great headless CMS. So, definitely, please check it out. Go out there and build some sites with it.

Now, let’s deploy the site that we created to Atlas.

So, what we’re going to do is we’re going to create a project in user portal, and then hook up our repo to it, and get it running on the Internet. So, the way that Atlas works is that it connects with your GitHub account.

So, I’m going to go over to user portal, go to Atlas, and I’m going to click create a new app. When I come in here, it’ll connect to GitHub. I’ve already given access to the repo to Atlas. So now I see it in my list. Here it is, Summit 2021. Click on it.

I’ll choose my region, US central. And then I need to tell it what branch I want to use. I’m going to use the main branch. And I’m going to call my environment Production. So this is where you can create multiple deployments for an Atlas front-end. And it’s based on the branch that you connect.

So, I’m using the main branch, that’s all that I have. But if you had a dev branch, you might create a developer environment. And you can also create a bunch of these for feature branches or whatnot, if you want to show someone what something will look like before you merge it via PR.

Also need to connect this to a WordPress site. So, I have one already, Summit 2021 Demo. And then I need to create some environment variables. So, let’s grab those. I need to grab that out of the code.

So if I come over here, I have a dot env dot local file. The only environment variable I’m worried about for this is the Next Public WordPress URL. So what happens here is I can give it this environment variable name and a value, and then that will be available to me at build time and runtime to my node process.

All right. I have that WordPress site already set up. And it’s at https Summit 2021 demo dot WP Engine powered dot com.


All right. So let’s go ahead and create that app.

So, the app is being created. Once it’s done, we’ll be able to get a new URL and view it on the Internet. So, let’s check it out.

So we’ll see in here, we have all the information about what we’re deploying, like what repo we’re using, what region we’re in, and that the code is building. Once the code has built, we’ll have another section down here to show the build log. So, if there are any errors or anything like that, they’ll show up there.

All right. I’ll wait for that to deploy, and check it out.

All right. So, our site deployed. And now we have a URL that we can click on and check it out. So it’s at And there it is. Super fast. If I click on About, we’ll see all of our data coming through for our custom content type that we created with the Modeler.

So, this is awesome. So just like that, we were able to create a little site. Use the Atlas Content Modeler to create custom content types. And then we deployed that to the Atlas platform and got it running on the Internet really quickly.

We just hooked up our GitHub account. And what happened is, the platform pulls down our code from the branch that we tell it to, we run NPM Install. Then we run NPM run WPE dash build. That’s your chance to do any static file generation, or whatever you need to do. And then whenever we run the site, we run NPM Start. And it needs to run on port 8080.

So that’s what we did. It’s up and running. And we’re good to go. Now, what I want to do is, tell you a little bit about Content Engine, show you a demo, and tell you what we have coming in the future.

All right. Let’s do it.

What you’re seeing right now is a site that’s running on Content Engine. We replicated our site to another WordPress Install, and we hooked that up Content Engine. So what Content Engine is, is it sits between your front-end, so you’re node app or whatnot, and you’re back-end on WordPress.

And we suck data out of WordPress into Content Engine. So now on your front-end, instead of talking to WordPress directly, you can talk to Content Engine.

Now the thing about it is that it’s globally distributed and it’s super fast. So, on this site right now, there’s no static generation or anything. We’re just hitting dynamic pages, and it’s really fast. So let’s click around and just see that.

So you can see that as we click, it’s super fast. Just like what you would expect almost from a static site, right? And this is all happening because we have this really fast data layer that’s sitting in the middle.

So, if you look at this site versus our other Torque site, it looks the same, we’re pulling all of the same data in. And it’s incredibly fast. And this schema that we have is much simpler than you might get out of WordPress directly.

So, I’m not promising anything right now, but I just wanted to give you a sneak peak of Content Engine, what’s to come. So, definitely stay tuned. And sign up for the Beta, if you want to play with it. We’re going to have that coming out soon. I have a link in the notes for this session. Click on that, sign up, and be part of Beta.

So, hopefully, you enjoyed this Atlas demo. I’m really excited about everything that we’re doing related to Headless WordPress here at WP Engine. And I hope that you go out and try that Content Modeler, and you give us feedback. We really appreciate that. And we’re really excited about all the different directions that we can take that play in.

Thanks for coming to this session. And go out there, build some awesome Headless WordPress sites on Atlas. And happy coding.

Get started.

Build faster, protect your brand, and grow your business with a WordPress platform built to power remarkable online experiences.