How to deploy Gatsby with WordPress on Platform.sh

Platform.sh maintains a template that you can quickly deploy, and then use this guide as a reference for the Platform.sh specific changes that have been made to Gatsby and WordPress to make it work. Click the button below to sign up for a free trial account and deploy the project.

Deploy on Platform.sh

Shared Platform.sh configuration 

Your local clone of the template has the following project structure:

β”œβ”€β”€ .platform
β”‚   β”œβ”€β”€ routes.yaml
β”‚   └── services.yaml
β”œβ”€β”€ wordpress
β”‚   β”œβ”€β”€ # App code
β”‚   └── .platform.app.yaml
β”œβ”€β”€ gatsby
β”‚   β”œβ”€β”€ # App code
β”‚   └── .platform.app.yaml
└── README.md

From this repository, you deploy a Gatsby app and a WordPress app. The code for each of them resides in their own directories. When deploying a single app project such as Gatsby, the repository needs three configuration files that describe its infrastructure, described below in detail. For multi-app projects, two of those files remain in the project root and are shared between Gatsby and WordPress. Each app keeps its own app configuration file (.platform.app.yaml) in its subdirectory.

.platform/services.yaml 

This file describes which service containers (such as a database) your project should include. Gatsby does not require services to deploy, but WordPress does. So the following examples shows these service configurations:

db:
    type: mariadb:10.4
    disk: 512

.platform/routes.yaml 

This routes.yaml file defines how requests are handled by Platform.sh. The following example shows Gatsby being served from the primary domain and WordPress being accessible from the backend subdomain.

"https://www.{default}/":
  type: upstream
  upstream: "gatsby:http"

"https://{default}/":
    type: redirect
    to: "https://www.{default}/"

"https://backend.{default}/":
    type: upstream
    upstream: "wordpress:http"

WordPress 

The multi-app template has a single modification to Platform.sh’s standard WordPress template: the name attribute in WordPress’s .platform.app.yaml has been updated to wordpress. This value is used to define the relationship between Gatsby and WordPress and in the routes configuration.

Gatsby 

The frontend Gatsby app has a slightly different configuration from the basic Gatsby deployment. Below is the gatsby/.platform.app.yaml file that configures the app.

# .platform.app.yaml

# The name of this application, which must be unique within a project.
name: 'gatsby'

# The type key specifies the language and version for your application.
type: 'nodejs:14'

# Restrict Yarn memory use when running during post deploy hook.
variables:
    env:
        NODE_OPTIONS: --max_old_space_size=1536

# The hooks that will be triggered when the package is deployed.
hooks:
    # Post deploy hook builds Gatsby frontend now that backend content is available.
    post_deploy: |
                npm run build

relationships:
    wordpress: "wordpress:http"

# The size of the persistent disk of the application (in MB).
disk: 1280

# The configuration of the application when it is exposed to the web.
web:
    locations:
        '/':
            # The public directory of the application relative to its root.
            root: 'public'
            index: ['index.html']
            scripts: false
            allow: true

mounts:
  '/.cache':
      source: local
      source_path: cache
  '/.config':
      source: local
      source_path: config
  'public':
      source: local
      source_path: public

In particular, notice:

  • relationships

    Access to another service or app container in the cluster is given through relationships. In this case, one has been defined to the backend WordPress container using it’s name.

  • post_deploy

    Platform.sh containers reside in separate build containers at build time, before their images are moved to the final app container at deploy time. These build containers are isolated and so Gatsby can’t access WordPress during the build hook, where you would normally run the gatsby build command. WordPress isn’t available until after the deploy hook. So the Gatsby build is postponed until the post_deploy hook.

  • mounts

    There are consequences to postponing the Gatsby build, as you don’t generally have write access to the container this late in the pipeline. To allow Gatsby to write to public, that directory has been defined as a mount.

You can then modify gatsby-config.js to read from the backend WordPress container through the wordpress relationship defined above to configure the baseUrl attribute for gatsby-source-wordpress. The plugin requires you to define the protocol, which in this case is http because WordPress content is retrieved through an internal request to the backend container. Also, you need to declare hostingWPCOM: false as you don’t pull data from a WordPress site hosted at wordpress.com.

This is facilitated by Platform.sh’s Config Reader library. So be sure to install this to the Gatsby dependencies first when replicating. When used, Gatsby pulls the information to communicate with the WordPress container on the current branch.

const config = require("platformsh-config").config();

var backend_route = "";
if ( config.isValidPlatform() && !config.inBuild()) {
  require("dotenv").config({
    path: `.env.${process.env.NODE_ENV}`,
  })
  backend_route = config.credentials("wordpress")["host"]
} else {
  require("dotenv").config()
  backend_route = process.env.API_URL;
}

module.exports = {
  siteMetadata: {
    title: `Gatsby + Wordpress on Platform.sh`,
    description: `An example to learn how to source data from WordPress.`,
    author: `@gatsbyjs`,
  },
  plugins: [
    // https://public-api.wordpress.com/wp/v2/sites/gatsbyjsexamplewordpress.wordpress.com/pages/
    /*
     * Gatsby's data processing layer begins with β€œsource”
     * plugins. Here the site sources its data from WordPress.
     */
    {
      resolve: `gatsby-source-wordpress`,
      options: {
        /*
         * The base URL of the WordPress site without the trailingslash and the protocol. This is required.
         * Example : 'demo.wp-api.org' or 'www.example-site.com'
         */
        baseUrl: backend_route,
        // The protocol. This can be http or https.
        protocol: `http`,
        // Indicates whether the site is hosted on wordpress.com.
        // If false, then the assumption is made that the site is self hosted.
        // If true, then the plugin will source its content on wordpress.com using the JSON REST API V2.
        // If your site is hosted on wordpress.org, then set this to false.
        hostingWPCOM: false,
        // If useACF is true, then the source plugin will try to import the WordPress ACF Plugin contents.
        // This feature is untested for sites hosted on WordPress.com
        useACF: true,
      },
    },
    /**
     * The following plugins aren't required for gatsby-source-wordpress,
     * but we need them so the default starter we installed above will keep working.
     **/
    `gatsby-plugin-react-helmet`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        name: `gatsby-starter-default`,
        short_name: `starter`,
        start_url: `/`,
        background_color: `#663399`,
        theme_color: `#663399`,
        display: `minimal-ui`,
        icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
      },
    },
  ],
}

Lastly, the Gatsby app itself needs to include GraphQL queries to handle the data coming from WordPress and create content pages. The most important files in the template you should consult are:

  • gatsby/gatsby-node.js

    Dynamically creates individual pages from the data source using Gatsby’s Node API. It retrieves all of WordPress’s posts using the GraphQL query allWordpressPost. A page is created (createPage) with an assigned path and formatting described by the blog-post.js template file below (component).

  • gatsby/src/templates/blog-post.js

    The template file that defines how a single WordPress post should be formatted on Gatsby, retrieving the data from that post using the allWordpressPost GraphQL query and filtering for its slug.

  • gatsby/src/pages/index.js

    Retrieves all of WordPress’s content to generate a list of posts on the homepage using the allWordpressPost GraphQL query.

Deploy and post-install 

When you first deploy the template, the frontend Gatsby site will fail with a 403 error. Visit the backend subdomain of your site and finish the installation of WordPress. You don’t need to set database credentials as they’re already provided.

WordPress comes with an initial β€œHello world” article, and it isn’t necessary to add any more content to the site.

Once you’ve finished, redeploy the project with the CLI command platform redeploy to view your Gatsby site, It’s now pulling its content from a backend WordPress container in the same project.

Next steps 

With Gatsby now deployed and pulling content from a backend WordPress application, there are a few things you may wish to change about your project going forward.

applications.yaml 

You can optionally combine the application configuration (.platform.app.yaml) for Gatsby and WordPress into a single configuration file. Like services.yaml and routes.yaml, this file is shared across the project and resides in the .platform subdirectory. You need to explicitly define the source of each application.

Multiple content sources 

Gatsby supports pulling multiple sources into its build. This includes external services like Stripe and additional backend CMSs for different sets of content. As in this example with WordPress, you can branch off your repository and add an additional directory that contains the codebase for another backend. Then add the source plugin for that backend to gatsby-config.js.

Plan size 

As mentioned previously, you should have at least a Medium plan for your multi-app projects. This size gives the project enough resources for all of your containers as well as the memory necessary to actually pull content from WordPress into Gatsby during its build.

Keep in mind that the increased plan size applies only to your Production environment, and not to development environments (which default to Standard ). As you continue to work with Gatsby and a backend headless CMS, you may want to upsize your development environments.