7 Thoughts From 7 Years of Headless WordPress Development

I’ve been working with headless WordPress for about 7 years now, first at AppPresser working on mobile apps, and now at GoDaddy working with Ecommerce.

The things I’ve learned can’t be distilled into one blog post, but these are the most important ideas that can trip you up when starting a new project.

wtf is headless

Headless means we are building something that doesn’t live in WordPress, that needs to communicate with WordPress through an API. Examples:

  • a mobile app (React Native, Ionic, etc.)
  • a single page app on the web (React, Vue, etc) that is inside an iframe, like a checkout modal or a chat widget
  • a React admin interface for a plugin
  • a static frontend for your WP site using NextJS, Astro, Gatsby, etc.

You can build some fast, beautiful experiences with headless technology, but it doesn’t come without trade-offs.

1. Customization

Customizing WordPress doesn’t work the same way in a headless environment. Themes, the customizer, plugins, widgets, menus, permalinks, and other standard options don’t work out of the box.

You are not loading a theme or any plugins, so you won’t get the stylesheet or theme options you are used to. You can’t use actions and filters in the same way, and things like shortcodes may not parse correctly.

Your headless app lives in its own world, completely separate from WordPress. If a client asks you to make their headless site look exactly like their theme, they need to understand these are two separate things. When they change a color in the customizer, or make their logo bigger, it doesn’t automatically show up on their headless site.

This is not to say you can’t customize things, you could put all the theme colors into an API and grab those in your app. You just have to build a way to do that yourself. It’s a trade-off.

2. Plugins don’t work

In a headless app, you can’t just add a plugin to give your site a new feature.

If you build a static frontend with something like NextJS, and you have a Gravity Form, it will not work on your static site out of the box. Same with WooCommerce and every other plugin. You must build the whole thing from scratch, meaning you have to create a form on your static site, then send and receive data from WordPress using APIs.

This is all doable, but it might be surprising if you are used to the plug-and-play nature of WordPress plugins.

3. No scripts, CSS, or form processing

One of the reasons plugins don’t work is because you are not loading any plugin scripts or CSS files in your app. You are also not using any WordPress form processing, so anything with a page reload like a contact form does not work.

This means you have to rebuild the UI entirely, including styles and interactivity. In the case of a form, you need to create your own inputs, drop downs, validation, saving data, error states, API requests to submit the form, etc.

Don’t expect the form styles and validation on your site to magically work in your app, you will be starting from scratch.

4. You can use REST or GraphQL

To send and receive data, you need an API.

WordPress has a built in REST API, you can also use a plugin like WPGraphQL (my personal favorite). Some plugins have their own APIs, like WooCommerce.

The plugins that support APIs are a mixed bag. Most of them don’t support any API, and if they do it might be a custom API. It’s almost exclusively REST, I don’t know of any major plugin that has official support for GraphQL. (That doesn’t mean you can’t use WPGraphQL, I am!)

I’ve worked with the REST API for years, and after creating dozens of custom endpoints, I really like the GraphQL method. With GraphQL you only have one endpoint, and you can get back only the data you request. There’s a bit of a learning curve, but it’s a popular technology so it’s worth your time.

5. You will need to customize the APIs

No matter what API you choose, you probably won’t have all the data you need. Most projects require customizing the APIs, especially if you are dealing with plugin data.

For example, if you are building an appointment scheduling app, you will need custom post types and post meta to display scheduled events. Then you need a way to handle creating a new appointment from the app. None of that exists out of the box with WordPress, so you need to add data to the API responses, then create your own way to push to the database.

With the REST API, you can customize responses, or create your own endpoints. With WPGraphQL, you can register new fields, or create your own queries and mutations.

6. Authentication can be tricky

WordPress uses nonces and cookies for authentication. If you are building an app that is completely separate from the site, such as a mobile app, you will need to use custom authentication.

JWT is the easiest way to do this, but it is not always appropriate. Sometimes you may need to use OAuth instead.

If you are building an app that lives in WordPress, such as a React admin interface for a plugin, you will still be able to use cookie authentication. If you are using the REST API, you can add a wp_rest nonce to a localized script, then send that in your API calls. (Anything that is not same-domain cannot use nonces at all)

WPGraphQL authentication works in a similar way.

7. Ecommerce is even trickier

Let’s say you are building a headless site that shows products from WooCommerce and allows people to purchase them.

You need to fetch products, with variations and everything else. (Just dealing with variations and attributes alone is a big task). Then you need to deal with the cart, and checking out. The cart isn’t so bad, but checking out gets tricky. You could send all the data to WordPress and checkout the normal way, that’s the easiest method. If you want to handle checkout on the headless side, you have a lot of work to do, godspeed.

That’s what I’ve been working on for the past several months, maybe I’ll write an article in the future on how to handle checkout completely on the headless side.

Why, why, why?

You may be thinking, if it’s that hard, what kind of insane person would want to do this, and why?

The answer is that these trade-offs are worth it in many cases. In other cases, like a mobile app, there is simply no other way to do it.

In the world of front-end development, the things I mentioned are par for the course. They are no big deal. It’s only coming from WordPress-land that any of this is surprising.

Here are some great use cases for headless:

  • any single page app like mobile
  • a reactive form builder in the WordPress admin
  • offline product catalog
  • a static website
  • a frontend for multiple backends, like WordPress + Shopify + Salesforce
  • lots more…

If you’re like me, building frontends is a ton of fun, and that’s reason enough.