Deploying the headless CMS to Platform.sh
Platform.sh is the superior way to deploy a headless application. Why? Because with Platform. sh, you can run both the head (Gatsby) and the CMS (for example, WordPress or Strapi) with the same tools, the same development process, and the same SLAs—without additional vendor relationships or costs. Let’s get started with our multiapp project. First, we’ll go into a little detail about how we can configure a two-application Gatsby project with either Strapi or WordPress as the backend.Overview
For both Strapi and WordPress backends, we’re going to use the same multiapp project structure:gatsby subdirectory, and either backend code we use will also be located in its own subdirectory. Each app will have its own .platform.app.yaml file to describe its type, name, build process and how to start it.
This post focuses primarily on deploying Gatsby with a connected backend CMS, rather than the details specific to writing new components and templates in Gatsby to display content. Both templates—Gatsby with Strapi and Gatsby with WordPress—are based on separate tutorials from Strapi and Gatsby that, respectively, go into much more detail—if you’re interested in building those pages from scratch.
gatsby/gatsby-config.js. Inside that file, we can define all of the source plugins that will actually add our backend content to the Gatsby data layer using GraphQL. That file has the following structure:
plugins attribute for each backend:
During builds, Gatsby will use these modules to place queries against the backend app, making content accessible to display on the site. We’re also going to use the Node.js Config Reader library to access the backend relationship within our gatsby-config.js file, by adding it to the options for each of the source plugins listed above. So, we need to add it to our dependencies:
gatsby-config.js:
build hook to the post_deploy hook. Now that we’ve granted access to the backend with a relationship, it won’t be available until after the deploy hook. We still need to get that content to Gatsby, so we’ve moved npm run build to the post_deploy hook to get around this, and given write access to the .cache and public directories that will be created.
Pulling Strapi content into Gatsby
For Strapi, we’re going to place all of our code inside astrapi subdirectory, and name the application strapi in its .platform.app.yaml file.
If you haven’t already tried Strapi, I’d recommend you do. Strapi is a headless CMS that provides a simple UI that makes building APIs super simple. If you compare our Strapi template to the contents of the strapi subdirectory of the Gatsby-Strapi template, you’ll see that the code is identical except for a single line.
Namely in the build script build.sh, we’ve added the following:
routes.yaml file, we define three routes for our two applications. Two upstreams and a redirect:
services.yaml file:
relationships block of Gatsby’s .platform.app.yaml file now that we’ve named the Strapi app:
gatsby-source-strapi) to our dependencies with the following command:
plugins attribute of our gatsby-config.js file:
strapi relationship and build a string for that URL.
We’ve also defined the two primary contentTypes we want Gatsby to be concerned about: articles and categories. All calls to Strapi will be concerned with these two endpoints, so we’ll need to add them to Strapi for this to work (more on this later).
In Gatsby, we can control how our Strapi content is displayed by templating GraphQL queries in our pages, components, and template scripts. The tutorial our template is based on goes into much greater detail about these changes, but we can look at one example from our src/pages/index.js file, which lists all of the articles or blog posts served from Strapi:
StaticQuery on Strapi, retrieving all of its articles and using the ArticlesComponent defined in components/articles.js to display their images, title, and a snippet of their content.
Now, we can deploy our repository to Plaform.sh. When we do so, however, our primary route for our
Master environment is going to give us a 403 response; this is expected. Gatsby is trying to pull content from Strapi, when Strapi hasn’t been set up with any content to serve. So let’s add some.
If we visit the backend.<generated-url> URLfor our environment, Strapi will prompt us to first create an admin user. Once we do that, we’ll have access to the admin dashboard and begin creating our content types.
In our Gatsby app, we specified that we wanted two content types: article and category. We create an article collection so that every article we post contains the required fields title, content, image, and published_at for the publish date. Then create a category collection with only the single field name. Finally, we add a “Relation” field to article to category, such that a category contains many articles.
Note: You can find more detailed information about these steps in the template’s README.
articles and categories endpoints public.
Now that we have content being served from our Strapi backend, we can redeploy the project with the command platform redeploy, and our Gatsby app will pull that content when it builds.
Pulling WordPress content into Gatsby
Setting up WordPress to deploy with Gatsby is very similar to Strapi. We’re going to put all of our WordPress code in awordpress subdirectory. Then name the app wordpress, and modify the backend route we described previously to match:
services.yaml file as well:
relationships block needs to match WordPress in its .platform.app.yaml:
gatsby-config.js to use the gatsby-source-wordpress plugin, instead, by first installing it
gatsby-config.js:
wordpress relationship. We don’t need to include the http:// with that URL, because gatsby-source-wordpress provides a separate protol attribute to include it. We don’t need to specify contentTypes in this case, either.
If we take a look at our pages/index.js as its modified for WordPress, we can see that it looks very similar to Strapi, but has been modified to the specific queries that need to be placed on the built-in Wordpress’s GraphQL, using allWordpressPost instead:
Now that our code has been set up, we push to Platform.sh, and run into the same 403 response we did with Strapi. In this case, it’s because WordPress has not been fully installed on that container yet. We just need to visit the
backend.<generated-url> URL for our environment, and complete the installation.
When the install has completed, WordPress already comes with a starter “Hello world” post, so there’s no need to create any additional content. After, we once again platform redeploy, and our Gatsby WordPress app is off and running!
Simple, straightforward headless CMS pattern deployment
Deploying the headless CMS pattern on Platform.sh is simple and straightforward once you define your cluster. The great thing is that your team can focus on developing the app itself, leveraging best-in-class source plugins, rather than reinventing the wheel for each added feature. Same goes for content. With a few changes, we got Gatsby talking to both a Strapi and a WordPress backend, pulling in content to build the final application. I invite you to try it out yourself with the resources below. Take care!Our webinar that explores Gatsby and the headless CMS pattern is now available on demand. Be sure to check it out below, and click on through to the YouTube playlist to see the rest of the series.
Resources and references
- Platform.sh multiapp documentation
- Deploy Friday: E02 Gatsby & headless CMS, including Strapi, Drupal, and Oracle Content & Experience
- Gatsby + Strapi template
gatsby-source-strapidocumentation- Blog: Build a static blog with Gatsby and Strapi
- Gatsby + WordPress template
gatsby-source-wordpressdocumentation- WordPress Source Plugin Tutorial