Skip to content
Marc Boisvert-Dupras

WordPress, Remix & GraphQL

Posted in Tutorial, WordPress 6 minutes read

So, as it often does, what started as a simple discussion at work turned into a fun little weekend project.

We’ve been exploring different architectures for our projects and one that as been of particular interest to me is using WordPress as a content API to be consumed inside of a Single Page App.

I’ve also been meaning to find a reason to sharpen my React & GraphQL knowledge and also try out Remix. Thus came the idea to rebuild my personal website using the aforementioned technologies. So, let’s get on with it.

Table of contents

  1. Motivation
  2. Downsides
  3. Implementation
  4. Conclusion
  5. Further reading

Why not just go for the standard way of doing things?

While WordPress has improved over the years, there are still a number of things that could be improved about it, for example security and performance.

One could for example completely isolate their WordPress instance from the outside world through firewall rules and make only the API endpoints available for client consumption.

On the performance side, there’s only so much that can be done with various levels of caching. Using a modern Javascript framework to render our frontend application enables a whole new set of opportunities to optimize content delivery, for example distributing our app to the edge giving us incredibly easy dynamic scaling.

In addition to this, in the case of Remix, we benefit from a fullstack application framework where we can essentially do anything a regular full-fledged framework like Laravel or Rails can do. Therefore, we’re not limited to using one data source like WordPress for our content, we could effectively gather content from multiple sources and integrate them seamlessly throughout our app.

We could even use a completely different authentication layer to authorize our application users and not expose our WordPress instance with something like Auth0.

The downsides of using WordPress as a Headless CMS

Of course it’s not all so simple. One of the major downsides of using WordPress as a headless CMS is losing the ability to use actions, filters and plugins to directly alter template as you would traditionally do.

Unfortunately, this also extends to certain Gutenberg blocks although a WPGraphQL plugin exists to partially address this problem.

Similarly, handling SEO can seem a bit tricky at first however we have a number of solutions at our disposal. One of the simpler approaches would be to use custom fields on our Posts, fetch this data through our GraphQL API and finally manually set our meta & SEO tags however we like. With Remix, this means exporting a MetaFunction and configuring the relevant properties. Other solutions exist too, for example using the Yoast SEO plugin with the corresponding WPGraphQL extension.

Personally, my main issue with this architecture lies with using WooCommerce. While not a problem on this particular site, it is a problem for client projects mainly due to the fact that as far as I know, the whole checkout process isn’t API friendly yet and this complicates things a bit. Of course you could always roll out your own checkout flow using something like Stripe Elements.


Time to take a look at how all this comes together. Let’s start with setting up our content API.


I started by spinning up (pun intended) a new WordPress installation on SpinupWP. This takes care of configuring a secure environment on my Vultr instance ready for production.

Next, I installed the following plugins:

At this point, feel free to configure WPGraphQL to your liking or stick to the defaults. Do note your GraphQL endpoint if you choose to change it.


Next, let’s set-up our Remix application. Start by initializing a new project and choosing the Vercel deployment target.

npx create-remix@latest
cd your-project-nameCode language: CSS (css)

Next, we’ll install some packages to communicate with our GraphQL API.

npm i -D @apollo/client graphqlCode language: CSS (css)

Once that’s done, let’s set-up our Apollo Client. Start by creating a directory at the root level of your project. In my case, I named it graphql. Then we can create a new file named client.ts (or .js if that’s what you’re using!) and paste the following to create our client. Don’t forget to change your endpoint uri!

import { ApolloClient, InMemoryCache } from "@apollo/client";

export const client = new ApolloClient({
    uri: `https://your-wordpress-endpoint.test/graphql`,
    cache: new InMemoryCache()
});Code language: JavaScript (javascript)

Finally, in our routes/index.tsx file we can import our client and start loading some posts from WordPress. Here’s a basic example of how we might do that.

import { useLoaderData } from "@remix-run/react";
import { client } from "graphql/client";
import { gql } from "@apollo/client";

const POSTS_QUERY = gql`
    posts(first: 10, after: null, where: { status: PUBLISH, orderby: [{ field: DATE, order: DESC }] }) {
      edges {
        node {
          categories {
            edges {
              node {
      pageInfo {

export const loader = async () => {
  const res = await client.query({
    query: POSTS_QUERY,

  return res;

export default function Posts() {
  const { data } = useLoaderData();
  const posts = data?.posts.edges;

  return (
    {posts.length > 0 && Post) => (
}Code language: JavaScript (javascript)

That’s all! We should now have some posts loaded into our route. For a more complete example, feel free to check out the repository for this site!

Wrapping up

Using WordPress as a headless CMS in conjunction with modern frontend technologies like React, GraphQL, and Remix opens up a wealth of opportunities for developers to build powerful, scalable, and flexible applications. By leveraging these technologies, we can enhance the performance, security, and maintainability of our projects while providing a seamless content delivery experience to our users.

However, it is important to recognize and address the challenges that come with this approach, such as losing the ability to directly modify templates using actions, filters, and plugins, as well as handling SEO and eCommerce functionality. With the right tools, solutions, and ingenuity, these challenges can be overcome, allowing developers to fully harness the potential of this architecture.

This fun weekend project has not only provided an opportunity to learn and grow as a developer, but also served as a testament to the power and versatility of combining WordPress with modern frontend technologies. We encourage you to explore this approach for your own projects, and hope that our implementation example serves as a useful starting point on your journey. Happy coding!

Further reading