Headless WordPress with Astro
Astro's islands make it a lighter headless front end than Next.js for content sites. Here is the data layer, the build strategy and the trade-offs.

In this article
Most headless WordPress tutorials assume the front end is Next.js. That makes sense for application-like sites, but most WordPress work is brochure sites, blogs and marketing pages: mostly static content with a few interactive pieces. For that kind of site, shipping a full React runtime to every visitor is more machinery than the content needs.
Astro was built for exactly this case. It renders pages to plain HTML and only sends JavaScript for the components you mark as interactive. This guide covers how I set up Astro against a WordPress back end, how content stays fresh, and where Astro becomes awkward enough that I would choose something else.
Why islands beat full hydration for a content site
A React framework typically renders the page on the server and then hydrates the whole tree in the browser, so the page becomes a running application. Even a page that is ninety per cent text pays for downloading and executing the code for all of it.
Astro inverts that. Every component renders to HTML at build time, and only components given a client directive — client:load, client:idle or client:visible — ship JavaScript and hydrate, each one independently. A blog post with a newsletter form and an image carousel sends JavaScript for those two islands and nothing else. That is how Astro sites routinely pass Core Web Vitals without careful tuning.
It also lets you mix frameworks. An island can be React, Vue, Svelte or plain Astro, which is useful when a client already has a React component they want to keep.
Fetching at build time: REST or WPGraphQL
The WordPress REST API works with no extra plugins. Posts live at /wp-json/wp/v2/posts, and adding _embed includes the featured image, author and terms in one response. It returns at most 100 items per request, so paginate using the X-WP-TotalPages response header rather than assuming one request is enough.
WPGraphQL, a free plugin, lets you ask for exactly the fields each template needs, including related data, in a single query. On sites with many custom fields or relationships it produces smaller responses and fewer requests than REST.
For a straightforward site with posts, pages and a few custom fields, I use REST: it is always there and easy to inspect in a browser. Once a site has complex Advanced Custom Fields data or deep relationships between content types, WPGraphQL earns its plugin slot.
Content collections and typing the WordPress response
Astro's content layer lets you define a collection with a loader — an async function that fetches entries from anywhere and returns them with an id. Point a loader at WordPress, and posts become a collection you query with getCollection and getEntry, exactly like local Markdown.
Give the collection a schema with Zod. WordPress responses are loosely shaped: titles arrive as objects with a rendered property, featured images may be missing, and custom fields depend on plugin settings. Declaring the shape once means a missing field fails the build with a clear message instead of rendering undefined on a live page.
Map the response into a cleaner shape in the loader — title, slug, date, excerpt, html, image, categories — so templates never need to know what WordPress's raw JSON looks like.
- Render post content with the set:html directive. The HTML comes from your own WordPress editors, so treat the WordPress admin as a trusted boundary and restrict who can post unfiltered HTML.
- Load WordPress's block library styles or your own equivalents. Without them, Gutenberg columns, buttons and galleries render unstyled.
- Rewrite internal links in post content from the WordPress domain to the front-end domain, so links between posts stay on the Astro site.
- Add the WordPress media domain to Astro's allowed image domains if you want Astro's image component to optimise remote images.
Rebuild triggers from a WordPress save hook
A static Astro site only changes when it is rebuilt, so the editor's experience depends on rebuilds happening automatically. Netlify, Vercel and Cloudflare Pages all provide deploy hooks: a secret URL that starts a new build when it receives a POST.
On the WordPress side, a small plugin hooks transition_post_status and calls the deploy hook with wp_remote_post when a post is published, updated or unpublished. Debounce it — schedule a single event a minute or two out and skip scheduling if one is pending — so an editor saving ten times in five minutes triggers one build, not ten.
Build times grow with content. A few hundred posts build in well under a minute, but sites with thousands of pages should consider rendering low-traffic archive pages on demand rather than at build time.
Where Astro gets awkward
- Previews. Editors expect the Preview button to show a draft. With a static site there is no draft page to show, so you need one server-rendered preview route, using an adapter and an application password to fetch the draft from WordPress.
- Search. There is no database query to run at visit time. Pagefind, which indexes the built HTML and searches it in the browser, works very well for content sites. WordPress's REST search endpoint called from an island is the alternative.
- Forms. Contact forms need somewhere to post: a form service, a serverless function or a REST endpoint on the WordPress side.
- Gated and personalised content. Memberships, logged-in dashboards and anything per-user need server rendering for those routes, and the more of the site that becomes, the less Astro's static model helps.
When to reach for Next.js instead
Astro is my default for headless WordPress when the site is mostly content: marketing pages, blogs, documentation, portfolios. Next.js is the better choice when the front end behaves like an application — user accounts, carts and checkout, dashboards, heavy client-side state — or when the team already works in React every day and wants one framework everywhere.
Before going headless at all, ask whether the site needs it. A well-built traditional WordPress theme is cheaper to run and simpler to edit. Headless with Astro is worth it when performance, security isolation or a multi-channel content model justifies running two systems instead of one.
Frequently asked questions
Is Astro a good front end for headless WordPress?
Yes, for content-led sites such as blogs, marketing sites and portfolios. Astro renders pages to static HTML and ships JavaScript only for interactive components, so sites are fast by default. It is a weaker fit for application-style sites with accounts, carts or heavy personalisation.
How does Astro compare to Next.js for a WordPress site?
Astro sends far less JavaScript because it hydrates only the islands you mark as interactive, which suits content sites. Next.js hydrates the whole page and has stronger support for dynamic, logged-in and application-like features. Choose Astro for content, Next.js for app-like behaviour.
Can Astro rebuild automatically when a post is published?
Yes. Create a deploy hook URL on your host, such as Netlify, Vercel or Cloudflare Pages, and have a small WordPress plugin call it on transition_post_status when content is published or updated. Debounce the call so several quick saves trigger one build.
Does Astro support WordPress previews?
Not out of the box on a fully static site. Add a server-rendered preview route using an Astro adapter, fetch the draft from WordPress with an application password, and point WordPress's preview link at that route.
Should I use the REST API or WPGraphQL with Astro?
Use the REST API for simple sites, because it needs no extra plugin and is easy to debug. Use WPGraphQL when you have many custom fields or related content types, because one query can fetch exactly what each template needs.