{"id":394,"date":"2022-04-07T13:47:19","date_gmt":"2022-04-07T19:47:19","guid":{"rendered":"https:\/\/developers.wpengine.com\/blog\/?p=394"},"modified":"2023-06-15T13:54:21","modified_gmt":"2023-06-15T19:54:21","slug":"build-simple-headless-wordpress-app-next-js-wpgraphql","status":"publish","type":"post","link":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-next-js-wpgraphql\/","title":{"rendered":"Crash Course: Build a Simple Headless WordPress App with Next.js &#038; WPGraphQL"},"content":{"rendered":"\n<p>In this tutorial, you will learn how to create a simple headless WordPress app using <a href=\"https:\/\/developers.wpengine.com\/docs\/glossary#next-js\">Next.js<\/a> and <a href=\"https:\/\/developers.wpengine.com\/docs\/glossary#wpgraphql\">WPGraphQL<\/a>. This tutorial assumes a basic understanding of JavaScript, <a href=\"https:\/\/developers.wpengine.com\/docs\/glossary#react\">React<\/a>, and WordPress. Using the prepared GitHub repository will allow us to focus on points specific to Next.js as a framework and Apollo Client for data fetching in WPGraphQL. By the end of this tutorial you will be able to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Create static and dynamic routes in Next.js<\/li>\n\n\n\n<li>Use the GraphiQL IDE to compose GraphQL queries<\/li>\n\n\n\n<li>Use Apollo Client fetch data in your app<\/li>\n\n\n\n<li>Choose appropriate Next.js rendering methods based on your content<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"Build a Headless WordPress Site with Next.js and WPGraphQL\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/wfy51nhjfUQ?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites  <\/h2>\n\n\n\n<p>To get started, you&#8217;ll need to make sure that you have both <a href=\"https:\/\/nodejs.org\/en\/\">Node.js<\/a> and <a href=\"https:\/\/docs.npmjs.com\/downloading-and-installing-node-js-and-npm\">npm<\/a> installed. If you aren&#8217;t sure whether or not you have this software installed, you can run the following commands in your terminal: <\/p>\n\n\n<pre class=\"wp-block-code language-bash\"><span><code class=\"hljs shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span>node -v\n<\/span><\/span><span class='shcb-loc'><span>npm -v\n<\/span><\/span><\/code><\/span><\/pre>\n\n\n<p>The terminal output should either tell you which versions you have installed or that it cannot find the commands <code>node<\/code> or <code>npm<\/code> to run them. Using <a href=\"https:\/\/github.com\/nvm-sh\/nvm\">a tool like <code>nvm<\/code> (Node Version Manager)<\/a> to install and manage versions of Node.js on your machine can be helpful when working on multiple projects.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Configure Your WordPress Site<\/h2>\n\n\n\n<p>Next, let&#8217;s set up a local WordPress site that can be used as the data source for our example application. In the next section, we will walk through creating a WordPress site via <a href=\"https:\/\/localwp.com\/\">Local<\/a> and populating that with some test data. If you already have a WordPress site that you want to use, you can skip ahead to the &#8220;Install Plugins and Check Settings&#8221; section.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Create a WordPress Site with Local<\/h3>\n\n\n\n<p><a href=\"https:\/\/localwp.com\/\">Local<\/a> is WP Engine&#8217;s local development tool, and it makes it very easy to work with WordPress locally.  You can <a href=\"https:\/\/localwp.com\/help-docs\/getting-started\/installing-local\/\">install the app<\/a> and create a new WordPress site in a few steps.<\/p>\n\n\n\n<p>Click <code>Create A New Site<\/code> on the application home screen to create a new site.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-01-at-12.32.12-PM.png\" alt=\"\" class=\"wp-image-411\"\/><\/figure>\n\n\n\n<p>Choose a name for your new site, and then click <code>Continue<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-01-at-12.34.18-PM.png\" alt=\"\" class=\"wp-image-412\"\/><\/figure>\n\n\n\n<p>For most users, you can stick with the <code>Preferred<\/code> installation environment, and then click <code>Continue<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-01-at-12.35.08-PM.png\" alt=\"\" class=\"wp-image-413\"\/><\/figure>\n\n\n\n<p>Lastly, specify values for the <code>WordPress Username<\/code> and <code>WordPress Password<\/code>, and be sure to remember these values. Once that is complete, click <code>Add Site<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-01-at-12.36.08-PM.png\" alt=\"\" class=\"wp-image-414\"\/><\/figure>\n\n\n\n<p>Depending on your permissions, Local may ask for permission to make modifications to your system. After your site has been successfully installed, you will see it in the Local dashboard. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-01-at-12.38.12-PM.png\" alt=\"\" class=\"wp-image-415\"\/><\/figure>\n\n\n\n<p>To access the WP Admin panel of your new site, click <code>Admin<\/code> in the site details pane. You will need to authenticate with the username and password you created in the previous step. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Install Plugins and Check Settings<\/h3>\n\n\n\n<p>With a basic WordPress site up and running, there are a few things left to install and some settings to check. <\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Check Permalink Settings<\/h4>\n\n\n\n<p>All of the code in this crash course assumes that you have the <code>Post name<\/code> option selected for your permalink settings. To check or modify this setting, open the <code>Settings &gt; Permalinks<\/code> menu in the WP Admin dashboard. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-01-at-12.45.22-PM-1024x443.png\" alt=\"\" class=\"wp-image-416\" width=\"610\" height=\"263\"\/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Install WPGraphQL and Enable Debug Mode<\/h4>\n\n\n\n<p>From the <code>Plugins &gt; Add new<\/code> menu, search for <code>wpgraphql<\/code> in the WordPress plugin repository. Install and activate the plugin, which will add a <code>GraphQL<\/code> tab to your WP Admin sidebar.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-01-at-12.49.13-PM-1024x480.png\" alt=\"\" class=\"wp-image-417\"\/><\/figure>\n\n\n\n<p>Activate Debug Mode. Open the <code>GraphQL &gt; Settings<\/code> menu and check the option labeled <code>Enable GraphQL Debug Mode<\/code> and then click <code>Save Changes<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-01-at-12.51.53-PM-1024x399.png\" alt=\"\" class=\"wp-image-418\"\/><\/figure>\n\n\n\n<p>With Debug Mode enabled, you will get more helpful error output as your develop your application. Note that using Debug Mode is not recommended for production sites.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Import Placeholder Content<\/h4>\n\n\n\n<p>If you&#8217;re working with a newly created WordPress site, you can run <a href=\"https:\/\/wordpress.org\/support\/article\/importing-content\/\">the import process<\/a> on <a href=\"https:\/\/github.com\/JEverhart383\/crash-course-headless-wp-next-wpgraphql\/blob\/main\/crashcoursesite.WordPress.2022-04-01.xml\">this export file<\/a> to create some placeholder content for use with this tutorial. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Get Your Next.js App Running Locally<\/h2>\n\n\n\n<p>Now that you have a WordPress site with at least some content, whether running locally or on the web, we can get started with Next.js.<\/p>\n\n\n\n<p>The rest of this tutorial is based on the files that can be found in <a href=\"https:\/\/github.com\/JEverhart383\/crash-course-headless-wp-next-wpgraphql.git\">the crash course&#8217;s GitHub repository<\/a>. This repository is heavily based on <a href=\"https:\/\/nextjs.org\/docs\/api-reference\/create-next-app\">the default Next.js template<\/a> created with <code>create-next-app<\/code> CLI tool, with some additional scaffolding and styles provided by the WP Engine DevRel team.<\/p>\n\n\n\n<p>To clone the repository to you local machine, you can run the following command:<\/p>\n\n\n<pre class=\"wp-block-code language-bash\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span>git <span class=\"hljs-keyword\">clone<\/span> https:<span class=\"hljs-comment\">\/\/github.com\/JEverhart383\/crash-course-headless-wp-next-wpgraphql.git<\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Once the project finishes cloning, run the following commands to switch into that directory and install all of the project&#8217;s dependencies using <code>npm<\/code>. After the dependencies finish downloading, you can run the project in your browser using <code>npm run dev<\/code>.<\/p>\n\n\n<pre class=\"wp-block-code language-bash\"><span><code class=\"hljs shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span>cd crash-course-headless-wp-next-wpgraphql\n<\/span><\/span><span class='shcb-loc'><span>npm install\n<\/span><\/span><span class='shcb-loc'><span>npm run dev\n<\/span><\/span><\/code><\/span><\/pre>\n\n\n<p>With the app running locally, you should be able to view the app at <code>http:\/\/localhost:3000<\/code> in your browser, and the app will recompile and update as make changes to the files in the project directory.<\/p>\n\n\n\n<p>All of the posts you see on the local site are dummy data sourced from a local JSON file. In the next step, we&#8217;ll connect Apollo Client to WordPress and WPGraphQL to display actual post data from your site.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Connect Apollo Client to WordPress<\/h2>\n\n\n\n<p>The first step in replacing our mock post data with data from your WordPress site involves configuring Apollo Client to work with your site via WPGraphQL. <\/p>\n\n\n\n<p>While technically, you could <code>POST<\/code> your queries directly to your GraphQL server using only the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Fetch_API\/Using_Fetch\">Fetch API<\/a>, using a GraphQL client like <a href=\"https:\/\/www.apollographql.com\/docs\/react\/why-apollo\">Apollo Client has a lot of added benefits<\/a> that are beyond the scope of this post. Many of the following steps are also contained on <a href=\"https:\/\/www.apollographql.com\/docs\/react\/get-started#1-setup\">the Get Started page of the Apollo Client docs<\/a>, so be sure to reference that page if you are interested in learning more about the library.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Create a .env File<\/h3>\n\n\n\n<p>The first thing we&#8217;ll do to start this process is make the URL of our WordPress site available to our application through an environment variable. By default, Next.js will look for a file named <code>.env.local<\/code> in the root directory of the project to load any <a href=\"https:\/\/nextjs.org\/docs\/basic-features\/environment-variables\">environment variables<\/a>.<\/p>\n\n\n\n<p>Create a file named <code>.env.local<\/code> in the project&#8217;s root directory.<\/p>\n\n\n\n<p>Open the file and paste in the following line, replacing &#8220;https:\/\/headlesswp.local&#8221; with the URL of your WordPress site.<\/p>\n\n\n<pre class=\"wp-block-code language-text\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span>NEXT_PUBLIC_WORDPRESS_API_URL=https:<span class=\"hljs-comment\">\/\/headlesswp.local<\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>By adding this environment variable, you can access its value in your application through the <code>process.env<\/code> object. It is a good idea to stop and start your local development server when making changes to environment variables as they typically only get loaded as the application boots. You can do this by hitting <code>ctrl<\/code> + <code>c<\/code>, then running <code>npm run dev<\/code> again.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Configure Apollo Client <\/h3>\n\n\n\n<p>Now that our Next.js application can access the URL of our WordPress site, we can create the Apollo Client instance that will be used to request data.<\/p>\n\n\n\n<p>In the blank <code>\/lib\/apollo.js<\/code> file, add the following code:<\/p>\n\n\n<pre class=\"wp-block-code language-js\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { ApolloClient, InMemoryCache } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@apollo\/client\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> client = <span class=\"hljs-keyword\">new<\/span> ApolloClient({\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">uri<\/span>: <span class=\"hljs-string\">`<span class=\"hljs-subst\">${process.env.NEXT_PUBLIC_WORDPRESS_API_URL}<\/span>\/graphql`<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">cache<\/span>: <span class=\"hljs-keyword\">new<\/span> InMemoryCache(),\n<\/span><\/span><span class='shcb-loc'><span>});\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The first line of code here imports <code>ApolloClient<\/code> and <code>InMemoryCache<\/code> from the <code>@apollo\/client<\/code> package.<\/p>\n\n\n\n<p>Then, below that we create a new instance of <code>ApolloClient<\/code> and export that as a variable named <code>client<\/code>. When we create the new client, we pass in a configuration object with <code>uri<\/code> and <code>cache<\/code> properties. The <code>uri<\/code> property should point the GraphQL client to your server&#8217;s <code>\/graphql<\/code> endpoint, and the <code>cache<\/code> property gets assigned to a new <code>InMemoryCache<\/code> instance. The <a href=\"https:\/\/www.apollographql.com\/docs\/react\/caching\/overview\">caching features of Apollo Client <\/a>help speed up your application by storing query results in memory.<\/p>\n\n\n\n<p>With our client fully configured, the next step is to make our client available across your application using the <code>ApolloProvider<\/code> component.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Wrap App in ApolloProvider<\/h3>\n\n\n\n<p>Even though we have a valid <code>ApolloClient<\/code> object in <code>\/lib\/apollo.js<\/code> we still need to import it somewhere and make it available inside of our React application&#8217;s component tree. To do this, we&#8217;ll make some changes to the code at the root of our Next.js application, which is contained in the <code>\/pages\/_app.js<\/code> file. <\/p>\n\n\n\n<p>Inside of this file, add the following import statements. These pull in the <code>client<\/code> we created in the previous step and the <code>ApolloProvider<\/code> component that Apollo Client provides.<\/p>\n\n\n<pre class=\"wp-block-code language-js\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { ApolloProvider } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@apollo\/client\/react\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { client } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/lib\/apollo\"<\/span>;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Next, wrap the base page <code>&lt;Component&gt;<\/code> inside of the <code>ApolloProvider<\/code> component, passing the configured <code>client<\/code> as a prop:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">MyApp<\/span>(<span class=\"hljs-params\">{ Component, pageProps }<\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">return<\/span> (\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ApolloProvider<\/span> <span class=\"hljs-attr\">client<\/span>=<span class=\"hljs-string\">{client}<\/span>&gt;<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Component<\/span> {<span class=\"hljs-attr\">...pageProps<\/span>} \/&gt;<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ApolloProvider<\/span>&gt;<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">    )<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">}<\/span><\/span><\/span><\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Wrapping your app in an <code>ApolloProvider<\/code> gives you the ability to use the <a href=\"https:\/\/www.apollographql.com\/docs\/react\/api\/react\/hooks\/\">React hooks that Apollo Client provides<\/a>, such as <code>useQuery()<\/code>, <code>useLazyQuery()<\/code>, <code>useMutation()<\/code> etc. from anywhere in your app. While we won&#8217;t be leveraging those hooks in this app, I recommend that if you&#8217;re working with Apollo Client in a React project, you wrap your app in an <code>ApolloProvider<\/code> so that you&#8217;re able to do so when needed.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Make the Index Page Dynamic<\/h2>\n\n\n\n<p>Now that we have a fully configured data fetching client available in our component tree, we can start making the pages of this tutorial site dynamic. To get started, open up the <code>\/pages\/index.js<\/code> file in your editor. <\/p>\n\n\n\n<p>Next.js uses a routing method know as page-based routing, meaning that generally, the routes of your site or application will correspond to the file structure of your <code>\/pages<\/code> folder. In this case, the <code>index.js<\/code> file at the root of the directory corresponds to the root your your site, which should be available at the <code>\/<\/code> URL. In the next step, we&#8217;ll look at creating dynamic route paths, but be sure to read <a href=\"https:\/\/nextjs.org\/docs\/routing\/introduction\">the Next.js docs on routing for more details<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Page Components<\/h3>\n\n\n\n<p>When Next.js processes a page-based route, it expects the default export of a given route to be a React component, commonly referred to as a &#8220;page component&#8221;. Let&#8217;s take a look at the default export for our <code>\/pages\/index.js<\/code> route:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Home<\/span>(<span class=\"hljs-params\">{ posts }<\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">return<\/span> (\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"container\"<\/span>&gt;<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Head<\/span>&gt;<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title<\/span>&gt;<\/span>Headless WP Next Starter<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">title<\/span>&gt;<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"icon\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"favicon.ico\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">link<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Head<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"title\"<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">          Headless WordPress Next.js Starter<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"description\"<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">          Get started by editing <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">code<\/span>&gt;<\/span>pages\/index.js<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">code<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"grid\"<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">          {<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">            posts.map((post) =&gt; {<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">              return (<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">PostCard<\/span> <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{post.id}<\/span> <span class=\"hljs-attr\">post<\/span>=<span class=\"hljs-string\">{post}<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">PostCard<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">              )<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">            })<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">          }<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">main<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Footer<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Footer<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">  )<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">}<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In this case, we are exporting a component named <code>HomePage<\/code> by default, and the <code>HomePage<\/code> component accepts a props object, on which we are expecting a <code>posts<\/code> property to exist. The return value of this component is a JSX Element, and can contain other nested components, like <code>PostCard<\/code> and <code>Footer<\/code>, for example. <\/p>\n\n\n\n<p>Inside of the <code>HomePage<\/code> component, we&#8217;ve written an expression that  iterates over the <code>posts<\/code> array, passing the data for each post into a <code>PostCard<\/code> component, and then returning that custom component. The result that gets rendered to the page looks like this, a card for each post in the array:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-01-at-2.47.05-PM-1024x356.png\" alt=\"\" class=\"wp-image-419\"\/><\/figure>\n\n\n\n<p>While this example is pulling in placeholder dummy data, in the next step we&#8217;ll work towards populating these components with data fetched from our WordPress site.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Data Fetching<\/h3>\n\n\n\n<p>Now that we have a general understanding of how the <code>HomePage<\/code> component works, let&#8217;s take a look at how that component gets its data. First, let&#8217;s add two import statements to the top of our <code>\/pages\/index.js<\/code> file:<\/p>\n\n\n<pre class=\"wp-block-code language-js\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { client } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'..\/lib\/apollo'<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { gql } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@apollo\/client\"<\/span>;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In some styles of React development, particularly styles using client-side rendering, each component can be responsible for sourcing its own data. However, since we are using Next.js to statically generate our pages, all of the data sourcing code for this example will be inside of the <code>getStaticProps()<\/code> function.<\/p>\n\n\n\n<p>With the placeholder data in use, the <code>getStaticProps()<\/code> function in the <code>index.js<\/code> file should look like this:<\/p>\n\n\n<pre class=\"wp-block-code language-js\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">getStaticProps<\/span>(<span class=\"hljs-params\"><\/span>)<\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> posts = <span class=\"hljs-keyword\">await<\/span> getAllPosts()\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">return<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-attr\">props<\/span>: {\n<\/span><\/span><span class='shcb-loc'><span>      posts\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>  }\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>To make this page dynamic, we will replace the call to the <code>getAllPosts<\/code> function with a GraphQL query that pulls data from a WordPress site. <\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Constructing a GraphQL Query<\/h4>\n\n\n\n<p>The first step in integrating our Next.js app and WordPress site is to construct a GraphQL query that returns the data we&#8217;ll need to build out the rest of our features. One of the most common ways to build GraphQL queries is using <a href=\"https:\/\/www.wpgraphql.com\/docs\/interacting-with-wpgraphql\/#graphql-ides-and-tools\">the built-in GraphiQL IDE<\/a> that comes with WPGraphQL.<\/p>\n\n\n\n<p>In the WordPress Admin sidebar, head to <code>GraphQL<\/code> &gt; <code>GraphiQL IDE<\/code> to get started.<\/p>\n\n\n\n<p>Using the <code>QueryComposer<\/code> feature of the GraphiQL IDE allows developers to manually select fields from the GraphQL scheme to add to a query and then run that query against the site&#8217;s database in real time. This can be extremely useful to you as your application parses responses from GraphQL so that developers know exactly how to traverse the response object and its properties.<\/p>\n\n\n\n<p>Once you compose your query, you can hit the play icon (\u25b6\ufe0f) to execute it and see the data that gets returned in the right-most pane.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-01-at-2.59.07-PM-1024x516.png\" alt=\"\" class=\"wp-image-420\"\/><\/figure>\n\n\n\n<p>Once you settle on a query that meets all of your requirements, you can copy\/paste the query that you composed into your app.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Running the Query<\/h4>\n\n\n\n<p>Back in <code>\/pages\/index.js<\/code>, replace the code inside of the <code>getStaticProps()<\/code> function with the code below.<\/p>\n\n\n\n<p>Here, we pass the query we composed to a <code>gql<\/code> <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Template_literals#tagged_templates\">tagged template literal<\/a> (&#8220;gql&#8221; followed by two backticks) and assign the return value to a <code>GET_POSTS<\/code> variable.<\/p>\n\n\n<pre class=\"wp-block-code language-js\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">getStaticProps<\/span>(<span class=\"hljs-params\"><\/span>)<\/span>{\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-comment\">\/\/ Paste your GraphQL query inside of a gql tagged template literal<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> GET_POSTS = gql<span class=\"hljs-string\">`<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">    query AllPostsQuery {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      posts {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        nodes {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          title<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          content<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          date<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          uri<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">    }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">  `<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-comment\">\/\/ Here we make a call with the client and pass in our query string to the <\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-comment\">\/\/ configuration objects 'query' property<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> response = <span class=\"hljs-keyword\">await<\/span> client.query({\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-attr\">query<\/span>: GET_POSTS\n<\/span><\/span><span class='shcb-loc'><span>  });\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-comment\">\/\/ Once we get the response back, we need to traverse it to pull out the <\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-comment\">\/\/ data we want to pass into the HomePage<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> posts = response?.data?.posts?.nodes; \n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">return<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-attr\">props<\/span>: {\n<\/span><\/span><span class='shcb-loc'><span>      posts\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>  }\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This code example is heavily commented with what each line is doing, so walk through each line and make sure you comprehend what is happening before moving on. If you save and refresh your browser window, the index page of our demo site should now look something like this (if you installed placeholder content from the repo):<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-01-at-3.22.35-PM-1024x263.png\" alt=\"\" class=\"wp-image-421\"\/><\/figure>\n\n\n\n<p>From here you could experiment with adding additional fields to your GraphQL query and work on surfacing that data on the <code>PostCard<\/code> component, which can be found in the <code>\/components\/PostCard.js<\/code> file.<\/p>\n\n\n\n<p>In the next step, we&#8217;ll do something similar to create a post detail page using dynamic routing in Next.js.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Make the Post Page Dynamic<\/h2>\n\n\n\n<p>In the last section, we focused on pulling multiple posts into the site home page using Apollo Client and WPGraphQL. This section will build on that example and look at how to create individual pages for each blog post with a customized URL. To do that, we&#8217;ll start with a short conceptual overview of dynamic routing.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Dynamic Route Overview<\/h3>\n\n\n\n<p>Dynamic routing is a huge concept in web applications and is necessary to build a dynamic site of any real size, and even WordPress core has methods of structuring dynamic routes paths via permalinks. With dynamic routing, we can extract information from a URL structure and use that information to generate a customized response.<\/p>\n\n\n\n<p>Let&#8217;s look at the following examples:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span>\/blog\/getting-started-<span class=\"hljs-keyword\">with<\/span>-vue\n<\/span><\/span><span class='shcb-loc'><span>\/blog\/react-overview\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>\/blog\/&#91;title]\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Above we have a pretty typical link structure, with several posts branching off the <code>\/blog<\/code> path. When each of these URLs gets visited, the application receiving the request can access the value of the <code>[title]<\/code> section of the route and use that value to produce a request, by querying the database for a post with a title that matches the value in the URL. <\/p>\n\n\n\n<p><a href=\"https:\/\/nextjs.org\/docs\/routing\/dynamic-routes\">Next.js accomplishes dynamic routing<\/a> by requiring a naming convention for our page component files. If you create a file called <code>\/pages\/[uri].js<\/code>, you can access the value of the requested route and extract the <code>uri<\/code> to be used inside of your application. Let&#8217;s see how this works in practice in our <code>SlugPage<\/code> component, which is the default export from the <code>\/pages\/[uri].js<\/code> file. <\/p>\n\n\n\n<p>If we look at the code inside of the <code>getStaticProps()<\/code> function, we can see that this example accepts a <code>params<\/code> object as an argument:<\/p>\n\n\n<pre class=\"wp-block-code language-js\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">getStaticProps<\/span>(<span class=\"hljs-params\">{ params }<\/span>)<\/span>{\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">const<\/span> response = <span class=\"hljs-keyword\">await<\/span> getPostByUri(params.uri)\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">const<\/span> post = response?.data?.post\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">return<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-attr\">props<\/span>: {\n<\/span><\/span><span class='shcb-loc'><span>        post\n<\/span><\/span><span class='shcb-loc'><span>      }\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>  }\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In this case, the <code>params<\/code> object contains information about our dynamic URL segments. If we access the <code>params.uri<\/code> property, we get the value of that URL segment for a particular request that we can pass into our data fetching code. Behind the scenes, the <code>getPostByUri()<\/code> function filters an array of posts for the one that matches the <code>uri<\/code> of the request. Understanding how to work with dynamic routes is a core concept for building web applications and in turn working with headless WordPress, so be sure to review the Next.js docs linked above for additional info on this feature.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Pre-rendering Static Paths<\/h4>\n\n\n\n<p>When using static generation with <code>getStaticProps()<\/code>, Next.js will generate a static version of our page when it starts serving our application. For a component like our <code>HomePage<\/code>, that is easy for Next.js to do since it doesn&#8217;t require any input from the user in the form of a dynamic URL segment\u2013 the home page is the same for every user and is only available at one URL.<\/p>\n\n\n\n<p>When we create a dynamic route, like we did in <code>\/pages\/[uri].js<\/code>,  it&#8217;s impossible for Next.js to pre-generate those pages without knowing what the value of <code>params.uri<\/code> will be. To solve this problem, anytime we use <code>getStaticProps()<\/code> with a dynamic route segment like <code>[uri]<\/code> we are also required to export a function called <a href=\"https:\/\/nextjs.org\/docs\/basic-features\/data-fetching\/get-static-paths\"><code>getStaticPaths()<\/code><\/a>,which looks like this:<\/p>\n\n\n<pre class=\"wp-block-code language-js\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">getStaticPaths<\/span>(<span class=\"hljs-params\"><\/span>)<\/span>{\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">const<\/span> paths = &#91;<span class=\"hljs-string\">'\/narwal'<\/span>,<span class=\"hljs-string\">'\/kombucha'<\/span>, <span class=\"hljs-string\">'\/baby-unicorns'<\/span>]\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">return<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>        paths,\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-attr\">fallback<\/span>: <span class=\"hljs-string\">'blocking'<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>One of the properties on the object returned by this function should be an array of any paths that we want to pre-render to static assets. This allows Next.js to process those resources before a user visits those pages. Any dynamic route that hasn&#8217;t been pre-rendered using this method will be generated when the first user requests the URL and then made available for all subsequent requests. That means that it&#8217;s also valid to return an empty array of paths in this function:<\/p>\n\n\n<pre class=\"wp-block-code language-js\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">getStaticPaths<\/span>(<span class=\"hljs-params\"><\/span>)<\/span>{\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">const<\/span> paths = &#91;]\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">return<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>        paths,\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-attr\">fallback<\/span>: <span class=\"hljs-string\">'blocking'<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In this example, all of the pages will be generated on the first user request, which means that first request will typically be much slower than subsequent request because Next.js has to both render and serve the page. <\/p>\n\n\n\n<p>However, this function gives the developer a ton of flexibility in how they optimize their applications. For example, you could hard code an array of your most popular paths to optimize those posts, but it is also possible to create that array programmatically in a variety of ways, like getting the URIs for your ten most recent blog posts. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Add GraphQL Query<\/h3>\n\n\n\n<p>To update the data fetching code in our dynamic <code>SlugPage<\/code> component, we&#8217;ll first need to add two import statements to the top of the file:<\/p>\n\n\n<pre class=\"wp-block-code language-js\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { client } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'..\/lib\/apollo'<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { gql } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@apollo\/client\"<\/span>;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>With these new imports available, we can start constructing our query in the GraphiQL IDE. Open the IDE, create a new query named <code>GetPostByURI<\/code> and select <code>post<\/code> from the list of schema objects. If you check the <code>$id<\/code> and <code>$idType<\/code> options, GraphiQL will help you begin to parameterize your query so that we can pass in variables in the next step. Add the fields you see below to your query and then copy the code in the query composer window.  <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-04-at-10.11.57-AM-1-1024x564.png\" alt=\"\" class=\"wp-image-424\"\/><\/figure>\n\n\n\n<p>Back in the <code>\/pages\/[uri].js<\/code> file, we can now replace the code in the <code>getStaticProps<\/code> function to use this query:<\/p>\n\n\n<pre class=\"wp-block-code language-js\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">getStaticProps<\/span>(<span class=\"hljs-params\">{ params }<\/span>)<\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> GET_POST = gql<span class=\"hljs-string\">`<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">    query GetPostByURI($id: ID!) {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      post(id: $id, idType: URI) {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        title<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        content<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        date<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        author {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          node {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">            firstName<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">            lastName<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">    }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">  `<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-comment\">\/\/  the params argument for this function corresponds to the dynamic URL segments<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-comment\">\/\/  we included in our page-based route. So, in this case, the `params` object will have<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-comment\">\/\/  a property named `uri` that contains that route segment when a user hits the page<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> response = <span class=\"hljs-keyword\">await<\/span> client.query({\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-attr\">query<\/span>: GET_POST,\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-attr\">variables<\/span>: {\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-attr\">id<\/span>: params.uri\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>  })\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> post = response?.data?.post\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">return<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-attr\">props<\/span>: {\n<\/span><\/span><span class='shcb-loc'><span>      post\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>  }\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>One change you may need to make to your GraphQL query would be to change <code>$id: ID = \"\/narwal\"<\/code> to <code>$id: ID!<\/code> so that we can pass that in as a variable to <code>ApolloClient<\/code> when we actually make the query. To pass those variables, pass <code>client.query<\/code> a second <code>variables<\/code> object where each variable is a property that corresponds to the variable in the query. In this case, <code>id: params.uri<\/code> will replace the <code>$id<\/code> in our GraphQL query. <\/p>\n\n\n\n<p>With our data fetching code in place, refresh your browser and visit the page for one of your posts. If you used the XML export file in earlier steps, you should see something like this if you visit the <code>\/narwal<\/code> path in your browser.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-04-at-10.27.18-AM-1024x656.png\" alt=\"\" class=\"wp-image-425\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Done! \ud83c\udf89<\/h2>\n\n\n\n<p>Congratulations on creating a headless WordPress site! We covered a lot of ground in this crash course. Hopefully you now have a good understanding of how you can leverage tools like Next.js and WPGraphQL to build headless WordPress sites.<\/p>\n\n\n\n<p>If for any reason you weren&#8217;t able to follow along with the steps outlined in this post, you can access the finished state of our example app on <a href=\"https:\/\/github.com\/JEverhart383\/crash-course-headless-wp-next-wpgraphql\/tree\/finished\">this GitHub branch<\/a>.<\/p>\n\n\n\n<p>Looking for a place to host your headless WordPress project? Check out WP Engine\u2019s&nbsp;<a href=\"https:\/\/wpengine.com\/atlas\/\" target=\"_blank\" rel=\"noreferrer noopener\">Atlas platform<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial, you will learn how to create a simple headless WordPress app using Next.js and WPGraphQL. This tutorial assumes a basic understanding of JavaScript, React, and WordPress. Using [&hellip;]<\/p>\n","protected":false},"author":19,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_EventAllDay":false,"_EventTimezone":"","_EventStartDate":"","_EventEndDate":"","_EventStartDateUTC":"","_EventEndDateUTC":"","_EventShowMap":false,"_EventShowMapLink":false,"_EventURL":"","_EventCost":"","_EventCostDescription":"","_EventCurrencySymbol":"","_EventCurrencyCode":"","_EventCurrencyPosition":"","_EventDateTimeSeparator":"","_EventTimeRangeSeparator":"","_EventOrganizerID":[],"_EventVenueID":[],"_OrganizerEmail":"","_OrganizerPhone":"","_OrganizerWebsite":"","_VenueAddress":"","_VenueCity":"","_VenueCountry":"","_VenueProvince":"","_VenueState":"","_VenueZip":"","_VenuePhone":"","_VenueURL":"","_VenueStateProvince":"","_VenueLat":"","_VenueLng":"","_VenueShowMap":false,"_VenueShowMapLink":false,"footnotes":""},"categories":[23],"tags":[],"class_list":["post-394","post","type-post","status-publish","format-standard","hentry","category-headless"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Crash Course: Build a Simple Headless WordPress App with Next.js &amp; WPGraphQL - Builders<\/title>\n<meta name=\"description\" content=\"Crash Course: Build a headless WordPress site with Next.js and WPGraphQL!\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-next-js-wpgraphql\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Crash Course: Build a Simple Headless WordPress App with Next.js &amp; WPGraphQL - Builders\" \/>\n<meta property=\"og:description\" content=\"Crash Course: Build a headless WordPress site with Next.js and WPGraphQL!\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-next-js-wpgraphql\/\" \/>\n<meta property=\"og:site_name\" content=\"Builders\" \/>\n<meta property=\"article:published_time\" content=\"2022-04-07T19:47:19+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-06-15T19:54:21+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-01-at-12.32.12-PM.png\" \/>\n<meta name=\"author\" content=\"Jeff Everhart\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@wpebuilders\" \/>\n<meta name=\"twitter:site\" content=\"@wpebuilders\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jeff Everhart\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"19 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-next-js-wpgraphql\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-next-js-wpgraphql\\\/\"},\"author\":{\"name\":\"Jeff Everhart\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#\\\/schema\\\/person\\\/b5a7f380738d25f57b00a5aaacf3db52\"},\"headline\":\"Crash Course: Build a Simple Headless WordPress App with Next.js &#038; WPGraphQL\",\"datePublished\":\"2022-04-07T19:47:19+00:00\",\"dateModified\":\"2023-06-15T19:54:21+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-next-js-wpgraphql\\\/\"},\"wordCount\":3082,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-next-js-wpgraphql\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2022\\\/04\\\/Screen-Shot-2022-04-01-at-12.32.12-PM.png\",\"articleSection\":[\"Headless\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-next-js-wpgraphql\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-next-js-wpgraphql\\\/\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-next-js-wpgraphql\\\/\",\"name\":\"Crash Course: Build a Simple Headless WordPress App with Next.js & WPGraphQL - Builders\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-next-js-wpgraphql\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-next-js-wpgraphql\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2022\\\/04\\\/Screen-Shot-2022-04-01-at-12.32.12-PM.png\",\"datePublished\":\"2022-04-07T19:47:19+00:00\",\"dateModified\":\"2023-06-15T19:54:21+00:00\",\"description\":\"Crash Course: Build a headless WordPress site with Next.js and WPGraphQL!\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-next-js-wpgraphql\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-next-js-wpgraphql\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-next-js-wpgraphql\\\/#primaryimage\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2022\\\/04\\\/Screen-Shot-2022-04-01-at-12.32.12-PM.png\",\"contentUrl\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2022\\\/04\\\/Screen-Shot-2022-04-01-at-12.32.12-PM.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-next-js-wpgraphql\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Crash Course: Build a Simple Headless WordPress App with Next.js &#038; WPGraphQL\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#website\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/\",\"name\":\"Builders\",\"description\":\"Reimagining the way we build with WordPress.\",\"publisher\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#organization\",\"name\":\"WP Engine\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/WP-Engine-Horizontal@2x.png\",\"contentUrl\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/WP-Engine-Horizontal@2x.png\",\"width\":348,\"height\":68,\"caption\":\"WP Engine\"},\"image\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/wpebuilders\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UCh1WuL54XFb9ZI6m6goFv1g\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#\\\/schema\\\/person\\\/b5a7f380738d25f57b00a5aaacf3db52\",\"name\":\"Jeff Everhart\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/237d84b2a63acb8c427ba3246f9c5fc1b436aac578a5df421927c23b4fde45f5?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/237d84b2a63acb8c427ba3246f9c5fc1b436aac578a5df421927c23b4fde45f5?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/237d84b2a63acb8c427ba3246f9c5fc1b436aac578a5df421927c23b4fde45f5?s=96&d=mm&r=g\",\"caption\":\"Jeff Everhart\"},\"description\":\"Jeff is a Senior Developer Advocate at WP Engine, focusing on educational resources that blend JavaScript and WordPress to support the Atlas headless WordPress platform and ecosystem.\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/author\\\/jeff-everhartwpengine-com\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Crash Course: Build a Simple Headless WordPress App with Next.js & WPGraphQL - Builders","description":"Crash Course: Build a headless WordPress site with Next.js and WPGraphQL!","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-next-js-wpgraphql\/","og_locale":"en_US","og_type":"article","og_title":"Crash Course: Build a Simple Headless WordPress App with Next.js & WPGraphQL - Builders","og_description":"Crash Course: Build a headless WordPress site with Next.js and WPGraphQL!","og_url":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-next-js-wpgraphql\/","og_site_name":"Builders","article_published_time":"2022-04-07T19:47:19+00:00","article_modified_time":"2023-06-15T19:54:21+00:00","og_image":[{"url":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-01-at-12.32.12-PM.png","type":"","width":"","height":""}],"author":"Jeff Everhart","twitter_card":"summary_large_image","twitter_creator":"@wpebuilders","twitter_site":"@wpebuilders","twitter_misc":{"Written by":"Jeff Everhart","Est. reading time":"19 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-next-js-wpgraphql\/#article","isPartOf":{"@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-next-js-wpgraphql\/"},"author":{"name":"Jeff Everhart","@id":"https:\/\/wpengine.com\/builders\/#\/schema\/person\/b5a7f380738d25f57b00a5aaacf3db52"},"headline":"Crash Course: Build a Simple Headless WordPress App with Next.js &#038; WPGraphQL","datePublished":"2022-04-07T19:47:19+00:00","dateModified":"2023-06-15T19:54:21+00:00","mainEntityOfPage":{"@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-next-js-wpgraphql\/"},"wordCount":3082,"commentCount":0,"publisher":{"@id":"https:\/\/wpengine.com\/builders\/#organization"},"image":{"@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-next-js-wpgraphql\/#primaryimage"},"thumbnailUrl":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-01-at-12.32.12-PM.png","articleSection":["Headless"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-next-js-wpgraphql\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-next-js-wpgraphql\/","url":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-next-js-wpgraphql\/","name":"Crash Course: Build a Simple Headless WordPress App with Next.js & WPGraphQL - Builders","isPartOf":{"@id":"https:\/\/wpengine.com\/builders\/#website"},"primaryImageOfPage":{"@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-next-js-wpgraphql\/#primaryimage"},"image":{"@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-next-js-wpgraphql\/#primaryimage"},"thumbnailUrl":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-01-at-12.32.12-PM.png","datePublished":"2022-04-07T19:47:19+00:00","dateModified":"2023-06-15T19:54:21+00:00","description":"Crash Course: Build a headless WordPress site with Next.js and WPGraphQL!","breadcrumb":{"@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-next-js-wpgraphql\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-next-js-wpgraphql\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-next-js-wpgraphql\/#primaryimage","url":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-01-at-12.32.12-PM.png","contentUrl":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-01-at-12.32.12-PM.png"},{"@type":"BreadcrumbList","@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-next-js-wpgraphql\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/wpengine.com\/builders\/"},{"@type":"ListItem","position":2,"name":"Crash Course: Build a Simple Headless WordPress App with Next.js &#038; WPGraphQL"}]},{"@type":"WebSite","@id":"https:\/\/wpengine.com\/builders\/#website","url":"https:\/\/wpengine.com\/builders\/","name":"Builders","description":"Reimagining the way we build with WordPress.","publisher":{"@id":"https:\/\/wpengine.com\/builders\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/wpengine.com\/builders\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/wpengine.com\/builders\/#organization","name":"WP Engine","url":"https:\/\/wpengine.com\/builders\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wpengine.com\/builders\/#\/schema\/logo\/image\/","url":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2024\/05\/WP-Engine-Horizontal@2x.png","contentUrl":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2024\/05\/WP-Engine-Horizontal@2x.png","width":348,"height":68,"caption":"WP Engine"},"image":{"@id":"https:\/\/wpengine.com\/builders\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/wpebuilders","https:\/\/www.youtube.com\/channel\/UCh1WuL54XFb9ZI6m6goFv1g"]},{"@type":"Person","@id":"https:\/\/wpengine.com\/builders\/#\/schema\/person\/b5a7f380738d25f57b00a5aaacf3db52","name":"Jeff Everhart","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/237d84b2a63acb8c427ba3246f9c5fc1b436aac578a5df421927c23b4fde45f5?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/237d84b2a63acb8c427ba3246f9c5fc1b436aac578a5df421927c23b4fde45f5?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/237d84b2a63acb8c427ba3246f9c5fc1b436aac578a5df421927c23b4fde45f5?s=96&d=mm&r=g","caption":"Jeff Everhart"},"description":"Jeff is a Senior Developer Advocate at WP Engine, focusing on educational resources that blend JavaScript and WordPress to support the Atlas headless WordPress platform and ecosystem.","url":"https:\/\/wpengine.com\/builders\/author\/jeff-everhartwpengine-com\/"}]}},"_links":{"self":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/posts\/394","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/users\/19"}],"replies":[{"embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/comments?post=394"}],"version-history":[{"count":0,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/posts\/394\/revisions"}],"wp:attachment":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/media?parent=394"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/categories?post=394"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/tags?post=394"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}