Mathias Ahlgren
Posted on June 27, 2024
Here, I'm diving into the exciting world of headless WordPress and Astro. If you're looking to combine the content management power of WordPress with the blazing-fast performance of a static site generator, you're in for a treat. Let's get started!
Introduction
So, what's all this fuss about headless WordPress and Astro? Well, imagine taking WordPress's fantastic content management capabilities and pairing them with a modern, lightning-fast front end. That's exactly what we're doing here!
Headless WordPress means we're using WordPress solely as a backend, handling all our content creation and management. Meanwhile, Astro steps in as our front-end superhero, delivering that content to users with incredible speed and flexibility.
Why bother with this setup? Simple: you get the best of both worlds. Content editors can stick with the familiar WordPress interface, while developers can build a blazing-fast, SEO-friendly frontend using modern tools and frameworks. It's a win-win!
Before we dive in, I've got a hot tip for you: check out AstroWP - headless WordPress starter kit. It's an awesome resource that can jumpstart your headless WordPress project with Astro. While we'll be building our site from scratch in this tutorial, AstroWP is definitely worth exploring if you want to hit the ground running on future projects.
Prerequisites
Before we jump in, let's make sure you've got everything you need:
- A WordPress installation (don't worry, we'll cover this)
- Basic knowledge of JavaScript and React (we'll be using some React components)
- Node.js and npm installed on your machine
- Familiarity with the command line (nothing too scary, I promise!)
Got all that? Great! Let's dive in.
Setting Up WordPress
First things first, let's get WordPress up and running:
If you haven't already, install WordPress on your favorite web host. There are tons of great guides out there if you need help with this step.
Once WordPress is installed, log into your admin panel and head to the Plugins section. You need to install a crucial plugin called WPGraphQL. This nifty tool exposes your WordPress data through a GraphQL API, which we'll use to fetch content for our Astro site.
Search for "WPGraphQL" in the plugin directory, install it, and activate it. Easy peasy!
Now, let's create some sample content. Add a few blog posts and pages so we have something to work with. Don't stress about making it perfect – we're just testing things out.
Alright, our WordPress setup is good to go. Time to switch gears and set up Astro!
Setting Up Astro
Now for the fun part – let's get Astro up and running:
Open up your terminal and navigate to where you want your project to live.
Run the following command to create a new Astro project:
npm create astro@latest
Follow the prompts to set up your project. When asked about the template, choose "Empty" for now.
Once the installation is complete, cd into your new project directory and run:
npm install
This will install all of the needed dependencies.
npm run dev
This starts the development server and gives you a local preview of your site.
- Open up your browser and navigate to
http://localhost:4321
. You should see a blank Astro site. Not very exciting yet, but we're about to change that!
Take a moment to explore the project structure. You'll see a src
folder with pages
and components
subdirectories. This is where we'll be spending most of our time.
Connecting Astro to WordPress
Now that we have both WordPress and Astro set up, it's time to introduce them to each other:
- First, we need to install a few dependencies. Run the following command:
npm install @astrojs/react react react-dom
- Next, let's configure Astro to use React components. Open up your
astro.config.mjs
file and add the React integration:
import { defineConfig } from 'astro/config';
import react from "@astrojs/react";
export default defineConfig({
integrations: [react()]
});
- Now, we need to set up our environment variables. Create a new file in your project root called
.env
and add the following:
WP_URL=https://your-wordpress-site.com/graphql
Replace https://your-wordpress-site.com
with your actual WordPress site URL.
Great job! We've now got the groundwork laid for our headless WordPress + Astro site. In the next section, we'll start fetching data from WordPress and displaying it in our Astro site. Exciting times ahead!
Fetching Data from WordPress
Alright, now we're getting to the good stuff. Let's fetch some data from WordPress and display it in our Astro site:
First, let's create a new file in the
src/pages
directory calledindex.astro
. This will be our homepage.Open up
index.astro
and add the following code:
---
const response = await fetch(import.meta.env.WP_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `
query HomePagePosts {
posts(first: 5) {
nodes {
title
excerpt
slug
}
}
}
`
})
});
const json = await response.json();
const posts = json.data.posts.nodes;
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>My Headless WordPress Site</title>
</head>
<body>
<h1>Welcome to My Blog</h1>
<ul>
{posts.map((post) => (
<li>
<h2>{post.title}</h2>
<p set:html={post.excerpt}></p>
<a href={`/posts/${post.slug}`}>Read more</a>
</li>
))}
</ul>
</body>
</html>
This code does a few things:
- It sends a GraphQL query to our WordPress site to fetch the latest 5 posts.
- It then takes that data and renders it in a simple HTML structure.
- Save the file and check out your Astro dev server. You should now see your WordPress posts displayed on the page!
Pretty cool, right? We're now pulling data from WordPress and displaying it in our Astro site. But we can do even better. In the next section, we'll set up dynamic routing to create individual pages for each of our blog posts.
Creating Dynamic Routes
Now that we've got our posts showing up on the homepage, let's create individual pages for each post:
Create a new file in
src/pages
calledposts/[slug].astro
. The square brackets in the filename tell Astro that this is a dynamic route.Open
[slug].astro
and add the following code:
---
export async function getStaticPaths() {
const response = await fetch(import.meta.env.WP_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `
query AllPosts {
posts {
nodes {
slug
}
}
}
`
})
});
const json = await response.json();
const posts = json.data.posts.nodes;
return posts.map((post) => {
return {
params: { slug: post.slug },
props: { slug: post.slug },
};
});
}
const { slug } = Astro.props;
const response = await fetch(import.meta.env.WP_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `
query SinglePost($slug: ID!) {
post(id: $slug, idType: SLUG) {
title
content
}
}
`,
variables: {
slug: slug,
}
})
});
const json = await response.json();
const post = json.data.post;
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>{post.title}</title>
</head>
<body>
<h1>{post.title}</h1>
<div set:html={post.content}></div>
<a href="/">Back to Home</a>
</body>
</html>
This code does a few important things:
- The
getStaticPaths
function fetches all post slugs from WordPress and tells Astro to create a page for each one. - We then fetch the specific post data for each page and render it.
- Now, if you click on the "Read more" links on your homepage, you should be taken to individual post pages!
Awesome work! We've now got a fully functional headless WordPress site built with Astro. Of course, there's always room for improvement. In the next sections, we'll look at styling our site and optimizing its performance.
Styling Your Astro Site
Now that we've got our content displaying correctly, let's make it look a bit nicer:
Astro supports several styling options out of the box. For this tutorial, we'll use Astro's built-in CSS support.
Create a new file in
src/styles
calledglobal.css
.Add some basic styles to
global.css
:
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
h1, h2 {
color: #2c3e50;
}
a {
color: #3498db;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
- Now, let's import this CSS file in our pages. In both
index.astro
andposts/[slug].astro
, add this line in the<head>
section:
<link rel="stylesheet" href="/styles/global.css" />
- Refresh your browser, and you should see a much nicer-looking site!
Remember, this is just a starting point. Feel free to expand on these styles and make the site your own!
Optimizing Performance
One of Astro's big selling points is its focus on performance. Let's take advantage of some of Astro's features to make our site even faster:
Astro uses partial hydration, which means it only sends JavaScript to the browser when it's needed. This is great for performance, but we haven't actually used any client-side JavaScript yet. If you need interactivity, you can use Astro's client directives like
client:load
orclient:idle
on your components.For image optimization, Astro has a built-in Image component. Let's use it for our post thumbnails. First, install the sharp package:
npm install sharp
- Then, in your
index.astro
file, import the Image component and use it for your post thumbnails:
---
import { Image } from 'astro:assets';
// ... rest of your frontmatter code
---
<!-- In your HTML -->
<Image src={post.featuredImage.node.sourceUrl} width={300} height={200} alt={post.title} />
Note: You'll need to modify your GraphQL query to fetch the featured image data.
- Astro also automatically optimizes your CSS and HTML. It removes unused CSS and minifies your HTML in production builds.
Deployment
We're in the home stretch! Let's get your site deployed:
- First, build your site with:
npm run build
This will create a
dist
folder with your production-ready site.You can deploy this folder to any static hosting service. Netlify and Vercel are popular options that work great with Astro.
If you're using Netlify, you can simply drag and drop your
dist
folder onto their site to deploy.For automated deployments, you can set up a GitHub repository for your project and connect it to your hosting service. Then, every time you push to your main branch, your site will automatically rebuild and deploy.
Summary
And there you have it! We've successfully set up a headless WordPress site with Astro. We've covered everything from initial setup to deployment, touching on data fetching, routing, styling, and performance optimization along the way.
Remember, this is just the beginning. There's so much more you can do with this setup. You could add custom post types, implement search functionality, or even turn your site into a full-fledged e-commerce platform.
I hope this tutorial has been helpful and has sparked some ideas for your own projects. Happy coding!
Troubleshooting Common Issues
Before we wrap up, let's quickly address some common issues you might run into:
CORS errors: If you're getting CORS errors when trying to fetch data from WordPress, you may need to install a CORS plugin in WordPress or configure your server to allow cross-origin requests.
GraphQL errors: Double-check your query syntax if you're getting GraphQL errors. The WPGraphQL plugin provides a GraphiQL interface in the WordPress admin panel where you can test your queries.
Astro build problems: If you're having issues building your Astro site, make sure all your dependencies are up to date. You can also try clearing your
.astro
cache folder.
Remember, the Astro and WordPress communities are very helpful. If you run into any issues you can't solve, don't hesitate to reach out for help!
Posted on June 27, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.