{"id":527,"date":"2023-07-07T20:25:00","date_gmt":"2023-07-08T01:25:00","guid":{"rendered":"https:\/\/developers.wpengine.com\/blog\/?p=527"},"modified":"2023-12-15T13:52:48","modified_gmt":"2023-12-15T19:52:48","slug":"build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields","status":"publish","type":"post","link":"https:\/\/wpengine.com\/builders\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\/","title":{"rendered":"Crash Course: Build a Headless WordPress App with Faust.js, WPGraphQL &amp; Advanced Custom Fields"},"content":{"rendered":"\n<p>This tutorial will teach you how to create a headless WordPress app using <a href=\"https:\/\/faustjs.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">Faust.js<\/a>, <a href=\"https:\/\/www.wpgraphql.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">WPGraphQL<\/a>, and <a href=\"https:\/\/wordpress.org\/plugins\/atlas-content-modeler\/\" target=\"_blank\" rel=\"noreferrer noopener\">Advanced Custom Fields (ACF)<\/a>. It assumes a basic understanding of JavaScript, React fundamentals, GraphQL fundamentals, and WordPress. <\/p>\n\n\n\n<p>By the end of this tutorial, you will be able to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Create custom post types and fields using Advanced Custom Fields<\/li>\n\n\n\n<li>Create new posts for those models in the WordPress Admin dashboard<\/li>\n\n\n\n<li>Run test queries to get ACF data using the GraphiQL IDE<\/li>\n\n\n\n<li>Use Faust.js and Apollo Client to fetch ACF data in our decoupled Next.js app and render our React components<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">What We&#8217;ll Build<\/h2>\n\n\n\n<p>To showcase how to use Faust.js and ACF, we will build a site containing Taylor Swift&#8217;s discography.<\/p>\n\n\n\n<p>This will require the following three types of pages:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"911\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-10.19.11-AM-1024x911.png\" alt=\"Completed page showing all albums\" class=\"wp-image-5210\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-10.19.11-AM-1024x911.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-10.19.11-AM-300x267.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-10.19.11-AM-768x683.png 768w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-10.19.11-AM-1536x1367.png 1536w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-10.19.11-AM-2048x1822.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"824\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-1.31.58-PM-1-1024x824.png\" alt=\"Completed page showing album details page\" class=\"wp-image-5212\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-1.31.58-PM-1-1024x824.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-1.31.58-PM-1-300x241.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-1.31.58-PM-1-768x618.png 768w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-1.31.58-PM-1-1536x1236.png 1536w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-1.31.58-PM-1-2048x1649.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"675\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-3.18.59-PM-1-1024x675.png\" alt=\"Completed page showing individual song details page\" class=\"wp-image-5213\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-3.18.59-PM-1-1024x675.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-3.18.59-PM-1-300x198.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-3.18.59-PM-1-768x506.png 768w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-3.18.59-PM-1-1536x1012.png 1536w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-3.18.59-PM-1-2048x1350.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>We&#8217;ll use ACF to create the content models we need in WordPress, and then we&#8217;ll query for that data from a decoupled frontend Next.js and Faust.js app.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>\/albums<\/code> \u2013 This main &#8220;Albums&#8221; page should contain a gallery of each of Taylor Swift&#8217;s albums.<\/li>\n\n\n\n<li><code>\/albums\/red-taylors-version<\/code>&nbsp;\u2013 This&nbsp;&#8220;Album details&#8221; page should have the info about an individual album. &#8220;red-taylors-version&#8221; in this example represents the slug of the album.<\/li>\n\n\n\n<li><code>\/songs\/all-too-well-10-minute-version-taylors-version<\/code>&nbsp;\u2013 This &#8220;Song details&#8221; page should contain the info about an individual song. &#8220;all-too-well-10-minute-version-taylors-version&#8221; in this example represents the slug of the song.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>To get started, you&#8217;ll need to have both&nbsp;<a href=\"https:\/\/nodejs.org\/en\/\" target=\"_blank\" rel=\"noreferrer noopener\">Node.js<\/a>&nbsp;and&nbsp;<a href=\"https:\/\/docs.npmjs.com\/downloading-and-installing-node-js-and-npm\" target=\"_blank\" rel=\"noreferrer noopener\">npm<\/a>&nbsp;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\"><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 nvm (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 Headless WordPress Site<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Create a New Faust Project<\/h3>\n\n\n\n<p>To create a Faust project, run the following:<\/p>\n\n\n<pre class=\"wp-block-code\" 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>npx create-next-app \\\n<\/span><\/span><span class='shcb-loc'><span>    -e https:<span class=\"hljs-comment\">\/\/github.com\/wpengine\/faustjs\/tree\/main \\<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    --example-path examples\/next\/faustwp-getting-started \\\n<\/span><\/span><span class='shcb-loc'><span>    --<span class=\"hljs-keyword\">use<\/span>-<span class=\"hljs-title\">npm<\/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>Now, <code>cd<\/code> into your new app and copy the sample environment template:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-selector-tag\">cp<\/span> <span class=\"hljs-selector-class\">.env<\/span><span class=\"hljs-selector-class\">.local<\/span><span class=\"hljs-selector-class\">.sample<\/span> <span class=\"hljs-selector-class\">.env<\/span><span class=\"hljs-selector-class\">.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\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Finally, run the dev server:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span>npm run dev\n<\/span><\/span><\/code><\/span><\/pre>\n\n\n<p>You can now visit&nbsp;<a href=\"http:\/\/localhost:3000\/\" target=\"_blank\" rel=\"noreferrer noopener\">http:\/\/localhost:3000<\/a>&nbsp;to see your new project.<\/p>\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. Then, we&#8217;ll populate the site with the specific data for this tutorial.<\/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\/\" target=\"_blank\" rel=\"noreferrer noopener\">Local<\/a>&nbsp;is WP Engine&#8217;s local development tool, and it makes it very easy to work with WordPress locally. You can&nbsp;<a href=\"https:\/\/localwp.com\/help-docs\/getting-started\/installing-local\/\" target=\"_blank\" rel=\"noreferrer noopener\">install the app<\/a>&nbsp;and create a new WordPress site in a few steps.<\/p>\n\n\n\n<p>Now, we&#8217;re ready to create a WordPress site! Click the&nbsp;<code>+<\/code>&nbsp;button at the bottom left corner of the window. Select&nbsp;<code>Create a new site<\/code>, then click&nbsp;<code>Continue<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/03\/Screen-Shot-2023-03-09-at-10.46.13-PM-1024x685.png\" alt=\"Local 'Create a site' screen\" class=\"wp-image-860\"\/><\/figure>\n\n\n\n<p>Choose a name for your new site, and then click&nbsp;<code>Continue<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/03\/Screen-Shot-2023-03-09-at-10.47.18-PM-1024x684.png\" alt=\"Local 'What's your site's name?' screen\" class=\"wp-image-861\"\/><\/figure>\n\n\n\n<p>Select the <code>Preferred<\/code> configuration for your environment. Then, click&nbsp;<code>Continue<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/03\/Screen-Shot-2023-03-13-at-2.01.34-PM-1024x691.png\" alt=\"Local 'Choose your environment' screen\" class=\"wp-image-893\"\/><\/figure>\n\n\n\n<p>Lastly, specify values for the&nbsp;<code>WordPress username<\/code>&nbsp;and&nbsp;<code>WordPress password<\/code>. Be sure to remember these values! Once that is complete, click&nbsp;<code>Add Site<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/03\/Screen-Shot-2023-03-09-at-10.51.15-PM-1024x684.png\" alt=\"Local 'Set up WordPress' screen\" class=\"wp-image-863\"\/><\/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-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/03\/Screen-Shot-2023-03-09-at-10.59.22-PM-1024x686.png\" alt=\"Local screen showing WordPress site running\" class=\"wp-image-864\"\/><\/figure>\n\n\n\n<p>To access the WP Admin panel of your new site, click&nbsp;<code>WP Admin<\/code>&nbsp;in the site details pane and authenticate with the username and password you created in the previous step.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"> Connect Your WordPress Site<\/h3>\n\n\n\n<p>Our current Faust.js app loads WordPress content from the demo site at&nbsp;<a href=\"https:\/\/faustexample.wpengine.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/faustexample.wpengine.com<\/a>. We want to point it to a different WordPress site.<\/p>\n\n\n\n<p>First, install and activate the <a href=\"https:\/\/wordpress.org\/plugins\/faustwp\/\" target=\"_blank\" rel=\"noreferrer noopener\">Faust<\/a> and <a href=\"https:\/\/wordpress.org\/plugins\/wp-graphql\/\" target=\"_blank\" rel=\"noreferrer noopener\">WPGraphQL<\/a> plugins on your site.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>From the&nbsp;<code>Plugins &gt; Add new<\/code>&nbsp;menu, search for <code>Faust<\/code> in the WordPress plugin repository. Install and activate this plugin.<\/li>\n\n\n\n<li>From the&nbsp;<code>Plugins &gt; Add new<\/code>&nbsp;menu, search for&nbsp;<code>WPGraphQL<\/code>&nbsp;in the WordPress plugin repository. Install and activate this plugin, adding a&nbsp;<code>GraphQL<\/code> tab to your WP Admin sidebar.<\/li>\n<\/ul>\n\n\n\n<p>Once the necessary plugins have been installed, open the&nbsp;<code>.env.local<\/code>&nbsp;file you created earlier in a code editor. It should look something like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" 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><span class=\"hljs-comment\"># Your WordPress site URL<\/span>\n<\/span><\/span><span class='shcb-loc'><span>NEXT_PUBLIC_WORDPRESS_URL=https:<span class=\"hljs-comment\">\/\/faustexample.wpengine.com<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-comment\"># Plugin secret found in WordPress Settings-&gt;Headless<\/span>\n<\/span><\/span><span class='shcb-loc'><span>FAUST_SECRET_KEY=YOUR_PLUGIN_SECRET\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\">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>We need to update this information in our WordPress instance. The necessary values can be found in the WordPress Admin sidebar under <code>Settings<\/code> &gt; <code>Faust<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"810\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-19-at-2.03.40-PM-1-1024x810.png\" alt=\"Faust's settings page showing Front-end site URL and Secret Key\" class=\"wp-image-5214\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-19-at-2.03.40-PM-1-1024x810.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-19-at-2.03.40-PM-1-300x237.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-19-at-2.03.40-PM-1-768x608.png 768w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-19-at-2.03.40-PM-1-1536x1215.png 1536w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-19-at-2.03.40-PM-1-2048x1620.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>In the <code>.env.local<\/code> file, update the&nbsp;<code>NEXT_PUBLIC_WORDPRESS_URL<\/code>&nbsp;value with your WordPress site URL (including&nbsp;<code>http:\/\/<\/code>&nbsp;or&nbsp;<code>https:\/\/<\/code>) and the&nbsp;<code>FAUST_SECRET_KEY<\/code>&nbsp;value with the secret key found on Faust&#8217;s Settings page.<\/p>\n\n\n\n<p>Additionally, on the WordPress Admin Settings page, set the <code>Front-end site URL<\/code> to match the URL running our frontend Faust.js app locally.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Install Plugins and Check Settings<\/h3>\n\n\n\n<p>With a basic headless WordPress site up and running, there are a few things left to install and a few settings to check.<\/p>\n\n\n\n<p>There are two additional plugins we need to add:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>From the&nbsp;<code>Plugins &gt; Add new<\/code>&nbsp;menu, search for&nbsp;<code>Advanced Custom Fields<\/code>&nbsp;in the WordPress plugin repository. Install and activate this plugin, adding a&nbsp;<code>Custom Fields<\/code> tab to your WP Admin sidebar. The <code>ACF<\/code> plugin is used to register our custom post types and custom fields.<\/li>\n\n\n\n<li><code>WPGraphQL for Advanced Custom Fields<\/code> is not currently available on the WordPress.org repository, so you must download it from GitHub. To install the plugin from GitHub,\u00a0<a href=\"https:\/\/github.com\/wp-graphql\/wpgraphql-acf\/releases\" target=\"_blank\" rel=\"noreferrer noopener\">download the latest release zip file<\/a>, upload the Zip file to your WordPress install, and activate the plugin. This is the WPGraphQL extension that exposes ACF data via the WPGraphQL schema.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"521\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.30.27-PM-1024x521.png\" alt=\"\" class=\"wp-image-5487\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.30.27-PM-1024x521.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.30.27-PM-300x153.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.30.27-PM-768x390.png 768w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.30.27-PM-1536x781.png 1536w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.30.27-PM-2048x1041.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Open the&nbsp;<code>GraphQL &gt; Settings<\/code>&nbsp;menu and check the option labeled&nbsp;<code>Enable GraphQL Debug Mode<\/code>&nbsp;and then check the option labeled <code>Enable Public Introspection<\/code>. Click&nbsp;<code>Save Changes<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"781\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.32.04-PM-1024x781.png\" alt=\"\" class=\"wp-image-5488\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.32.04-PM-1024x781.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.32.04-PM-300x229.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.32.04-PM-768x585.png 768w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.32.04-PM-1536x1171.png 1536w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.32.04-PM-2048x1561.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>With Debug Mode enabled you will get more helpful error output as you develop your application. Note that using Debug Mode is not recommended for production sites.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Create Custom Post Types and Custom Fields<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Plan Content<\/h3>\n\n\n\n<p>Let&#8217;s think about what custom post types and custom fields we need to create to store the necessary data.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Songs<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Song Title&nbsp;\u2013 Text field. The song&#8217;s name.<\/li>\n\n\n\n<li>Length&nbsp;\u2013 Text field. The song&#8217;s timestamp.<\/li>\n\n\n\n<li>Lyrics&nbsp;\u2013 Text area field. The song&#8217;s formatted lyrics.<\/li>\n\n\n\n<li>Genre&nbsp;\u2013 Taxonomy. These taxonomy terms represent the song&#8217;s genres (Pop, Country, Alternative, etc.).<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Albums<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Album Title&nbsp;\u2013 Text field. The album&#8217;s name.<\/li>\n\n\n\n<li>Release Date&nbsp;\u2013 Date picker field. The album&#8217;s release date.<\/li>\n\n\n\n<li>Cover&nbsp;\u2013 Image field. An uploaded image of the album&#8217;s cover.<\/li>\n\n\n\n<li>Track List&nbsp;\u2013 Relationship field. These relationships between&nbsp;<code>Album<\/code>&nbsp;\u2192&nbsp;<code>Songs<\/code> represent the songs on each album.<\/li>\n<\/ul>\n\n\n\n<p>Now that we have our game plan together for what post types and fields we&#8217;ll need to set up using Advanced Custom Fields, let&#8217;s get to it!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Create Songs<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Songs Post Type<\/h4>\n\n\n\n<p>Let&#8217;s create our&nbsp;<code>Songs<\/code>&nbsp;post type first since it&#8217;s a bit simpler. In the WordPress Admin sidebar, we&#8217;ll go to&nbsp;<code>ACF<\/code>&nbsp;&gt;&nbsp;<code>Post Types<\/code>. This should bring us to this page where we can add a new post type.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"784\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.36.43-PM-1024x784.png\" alt=\"\" class=\"wp-image-5489\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.36.43-PM-1024x784.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.36.43-PM-300x230.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.36.43-PM-768x588.png 768w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.36.43-PM-1536x1176.png 1536w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.36.43-PM-2048x1569.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Click <code>+ Add New<\/code> and fill out the following fields:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Set <code>Plural Label<\/code>&nbsp;to &#8220;Songs&#8221;<\/li>\n\n\n\n<li>Set <code>Singular Label<\/code>&nbsp;to &#8220;Song&#8221;<\/li>\n\n\n\n<li>Set&nbsp;<code>Post Type Key<\/code>&nbsp;to &#8220;song&#8221;<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"716\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.41.45-PM-1024x716.png\" alt=\"\" class=\"wp-image-5490\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.41.45-PM-1024x716.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.41.45-PM-300x210.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.41.45-PM-768x537.png 768w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.41.45-PM-1536x1074.png 1536w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.41.45-PM-2048x1432.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The post type still needs to be shown in GraphQL so we can access the posts we create. Further down on this screen, click the slider for <code>Advanced Configuration<\/code>. Select the furthest right tab titled <code>GraphQL<\/code> and enable the <code>Show in GraphQL<\/code> slider. The autogenerated&nbsp;<code>GraphQL Single Name<\/code>&nbsp;and&nbsp;<code>GraphQL Plural Name<\/code>&nbsp;can be kept without editing.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"717\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.55.25-AM-1024x717.png\" alt=\"\" class=\"wp-image-5497\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.55.25-AM-1024x717.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.55.25-AM-300x210.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.55.25-AM-768x538.png 768w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.55.25-AM-1536x1076.png 1536w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.55.25-AM-2048x1434.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Then click the <code>Save Changes<\/code> button to create the new post type.<\/p>\n\n\n\n<p>In the WordPress Admin sidebar, you&#8217;ll see that a menu item has been added for our new&nbsp;<code>Songs<\/code>&nbsp;custom post type.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Songs Custom Fields<\/h4>\n\n\n\n<p>After saving the new <code>Songs<\/code> post type, you will get a success banner on the top of the screen alerting you &#8211; <code>Songs post type created<\/code>. There are several options underneath this message. Click on the first option to <code>Add fields to Songs<\/code>.<\/p>\n\n\n\n<p>This will navigate you to the form to add a new field group and auto-fill the title of this field group as &#8220;Song fields&#8221;. Within this form, we can create all the fields that should belong to a song.<\/p>\n\n\n\n<p>Our first field will be the song&#8217;s title. We&#8217;ll set the field up like this:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Select&nbsp;<code>Text<\/code>&nbsp;for the Field Type.<\/li>\n\n\n\n<li>Enter a&nbsp;<code>Field Label<\/code>&nbsp;of &#8220;Song Title.&#8221;<\/li>\n\n\n\n<li>Stick with the auto-generated&nbsp;<code>Field Name<\/code>&nbsp;of \u201csong_title.\u201d<\/li>\n\n\n\n<li>Leave the <code>Default Value<\/code> empty.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"718\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.49.51-PM-1024x718.png\" alt=\"\" class=\"wp-image-5491\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.49.51-PM-1024x718.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.49.51-PM-300x210.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.49.51-PM-768x538.png 768w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.49.51-PM-1536x1077.png 1536w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.49.51-PM-2048x1436.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>We&#8217;ll create the Length, Lyrics, and Genre fields in a similar way by clicking the <code>+ Add Field<\/code> button underneath each completed field.<\/p>\n\n\n\n<p>The Length field will look like this:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Select&nbsp;<code>Text<\/code>&nbsp;for the Field Type.<\/li>\n\n\n\n<li>Enter a&nbsp;<code>Field Label<\/code>&nbsp;of &#8220;Length.&#8221;<\/li>\n\n\n\n<li>Stick with the auto-generated&nbsp;<code>Field Name<\/code>&nbsp;of &#8220;length.&#8221;<\/li>\n\n\n\n<li>Leave the <code>Default Value<\/code> empty.<\/li>\n<\/ul>\n\n\n\n<p>The Lyrics field will look like this:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Select&nbsp;<code>Text Area<\/code>&nbsp;for the Field Type.<\/li>\n\n\n\n<li>Enter a&nbsp;<code>Field Label<\/code>&nbsp;of &#8220;Lyrics.&#8221;<\/li>\n\n\n\n<li>Stick with the auto-generated&nbsp;<code>Field Name<\/code>&nbsp;of &#8220;lyrics.&#8221;<\/li>\n<\/ul>\n\n\n\n<p>As the last field for the <code>Song<\/code> post type, we need to add a <code>Genre<\/code> field. Grouping <code>Songs<\/code> based on their genre (Alternative, Country, Pop, etc.) is a perfect use case for a WordPress&nbsp;<a href=\"https:\/\/wordpress.org\/support\/article\/taxonomies\/\" target=\"_blank\" rel=\"noreferrer noopener\">taxonomy<\/a>. The Genre field will look like this:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Select&nbsp;<code>Taxonomy<\/code>&nbsp;for the Field Type.<\/li>\n\n\n\n<li>Enter a&nbsp;<code>Field Label<\/code>&nbsp;of &#8220;Genre.&#8221;<\/li>\n\n\n\n<li>Stick with the auto-generated&nbsp;<code>Field Name<\/code>&nbsp;of &#8220;genre.&#8221;<\/li>\n\n\n\n<li>Select <code>Tag<\/code> as the type of taxonomy to be displayed.<\/li>\n\n\n\n<li>Check the slider for <code>Create Terms<\/code>, <code>Save Terms<\/code>, and <code>Load Terms<\/code>.<\/li>\n\n\n\n<li>Select <code>Term ID<\/code> as the <code>Return Value.<\/code><\/li>\n\n\n\n<li>Select <code>Checkbox<\/code> for the <code>Appearance<\/code>.<\/li>\n<\/ul>\n\n\n\n<p>Finally, scroll down past the Fields section to the Settings section. Ensure the Rules say, &#8220;Show this field group if Post Type is equal to Song.&#8221;<\/p>\n\n\n\n<p>Then, just below the Settings section (and the ACF PRO ad), in the GraphQL section, check the slider for <code>Show in GraphQL<\/code> to access this data in our frontend app.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"718\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.53.43-PM-1024x718.png\" alt=\"\" class=\"wp-image-5493\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.53.43-PM-1024x718.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.53.43-PM-300x210.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.53.43-PM-768x539.png 768w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.53.43-PM-1536x1078.png 1536w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-24-at-11.53.43-PM-2048x1437.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Click <code>Save Changes<\/code> at the top of the screen.<\/p>\n\n\n\n<p>That&#8217;s it for our&nbsp;<code>Songs<\/code>&nbsp;custom post type and custom fields! Now, let&#8217;s turn to the <code>Albums<\/code> post type.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Albums Post Type<\/h4>\n\n\n\n<p>In the WordPress Admin sidebar, navigate again to&nbsp;<code>ACF<\/code>&nbsp;&gt;&nbsp;<code>Post Types<\/code> to add a new post type.<\/p>\n\n\n\n<p>Click <code>+ Add New<\/code> and fill out the following fields:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Set <code>Plural Label<\/code>&nbsp;to &#8220;Albums.&#8221;<\/li>\n\n\n\n<li>Set <code>Singular Label<\/code>&nbsp;to &#8220;Album.&#8221;<\/li>\n\n\n\n<li>Set&nbsp;<code>Post Type Key<\/code>&nbsp;to &#8220;album.&#8221;<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"718\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.07.31-AM-1024x718.png\" alt=\"\" class=\"wp-image-5494\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.07.31-AM-1024x718.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.07.31-AM-300x210.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.07.31-AM-768x538.png 768w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.07.31-AM-1536x1077.png 1536w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.07.31-AM-2048x1436.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Just as we did with the <code>Song<\/code> post type, we need to enable the <code>Album<\/code> post type to be shown in GraphQL. Further down on this screen, click the slider for <code>Advanced Configuration<\/code>. Select the furthest right tab titled <code>GraphQL<\/code> and enable the <code>Show in GraphQL<\/code> slider. The autogenerated&nbsp;<code>GraphQL Single Name<\/code>&nbsp;and&nbsp;<code>GraphQL Plural Name<\/code>&nbsp;can be kept without editing.<\/p>\n\n\n\n<p>Then click the <code>Save Changes<\/code> button to create the new post type.<\/p>\n\n\n\n<p>In the WordPress Admin sidebar, you&#8217;ll see that a menu item has been added for our new&nbsp;<code>Albums<\/code>&nbsp;custom post type.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Albums Model Fields<\/h4>\n\n\n\n<p>After saving the new <code>Albums<\/code> post type, you will get a success banner on the top of the screen alerting you &#8211; <code>Albums post type created<\/code>. Click on the link to <code>Add fields to Albums<\/code>.<\/p>\n\n\n\n<p>This will navigate you to the form to add a new field group and auto-fill the title of this field group as &#8220;Album fields&#8221;. Within this form, we can create all the fields that should belong to an album.<\/p>\n\n\n\n<p>Our first field will be the album&#8217;s title. We&#8217;ll set the field up like this:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Select&nbsp;<code>Text<\/code>&nbsp;for the Field Type.<\/li>\n\n\n\n<li>Enter a&nbsp;<code>Field Label<\/code>&nbsp;of &#8220;Album Title.&#8221;<\/li>\n\n\n\n<li>Stick with the auto-generated&nbsp;<code>Field Name<\/code>&nbsp;of &#8220;album_title.&#8221;<\/li>\n\n\n\n<li>Leave the <code>Default Value<\/code> empty.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"718\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.12.28-AM-1024x718.png\" alt=\"\" class=\"wp-image-5495\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.12.28-AM-1024x718.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.12.28-AM-300x210.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.12.28-AM-768x538.png 768w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.12.28-AM-1536x1077.png 1536w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.12.28-AM-2048x1436.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>We&#8217;ll create the Release Date, Cover, and Track List fields in a similar way, but using different <code>Field Types<\/code>.<\/p>\n\n\n\n<p>The Release Date field will look like this:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Select&nbsp;<code>Date Picker<\/code>&nbsp;for the Field Type.<\/li>\n\n\n\n<li>Enter a&nbsp;<code>Field Label<\/code>&nbsp;of &#8220;Release Date.&#8221;<\/li>\n\n\n\n<li>Stick with the auto-generated&nbsp;<code>Field Name<\/code>&nbsp;of &#8220;release_date.&#8221;<\/li>\n\n\n\n<li>Select &#8220;m\/d\/Y&#8221; as the <code>Display Format<\/code> and <code>Return Format<\/code>.<\/li>\n<\/ul>\n\n\n\n<p>The Cover field will look like this:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Select&nbsp;<code>Image<\/code>&nbsp;for the Field Type.<\/li>\n\n\n\n<li>Enter a&nbsp;<code>Field Label<\/code>&nbsp;of &#8220;Cover.&#8221;<\/li>\n\n\n\n<li>Stick with the auto-generated&nbsp;<code>Field Name<\/code>&nbsp;of &#8220;cover.&#8221;<\/li>\n\n\n\n<li>Select &#8220;Image ID&#8221; as the <code>Return Format<\/code>.<\/li>\n\n\n\n<li>Select &#8220;All&#8221; for the <code>Library<\/code>.<\/li>\n<\/ul>\n\n\n\n<p>The Track List field will look like this:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Select&nbsp;<code>Relationship<\/code>&nbsp;for the Field Type.<\/li>\n\n\n\n<li>Enter a&nbsp;<code>Field Label<\/code>&nbsp;of &#8220;Track List.&#8221;<\/li>\n\n\n\n<li>Stick with the auto-generated&nbsp;<code>Field Name<\/code>&nbsp;of &#8220;track_list.&#8221;<\/li>\n\n\n\n<li>Select &#8220;Song&#8221; for the <code>Filter by Post Type<\/code>.<\/li>\n\n\n\n<li>Leave <code>Filter by Taxonomy<\/code> blank and leave all options for <code>Filters<\/code> checked.<\/li>\n\n\n\n<li>Select &#8220;Post Object&#8221; for the <code>Return Format<\/code>.<\/li>\n<\/ul>\n\n\n\n<p>Finally, scroll down past the Fields section to the Settings section. Ensure the Rules say, &#8220;Show this field group if Post Type is equal to Album.&#8221;<\/p>\n\n\n\n<p>Then, just below the Settings section (and the ACF PRO ad), in the GraphQL section, check the slider for <code>Show in GraphQL<\/code> to access this data in our frontend app.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"716\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.15.06-AM-1024x716.png\" alt=\"\" class=\"wp-image-5496\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.15.06-AM-1024x716.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.15.06-AM-300x210.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.15.06-AM-768x537.png 768w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.15.06-AM-1536x1075.png 1536w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.15.06-AM-2048x1433.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Click <code>Save Changes<\/code> at the top of the screen.<\/p>\n\n\n\n<p>That&#8217;s it for our&nbsp;<code>Albums<\/code>&nbsp;custom post type and custom fields!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Populate Data about Taylor Swift&#8217;s Discography<\/h3>\n\n\n\n<p>Next, let&#8217;s look at how to create and edit&nbsp;<code>Album<\/code>&nbsp;and <code>Song<\/code> data.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Add Song Data<\/h4>\n\n\n\n<p>From the WordPress Admin sidebar, go to&nbsp;<code>Songs<\/code>&nbsp;&gt;&nbsp;<code>Add New<\/code>. You&#8217;ll see the fields we registered reflected here. Create entries for each of Taylor Swift&#8217;s songs (Taylor&#8217;s Version, of course).<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"829\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/songdata.png\" alt=\"WordPress screen showing how to add a new Song\" class=\"wp-image-5224\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/songdata.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/songdata-300x243.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/songdata-768x622.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Add Album Data<\/h4>\n\n\n\n<p>From the WordPress Admin sidebar, go to&nbsp;<code>Albums<\/code>&nbsp;&gt;&nbsp;<code>Add New<\/code>. You&#8217;ll see the fields we registered reflected here. Create entries for each of Taylor Swift&#8217;s albums (again, Taylor&#8217;s Version, of course).<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"897\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/albumdata.png\" alt=\"WordPress screen showing how to add a new Album\" class=\"wp-image-5225\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/albumdata.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/albumdata-300x263.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/albumdata-768x673.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Test a Query in the GraphiQL IDE<\/h4>\n\n\n\n<p>At this point, our&nbsp;custom post types and custom fields have been created and populated with data, and we have chosen to automatically add them to the GraphQL schema. This means that we are already set up to query for <code>Songs<\/code> or <code>Albums<\/code> data from our frontend JavaScript app! Let&#8217;s fire off a test query to try that out.<\/p>\n\n\n\n<p>Head over to the&nbsp;embedded GraphiQL IDE&nbsp;that the WPGraphQL plugin provides and use the Query Composer to build a query using <code>songs<\/code> or <code>albums<\/code>. Here&#8217;s an example:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span>{\n<\/span><\/span><span class='shcb-loc'><span>  songs(first: 10) {\n<\/span><\/span><span class='shcb-loc'><span>    nodes {\n<\/span><\/span><span class='shcb-loc'><span>      songFields {\n<\/span><\/span><span class='shcb-loc'><span>        songTitle\n<\/span><\/span><span class='shcb-loc'><span>        length\n<\/span><\/span><span class='shcb-loc'><span>        lyrics\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><span class='shcb-loc'><span>}\n<\/span><\/span><\/code><\/span><\/pre>\n\n\n<p>Go ahead and click the \u25b6\ufe0f icon to fire off the query, and you&#8217;ll see that the data for the&nbsp;<code>Songs<\/code>&nbsp;posts you had created comes back in the response. Magic! \u2728<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"693\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.58.08-AM-1024x693.png\" alt=\"\" class=\"wp-image-5498\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.58.08-AM-1024x693.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.58.08-AM-300x203.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.58.08-AM-768x520.png 768w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.58.08-AM-1536x1040.png 1536w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-12.58.08-AM-2048x1386.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Generating Possible types JSON<\/h4>\n\n\n\n<p>Finally, Apollo Client v3 requires you to provide a&nbsp;<code>possibleTypes object<\/code>&nbsp;that maps interfaces to all their possible types. Faust provides a <code>cli<\/code> command you can use on your package.json scripts to generate this file.<\/p>\n\n\n\n<p>In the terminal, run the <code>generate<\/code> script:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span>npm run generate\n<\/span><\/span><\/code><\/span><\/pre>\n\n\n<p>Done! Our&nbsp;Songs&nbsp;and&nbsp;Albums&nbsp;content models are now fully built out, and we&#8217;ve seen how we can query for them via WPGraphQL. Now let&#8217;s use this data in our frontend Faust.js app.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Build the Albums Page<\/h2>\n\n\n\n<p>Now that you have a WordPress site with the Taylor Swift discography data, we can get started with Faust.js.<\/p>\n\n\n\n<p>In a code editor, open the Faust.js project directory that you created. After opening the project directory, your text editor should look like this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/03\/Screen-Shot-2023-03-13-at-3.23.46-PM-1024x914.png\" alt=\"Faust.js app directory opened in VS Code\" class=\"wp-image-896\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Create <code>albums.js<\/code><\/h3>\n\n\n\n<p>To get started, create a new file titled <code>albums.js<\/code> inside the <code>pages<\/code> directory. We want to create a new page displaying a grid of all of Taylor Swift&#8217;s albums.<\/p>\n\n\n\n<p>Next.js uses a routing method known as page-based routing, meaning that generally, the routes of your site or application will correspond to the file structure of your&nbsp;<code>\/pages<\/code>&nbsp;folder. In this case, the&nbsp;<code>albums.js<\/code>&nbsp;file corresponds to your site&#8217;s local URL <code>\/albums<\/code>.<\/p>\n\n\n\n<p>To get the data we need, start by adding an import statement to the top of our&nbsp;<code>pages\/albums.js<\/code>&nbsp;file:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" 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> { gql, useQuery } <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-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>Add another import statement for a component that we will build in a later step &#8211; <code>AlbumCard<\/code>.<\/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-keyword\">import<\/span> AlbumCard <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/components\/AlbumCard\"<\/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>Then, back inside the WordPress Admin dashboard, use the Query Composer to build a query that will return all the data about each album for our home page: album cover image, release date, database ID, and slug. The completed query should look like this:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span>{\n<\/span><\/span><span class='shcb-loc'><span>  albums {\n<\/span><\/span><span class='shcb-loc'><span>    nodes {\n<\/span><\/span><span class='shcb-loc'><span>      albumFields {\n<\/span><\/span><span class='shcb-loc'><span>        releaseDate\n<\/span><\/span><span class='shcb-loc'><span>        cover {\n<\/span><\/span><span class='shcb-loc'><span>          node {\n<\/span><\/span><span class='shcb-loc'><span>            databaseId\n<\/span><\/span><span class='shcb-loc'><span>            mediaItemUrl\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><span class='shcb-loc'><span>      databaseId\n<\/span><\/span><span class='shcb-loc'><span>      slug\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><\/pre>\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"693\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-1.05.08-AM-1024x693.png\" alt=\"\" class=\"wp-image-5499\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-1.05.08-AM-1024x693.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-1.05.08-AM-300x203.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-1.05.08-AM-768x520.png 768w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-1.05.08-AM-1536x1039.png 1536w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-1.05.08-AM-2048x1386.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Then, back in our code editor, we will create a GraphQL query named <code>GET_ALBUMS<\/code> underneath the <code>import<\/code> statement. Copy the query we built in the GraphiQL IDE and paste it into a <code>gql<\/code> function. Remember to wrap query strings in the <code>gql<\/code> function to parse them into query documents.<\/p>\n\n\n<pre class=\"wp-block-code\" 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\">const<\/span> GET_ALBUMS = gql<span class=\"hljs-string\">`<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">  query getAlbums {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">    albums {<\/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\">        albumFields {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          cover {<\/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\">              databaseId<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">              mediaItemUrl<\/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\">          releaseDate<\/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\">        databaseId<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        slug<\/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><\/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>Next, create a function to hold our Albums page. Inside the <code>Albums<\/code> function, pass the <code>GET_ALBUMS<\/code> query to the <code>useQuery<\/code> hook.<\/p>\n\n\n\n<p>The <code>useQuery<\/code> React hook is the primary API for executing queries in an Apollo application. To run a query within a React component, call <code>useQuery<\/code> and pass it a GraphQL query string &#8211; like the one we just created. When your component renders, <code>useQuery<\/code> returns an object from Apollo Client that contains <code>loading<\/code>, <code>error<\/code>, and <code>data<\/code> properties you can use to render your UI.<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" 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\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Albums<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> { loading, error, data } = useQuery(GET_ALBUMS);\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">if<\/span> (loading) <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"Loading...\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">if<\/span> (error) <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">`Error! <span class=\"hljs-subst\">${error.message}<\/span>`<\/span>;\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>}\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>Inside the&nbsp;<code>Albums<\/code>&nbsp;component, we need to write an expression that iterates over the&nbsp;<code>albums<\/code>&nbsp;array to display each. We will do this by rendering an&nbsp;unordered list, then map over the&nbsp;<code>albums<\/code>&nbsp;and render a&nbsp;list item containing an&nbsp;<code>AlbumCard<\/code>&nbsp;component for each album.<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" 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\">return<\/span> (\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ul<\/span>&gt;<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\">      {data.albums.nodes.map((album) =&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\">li<\/span> <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{album.databaseId}<\/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\">AlbumCard<\/span> <span class=\"hljs-attr\">album<\/span>=<span class=\"hljs-string\">{album}<\/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\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/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><\/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\">ul<\/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><\/span><\/span><\/span><\/span><\/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<h3 class=\"wp-block-heading\">Create the AlbumCard Component<\/h3>\n\n\n\n<p>Now, let&#8217;s create the component that we are calling in this main file. Inside of the <code>components<\/code> directory, create a new file called <code>AlbumCard.js<\/code>.<\/p>\n\n\n\n<p>First, add an import statement for the <a href=\"https:\/\/nextjs.org\/docs\/api-reference\/next\/link\" target=\"_blank\" rel=\"noreferrer noopener\">Next.js Link component<\/a>.<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" 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\">import<\/span> Link <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/link\"<\/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>Then, create a function called <code>AlbumCard<\/code> that accepts an individual album&#8217;s data as a <code>prop<\/code>. Inside of the <code>return<\/code> statement, display an image of the album&#8217;s cover wrapped in a link that points to the individual album details page that we will build out later.<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" 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><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\">AlbumCard<\/span>(<span class=\"hljs-params\">{ album }<\/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\">Link<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">{<\/span>`\/<span class=\"hljs-attr\">albums<\/span>\/${<span class=\"hljs-attr\">album.slug<\/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\">img<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{album?.albumFields.cover?.node?.mediaItemUrl}<\/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\">Link<\/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-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<h3 class=\"wp-block-heading\">Create the Layout Component<\/h3>\n\n\n\n<p>Now, let&#8217;s create the component that we can use to wrap around every other JSX element to follow Next.js&#8217; rule that JSX expressions must have one parent element. Inside of the <code>components<\/code> directory, create a new file called <code>Layout.js<\/code>.<\/p>\n\n\n\n<p>Add an import statement for the <a href=\"https:\/\/nextjs.org\/docs\/api-reference\/next\/head\" target=\"_blank\" rel=\"noreferrer noopener\">Next.js Head component<\/a>. Add the following code to the <code>return<\/code> statement of the <code>Layout<\/code> function.<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" 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\">import<\/span> Head <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/head\"<\/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\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Layout<\/span>(<span class=\"hljs-params\">{ children }<\/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;&gt;<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Head<\/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\">title<\/span>&gt;<\/span>TS Discography<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">title<\/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\">      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Head<\/span>&gt;<\/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\">&lt;<span class=\"hljs-name\">main<\/span>&gt;<\/span>{children}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">main<\/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;\/&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><\/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><\/span><\/span><\/span><\/span><\/span><\/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>Back in <code>albums.js<\/code>, import this file:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" 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\">import<\/span> Layout <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/components\/Layout\"<\/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>Then, wrap everything currently inside of the <code>return<\/code> statement inside of a <code>&lt;Layout&gt;<\/code> component.<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Layout<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  ...\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Layout<\/span>&gt;<\/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\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Style the Albums Page<\/h3>\n\n\n\n<p>Check out the site running in the browser! You can see the ten album covers displayed, but it&#8217;s not very pretty. Let&#8217;s add some styles to this page! In the <code>styles<\/code> directory, add the following SCSS declarations to the existing <code>_base.scss<\/code> file:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-selector-class\">.gallery<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">5%<\/span> <span class=\"hljs-number\">0<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">display<\/span>: grid;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">grid-template-columns<\/span>: <span class=\"hljs-built_in\">repeat<\/span>(<span class=\"hljs-number\">3<\/span>, <span class=\"hljs-number\">1<\/span>fr);\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">grid-gap<\/span>: <span class=\"hljs-number\">15px<\/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-selector-class\">.galleryItem<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">list-style-type<\/span>: none;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">opacity<\/span>: <span class=\"hljs-number\">1<\/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-selector-class\">.galleryItem<\/span><span class=\"hljs-selector-pseudo\">:hover<\/span> <span class=\"hljs-selector-tag\">img<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">opacity<\/span>: .<span class=\"hljs-number\">6<\/span>;\n<\/span><\/span><span class='shcb-loc'><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\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Back in the <code>albums.js<\/code> file, add the <code>.gallery<\/code> class to the <code>ul<\/code> element and the <code>.galleryItem<\/code> class to the <code>li<\/code> element.<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span>      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ul<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"gallery\"<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>        ...\n<\/span><\/span><span class='shcb-loc'><span>          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"galleryItem\"<\/span> <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{album.databaseId}<\/span>&gt;<\/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\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Review the <code>albums.js<\/code> File<\/h3>\n\n\n\n<p>After all of these steps, your <code>albums.js<\/code> file should look like this:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-16\" 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> { gql, useQuery } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@apollo\/client\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> AlbumCard <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/components\/AlbumCard\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> Layout <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/components\/Layout\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> GET_ALBUMS = gql<span class=\"hljs-string\">`<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">  query getAlbums {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">    albums {<\/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\">        albumFields {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          cover {<\/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\">              databaseId<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">              mediaItemUrl<\/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\">          releaseDate<\/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\">        databaseId<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        slug<\/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>\n<\/span><\/span><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\">Albums<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> { loading, error, data } = useQuery(GET_ALBUMS);\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">if<\/span> (loading) <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"Loading...\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">if<\/span> (error) <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">`Error! <span class=\"hljs-subst\">${error.message}<\/span>`<\/span>;\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=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Layout<\/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\">ul<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"gallery\"<\/span>&gt;<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        {data.albums.nodes.map((album) =&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\">li<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"galleryItem\"<\/span> <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{album.databaseId}<\/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\">&lt;<span class=\"hljs-name\">AlbumCard<\/span> <span class=\"hljs-attr\">album<\/span>=<span class=\"hljs-string\">{album}<\/span> \/&gt;<\/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\">&lt;\/<span class=\"hljs-name\">li<\/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><\/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\">&lt;\/<span class=\"hljs-name\">ul<\/span>&gt;<\/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\">&lt;\/<span class=\"hljs-name\">Layout<\/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><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><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<h2 class=\"wp-block-heading\">Build the Single Album Details Page<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Create <code>[albumSlug].js<\/code><\/h3>\n\n\n\n<p>Now, let&#8217;s create the page that displays an individual album&#8217;s details. Inside of the&nbsp;<code>pages<\/code>&nbsp;directory, create a new folder called <code>albums<\/code> with a file inside called&nbsp;<code>[albumSlug].js<\/code>.<\/p>\n\n\n\n<p>To get the data we need, start by adding an import statement to the top of our&nbsp;<code>albums\/[albumSlug].js<\/code>&nbsp;file:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-17\" 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> { gql, useQuery } <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-17\"><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>Then, back inside the WordPress Admin dashboard, use the Query Composer to build a query that will return all of the data about the specific album for our album details page: album title, cover image, release date, and the list of all of the songs on that album.<\/p>\n\n\n\n<p>We need to determine which album data to retrieve based on the slug from the URL. Let&#8217;s hard-code the slug <code>red-taylors-version<\/code> into the query to test that it returns the correct information.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" 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>{\n<\/span><\/span><span class='shcb-loc'><span>  album(id: <span class=\"hljs-string\">\"red-taylors-version\"<\/span>, <span class=\"hljs-attr\">idType<\/span>: SLUG) {\n<\/span><\/span><span class='shcb-loc'><span>    albumFields {\n<\/span><\/span><span class='shcb-loc'><span>      albumTitle\n<\/span><\/span><span class='shcb-loc'><span>      cover {\n<\/span><\/span><span class='shcb-loc'><span>        node {\n<\/span><\/span><span class='shcb-loc'><span>          mediaItemUrl\n<\/span><\/span><span class='shcb-loc'><span>          altText\n<\/span><\/span><span class='shcb-loc'><span>        }\n<\/span><\/span><span class='shcb-loc'><span>      }\n<\/span><\/span><span class='shcb-loc'><span>      releaseDate\n<\/span><\/span><span class='shcb-loc'><span>      trackList {\n<\/span><\/span><span class='shcb-loc'><span>        nodes {\n<\/span><\/span><span class='shcb-loc'><span>          ... on Song {\n<\/span><\/span><span class='shcb-loc'><span>            id\n<\/span><\/span><span class='shcb-loc'><span>            slug\n<\/span><\/span><span class='shcb-loc'><span>            songFields {\n<\/span><\/span><span class='shcb-loc'><span>              songTitle\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><span class='shcb-loc'><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>}\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><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>However, this query needs to be able to return the data for any album, not just Red (Taylor&#8217;s Version). We can add a variable called <code>albumSlug<\/code> into the query instead of hard-coding the value. Below the query, we can set a value for the query to ensure it still works as expected.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" 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>query getAlbumDetails($albumSlug: ID!) {\n<\/span><\/span><span class='shcb-loc'><span>  album(id: $albumSlug, idType: SLUG) {\n<\/span><\/span><span class='shcb-loc'><span>    albums {\n<\/span><\/span><span class='shcb-loc'><span>      albumTitle\n<\/span><\/span><span class='shcb-loc'><span>      cover {\n<\/span><\/span><span class='shcb-loc'><span>        sourceUrl\n<\/span><\/span><span class='shcb-loc'><span>        mediaItemUrl\n<\/span><\/span><span class='shcb-loc'><span>        altText\n<\/span><\/span><span class='shcb-loc'><span>      }\n<\/span><\/span><span class='shcb-loc'><span>      releaseDate\n<\/span><\/span><span class='shcb-loc'><span>      trackList {\n<\/span><\/span><span class='shcb-loc'><span>        ... on Song {\n<\/span><\/span><span class='shcb-loc'><span>          id\n<\/span><\/span><span class='shcb-loc'><span>          songs {\n<\/span><\/span><span class='shcb-loc'><span>            songTitle\n<\/span><\/span><span class='shcb-loc'><span>          }\n<\/span><\/span><span class='shcb-loc'><span>          slug\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><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-19\"><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<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"693\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-1.18.29-AM-1024x693.png\" alt=\"\" class=\"wp-image-5500\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-1.18.29-AM-1024x693.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-1.18.29-AM-300x203.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-1.18.29-AM-768x520.png 768w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-1.18.29-AM-1536x1040.png 1536w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-1.18.29-AM-2048x1386.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Then, back in our code editor, we will create a GraphQL query named <code>GET_ALBUM_DETAILS<\/code> underneath the <code>import<\/code> statement. Copy the query we built in the GraphiQL IDE and paste it into a <code>gql<\/code> function. Remember to wrap query strings in the <code>gql<\/code> function to parse them into query documents.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" 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><span class=\"hljs-keyword\">const<\/span> GET_ALBUM_DETAILS = gql`\n<\/span><\/span><span class='shcb-loc'><span>query GetAlbumDetails($albumSlug: ID!) {\n<\/span><\/span><span class='shcb-loc'><span>  album(id: $albumSlug, idType: SLUG) {\n<\/span><\/span><span class='shcb-loc'><span>    albumFields {\n<\/span><\/span><span class='shcb-loc'><span>      albumTitle\n<\/span><\/span><span class='shcb-loc'><span>      cover {\n<\/span><\/span><span class='shcb-loc'><span>        node {\n<\/span><\/span><span class='shcb-loc'><span>          mediaItemUrl\n<\/span><\/span><span class='shcb-loc'><span>          altText\n<\/span><\/span><span class='shcb-loc'><span>        }\n<\/span><\/span><span class='shcb-loc'><span>      }\n<\/span><\/span><span class='shcb-loc'><span>      releaseDate\n<\/span><\/span><span class='shcb-loc'><span>      trackList {\n<\/span><\/span><span class='shcb-loc'><span>        nodes {\n<\/span><\/span><span class='shcb-loc'><span>          ... on Song {\n<\/span><\/span><span class='shcb-loc'><span>            id\n<\/span><\/span><span class='shcb-loc'><span>            slug\n<\/span><\/span><span class='shcb-loc'><span>            songFields {\n<\/span><\/span><span class='shcb-loc'><span>              songTitle\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><span class='shcb-loc'><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>}\n<\/span><\/span><span class='shcb-loc'><span>`;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><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>Import the <a href=\"https:\/\/nextjs.org\/docs\/api-reference\/next\/router\" target=\"_blank\" rel=\"noreferrer noopener\">Next.js Router component<\/a>. The <code>useRouter<\/code> hook&#8217;s <code>query<\/code> object allows us to access the dynamic route parameter <code>albumSlug<\/code> that we created with the <code><code>[albumSlug].js<\/code><\/code> file and use that inside of our GraphQL client.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" 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> { useRouter } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/router\"<\/span>;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><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>Then, create a function called <code>Album()<\/code> with a blank return statement for now. Inside this <code>Album<\/code> function, pass the <code>GET_ALBUM_DETAILS<\/code> query and the <code>albumSlug<\/code> retrieved from the <code>useRouter<\/code> hook to the <code>useQuery<\/code> hook to retrieve the requested data on the current album.<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-22\" 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\">Album<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> { query = {} } = useRouter();\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> { albumSlug } = query;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> { loading, error, data } = useQuery(GET_ALBUM_DETAILS, {\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-attr\">variables<\/span>: { albumSlug }\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> albumData = data?.album?.albumFields;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">if<\/span> (loading) <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"Loading...\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">if<\/span> (error) <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">`Error! <span class=\"hljs-subst\">${error.message}<\/span>`<\/span>;\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>}\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><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>Now that we have access to the individual album&#8217;s data, we&#8217;ll focus on the view for the page. Start with adding import statements for our <code>Layout<\/code> component and the <a href=\"https:\/\/nextjs.org\/docs\/api-reference\/next\/link\" target=\"_blank\" rel=\"noreferrer noopener\">Next.js Link component<\/a>.<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-23\" 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> Layout <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/..\/components\/Layout\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> Link <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/link\"<\/span>;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><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>Inside of the return statement of the <code>Album<\/code> function, we will build the JSX elements. First, wrap everything inside of the <code>Layout<\/code> component. At the top of the screen, we will also add a button for users to return to the main page of the site. List out the details of the album that we entered through ACF in WordPress: title, release date, cover image, and the list of songs.<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-24\" 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\">return<\/span> (\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Layout<\/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\">Link<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"\/albums\"<\/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\">p<\/span>&gt;<\/span> <span class=\"hljs-symbol\">&amp;#x2190;<\/span> View All Albums<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/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>&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\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>{albumData.albumTitle}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/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\">p<\/span>&gt;<\/span>Released on {albumData.releaseDate}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/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\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{albumData?.cover.node.mediaItemUrl}<\/span> <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">{albumData.cover.node.altText}<\/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 class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h3<\/span>&gt;<\/span>Track List<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h3<\/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\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ol<\/span>&gt;<\/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\">        {albumData.trackList.nodes.map((song) =&gt; (<\/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\">&lt;<span class=\"hljs-name\">li<\/span> <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{song.id}<\/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 class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Link<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">{<\/span>`\/<span class=\"hljs-attr\">songs<\/span>\/${<span class=\"hljs-attr\">song.slug<\/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 class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span>&gt;<\/span>{song.songFields.songTitle}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/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 class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Link<\/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\">li<\/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\">ol<\/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\">&lt;\/<span class=\"hljs-name\">Layout<\/span>&gt;<\/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><\/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-24\"><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<h3 class=\"wp-block-heading\">Style the Single Album Page<\/h3>\n\n\n\n<p>Check out the site running in the browser and navigate to the album details page by clicking on one of the cover images. You can see all of the information that we want, but it&#8217;s not very pretty. Let&#8217;s add some styles to this page!<\/p>\n\n\n\n<p>Go back to the <code>_base.scss<\/code> file and add the following additional SCSS declarations:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-25\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-selector-class\">.backButton<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">text-align<\/span>: right;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">2%<\/span> <span class=\"hljs-number\">5%<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">font-weight<\/span>: bold;\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-selector-class\">.backButton<\/span><span class=\"hljs-selector-pseudo\">:hover<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">text-decoration<\/span>: underline;\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-selector-class\">.title<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">text-align<\/span>: center;\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-selector-class\">.details<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">text-align<\/span>: center;\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-selector-class\">.cover<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">display<\/span>: block;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">margin<\/span>: auto;\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-selector-class\">.trackList<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">text-align<\/span>: center;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">text-decoration<\/span>: none;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">list-style-type<\/span>: none;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">padding-inline-start<\/span>: <span class=\"hljs-number\">0<\/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-selector-class\">.listItem<\/span> <span class=\"hljs-selector-tag\">a<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">text-decoration<\/span>: none;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">color<\/span>: black;\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-selector-class\">.listItem<\/span> <span class=\"hljs-selector-tag\">a<\/span><span class=\"hljs-selector-pseudo\">:hover<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">font-weight<\/span>: bold;\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-selector-class\">.lyrics<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">white-space<\/span>: pre-wrap;\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Use these SCSS classes and assign them to their respective elements in the <code>[albumSlug].js<\/code> file:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-26\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span>        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"backButton\"<\/span>&gt;<\/span> <span class=\"hljs-symbol\">&amp;#x2190;<\/span> View All Albums<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>      ...\n<\/span><\/span><span class='shcb-loc'><span>      <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>{albumData.albumTitle}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"details\"<\/span>&gt;<\/span>Released on {albumData.releaseDate}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"cover\"<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{albumData?.cover.node.mediaItemUrl}<\/span> <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">{albumData.cover.node.altText}<\/span> \/&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h3<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"details\"<\/span>&gt;<\/span>Track List<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h3<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ol<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"trackList\"<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>      ...\n<\/span><\/span><span class='shcb-loc'><span>          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"listItem\"<\/span> <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{song.id}<\/span>&gt;<\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-26\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Review the <code>[albumSlug].js<\/code> File<\/h3>\n\n\n\n<p>After all of these steps, your&nbsp;<code>[albumSlug].js<\/code>&nbsp;file should look like this:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-27\" 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> { gql, useQuery } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@apollo\/client\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { useRouter } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/router\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> Layout <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/..\/components\/Layout\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> Link <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/link\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> GET_ALBUM_DETAILS = gql<span class=\"hljs-string\">`<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">query GetAlbumDetails($albumSlug: ID!) {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">  album(id: $albumSlug, idType: SLUG) {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">    albumFields {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      albumTitle<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      cover {<\/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\">          mediaItemUrl<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          altText<\/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\">      releaseDate<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      trackList {<\/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\">          ... on Song {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">            id<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">            slug<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">            songFields {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">              songTitle<\/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-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>\n<\/span><\/span><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\">Album<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> { query = {} } = useRouter();\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> { albumSlug } = query;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> { loading, error, data } = useQuery(GET_ALBUM_DETAILS, {\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-attr\">variables<\/span>: { albumSlug }\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> albumData = data?.album?.albumFields;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">if<\/span> (loading) <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"Loading...\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">if<\/span> (error) <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">`Error! <span class=\"hljs-subst\">${error.message}<\/span>`<\/span>;\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=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Layout<\/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\">Link<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"\/albums\"<\/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\">p<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"backButton\"<\/span>&gt;<\/span> <span class=\"hljs-symbol\">&amp;#x2190;<\/span> View All Albums<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/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>&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\">&lt;<span class=\"hljs-name\">h1<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"title\"<\/span>&gt;<\/span>{albumData.albumTitle}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/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\">p<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"details\"<\/span>&gt;<\/span>Released on {albumData.releaseDate}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/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\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"cover\"<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{albumData?.cover.node.mediaItemUrl}<\/span> <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">{albumData.cover.node.altText}<\/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 class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h3<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"details\"<\/span>&gt;<\/span>Track List<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h3<\/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\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ol<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"trackList\"<\/span>&gt;<\/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\">        {albumData.trackList.nodes.map((song) =&gt; (<\/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\">&lt;<span class=\"hljs-name\">li<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"listItem\"<\/span> <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{song.id}<\/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 class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Link<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">{<\/span>`\/<span class=\"hljs-attr\">songs<\/span>\/${<span class=\"hljs-attr\">song.slug<\/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 class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span>&gt;<\/span>{song.songFields.songTitle}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/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 class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Link<\/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\">li<\/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\">ol<\/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\">&lt;\/<span class=\"hljs-name\">Layout<\/span>&gt;<\/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><\/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-27\"><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<h2 class=\"wp-block-heading\">Build the Song Details Page<\/h2>\n\n\n\n<p>Creating the individual song details page will be very similar to creating the individual album details page.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Create <code>[songSlug].js<\/code><\/h3>\n\n\n\n<p>First, let&#8217;s create a page to display an individual song&#8217;s details. Inside of the&nbsp;<code>pages<\/code>&nbsp;directory, create a new folder called&nbsp;<code>songs<\/code>&nbsp;with a new file inside of it called&nbsp;<code>[songSlug].js<\/code>.<\/p>\n\n\n\n<p>To get the data we need, we need to import several things:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-28\" 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> { gql, useQuery } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@apollo\/client\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { useRouter } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/router\"<\/span>;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-28\"><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>Then, back inside the WordPress Admin dashboard, use the Query Composer to build a query that will return all of the data about the specific song for our song details page: song title, length, lyrics, and genre.<\/p>\n\n\n\n<p>We need to determine which song data to retrieve based on the slug from the URL, just as we did with the album details page. We can use a variable in the query again to accept the song slug and return data about the corresponding song.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-29\" 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>query getSongDetails($songSlug: ID!) {\n<\/span><\/span><span class='shcb-loc'><span>  song(id: $songSlug, idType: SLUG) {\n<\/span><\/span><span class='shcb-loc'><span>    songFields {\n<\/span><\/span><span class='shcb-loc'><span>      songTitle\n<\/span><\/span><span class='shcb-loc'><span>      lyrics\n<\/span><\/span><span class='shcb-loc'><span>      length\n<\/span><\/span><span class='shcb-loc'><span>      genre {\n<\/span><\/span><span class='shcb-loc'><span>        nodes {\n<\/span><\/span><span class='shcb-loc'><span>          name\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><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-29\"><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<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"694\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-1.27.13-AM-1024x694.png\" alt=\"\" class=\"wp-image-5501\" srcset=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-1.27.13-AM-1024x694.png 1024w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-1.27.13-AM-300x203.png 300w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-1.27.13-AM-768x521.png 768w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-1.27.13-AM-1536x1041.png 1536w, https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/07\/Screenshot-2023-07-25-at-1.27.13-AM-2048x1388.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Then, back in our code editor, we will create a GraphQL query named <code>GET_SONG_DETAILS<\/code> underneath the <code>import<\/code> statement. Copy the query we built in the GraphiQL IDE and paste it into a <code>gql<\/code> function. Remember to wrap query strings in the <code>gql<\/code> function to parse them into query documents.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-30\" 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><span class=\"hljs-keyword\">const<\/span> GET_SONG_DETAILS = gql`\n<\/span><\/span><span class='shcb-loc'><span>  query getSongDetails($songSlug: ID!) {\n<\/span><\/span><span class='shcb-loc'><span>    song(id: $songSlug, idType: SLUG) {\n<\/span><\/span><span class='shcb-loc'><span>      songFields {\n<\/span><\/span><span class='shcb-loc'><span>        songTitle\n<\/span><\/span><span class='shcb-loc'><span>        lyrics\n<\/span><\/span><span class='shcb-loc'><span>        length\n<\/span><\/span><span class='shcb-loc'><span>        genre {\n<\/span><\/span><span class='shcb-loc'><span>          nodes {\n<\/span><\/span><span class='shcb-loc'><span>            name\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><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-30\"><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>Then, create a function called&nbsp;<code>Song()<\/code>&nbsp;with a blank return statement for now. Inside of this&nbsp;<code>Song<\/code>&nbsp;function, pass the <code>GET_SONG_DETAILS<\/code> query and the <code>songSlug<\/code> retrieved from the <code>useRouter<\/code> hook to the <code>useQuery<\/code> hook to retrieve the requested data on the current song.<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-31\" 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\">Song<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> { query = {} } = useRouter();\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> { songSlug } = query;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> { loading, error, data } = useQuery(GET_SONG_DETAILS, {\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-attr\">variables<\/span>: { songSlug }\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> songData = data?.song?.songFields;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">if<\/span> (loading) <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"Loading...\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">if<\/span> (error) <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">`Error! <span class=\"hljs-subst\">${error.message}<\/span>`<\/span>;\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>}\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-31\"><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>Now that we have access to the individual song&#8217;s data, we&#8217;ll focus on the view for the page. Start with adding import statements for our&nbsp;<code>Layout<\/code>&nbsp;component and the&nbsp;<a href=\"https:\/\/nextjs.org\/docs\/api-reference\/next\/link\" target=\"_blank\" rel=\"noreferrer noopener\">Next.js Link component<\/a>.<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-32\" 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> Layout <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/..\/components\/Layout\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> Link <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/link\"<\/span>;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-32\"><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>Inside the return statement of the&nbsp;<code>Song<\/code>&nbsp;function, we will build the JSX elements. This will be very similar to what we built for the <code>albumSlug<\/code> page. List out the details of the song that we entered through ACF in WordPress: title, length, genre, and lyrics.<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-33\" 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\">return<\/span> (\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Layout<\/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\">Link<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"\/albums\"<\/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\">p<\/span>&gt;<\/span> <span class=\"hljs-symbol\">&amp;#x2190;<\/span> View All Albums<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/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>&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\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>{songData.songTitle}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/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\">p<\/span>&gt;<\/span>Song Length: {songData.length}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/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\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/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\">        Genre:<span class=\"hljs-symbol\">&amp;nbsp;<\/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\">        {songData<\/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\">          .genre.nodes.map((genre) =&gt; genre.name)<\/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\">          .join(\", \")}<\/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>&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\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h3<\/span>&gt;<\/span>Lyrics<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h3<\/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\">div<\/span>&gt;<\/span>{songData.lyrics}<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>\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\">Layout<\/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><\/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-33\"><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<h3 class=\"wp-block-heading\">Style the Song Details Page<\/h3>\n\n\n\n<p>Check out the site running in the browser and navigate to the song details page by clicking on one of the song titles from the album&#8217;s tracklist. You can see all of the information that we want, but it&#8217;s not very pretty. Let&#8217;s add some styles to this page!<\/p>\n\n\n\n<p>We can use the existing classes that we added to <code>_base.scss<\/code> file for the album details page. Assign these classes to their respective elements in the <code>[songSlug].js<\/code> file:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-34\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span>        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"backButton\"<\/span>&gt;<\/span> <span class=\"hljs-symbol\">&amp;#x2190;<\/span> View All Albums<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>      ...\n<\/span><\/span><span class='shcb-loc'><span>      <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>{song.songTitle}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"details\"<\/span>&gt;<\/span>Song Length: {song.length}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"details\"<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>      ...\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h3<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"details\"<\/span>&gt;<\/span>Lyrics<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h3<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"details lyrics\"<\/span>&gt;<\/span>{songData.lyrics}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-34\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Review the [songSlug].js File<\/h3>\n\n\n\n<p>After all of these steps, your&nbsp;<code>[songSlug].js<\/code>&nbsp;file should look like this:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-35\" 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> { gql, useQuery } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@apollo\/client\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { useRouter } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/router\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> Layout <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/..\/components\/Layout\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> Link <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/link\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> GET_SONG_DETAILS = gql<span class=\"hljs-string\">`<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">  query getSongDetails($songSlug: ID!) {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">    song(id: $songSlug, idType: SLUG) {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      songFields {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        songTitle<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        lyrics<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        length<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        genre {<\/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\">            name<\/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-string\">`<\/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\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Song<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> { query = {} } = useRouter();\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> { songSlug } = query;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> { loading, error, data } = useQuery(GET_SONG_DETAILS, {\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-attr\">variables<\/span>: { songSlug }\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> songData = data?.song?.songFields;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">if<\/span> (loading) <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"Loading...\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">if<\/span> (error) <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">`Error! <span class=\"hljs-subst\">${error.message}<\/span>`<\/span>;\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=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Layout<\/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\">Link<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"\/albums\"<\/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\">p<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"backButton\"<\/span>&gt;<\/span> <span class=\"hljs-symbol\">&amp;#x2190;<\/span> View All Albums<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/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>&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\">&lt;<span class=\"hljs-name\">h1<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"title\"<\/span>&gt;<\/span>{songData.songTitle}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/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\">p<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"details\"<\/span>&gt;<\/span>Song Length: {songData.length}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/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\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"details\"<\/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\">        Genre:<span class=\"hljs-symbol\">&amp;nbsp;<\/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\">        {songData<\/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\">          .genre.nodes.map((genre) =&gt; genre.name)<\/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\">          .join(\", \")}<\/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>&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\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h3<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"details\"<\/span>&gt;<\/span>Lyrics<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h3<\/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\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"details lyrics\"<\/span>&gt;<\/span>{songData.lyrics}<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>\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\">Layout<\/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><\/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><\/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-35\"><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<h2 class=\"wp-block-heading\">Done! \ud83c\udf89<\/h2>\n\n\n\n<p>You should now be able to navigate back and forth between the home page, the album details page, and the song details page. Don&#8217;t forget to update your custom post type and field data as Taylor Swift releases her re-recordings. \ud83d\ude09<\/p>\n\n\n\n<p>Congratulations on creating a headless WordPress site! Hopefully, you now have a good understanding of how you can leverage tools like Faust.js, ACF, 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 tutorial at <a href=\"https:\/\/github.com\/graceerixon\/albums-and-songs-with-faust-wpgraphql-and-acf\" target=\"_blank\" rel=\"noreferrer noopener\">this GitHub repository<\/a>.<\/p>\n\n\n\n<p>Looking for a place to host your headless WordPress project? Check out WP Engine&#8217;s&nbsp;<a href=\"https:\/\/wpengine.com\/atlas\/\" target=\"_blank\" rel=\"noreferrer noopener\">Atlas platform<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial will teach you how to create a headless WordPress app using Faust.js, WPGraphQL, and Advanced Custom Fields (ACF). It assumes a basic understanding of JavaScript, React fundamentals, GraphQL [&hellip;]<\/p>\n","protected":false},"author":21,"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-527","post","type-post","status-publish","format-standard","hentry","category-headless"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Crash Course: Build a Headless WordPress App with Faust.js, WPGraphQL &amp; Advanced Custom Fields - Builders<\/title>\n<meta name=\"description\" content=\"This tutorial will teach you how to create a headless WordPress app using Faust.js, WPGraphQL, and Advanced Custom Fields (ACF).\" \/>\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-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\/\" \/>\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 Headless WordPress App with Faust.js, WPGraphQL &amp; Advanced Custom Fields - Builders\" \/>\n<meta property=\"og:description\" content=\"This tutorial will teach you how to create a headless WordPress app using Faust.js, WPGraphQL, and Advanced Custom Fields (ACF).\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wpengine.com\/builders\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\/\" \/>\n<meta property=\"og:site_name\" content=\"Builders\" \/>\n<meta property=\"article:published_time\" content=\"2023-07-08T01:25:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-12-15T19:52:48+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-10.19.11-AM-1024x911.png\" \/>\n<meta name=\"author\" content=\"Grace Erixon\" \/>\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=\"Grace Erixon\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"22 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\\\/\"},\"author\":{\"name\":\"Grace Erixon\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#\\\/schema\\\/person\\\/238dfb380aff5f2c58b8572d0b661deb\"},\"headline\":\"Crash Course: Build a Headless WordPress App with Faust.js, WPGraphQL &amp; Advanced Custom Fields\",\"datePublished\":\"2023-07-08T01:25:00+00:00\",\"dateModified\":\"2023-12-15T19:52:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\\\/\"},\"wordCount\":4024,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/Screenshot-2023-04-20-at-10.19.11-AM-1024x911.png\",\"articleSection\":[\"Headless\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\\\/\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\\\/\",\"name\":\"Crash Course: Build a Headless WordPress App with Faust.js, WPGraphQL &amp; Advanced Custom Fields - Builders\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/Screenshot-2023-04-20-at-10.19.11-AM-1024x911.png\",\"datePublished\":\"2023-07-08T01:25:00+00:00\",\"dateModified\":\"2023-12-15T19:52:48+00:00\",\"description\":\"This tutorial will teach you how to create a headless WordPress app using Faust.js, WPGraphQL, and Advanced Custom Fields (ACF).\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\\\/#primaryimage\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/Screenshot-2023-04-20-at-10.19.11-AM.png\",\"contentUrl\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/Screenshot-2023-04-20-at-10.19.11-AM.png\",\"width\":2270,\"height\":2020},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Crash Course: Build a Headless WordPress App with Faust.js, WPGraphQL &amp; Advanced Custom Fields\"}]},{\"@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\\\/238dfb380aff5f2c58b8572d0b661deb\",\"name\":\"Grace Erixon\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/85b32abfcbc7a3028fc8a4d3f0f299333783fc24197648f25e75661c9e1a8a97?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/85b32abfcbc7a3028fc8a4d3f0f299333783fc24197648f25e75661c9e1a8a97?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/85b32abfcbc7a3028fc8a4d3f0f299333783fc24197648f25e75661c9e1a8a97?s=96&d=mm&r=g\",\"caption\":\"Grace Erixon\"},\"description\":\"Grace Erixon is a Developer Advocate at WP Engine. She has been developing with headless WordPress since 2021. Connect with her on the Headless WordPress Discord community, Twitter, or LinkedIn.\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/author\\\/grace-erixonwpengine-com\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Crash Course: Build a Headless WordPress App with Faust.js, WPGraphQL &amp; Advanced Custom Fields - Builders","description":"This tutorial will teach you how to create a headless WordPress app using Faust.js, WPGraphQL, and Advanced Custom Fields (ACF).","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-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\/","og_locale":"en_US","og_type":"article","og_title":"Crash Course: Build a Headless WordPress App with Faust.js, WPGraphQL &amp; Advanced Custom Fields - Builders","og_description":"This tutorial will teach you how to create a headless WordPress app using Faust.js, WPGraphQL, and Advanced Custom Fields (ACF).","og_url":"https:\/\/wpengine.com\/builders\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\/","og_site_name":"Builders","article_published_time":"2023-07-08T01:25:00+00:00","article_modified_time":"2023-12-15T19:52:48+00:00","og_image":[{"url":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-10.19.11-AM-1024x911.png","type":"","width":"","height":""}],"author":"Grace Erixon","twitter_card":"summary_large_image","twitter_creator":"@wpebuilders","twitter_site":"@wpebuilders","twitter_misc":{"Written by":"Grace Erixon","Est. reading time":"22 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/wpengine.com\/builders\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\/#article","isPartOf":{"@id":"https:\/\/wpengine.com\/builders\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\/"},"author":{"name":"Grace Erixon","@id":"https:\/\/wpengine.com\/builders\/#\/schema\/person\/238dfb380aff5f2c58b8572d0b661deb"},"headline":"Crash Course: Build a Headless WordPress App with Faust.js, WPGraphQL &amp; Advanced Custom Fields","datePublished":"2023-07-08T01:25:00+00:00","dateModified":"2023-12-15T19:52:48+00:00","mainEntityOfPage":{"@id":"https:\/\/wpengine.com\/builders\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\/"},"wordCount":4024,"commentCount":0,"publisher":{"@id":"https:\/\/wpengine.com\/builders\/#organization"},"image":{"@id":"https:\/\/wpengine.com\/builders\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\/#primaryimage"},"thumbnailUrl":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-10.19.11-AM-1024x911.png","articleSection":["Headless"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/wpengine.com\/builders\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/wpengine.com\/builders\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\/","url":"https:\/\/wpengine.com\/builders\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\/","name":"Crash Course: Build a Headless WordPress App with Faust.js, WPGraphQL &amp; Advanced Custom Fields - Builders","isPartOf":{"@id":"https:\/\/wpengine.com\/builders\/#website"},"primaryImageOfPage":{"@id":"https:\/\/wpengine.com\/builders\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\/#primaryimage"},"image":{"@id":"https:\/\/wpengine.com\/builders\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\/#primaryimage"},"thumbnailUrl":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-10.19.11-AM-1024x911.png","datePublished":"2023-07-08T01:25:00+00:00","dateModified":"2023-12-15T19:52:48+00:00","description":"This tutorial will teach you how to create a headless WordPress app using Faust.js, WPGraphQL, and Advanced Custom Fields (ACF).","breadcrumb":{"@id":"https:\/\/wpengine.com\/builders\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wpengine.com\/builders\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wpengine.com\/builders\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\/#primaryimage","url":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-10.19.11-AM.png","contentUrl":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-20-at-10.19.11-AM.png","width":2270,"height":2020},{"@type":"BreadcrumbList","@id":"https:\/\/wpengine.com\/builders\/build-headless-wordpress-app-faust-wpgraphql-advanced-custom-fields\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/wpengine.com\/builders\/"},{"@type":"ListItem","position":2,"name":"Crash Course: Build a Headless WordPress App with Faust.js, WPGraphQL &amp; Advanced Custom Fields"}]},{"@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\/238dfb380aff5f2c58b8572d0b661deb","name":"Grace Erixon","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/85b32abfcbc7a3028fc8a4d3f0f299333783fc24197648f25e75661c9e1a8a97?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/85b32abfcbc7a3028fc8a4d3f0f299333783fc24197648f25e75661c9e1a8a97?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/85b32abfcbc7a3028fc8a4d3f0f299333783fc24197648f25e75661c9e1a8a97?s=96&d=mm&r=g","caption":"Grace Erixon"},"description":"Grace Erixon is a Developer Advocate at WP Engine. She has been developing with headless WordPress since 2021. Connect with her on the Headless WordPress Discord community, Twitter, or LinkedIn.","url":"https:\/\/wpengine.com\/builders\/author\/grace-erixonwpengine-com\/"}]}},"_links":{"self":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/posts\/527","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\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/comments?post=527"}],"version-history":[{"count":0,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/posts\/527\/revisions"}],"wp:attachment":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/media?parent=527"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/categories?post=527"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/tags?post=527"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}