Gatsby stands in between the simplicity-robustness of static site, and the versatile back-end of content management system. Using Gatsby means you can host the CMS in-house and publish content generated by Gatsby as static website.
In this tutorial, we talk about using Drupal content to power Gatsby. We'll borrow content of this awesome blog post to create a list of coffee types in Drupal, then transfer the list content to Gatsby.
This ultimate goal can be achieved with 3 steps:
- Build a Drupal server
- Build a Gatsby site that fetches content from Drupal server
- Buid the Gatsby site and publish it
1. Build a Drupal server
TL;DR: For those who are already familiar with Drupal already, this step is very simple. We create a content type named coffee
with 3 fields:
- Title - name of the coffee
- Body - description of the coffee
- Image - the name said itself
If you're new with Drupal, follow these step:
From the Drupal site, create the content type coffee
: go to Structure > Content types > Add content type, then enter basic declarations:
- Name: Coffee
- Description: leave empty if wished -- optional
- Submission form settings > Title field label: Title -- optional
- Publishing options > Default options: leave as default -- optional
- Display settings: uncheck the Display author and date information -- optional
- Menu settings: uncheck all Available menus -- optional
Then hit the Save and manage fields continue.
By default, the newly created content type comes with Body field of type Text (formatted, long, with summary)
. We'll use this field as the coffee description, so leave it untouched.
The missing part is the image field, so let's add one: click on Add field, select Image: field_image in Re-use an existing field then click Save and continue. The next page shows some configurations of field_image. In this tutorial, we'll leave all values as default.
The final content type should look like this 🎉:
Now it's time to create some Coffee nodes, just a few dozens of copy/paste to do.
Turn Drupal into API server using jsonapi
Download and enable module jsonapi and jsonapi_extras then navigate to http://[your-site]/jsonapi to see data of your Drupal site.
I use JSON Viewer Chrome extension to view JSON data in a better format
Note:
However, now if you logout, you'll get a 406 error when viewing /jsonapi endpoint, because you don't have permission to view JSON data.
By default, jsonapi
endpoint is at /jsonapi, and data is not accessible to anonymous users by default. We'll need to give permission to Access JSON API resource list to Anonymous user. Go to /admin/people/permissions and search for "JSON API", then check the checkboxes to allow Anonymous user and Authenticated user to access JSON API data.
Without this permission, Gatsby won't be able to communicate with Drupal and throw out an 406 error.
Module jsonapi_extras
will give you more control on the API settings (at /admin/config/services/jsonapi/settings) such as changing the endpoint. And jsonapi_extras
will help you avoid error 405 - Method Not Allowed when query data from Gatsby.
Now we are done with the server site set up. Let's switch to the Gatsby site.
2. Build a Gatsby site that fetches content from Drupal server
2.1. Build a Gatsby site
First, make sure you have node
and npm
installed on your computer.
Verify it by typing node -v
and npm -v
into Terminal
$ node -v
v10.1.0
$ npm -v
5.6.0
Install Gatsby's command line tool
npm install --global gatsby-cli
Create a new Gatsby site and run it, I'll call my Gatsby site coffees.gatsby
$ gatsby new coffees.gatsby // create folder coffees.gatsby and clone Gatsby code into it
$ cd coffees.gatsby
$ gatsby develop // start hot-reloading development environment
By default, new Gatsby site is accessible at localhost:8000
2.2. Fetch content from Drupal server
At this step, we'll be creating a new simple page /coffees that displays all coffee types in Drupal site.
2.2.1. Create the /coffees page
Create a new page in Gatsby is as simple as create a new JS file. All Gatsby pages should be stored in /src/pages. The filename will be the page URL. In this case, we create file coffees.js in /src/pages and add the following code into coffees.js
import React from "react"
const CoffeesPage = () => (
<div>
<h1>Different types of coffee</h1>
</div>
)
export default CoffeesPage
This simple code does one thing: create a new page at /coffees and content is a heading <h1>
saying "Different types of coffee"
2.2.2 Query Drupal content using GraphQL
In order to pull data from Drupal 8 site, we need to install gatsby-source-drupal
plugin
// in your coffees.gatsby folder
$ npm install --save gatsby-source-drupal
Configure gatsby-source-drupal
plugin
// In gatsby-config.js
plugins: [
...
{
resolve: 'gatsby-source-drupal',
options: {
baseUrl: 'http://dcmtl2018-demo.server/',
apiBase: 'jsonapi',
},
}
],
After adding the plugin configuration, the site should still functioning. If Gatsby yells error 406, check for permission on Drupal site; if Gatsby yells error 405, make sure module jsonapi_extras
enabled.
Build GraphQL to query all Coffee nodes from Drupal
Gatsby comes with an in-browser tool for writing named GraphiQL, validating and testing GraphQL queries and it can be found at localhost:[port]/___graphql
, in our case it's localhost:8000/___graphql
If all the configuration are rights, by default, the autocompletion function (CTRL + Space) of GraphiQL will be very handy to start with.
We'll be querying all Coffee nodes in this tutorial
After building the query successfully, let's go back to the coffees.js
file to execute the query.
Add the following code to the bottom of the file:
export const query = graphql`
query allNodeCoffee {
allNodeCoffee {
edges {
node {
id
title
body {
value
format
processed
summary
}
}
}
}
}
`
Then update the const CoffeesPage
to display title and body content:
const CoffeesPage = ({data}) => (
<div>
<h1>Different types of coffee</h1>
{ data.allNodeCoffee.edges.map(({ node }) => (
<div>
<h3>{ node.title }</h3>
<div dangerouslySetInnerHTML={{ __html: node.body.value }} />
</div>
))}
</div>
)
Thanks to hot-reloading, we could see the sweet fruit of the work right after saving the file
Rendering images in Gatsby
Now we have to query the image URL from Drupal, add the image to the page. To do so, we need to install few more plugins and their dependencies;
npm install --save gatsby-transformer-sharp gatsby-plugin-sharp gatsby-image
Update the gatsby-config.js
with new plugins:
plugins: [
...
'gatsby-transformer-sharp',
'gatsby-plugin-sharp',
],
In GraphiQL, try updating the current query to get image field. Here we need to specify the image dimensions (height and width). In GraphiQL preview screen, we should be able to see image field data.
{
allNodeCoffee {
edges {
node {
id
title
body {
value
format
processed
summary
}
relationships {
field_image {
localFile {
id
childImageSharp {
resolutions(width:220, height:140) {
base64
tracedSVG
aspectRatio
width
height
src
srcSet
srcWebp
srcSetWebp
originalName
}
}
}
}
}
}
}
}
}
Now let's use this new query in coffees.js
and print out the image
In order to use Image in Gatsby, we need to
- import
gatsby-image
:
import Img from "gatsby-image"
- Update the query:
export const query = graphql`
query allNodeCoffee {
allNodeCoffee {
edges {
node {
id
title
body {
value
format
processed
summary
}
relationships {
field_image {
localFile {
id
childImageSharp {
resolutions(width:220, height:140) {
base64
tracedSVG
aspectRatio
width
height
src
srcSet
srcWebp
srcSetWebp
originalName
}
}
}
}
}
}
}
}
}
`
- Print out image: now that we have the image information (path, data, dimensions ...) from the query, we can tell Gatsby to render it out using the following code:
const CoffeesPage = ({data}) => (
<div>
<h1>Different types of coffee</h1>
{ data.allNodeCoffee.edges.map(({ node }) => (
...
<Img resolutions={node.relationships.field_image.localFile.childImageSharp.resolutions}
key={node.relationships.field_image.localFile.id} />
...
))}
</div>
)
And voila!
So far, we have done:
- Create an API server with Drupal and
jsonapi
,jsonapi_extras
- Create a Gatsby site with page
coffees.js
that "reads" content from Drupal server
Let's move the the last step of the tutorial: publish Gatsby site.
3. Build the Gatsby site and publish it
Gatsby names itself as a static static site generator, meaning its main purpose is to generate a bunch of static HTML, JS, CSS and images files that can act as a static site. This action can be done by only one command:
$ gatsby build
Once finished, checkout /public
folder to see result of your hard work along this long tutorial. Deploying your site is now simply copy/push contents in /public
to server.
Conclusion
So far, in this tutorial, we get to know how to:
- Create a new Gatsby site
- Install new plugin in Gatsby
- Use GraphiQL to write, validating and test GraphQL query
- Use gatsby-image to optimize images then render image in Gatsby page