Skip to main content

Using GraphQL with Gatsby

Gatsby is a popular React-based static site generator that can connect with ExpressionEngine through Coilpack's GraphQL API. This guide assumes you have already installed Coilpack and ExpressionEngine.

Configure Coilpack

Coilpack ships with the GraphQL integration disabled by default. You will need to enable it by adding COILPACK_GRAPHQL_ENABLED=true to your Laravel .env file.

For the purposes of this guide we are also going to disable any authentication requirements on our GraphQL endpoint so you should also add COILPACK_GRAPHQL_AUTH_ENABLED=false to your .env file.

Create a Gatsby Site

Now we will create a new Gatsby site. You can perform this setup anywhere but it should be in a different directory than your Coilpack installation.

npm init gatsby my-coilpack-site -- -y

Change into your new Gatsby site's directory

cd my-coilpack-site

Install the GraphQL Source Plugin

npm install gatsby-source-graphql

Start the development server

npm run develop
tip

Gatsby will start a hot-reloading development environment accessible by default at http://localhost:8000

Configure Gatsby's GraphQL Plugin

Gatsby should have created a config file during installation at ./gatsby-config.js. We need to add an entry to the plugins array to tell Gatsby where to find our Coilpack site and its GraphQL endpoint.

/**
* @type {import('gatsby').GatsbyConfig}
*/
module.exports = {
...
plugins: [
{
resolve: "gatsby-source-graphql",
options: {
// Arbitrary name for the remote schema Query type
typeName: "EE",
// Field under which the remote schema will be accessible. You'll use this in your Gatsby query
fieldName: "ee",
// Url to query from
url: "http://coilpack-site-url.test/graphql",
// HTTP headers
headers: {
// Learn about environment variables: https://gatsby.dev/env-vars
// Authorization: `Bearer ${process.env.COILPACK_GRAPHQL_TOKEN}`,
},
},
},
]
};

Creating our Home Page

And then we will create a simplified home page at src/pages/index.js. We will be using the Channel Entries Query to list out our entries and the Global Variables Query to get our Site Name.

import * as React from 'react'
import { graphql } from 'gatsby'

const HomePage = ({ data }) => {
return (
<div>
<h1>{ data.ee.variables.site_name }</h1>
<ul>
{ data.ee.exp_channel_entries.data.map(entry => {
return (<li><a href={"entry/"+entry.url_title}>{entry.title}</a></li>)
})}
</ul>
</div>
)
}

export const query = graphql `
{
ee {
variables{
site_name
}
exp_channel_entries {
data {
entry_id
title
url_title
}
}
}
}
`

export default HomePage

You should see a list of your entries rendered out on your site's home page now. However clicking the links to these entries will result in a 404 page until we finish the rest of this guide.

Creating our Page Template

Next we will set up a template that each of our individual pages will use to populate and display their content.

Create a file at ./src/templates/page.js with the following code:

import React from "react"
import { graphql } from "gatsby"

export const query = graphql`
query($entryId: String) {
ee {
exp_channel_entries(entry_id: $entryId) {
data {
entry_id
title
url_title
page_content
}
}
}
}
`

const Entry = ({ data }) => (
<div>
<h1>{data.ee.exp_channel_entries.data[0].title}</h1>
<div dangerouslySetInnerHTML={{__html: data.ee.exp_channel_entries.data[0].page_content}}></div>
</div>
)

export default Entry

Populating the Pages

Now we need to add some code to Gatsby's Node API to handle creating our pages dynamically. This will tell Gatsby to query for Channel Entries during the build process and create a page (using our new template) for each entry.

Create a file at ./gatsby-node.js and add the following code:


exports.createPages = async ({ actions, graphql, reporter }) => {
const result = await graphql(`
query {
ee {
exp_channel_entries(per_page:1000) {
data {
entry_id
url_title
}
}
}
}
`)

if (result.errors) {
reporter.panic("Error loading entries!", reporter.errors)
}

result.data.ee.exp_channel_entries.data.forEach(entry => {
actions.createPage({
path: `/entry/${entry.url_title}`,
component: require.resolve(`./src/templates/page.js`),
context: {
entryId: `${entry.entry_id}`,
},
})
})
}

After you make this change you will need to stop the development server and restart it (npm run develop). Now you should be able to click through the links on your home page and see content in your page template.