- Jun 10, 2010
- 2,402
- 1,676
Generate a Website using Headless WordPress
I would like to show you a way you can use WordPress as a CMS on your next project, specifically, I am going to use the data from one of my WordPress websites as a headless CMS to generate and build another website. "Headless CMS?" you ask. You might have heard the term headless here, here and here and elsewhere, but what exactly does "headless" mean? A headless cms is a system that lives on the backend that doesn't want to be seen, only consumed. In the WordPress realm, you can think of the WP Admin dashboard where you create posts and pages as the headless piece, and your WP theme that visitors see is the frontend. The frontend of WordPress grabs its data from a database that is populated by the WP admin dashboard, but what I am going to show you below is how I am consuming the data from a WordPress backend and creating a website that does not have anything to do with WordPress.Our Stack
This is the technology stack I will be using:1. CMS - WordPress
2. Frontend - Next JS
3. Hosting - I'm using Vercel
WordPress
Obviously you need a WP install and it could be a local install or one hosted some place remotely. The great thing with WP is they already provide an API endpoint you can call, just add /wp-json/ to the end of any website that uses WP and you will see the available endpoints you can call. My website uses WooCommerce and we could get a listing of products just by adding /wp-json/wc/store/products to the homepage's url. Don't worry, only publicly available information is returned, the same information you would find as if you went to the product site.For my exercise I am going to use WPGraphQL to query my data. It doesn't matter if you choose to use WP's restful API or GraphQL for this, choose whatever you are familiar with. I'm choosing to use GraphQL because it allows me to build the exact data structure I need including any related information such as categories and tags, in a single request without having to make multiple requests to fetch related data. The benefits of GraphQL vs Rest API can be read here.
Install WPGraphQL using their instructions.
(optional) I am also using WooGraphQL since I am using WooCommerce and want to return woo product information.
WPGraphQL gives you a nice GraphQL IDE you can use to build your GraphQL data points that will be used in your frontend application. You will end up copying your GraphQL and using it in a client request on the frontend to fetch the data.
Example:
JSX:
import { fetchAPI } from "./fetch";
export async function getTheme(slug) {
const r = await fetchAPI(
`query Product(
$slug: [String]
) {
products(where: {category: "Themes", slugIn: $slug}) {
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
nodes {
id
name
shortDescription
modified
description
slug
image {
sourceUrl
srcSet
title
}
}
}
}
`,
{
variables: {
slug: [slug],
},
}
);
if (r) {
return r.products;
}
return [];
}
Next JS
With WordPress providing the backend data, I am going to use Next JS to build my frontend, the website. I'm choosing Next JS because of its awesomeness. Next JS is a React framework that allows you to build static websites, web apps, and server side rendering of dynamic web pages. Whereas PHP can only execute on the server and return your web page, Next JS can run anywhere.Install Next JS with Tailwind CSS.
Use the above link to install Next JS and install Tailwind CSS. I'm using Tailwind because it has great default styling and is amazing at building website themes and makes for a great fit for this project.
So far we have WordPress primed and ready to serve our data and now we need to have Next JS query our data. We could build a website that loads and dynamically fetches our products from WP in the browser (client-side), or we could use Next JS's server side rendering to query our product data on each page request and return the generated page, much like how WP and PHP works together. I'm not going to do either. I'm actually going to use Next JS to generate a static HTML website using my WP data. Next JS has the ability during the "build" phase to output static websites and I'm going to instruct Next JS to query my WP data, and build pages for each product.
Here's example code I would have to generate all of my product pages:
JSX:
import React from "react";
//
import Layout from "../components/Layout";
import Item from "../components/Item";
import { getThemes } from "../queries/get-themes";
import { getTheme } from "../queries/get-theme";
export default function Page({ product }) {
return (
<Layout>
<Item item={product?.nodes[0]} />
</Layout>
);
}
export async function getStaticProps(context) {
const product = await getTheme(context.params.slug);
return {
props: { product },
revalidate: 86400,
};
}
export async function getStaticPaths() {
const themes = await getThemes({
first: 100
});
// Get the paths we want to pre-render based on posts
const paths = themes?.nodes.map((theme) => ({
params: { slug: theme.slug },
}));
return { paths, fallback: "blocking" };
}
Working from the bottom up in the code above, we have "getStaticPaths". This method is used to fetch the products I want to build pages for and builds out the URL paths to those product pages. In this example, I'm only returning 100 pages. The "getStaticProps" method is called for each product and returns the product info. So if you went to https://www.nullwpthemes.com/rayden, then "rayden" is passed into getStaticProps and it's product information is returned and then passed into Page({ product }) to generate the page. The product info I am returning is the output of my GraphQL request I built with the product data I needed, which is just a nicely structured JSON object. This is where the beauty of the WPGraphQL IDE comes in because you can return your GraphQL request and see the generate data it will return inside the plugin.
By now you're probably thinking "Great, static sites... my data updates frequently." Next JS has an answer for that, Incremental Static Regeneration. Notice the "revalidate: 86400" option in my getStaticProps method? This tells Next to periodically regenerate static pages on a per-page basis without having to rebuild the entire site each time! This means pages that update daily after they've been published can stay fresh automatically.
So what if you have thousands of pages to build? You could have NextJS build every page which could take a minutes to hours, but I ain't got time fo' that. You can use the power of ISR in Next JS to generate only your critical pages and have the remaining pages generated later if they are landed.
Read more about that and ISR here.
Hosting
Now that we have our website built and ready to deploy we need some place to host it so people can access it. For a pure static HTML site or client-side only application you could host it on any CDN like S3 for dirt cheap and reap the benefits of amazing load times. For any server side rendering you want Next JS to do you will need a server. You could roll your own server but I like to keep costs low so I am choosing Vercel. Vercel is the team behind Next JS and they offer a solution that works seamlessly with Next, and best of all they have a FREE Hobby plan that is perfect for this and they allow you to use a custom domain name with your project.The build process is very nice. If you're using git for your Next JS website, and you should be, you can import your Next JS git repo into Vercel and whenever you push changes into your git repo then Vercel will automatically rebuild your website and make that the latest version. You can also setup preview deployments so you can make changes, deploy to preview, and have your client or stakeholder review the changes before deploying live.