{"id":31842,"date":"2025-04-11T14:51:03","date_gmt":"2025-04-11T19:51:03","guid":{"rendered":"https:\/\/wpengine.com\/builders\/?p=31842"},"modified":"2025-05-13T11:28:31","modified_gmt":"2025-05-13T16:28:31","slug":"astro-wordpress-routing-and-graphql","status":"publish","type":"post","link":"https:\/\/wpengine.com\/builders\/astro-wordpress-routing-and-graphql\/","title":{"rendered":"Astro + WordPress: Routing and GraphQL"},"content":{"rendered":"\n<p>I\u2019ve been using headless WordPress since before it was cool. I\u2019ve built numerous sites using Gatsby, Next.js, SvelteKit, and now Astro!&nbsp;<\/p>\n\n\n\n<p>I can wholeheartedly say Astro has been the best experience for me. While it should stand proud for various reasons, its feature set and approach make it an excellent match for use with headless WordPress.<\/p>\n\n\n\n<p>In preparation for this article, I moved a site from Gatsby to Astro. I learned a ton about Astro and hope to share that with you over a series of articles. Today, I\u2019ll share how I handled routing and querying WPGraphQL.&nbsp;<\/p>\n\n\n\n<p>If you\u2019re unfamiliar with Astro, scan their <a href=\"https:\/\/astro.build\/\" target=\"_blank\" rel=\"noreferrer noopener\">home page<\/a> and reference their docs as needed. A working example of what I\u2019m building is also available in the <a href=\"https:\/\/github.com\/wpengine\/hwptoolkit\/tree\/main\/examples\/astro\/template-hierarchy-data-fetching-urql\" target=\"_blank\" rel=\"noreferrer noopener\">wpengine\/hwptoolkit<\/a> repo!<\/p>\n\n\n\n<div class=\"wp-block-group has-polar-background-color has-background is-layout-flow wp-container-core-group-is-layout-7a03825d wp-block-group-is-layout-flow\" style=\"padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--40);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--40)\">\n<p class=\"has-large-font-size\"><strong>Table of Contents<\/strong><\/p>\n\n\n\n<ul id=\"Prerequisites\" class=\"wp-block-list\">\n<li><a href=\"#routing\">Routing <\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#basics-of-the-template-hierarchy\">Basics of the Template Hierarchy<\/a><\/li>\n\n\n\n<li><a href=\"#template-hierarchy-in-astro\">Template Hierarchy in Astro<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#catch-all-route\">Catch-All Route<\/a><\/li>\n\n\n\n<li><a href=\"#seed-query\">Seed Query<\/a><\/li>\n\n\n\n<li><a href=\"#calculating-possible-templates\">Calculating the Possible Templates<\/a><\/li>\n\n\n\n<li><a href=\"#creating-available-templates\">Creating Available Templates<\/a><\/li>\n\n\n\n<li><a href=\"#choosing-a-template\">Choosing A Template<\/a><\/li>\n\n\n\n<li><a href=\"#putting-it-all-together\">Putting it All Together<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#querying-data\">Querying Data<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#graphql-client\">GraphQL Client<\/a><\/li>\n\n\n\n<li><a href=\"#fetching-data-with-urql\">Fetching Data with URQL<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#conclusion\">Conclusion<\/a><\/li>\n<\/ul>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"routing\">Routing<\/h2>\n\n\n\n<p>Routing between WordPress and a headless app can be surprisingly complex. WordPress is unique in this aspect due to its opinionated nature. Myself and others on my team have recently written extensively on the complexities of <a href=\"https:\/\/github.com\/wpengine\/hwptoolkit\/blob\/main\/docs\/explanation\/routing.md\" target=\"_blank\" rel=\"noreferrer noopener\">routing<\/a> if you want to read more.&nbsp;<\/p>\n\n\n\n<p>You need to know now that teaching your frontend to route and template like the <a href=\"https:\/\/developer.wordpress.org\/themes\/basics\/template-hierarchy\/\" target=\"_blank\" rel=\"noreferrer noopener\">WordPress Template Hierarchy<\/a> has some significant advantages. We implemented this in <a href=\"https:\/\/faustjs.org\/docs\/tutorial\/learn-faust\/#template-hierarchy\" target=\"_blank\" rel=\"noreferrer noopener\">Faust,<\/a> but it has some drawbacks due to how Next.js works.&nbsp;<\/p>\n\n\n\n<p>Astro\u2019s flexibility and server-first model made implementing WordPress-style routing and templating a breeze with no drawbacks.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"basics-of-the-template-hierarchy\">Basics of the Template Hierarchy<\/h3>\n\n\n\n<p>The template hierarchy in WordPress can be complex and confusing.&nbsp;<\/p>\n\n\n\n<p>If you&#8217;re from the WordPress world and understand how its routing works\u2014great! You&#8217;ll still benefit from this section by learning how routing typically works in most JavaScript frameworks. For everyone else who may not be as familiar with WordPress routing, don&#8217;t worry\u2014let\u2019s break it down and make sense of it together.<\/p>\n\n\n\n<p>Most JavaScript-based meta-frameworks route using \u201cFile System\u201d routing. The specifics vary, but the idea is that the names of the files and folders determine what is rendered at a given route. Astro is <a href=\"https:\/\/docs.astro.build\/en\/guides\/routing\/#:~:text=Astro%20uses%20file%2Dbased%20routing,project%20src%2Fpages%2F%20directory.\" target=\"_blank\" rel=\"noreferrer noopener\">no exception<\/a>. File system routers make some assumptions, though.&nbsp;<\/p>\n\n\n\n<p>A given route is tied to a specific piece or type of data (e.g., blog posts) and template (e.g., all data at that route should be rendered roughly in a single way). For the route <code>\/blog\/[slug].astro<\/code>, the <code>[slug].astro<\/code> template renders a blog post as fetched by <code>slug<\/code> the same way it renders every other blog post. File system routing is robust and suited to solve the unique problems of JS web apps.<\/p>\n\n\n\n<p>WordPress flips this flow because it thinks about data first. A given post or page can be at any route and rendered with a variety of templates. The <a href=\"https:\/\/wordpress.org\/documentation\/article\/customize-permalinks\/\" target=\"_blank\" rel=\"noreferrer noopener\">WP Permalinks<\/a> system determines the full route (URI) of the content and the Template Hierarchy determines, based on the data, configuration, and available templates (templates are provided by a theme in WordPress). Only then is a page rendered. This system is extremely flexible and powerful.&nbsp;<\/p>\n\n\n\n<p>Practically, this flow does look a little different. When a request for <code>\/blog\/a-blog-post<\/code> comes into a WordPress site, the server only has that URI\u2014it doesn\u2019t magically know the data. WordPress uses the permalink system to look up the associated piece of data before choosing a template and rendering the page.&nbsp;<\/p>\n\n\n\n<p>This is the flow we\u2019ll have to mimic in Astro. URI =&gt; Data =&gt; Template =&gt; Render: Data + Template.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"template-hierarchy-in-astro\">Template Hierarchy in Astro<\/h3>\n\n\n\n<p>In Astro, this will look like 6 distinct steps:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Getting the URI<\/li>\n\n\n\n<li>Making a \u201cSeed Query\u201d to WordPress to fetch template data<\/li>\n\n\n\n<li>Collecting available templates for rendering<\/li>\n\n\n\n<li>Calculating possible templates the data could use<\/li>\n\n\n\n<li>Figuring out which of the available templates to use based on the prioritized order of most to least specific possible templates<\/li>\n\n\n\n<li>Fetching more data from WordPress to actually render the template<\/li>\n<\/ol>\n\n\n\n<p><\/p>\n\n\n\n<p>Does your brain hurt? Sorry, all will be explained.&nbsp;&nbsp;<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"catch-all-route\">Catch-All Route<\/h4>\n\n\n\n<p>We need the URI, the whole thing, not just a sub-path. This is easy in Astro with a catch-all route <code>pages\/[...uri].astro<\/code>.&nbsp;<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"seed-query\">Seed Query<\/h4>\n\n\n\n<p>We\u2019ll then need to fetch the data associated with that URL. The good news is that WPGraphQL has the perfect tool for the job!<br><\/p>\n\n\n<pre class=\"wp-block-code language-gql\" 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>query SeedQuery($uri: String!) {\n<\/span><\/span><span class='shcb-loc'><span>  nodeByUri($uri) {\n<\/span><\/span><span class='shcb-loc'><span>\u00a0   __typename\n<\/span><\/span><span class='shcb-loc'><span>\u00a0   id\n<\/span><\/span><span class='shcb-loc'><span>\u00a0   ... on ContenNode {\n<\/span><\/span><span class='shcb-loc'><span>\u00a0\u00a0\u00a0\u00a0  slug\n<\/span><\/span><span class='shcb-loc'><span>\u00a0   }\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-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><\/p>\n\n\n\n<p>This is an extremely simplified version of the Seed Query. The <a href=\"https:\/\/github.com\/wpengine\/hwptoolkit\/blob\/main\/examples\/astro\/template-hierarchy-data-fetching-urql\/example-app\/src\/lib\/seedQuery.js#L7-L84\" target=\"_blank\" rel=\"noreferrer noopener\">full Seed Query<\/a> I\u2019m using in the example implementation has to handle all content in WordPress with a URI (posts, pages, custom posts, taxonomies, authors, etc), even if it\u2019s unpublished draft content. This is the same seed query used by Faust.&nbsp;<\/p>\n\n\n\n<p>All that aside, now that the data has been retrieved from WordPress, we can determine what template to render. This is where things get complicated.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"calculating-possible-templates\">Calculating the Possible Templates<\/h4>\n\n\n\n<p>We have a data set from our seed query. But what template will render this data?&nbsp;<\/p>\n\n\n\n<p>In the case of the seed query, we could simply ask WordPress. But there is no easy WordPress functionality to get this data. My example uses the <a href=\"https:\/\/github.com\/wpengine\/hwptoolkit\/blob\/main\/examples\/astro\/template-hierarchy-data-fetching-urql\/example-app\/src\/lib\/templates.ts#L30-L166\" target=\"_blank\" rel=\"noreferrer noopener\">function we built for Faust<\/a> to take the data from the seed query and generate a list of possible templates. This list is in order of most specific to least specific. For a page, this looks like: <code>[page-sample-page, page-2, page, singular, index]<\/code>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"creating-available-templates\">Creating Available Templates<\/h4>\n\n\n\n<p>To render this WordPress data, we need a template, and unless we want them all to look identical, we have to break out of the file system router. Our one catch-all route needs to be able to render multiple templates.<\/p>\n\n\n\n<p>The logical assumption here might be to use a switch statement or key\/value pairs to select from a variety of registered templates. This is how Faust works.&nbsp;<\/p>\n\n\n\n<p>While this will work technically, there are issues with bundling. File system routes bundle code on a per-route basis. In Next.js this means the JS for all routes are in a single bundle due to the use of a catch-all route.&nbsp;<\/p>\n\n\n\n<p>Astro has <a href=\"https:\/\/github.com\/withastro\/astro\/issues\/8223\" target=\"_blank\" rel=\"noreferrer noopener\">similar bundling issues<\/a> (technically, if you don\u2019t ship any JS, this isn\u2019t an issue, but that\u2019s an unlikely scenario in reality). Because of this, standard JavaScript won\u2019t work. We need to work with the file system router to get bundling to work correctly.<\/p>\n\n\n\n<p>The solution is to use \u201crewrites\u201d. Rewrites are a web server term. If you\u2019re running a web server like Apache and use a basic setup to serve PHP or HTML you\u2019ll notice all your routes look like <code>\/about.html<\/code> or <code>\/blog-post.php?slug=headless-wordpress-rocks<\/code>.&nbsp;<\/p>\n\n\n\n<p>These aren\u2019t \u201cpretty\u201d. Rewrites let me configure Apache to serve <code>\/about.html<\/code> when a request comes in for <code>\/about<\/code>. Or a request for <code>\/blog\/headless-wordpress-rocks<\/code> to ask the PHP for <code>\/blog-post.php?slug=headless-wordpress-rocks<\/code> and to serve that. <\/p>\n\n\n\n<p>These are distinct from more common \u201credirects\u201d because we don\u2019t tell the browser to look somewhere else. Rewriting renders something other than what was requested without changing the URL.&nbsp;<\/p>\n\n\n\n<p>Rewrites let our catch-all route determine what template to use and rewrite the user&#8217;s request to the template route. So my <a href=\"https:\/\/github.com\/wpengine\/hwptoolkit\/tree\/main\/examples\/astro\/template-hierarchy-data-fetching-urql\/example-app\/src\/pages\/\" target=\"_blank\" rel=\"noreferrer noopener\">routes in Astro<\/a> now look like this:&nbsp;<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span>pages\/\n<\/span><\/span><span class='shcb-loc'><span>\u00a0\u00a0\u21b3\u00a0 &#91;...uri].astro\n<\/span><\/span><span class='shcb-loc'><span>\u00a0\u00a0\u21b3\u00a0 wp-templates\/\n<\/span><\/span><span class='shcb-loc'><span>      \u21b3\u00a0 index.astro\n<\/span><\/span><span class='shcb-loc'><span>      \u21b3\u00a0 home.astro\n<\/span><\/span><span class='shcb-loc'><span>      \u21b3\u00a0 archive.astro\n<\/span><\/span><span class='shcb-loc'><span>      \u21b3\u00a0 single.astro\n<\/span><\/span><\/code><\/span><\/pre>\n\n\n<p><\/p>\n\n\n\n<p>I now have 4 available templates. One issue here is someone could accidentally route directly to <code>\/wp-templates\/home<\/code> or any of these routes. To solve for this I have <a href=\"https:\/\/github.com\/wpengine\/hwptoolkit\/blob\/main\/examples\/astro\/template-hierarchy-data-fetching-urql\/example-app\/src\/pages\/wp-templates\/archive.astro#L4-L17\">a check<\/a> at the top of all templates to make sure this isn\u2019t the case, if it is, I rewrite to a 404 page.<\/p>\n\n\n\n<p>Finally, we don\u2019t want to hard code available templates into our JS code because it\u2019s cumbersome and error-prone. I chose to use Astro\u2019s <a href=\"https:\/\/docs.astro.build\/en\/guides\/content-collections\/\" target=\"_blank\" rel=\"noreferrer noopener\">Content Collections<\/a> feature to easily <a href=\"https:\/\/github.com\/wpengine\/hwptoolkit\/blob\/main\/examples\/astro\/template-hierarchy-data-fetching-urql\/example-app\/src\/content.config.ts#L7-L30\" target=\"_blank\" rel=\"noreferrer noopener\">read available templates<\/a> directly from the file system.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"choosing-a-template\">Choosing a template<\/h4>\n\n\n\n<p>We now have a list of possible templates and a list of available templates. Based on the prioritized list of possible templates, we can determine which of the available templates to use.&nbsp;<\/p>\n\n\n\n<p>A <a href=\"https:\/\/github.com\/wpengine\/hwptoolkit\/blob\/main\/examples\/astro\/template-hierarchy-data-fetching-urql\/example-app\/src\/lib\/templates.ts#L168-L184\" target=\"_blank\" rel=\"noreferrer noopener\">quick bit of JavaScript<\/a> can compare the list of possible templates (<code>[single-post-sample-post, single-post, single, singular, index]<\/code>) to the list of available templates (<code>[archive, home, archive, single]<\/code>) and the first match is our template. In this case \u201csingle\u201d is the winner!<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"putting-it-all-together\">Putting it all together<\/h4>\n\n\n\n<p>Now that we\u2019ve built all the pieces, we can put this into a <a href=\"https:\/\/github.com\/wpengine\/hwptoolkit\/blob\/main\/examples\/astro\/template-hierarchy-data-fetching-urql\/example-app\/src\/lib\/templateHierarchy.ts#L20-L79\" target=\"_blank\" rel=\"noreferrer noopener\">single function<\/a> that takes a URI and returns the template. Our <a href=\"https:\/\/github.com\/wpengine\/hwptoolkit\/blob\/main\/examples\/astro\/template-hierarchy-data-fetching-urql\/example-app\/src\/pages\/%5B...uri%5D.astro\" target=\"_blank\" rel=\"noreferrer noopener\">catch-all route<\/a> now looks something like this:<\/p>\n\n\n<pre class=\"wp-block-code lagnuages-js\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span>---\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-comment\">\/\/ ...<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> { uri = <span class=\"hljs-string\">\"\/\"<\/span> } = Astro.params <span class=\"hljs-keyword\">as<\/span> Params;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> results = <span class=\"hljs-keyword\">await<\/span> uriToTemplate({ uri });\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">if<\/span> (results.template) {\n<\/span><\/span><span class='shcb-loc'><span>\u00a0\u00a0<span class=\"hljs-keyword\">return<\/span> Astro.rewrite(results.template.path);\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-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><\/p>\n\n\n\n<p>The specifics look slightly different depending on whether you\u2019re server rendering at build time or on request. The full example shows rendering statically at build time.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"querying-data\">Querying Data&nbsp;<\/h2>\n\n\n\n<p>Routes are routing and our frontend is happily relying on the WordPress template hierarchy to route. Now, we want to render data, but our seed query didn\u2019t have much in it! We could expand that query, but this isn\u2019t recommended.&nbsp;<\/p>\n\n\n\n<p>While it is possible to get a lot of data from a single GraphQL request, this lowers caching hit rates. We\u2019d rather make several specific queries to GraphQL that are highly cachable than one large query that has a low cache hit rate due to being constantly invalidated. So, we\u2019re going to want to query data for each template.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"graphql-client\">GraphQL Client<\/h3>\n\n\n\n<p>There are plenty of great GraphQL clients out there, like Apollo. I chose <a href=\"https:\/\/nearform.com\/open-source\/urql\/\" target=\"_blank\" rel=\"noreferrer noopener\">URQL<\/a> for this demo to learn something new and for its minimalist approach. URQL is an excellent choice with plenty of advanced features that can be added if your project demands. It paired great with Astro!<\/p>\n\n\n\n<p>Once you <a href=\"https:\/\/github.com\/wpengine\/hwptoolkit\/blob\/main\/examples\/astro\/template-hierarchy-data-fetching-urql\/example-app\/src\/lib\/client.js\" target=\"_blank\" rel=\"noreferrer noopener\">set up a client<\/a> you can use that client across Astro to fetch data.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"fetching-data-with-urql\">Fetching Data with URQL<\/h3>\n\n\n\n<p>Luckily this is Astro, whether page or component, I can easily make asynchronous calls to fetch data!<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span>---\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-comment\">\/\/ \u2026<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> { data, error } = <span class=\"hljs-keyword\">await<\/span> client.query(\n<\/span><\/span><span class='shcb-loc'><span>\u00a0\u00a0gql<span class=\"hljs-string\">`<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">\u00a0\u00a0\u00a0\u00a0query MyQuery($variable: String!) {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0# ...Whatever I need<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">\u00a0\u00a0\u00a0\u00a0}<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">\u00a0\u00a0`<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>\u00a0\u00a0{\n<\/span><\/span><span class='shcb-loc'><span>\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-attr\">variable<\/span>: \u201cexample\u201d\n<\/span><\/span><span class='shcb-loc'><span>\u00a0\u00a0}\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\">if<\/span> (error) {\n<\/span><\/span><span class='shcb-loc'><span>\u00a0\u00a0<span class=\"hljs-built_in\">console<\/span>.error(<span class=\"hljs-string\">\"Error fetching data:\"<\/span>, error);\n<\/span><\/span><span class='shcb-loc'><span>\u00a0\u00a0<span class=\"hljs-keyword\">return<\/span> Astro.rewrite(<span class=\"hljs-string\">\"\/500\"<\/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-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><\/p>\n\n\n\n<p>If you need more data, remember to keep queries specific, one or more queries can be made in parallel:<\/p>\n\n\n<pre class=\"wp-block-code\" 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>---\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-comment\">\/\/ ...<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> &#91;query1Results, query2Results] = <span class=\"hljs-built_in\">Promise<\/span>.all(&#91;\n<\/span><\/span><span class='shcb-loc'><span>\u00a0\u00a0client.query(query1,variables1),\n<\/span><\/span><span class='shcb-loc'><span>\u00a0\u00a0client.query(query2,variables2),\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-comment\">\/\/ ...<\/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-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><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"conclusion\">Conclusion<\/h2>\n\n\n\n<p>Astro\u2019s ability to fetch data from any page or component, combined with its programmatic rewrites, makes it a dreamy framework for working with headless WordPress.&nbsp;<\/p>\n\n\n\n<p>We\u2019ve done so without breaking bundling or only being allowed large, difficult-to-cache queries. We can query only the data we need to drive a specific functionality on our site. Whether rendering at build (SSG) or request (SSR), this enables us to quickly get the data we need with high cache hit rates, leveraging WPGraphQL Smart Cache.&nbsp;<\/p>\n\n\n\n<p>My review: I love it! I\u2019m stoked on Astro and the developer experience it provides for working with headless WordPress.&nbsp;<\/p>\n\n\n\n<p>There are so many more cool features I haven\u2019t been able to address yet (e.g., form handling for WordPress Comments, content collections for advanced data fetching, etc.), so stay tuned\u2014I\u2019ll be writing more soon!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Are you interested in building a headless WordPress site using Astro? Astro makes for an amazing developer experience with headless WordPress. Learn how we handled routing and data fetching using WPGraphQL! <\/p>\n","protected":false},"author":25,"featured_media":31843,"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-31842","post","type-post","status-publish","format-standard","has-post-thumbnail","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>Astro + WordPress: Routing and GraphQL - Builders<\/title>\n<meta name=\"description\" content=\"Are you interested in building a headless WordPress site using Astro? Astro makes for an amazing developer experience with headless WordPress. Learn how we handled routing and data fetching using WPGraphQL!\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/wpengine.com\/builders\/astro-wordpress-routing-and-graphql\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Astro + WordPress: Routing and GraphQL\" \/>\n<meta property=\"og:description\" content=\"Are you interested in building a headless WordPress site using Astro? Astro makes for an amazing developer experience with headless WordPress. Learn how we handled routing and data fetching using WPGraphQL!\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wpengine.com\/builders\/astro-wordpress-routing-and-graphql\/\" \/>\n<meta property=\"og:site_name\" content=\"Builders\" \/>\n<meta property=\"article:published_time\" content=\"2025-04-11T19:51:03+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-05-13T16:28:31+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2025\/04\/WPE-Builders-Best-JavaScript-Frameworks-for-Headless-WordPress-2024-1920x1080@2x-1024x554.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"554\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Alex Moon\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@moon_meister\" \/>\n<meta name=\"twitter:site\" content=\"@wpebuilders\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Alex Moon\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/astro-wordpress-routing-and-graphql\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/astro-wordpress-routing-and-graphql\\\/\"},\"author\":{\"name\":\"Alex Moon\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#\\\/schema\\\/person\\\/868e9d9f8b846000f45cc7a25f46255a\"},\"headline\":\"Astro + WordPress: Routing and GraphQL\",\"datePublished\":\"2025-04-11T19:51:03+00:00\",\"dateModified\":\"2025-05-13T16:28:31+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/astro-wordpress-routing-and-graphql\\\/\"},\"wordCount\":1785,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/astro-wordpress-routing-and-graphql\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/Capture-Apr-11-2025.png\",\"articleSection\":[\"Headless\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/wpengine.com\\\/builders\\\/astro-wordpress-routing-and-graphql\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/astro-wordpress-routing-and-graphql\\\/\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/astro-wordpress-routing-and-graphql\\\/\",\"name\":\"Astro + WordPress: Routing and GraphQL - Builders\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/astro-wordpress-routing-and-graphql\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/astro-wordpress-routing-and-graphql\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/Capture-Apr-11-2025.png\",\"datePublished\":\"2025-04-11T19:51:03+00:00\",\"dateModified\":\"2025-05-13T16:28:31+00:00\",\"description\":\"Are you interested in building a headless WordPress site using Astro? Astro makes for an amazing developer experience with headless WordPress. Learn how we handled routing and data fetching using WPGraphQL!\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/astro-wordpress-routing-and-graphql\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/wpengine.com\\\/builders\\\/astro-wordpress-routing-and-graphql\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/astro-wordpress-routing-and-graphql\\\/#primaryimage\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/Capture-Apr-11-2025.png\",\"contentUrl\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/Capture-Apr-11-2025.png\",\"width\":1872,\"height\":958},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/astro-wordpress-routing-and-graphql\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Astro + WordPress: Routing and GraphQL\"}]},{\"@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\\\/868e9d9f8b846000f45cc7a25f46255a\",\"name\":\"Alex Moon\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/e751c6c4033ab32c97e38f1c218b0f11070378a7c7b797539c497ca289b4f205?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/e751c6c4033ab32c97e38f1c218b0f11070378a7c7b797539c497ca289b4f205?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/e751c6c4033ab32c97e38f1c218b0f11070378a7c7b797539c497ca289b4f205?s=96&d=mm&r=g\",\"caption\":\"Alex Moon\"},\"description\":\"Alex Moon is a Developer Advocate at WP Engine. He's been working in Open Source for over a decade and headless WordPress since the early days of WP GraphQL. When he's not writing code he's often found in the mountains or sailing the seas. Follow him on X or Bluesky for more headless WordPress goodness!\",\"sameAs\":[\"https:\\\/\\\/gurugoes.net\",\"https:\\\/\\\/x.com\\\/moon_meister\"],\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/author\\\/alexmoon-2-2-2-2-2-2-2-2-2-2-2-2-2-2\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Astro + WordPress: Routing and GraphQL - Builders","description":"Are you interested in building a headless WordPress site using Astro? Astro makes for an amazing developer experience with headless WordPress. Learn how we handled routing and data fetching using WPGraphQL!","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/wpengine.com\/builders\/astro-wordpress-routing-and-graphql\/","og_locale":"en_US","og_type":"article","og_title":"Astro + WordPress: Routing and GraphQL","og_description":"Are you interested in building a headless WordPress site using Astro? Astro makes for an amazing developer experience with headless WordPress. Learn how we handled routing and data fetching using WPGraphQL!","og_url":"https:\/\/wpengine.com\/builders\/astro-wordpress-routing-and-graphql\/","og_site_name":"Builders","article_published_time":"2025-04-11T19:51:03+00:00","article_modified_time":"2025-05-13T16:28:31+00:00","og_image":[{"width":1024,"height":554,"url":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2025\/04\/WPE-Builders-Best-JavaScript-Frameworks-for-Headless-WordPress-2024-1920x1080@2x-1024x554.png","type":"image\/png"}],"author":"Alex Moon","twitter_card":"summary_large_image","twitter_creator":"@moon_meister","twitter_site":"@wpebuilders","twitter_misc":{"Written by":"Alex Moon","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/wpengine.com\/builders\/astro-wordpress-routing-and-graphql\/#article","isPartOf":{"@id":"https:\/\/wpengine.com\/builders\/astro-wordpress-routing-and-graphql\/"},"author":{"name":"Alex Moon","@id":"https:\/\/wpengine.com\/builders\/#\/schema\/person\/868e9d9f8b846000f45cc7a25f46255a"},"headline":"Astro + WordPress: Routing and GraphQL","datePublished":"2025-04-11T19:51:03+00:00","dateModified":"2025-05-13T16:28:31+00:00","mainEntityOfPage":{"@id":"https:\/\/wpengine.com\/builders\/astro-wordpress-routing-and-graphql\/"},"wordCount":1785,"commentCount":0,"publisher":{"@id":"https:\/\/wpengine.com\/builders\/#organization"},"image":{"@id":"https:\/\/wpengine.com\/builders\/astro-wordpress-routing-and-graphql\/#primaryimage"},"thumbnailUrl":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2025\/04\/Capture-Apr-11-2025.png","articleSection":["Headless"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/wpengine.com\/builders\/astro-wordpress-routing-and-graphql\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/wpengine.com\/builders\/astro-wordpress-routing-and-graphql\/","url":"https:\/\/wpengine.com\/builders\/astro-wordpress-routing-and-graphql\/","name":"Astro + WordPress: Routing and GraphQL - Builders","isPartOf":{"@id":"https:\/\/wpengine.com\/builders\/#website"},"primaryImageOfPage":{"@id":"https:\/\/wpengine.com\/builders\/astro-wordpress-routing-and-graphql\/#primaryimage"},"image":{"@id":"https:\/\/wpengine.com\/builders\/astro-wordpress-routing-and-graphql\/#primaryimage"},"thumbnailUrl":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2025\/04\/Capture-Apr-11-2025.png","datePublished":"2025-04-11T19:51:03+00:00","dateModified":"2025-05-13T16:28:31+00:00","description":"Are you interested in building a headless WordPress site using Astro? Astro makes for an amazing developer experience with headless WordPress. Learn how we handled routing and data fetching using WPGraphQL!","breadcrumb":{"@id":"https:\/\/wpengine.com\/builders\/astro-wordpress-routing-and-graphql\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wpengine.com\/builders\/astro-wordpress-routing-and-graphql\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wpengine.com\/builders\/astro-wordpress-routing-and-graphql\/#primaryimage","url":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2025\/04\/Capture-Apr-11-2025.png","contentUrl":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2025\/04\/Capture-Apr-11-2025.png","width":1872,"height":958},{"@type":"BreadcrumbList","@id":"https:\/\/wpengine.com\/builders\/astro-wordpress-routing-and-graphql\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/wpengine.com\/builders\/"},{"@type":"ListItem","position":2,"name":"Astro + WordPress: Routing and GraphQL"}]},{"@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\/868e9d9f8b846000f45cc7a25f46255a","name":"Alex Moon","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/e751c6c4033ab32c97e38f1c218b0f11070378a7c7b797539c497ca289b4f205?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/e751c6c4033ab32c97e38f1c218b0f11070378a7c7b797539c497ca289b4f205?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/e751c6c4033ab32c97e38f1c218b0f11070378a7c7b797539c497ca289b4f205?s=96&d=mm&r=g","caption":"Alex Moon"},"description":"Alex Moon is a Developer Advocate at WP Engine. He's been working in Open Source for over a decade and headless WordPress since the early days of WP GraphQL. When he's not writing code he's often found in the mountains or sailing the seas. Follow him on X or Bluesky for more headless WordPress goodness!","sameAs":["https:\/\/gurugoes.net","https:\/\/x.com\/moon_meister"],"url":"https:\/\/wpengine.com\/builders\/author\/alexmoon-2-2-2-2-2-2-2-2-2-2-2-2-2-2\/"}]}},"_links":{"self":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/posts\/31842","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\/25"}],"replies":[{"embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/comments?post=31842"}],"version-history":[{"count":0,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/posts\/31842\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/media\/31843"}],"wp:attachment":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/media?parent=31842"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/categories?post=31842"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/tags?post=31842"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}