HeadstartWP — Guide to Headless WordPress


HeadstartWP is a comprehensive Next.js solution for headless WordPress sites. Learn how to set up, configure & solve some common issues.


Pressed for time but still want the lowdown on HeadstartWP? Here’s a quick overview of what you need to know to get started with the best headless WordPress framework:

  • Headless solution that pairs WordPress, React.js & Next.js
  • It’s completely free & open source
  • Includes multisite & draft preview support
  • Built-in support for translation & native support for the Polylang plugin
  • Route mapping utilizing Next.js’ catch-all routes feature
  • All the Next.js rendering options (SSG, ISR & SSR)
  • Huge performance advantages
  • A Content Block API that allows easy rendering of Gutenberg blocks

Getting Setup Quick

npx create-next-app --use-npm -e https://github.com/10up/headstartwp/tree/trunk/projects/wp-nextjs

It’s here! HeadstartWP

HeadstartWP: WordPress Headless

Hey there, WordPress gurus! Are you ready for something exciting? Because I’ve been bouncing off the walls waiting to introduce you to our supercharged solution for WordPress sites – HeadstartWP!

Brought to you by the wizards at 10up — I’m proud to call myself a team member, HeadstartWP is a game-changing headless solution that pairs the world’s most popular CMS, WordPress, with the unstoppable force of Next.js, the most widely used React.js framework​. And get this – it’s free and open source!

Packed with Power

What makes HeadstartWP so unique? Let me spill the beans. The headless team poured years of experience, expertise, and lessons learned from supporting countless headless sites into creating HeadstartWP, providing you with a toolbox full of goodies that makes decoupled site building a breeze​. It’s like they’ve given you a magic wand that effortlessly conjures up multisites, handles translations with ease, gives you a sneak peek at your draft content before publishing, and so much more​.

When it comes to headless WordPress implementation, consider HeadstartWP your essential Swiss Army knife. Starting off, it’s impressively lightweight yet robust, providing exactly what you need without any unnecessary fluff. Moving forward, it shines in its performance optimization, seamlessly supporting all the Next.js rendering patterns that you’ve grown to love, thereby significantly boosting your PageSpeed scores. Finally, let’s not overlook its innate multilingual capabilities, effortlessly opening up your website to a truly global audience. In short, with HeadstartWP, you’ve got the complete package.

Completely Infrastructure Agnostic

Here’s the real kicker about HeadstartWP – it’s completely infrastructure agnostic. That’s right! With this level of flexibility, you’re free to deploy your site wherever you see fit. Perhaps you’re more comfortable with a managed platform such as WordPress VIP or WP Engine? Or maybe you prefer to utilize your own AWS or Azure stack? Heck, you can even opt for a blend of both. With HeadstartWP, you’re firmly in the driver’s seat, empowered to navigate the route that aligns best with your needs.

Already used and loved by some of the world’s most well-known and high-traffic brands, HeadstartWP is constantly evolving with every iteration, making it one of the best solutions for headless WordPress implementation​. And trust me, this is just the beginning. So, buckle up, and let’s embark on this headless WordPress journey with HeadstartWP together!

Behind the Code: The Guiding Philosophy of HeadstartWP

Ready to delve further into what makes HeadstartWP tick? This framework isn’t a haphazard creation that popped up out of the blue. In fact, the formation and evolution of HeadstartWP has been driven by a key set of principles. So, let’s pause for a moment to appreciate these guiding lights that are integral to the uniqueness of HeadstartWP.

Using a Proven Foundation

First off, 10up doesn’t believe in reinventing the wheel. Why should they, when there’s a rock-solid foundation already available? That’s right, folks, I’m talking about Next.js. It’s the top-dog, full-stack React framework that has won the hearts of developers all over the world. It was chosen to build HeadstartWP on this solid ground, allowing focus on what 10up does best: solving the challenges of creating headless WordPress sites​.

HeadstartWP Reduces Complexity

The main goal of HeadstartWP was to reduce the complexity of building headless sites. 10up wanted to make creating headless WordPress sites as easy as pie, similar to creating traditional WordPress sites. The aim was to save developers the headache of having to figure out how to wire up the Next.js application with WordPress, and instead, let them focus on the important aspects of the site​.

The Sky’s the Limit

But 10up’s not just about making things easier. They’re also about pushing boundaries and exploring new possibilities. It’s all about sparking creativity and letting engineers discover new ways of building and scaling sites. With HeadstartWP, you can do everything from shipping component libraries for brand consistency and code reuse, to building complex app-like experiences. You can leverage the power of serverless technology or even host completely at the Edge. The world is your oyster when you go headless with HeadstartWP.

Low Cost

What’s more, 10up has designed HeadstartWP to be a thin layer that interacts with WordPress, built on top of a solid foundation. This means maintenance costs are kept low, as the most complex parts are handled by Next.js, which is maintained by the innovative folks at Vercel, with a little help from their friends at Google.

HeadstartWP Keeps it Simple

Finally, 10up is all about keeping things simple. Currently, HeadstartWP doesn’t work with WPGraphQL. While GraphQL is great for the right projects, it doesn’t always add value for most headless sites and can introduce additional complexity and engineering time. That said, 10up might add support for GraphQL in future releases, but for now, they’re keeping our stack straightforward and effective.

Quick Start with HeadstartWP

Feeling eager to jumpstart your journey with HeadstartWP? Well, you’re in for a treat because setting up HeadstartWP is a breeze! Just a few steps and you’ll be all set.

Before we dive into it, let’s talk about system requirements. You’ll need:

  • Node.js 16 or later
  • NPM version 7 or above
  • WordPress 5.9 or higher (earlier versions might work, but haven’t been tested)

Here’s how you get started:

First, if you’re new to Next.js, take a look at the Next.js docs. It will give you a solid understanding of the foundation HeadstartWP is built on.

After that, the quickest way to get rolling with HeadstartWP is by using create-next-app with the official starter project. Here’s the command you need:

npx create-next-app --use-npm -e https://github.com/10up/headstartwp/tree/trunk/projects/wp-nextjs

Once the project is set up, run npm run dev in your terminal, and voila! You can then open your newly created HeadstartWP site at http://localhost:3000 in your browser.

Environment Variables

A quick note on environment variables: the starter project will point to js1.10up.com by default. If you need to point to a different location, change the NEXT_PUBLIC_HEADLESS_WP_URL variable, or create a .env.local file to override the default environment variables. And if you’re developing locally using HTTPS with WordPress and don’t have valid certificates, make sure to add NODE_TLS_REJECT_UNAUTHORIZED=0 to avoid any hiccups.

And just like that, you’re on your way to creating amazing headless WordPress sites with HeadstartWP!​

HeadstartWP Fresh Install

We’re going to set up HeadstartWP in a spanking new Next.js project. It’s like moving into a clean, unfurnished apartment and making it your own with your unique style! The end goal? Having a project that’s primed and ready for you to create your magic.

Alright, let’s move on to step one – setting up your Next.js project! This is all about getting your Next.js project off the ground.

Install the Headstart WordPress Plugin

First things first, we’re going to install a super handy plugin that’ll make our headless WordPress site work seamlessly with our new setup. Let’s dive right in!

The best way to install this plugin is using Composer. It’s a tool for dependency management in PHP, and it makes installing plugins a breeze. Here’s how you do it:

composer require headstartwp/headstartwp

To set up the path for installing this as a WordPress Plugin, you’ll need to add the following to your composer.json file:

  "name": "your-vendor-name/your-project-name",
  "require": {
    "composer/installers": "^1.0",
    "headstartwp/headstartwp": "^1.0.0",
  "extra": {
    "installer-paths": {
      "plugins/{$name}/": [
  "config": {
    "allow-plugins": {
      "composer/installers": true

Manual Install

If you’re not a fan of Composer, no worries. You can also install the plugin manually. All you need to do is download the plugin’s zip file, move it to wp-content/plugins in your WordPress directory, and then activate the plugin from your WordPress admin dashboard.

Configuring the WordPress Headless Plugin

After you’ve installed and activated the plugin, it’s time to configure it.

First, you need to tell the plugin where your front-end site is located. To do this, go to your WordPress admin dashboard and click on Settings -> General. Scroll down until you find the Headless Frontend URL field. Enter the URL for your headless site in this field.

Headless WordPress Plugin

And there you have it! Your HeadstartWP plugin is now set up and ready to rock ‘n roll.

Setting Up Your Next.js Project

First things first, you gotta fire up your terminal and type in this command:

npx create-next-app@latest --use-npm

Boom! Just like that, you’ve got the latest version of create-next-app installed in your project using npm. It’s like the starter dough for your Next.js project.

But wait, we’re not done yet! To make this project really come alive, we need to install a couple more packages. Think of these as the secret ingredients to your recipe. Here’s the command you need:

npm install --save @headstartwp/core @headstartwp/next

With this command, you’re adding the @headstartwp/core and @headstartwp/next packages to your project. These packages are the backbone of your HeadstartWP framework, bringing in all the goodness that it has to offer.

Creating Your headless.config.js

Now that we’ve got our Next.js project and essential packages all setup, it’s time to dive into the next part of our journey. Let’s create a new file at the root of our project called headless.config.js.

Think of headless.config.js as the instruction manual that guides our HeadstartWP framework. It tells the framework how to behave and interact with our Next.js project.

Pop open your code editor, and let’s get to work on this new file. Here’s what you’ll want to type into headless.config.js:

 * Headless Config
 * @type {import('@headstartwp/core').HeadlessConfig}
module.exports = {
    sourceUrl: process.env.NEXT_PUBLIC_HEADLESS_WP_URL,

    useWordPressPlugin: true,

As you can see, this file is exporting a configuration object. The sourceUrl property is where you’ll want to put the URL of your WordPress site. You can put this URL in an environment variable called NEXT_PUBLIC_HEADLESS_WP_URL.

The useWordPressPlugin property is set to true, which means we’re telling our project to use the WordPress plugin. This plugin is a powerful tool that lets you use WordPress as a headless CMS with your Next.js project.

Creating & Configuring Your .env File

Alright, you’ve been doing awesome so far! Now let’s move on to the next stage in our step one: dealing with environment variables.

You’re probably like, “Wait, what are environment variables?” Well, they’re kind of like the secret codes that your app needs to work properly. They hold crucial data like API keys, database passwords, and in our case, the URL of your WordPress site.

Let’s start by creating a .env file (or you can use a .env.local file if you prefer) in the root of your project. Here’s what you should put in it:


This is the URL of your WordPress site. You can replace https://my-wordpress.test with your actual site’s URL.

By the way, you can name this environment variable whatever you like! Just remember to update the sourceUrl property in your headless.config.js file to match the name of your new environment variable.

One more thing! If you’re developing on your local machine and your WordPress site uses HTTPS but doesn’t have a valid certificate, you might run into some issues. But don’t worry, I’ve got a quick fix for you! Just add this line to your .env file:


This tells Node.js to ignore the self-signed certificate error and lets you carry on with your work uninterrupted.

Setting Up Your next.config.js File

Awesome job on setting up those environment variables! Now, let’s dive into the next part of step one: creating your next.config.js file.

Think of next.config.js as the brains behind your Next.js project. It’s where you specify your custom configuration settings, which helps tailor your project to your specific needs.

Grab your code editor, because we’re about to create a new file. Here’s what you should type into your next.config.js file:

const { withHeadlessConfig } = require('@headstartwp/next/config');
const headlessConfig = require('./headless.config');

 * Update whatever you need within the nextConfig object.
 * @type {import('next').NextConfig}
const nextConfig = {};

module.exports = withHeadlessConfig(nextConfig, headlessConfig);

First, we’re bringing in the withHeadlessConfig function from the @headstartwp/next/config package. We’re also importing our headless.config.js file that we created earlier.

Then, we’re creating an object called nextConfig. You can put any custom configurations you need for your Next.js project in this object.

Finally, we’re exporting the result of calling the withHeadlessConfig function with nextConfig and headlessConfig as arguments. This merges your custom Next.js configuration with the HeadstartWP configuration.

Building Your HeadstartWP _app.js File

Now that we’ve got our environment variables and configuration files all set, it’s time to create a custom _app.js file. This file is like the master switch that controls all the pages in your Next.js project. We’re going to wrap our entire application with the HeadlessApp component from the @headstartwp/next package.

Let’s get into the nitty-gritty of creating this file. Here’s what you’ll want to type into your src/pages/_app.js file:

import { HeadlessApp } from '@headstartwp/next';
import Link from 'next/link';
import Router from 'next/router';

import '../styles.css';

const MyApp = ({ Component, pageProps }) => {
    // only HeadlessApp needs fallback and themeJson, so we remove them from the props we pass down to the pages

    // eslint-disable-next-line react/prop-types, no-unused-vars
    const { fallback = {}, themeJson = {}, ...props } = pageProps;

    return (
                // instruct the framework to use Next.js link component or your own version
                linkComponent: Link,
            <Component {...props} />

export default MyApp;

In this file, we’re importing the HeadlessApp component, the Link component from next/link, and the Router from next/router. We’re also importing our main CSS file.

Then we’re defining a function called MyApp that takes an object as a parameter. This object includes Component and pageProps. Inside this function, we’re removing fallback and themeJson from pageProps and passing the rest of the props down to the pages.

Finally, we’re returning the HeadlessApp component, which wraps around the Component that represents the current page. We’re passing pageProps and a settings object to HeadlessApp. In settings, we’re setting linkComponent to Link, which tells the framework to use the Next.js link component.

Creating Your Preview Endpoint

You’re doing fantastic! Now let’s step into the next part of our setup journey: setting up the preview endpoint.

In simple terms, a preview endpoint allows you to take a sneak peek at your content before it goes live. The HeadstartWP WordPress plugin expects this preview endpoint to be at /api/preview.

Let’s get to work and enable support for previews! We’re going to create a new file at src/pages/api/preview.js. Here’s what you should type into this file:

import { previewHandler } from '@headstartwp/next';

 * The Preview endpoint just needs to proxy the default preview handler
 * @param {*} req Next.js request object
 * @param {*} res  Next.js response object
 * @returns
export default async function handler(req, res) {
    return previewHandler(req, res);

First, we’re importing the previewHandler function from the @headstartwp/next package.

Then, we’re defining an asynchronous function called handler that takes two parameters: req (the Next.js request object) and res (the Next.js response object). This function simply calls the previewHandler function with req and res as arguments.

Creating Your Revalidate Endpoint

Rocking on! Now, let’s tackle the next part of our setup process: setting up the revalidate endpoint. This one’s pretty cool because it supports Incremental Static Regeneration (ISR) revalidation, which is triggered by WordPress. ISR allows you to update static pages after they’ve been generated, which is super handy for keeping your content fresh!

But before we can use this nifty feature, you need to make sure you’ve got the WordPress plugin enabled and the ISR option activated in your WordPress settings.

HeadstartWP Revalidate

Once that’s done, it’s time to create a new file at src/pages/api/revalidate.js. Here’s what you should type into this file:

import { revalidateHandler } from '@headstartwp/next';

 * The revalidate endpoint just needs to proxy the default revalidate handler
 * @param {*} req Next.js request object
 * @param {*} res  Next.js response object
 * @returns
export default async function handler(req, res) {
    return revalidateHandler(req, res);

First, we’re importing the revalidateHandler function from the @headstartwp/next package.

Next, we’re defining an asynchronous function called handler that takes two parameters: req (the Next.js request object) and res (the Next.js response object). This function simply calls the revalidateHandler function with req and res as arguments.

Creating Your HeadstartWP First Route

Well, look at you, almost at the finish line! The next step is creating your first route. This is where the magic happens – we’re going to create a catch-all route called pages/[...path].js. This route will be responsible for rendering individual posts and pages. Pretty neat, right?

By setting up a [...path].js route, the HeadstartWP framework will automatically detect and extract URL parameters from the path argument. It’s like having your own personal detective, searching for clues in your URL paths!

Here’s the code you’ll need to create this route:

import {
} from '@headstartwp/next';
import { BlocksRenderer } from '@headstartwp/core/react';

const params = { postType: ['post', 'page' ] };

const SinglePostsPage = () => {
    const { loading, error, data } = usePost(params);

    if (loading) {
        return 'Loading...';

    if (error) {
        return 'error...';

    return (
            <BlocksRenderer html={data.post.content.rendered} />

export default SinglePostsPage;

Once you’ve got that set up, you can visit any single post or page (like http://localhost:3000/hello-world) and voila! You’ll see both the title and the content of that post or page.

And guess what? Date URLs will work too! So you could visit a URL like http://localhost:3000/2022/10/2/hello-world and it’ll work like a charm.

And there you go! You’ve created your first route and your Next.js project with HeadstartWP is looking pretty awesome. You’ve got this!

SSR/SSG: The Final Piece of HeadstartWP

Alrighty, we’re almost there! The last bit of setup we need to do is adding support for Server-Side Rendering (SSR) and Static Site Generation (SSG). Remember that single post route we created earlier? Well, it’s fetching data on the client side right now, which is alright but not ideal. We want our data to be fetched on the server side, and that’s where SSR/SSG come into play.

What we need to do is add the following code to our pages/[...path].js file:

// or export async function getServerSideProps(context)
export async function getStaticProps(context) {
    try {
        // make sure to pass the same params to fetchHookData and usePost
        const usePostData = await fetchHookData(usePost.fetcher(), context, { params });

        return addHookData([usePostData], {});
    } catch (e) {
        return handleError(e, context);

Here’s what’s happening in this code:

  1. We’re exporting an asynchronous function named getStaticProps. It’s one of Next.js’s data fetching methods that lets us fetch data at build time.
  2. Inside the function, we’re trying to fetch hook data using the fetchHookData function and usePost.fetcher() as parameters. We’re also passing in the current context and the parameters we defined earlier.
  3. We then return the fetched data using addHookData.
  4. If there are any errors during this process, we handle them using the handleError function.

Once you’ve added this to your file, go ahead and refresh your page. Bam! Your data is now being fetched on the server side. You’ve successfully set up your HeadstartWP project. Give yourself a pat on the back – you did great!


I encountered an error message Error: The Edge Function "src/middleware" is referencing unsupported modules... during deployment. How can I resolve this issue?

Error: The Edge Function "src/middleware" is referencing unsupported modules:

- index.js: ./resvg.wasm?module, ./yoga.wasm?module

NOW_SANDBOX_WORKER_EDGE_FUNCTION_UNSUPPORTED_MODULES: The Edge Function "src/middleware" is referencing unsupported modules:	- index.js: ./resvg.wasm?module, ./yoga.wasm?module

This error is typically caused by a compatibility problem with the Next.js version you are using, particularly version 13.4.4. To fix it, you should consider upgrading to the latest available version, which is 13.4.7 as of the time of writing this.

Error: The Edge Function "src/middleware" is referencing unsupported modules:
	- index.js: ./resvg.wasm?module, ./yoga.wasm?module
NOW_SANDBOX_WORKER_EDGE_FUNCTION_UNSUPPORTED_MODULES: The Edge Function "src/middleware" is referencing unsupported modules:	- index.js: ./resvg.wasm?module, ./yoga.wasm?module

$ npm i next@latest

Why am I getting Unsupported engine with running npm install?

Encountering the Unsupported engine error while running npm install typically occurs when you’re trying to install a package that requires a different version of Node.js or npm than what is currently installed on your system. To resolve this, update your Node.js or npm to the required version (>=v16) by checking your current version with node -v or npm -v in your terminal. Consider using NVM (Node Version Manager) to manage multiple Node.js versions on your system for seamless compatibility. Install NVM, run nvm install 16, and then nvm use 16.

When running composer install to install the HeadstartWP plugin, why do I get "./composer.json" does not match the expected JSON schema?

If you encounter the error message “./composer.json” does not match the expected JSON schema when running composer install to install the HeadstartWP plugin, the most probable reason is that you haven’t added the vendor prefix for the name property in your composer.json file. Make sure that the name property follows the format of headstartwp/project-name rather than just your-project-name. Adding the appropriate vendor prefix should resolve the issue and allow the installation to proceed smoothly.

Why am I getting The lock file is not up to date with the latest changes in composer.json. when running composer install for the HeadstartWP plugin?

If you encounter the error message The lock file is not up to date with the latest changes in composer.json while running composer install for the HeadstartWP plugin, you can resolve it by running composer update. This command ensures that the lock file is updated to match the latest changes in the composer.json file. Running composer update will synchronize the dependencies and bring everything up to date, allowing you to proceed with the installation smoothly.

Why is the HeadstartWP plugin getting installed in the vendor directory instead of the plugins directory?

This usually occurs if the composer/installers package isn’t included in your composer.json file. This package facilitates the customization of installation paths for specific package types, such as wordpress-plugin.

Frequently Asked Questions

Alright, we’ve covered a lot of ground so far. You’ve done a fantastic job keeping up! But, I bet there are still a few questions buzzing around in your mind regarding this headless WordPress framework. Don’t worry, it’s completely normal.

Does HeadstartWP support WPGraphQL?

At the moment, HeadstartWP and WPGraphQL aren’t on speaking terms. Although GraphQL is a fantastic tool for certain projects, it can sometimes add an extra layer of complexity that isn’t really necessary for most headless sites. Plus, it can also extend the time it takes to develop your project. That being said, the folks at 10up haven’t ruled out the possibility of integrating GraphQL in the future. But for now, their goal is to keep your stack simple, efficient, and effective.

Wrapping Up

So, are you ready to ride the wave of the headless revolution with HeadstartWP? With its rock-solid foundation powered by 10up, an unwavering commitment to simplicity, and a zest for exploring new frontiers, you’re all geared up to create the website you’ve always envisioned.

Now that you’ve mastered the art of setting up HeadstartWP, why not take your skills up a notch? Have a look at my comprehensive guide on how to integrate Storybook with HeadstartWP. It’s a great combo that works wonders together.

And if you’re all done with your project and itching to get it live, remember we’ve got you covered. Dive into my step-by-step guide to effortlessly deploy your HeadstartWP project to Vercel. Happy coding with HeadstartWP, my friend!

Share Your Thoughts

Your email address will not be published. Required fields are marked *

Latest Articles