Skip to main content

Integrate Gatsby with Apito

Gatsby is the fast and flexible framework that makes building websites with any CMS, API, or database fun again.

The best Headless CMS for Gatsby

Apito is a powerful headless cms to maintain and manage your Gatsby static site. it can deliver your content with GraphQL.

Gatsby automates code-splitting, image optimization, inlining critical styles, lazy-loading, and prefetching resources, and more to ensure your site is fast. You can read more about why you should use gatsby here

Apito with Gatsby benefits

Being a static site generator brings a lot of advantages: Performance, security, lower cost of scaling but also an excellent developer experience.

Gatsby brings huge benefits to content creators and developers by helping to solve many of the challenges with the headless approach.

Apito provides a perfect solution as a source for Gatsby’s static markup generation. Whether building a static site, or a more dynamic app/website Apito has you covered with its flexibility of content types, plugins, and customization.

Automate builds using Webhooks

You Take advantage of the built-in webhook feature that will allow you to automatically build your Gatsby project upon the update of your data.

Getting Started with Gatsby

Follow the integration guide from our documentation to see how to consume Apito's Content API from Gatsby. As a Static Site Generator, Gatsby will fetch your content from Apito at build time. Therefore, you need to configure Gatsby to communicate with your Apito Project

First run this following command

Install

npm install gatsby-source-graphql

We recommend using dotenv, which will then expose environment variables. Read more about dotenv and using environment variables here. Then we can use these environment variables via process.env and configure our plugin.

gatsby-config.js
    {
resolve: "gatsby-source-graphql",
options: {
typeName: "Apito",
fieldName: "apito",
url: "https://api.apito.io/secured/graphql",
// HTTP headers
headers: {
// Learn about environment variables: https://gatsby.dev/env-vars
Authorization: `Bearer ${process.env.SECRET_TOKEN}`,
},
// HTTP headers alternatively accepts a function (allows async) | use the above or this one. Dont use both
headers: async () => {
return {
Authorization: await getAuthorizationToken(),
}
},
// Additional options to pass to node-fetch
fetchOptions: {},
},
},

How to Query

{
# This is the fieldName you've defined in the config
features {
modules {
name
}
}
github {
viewer {
email
}
}
}

Schema definitions

By default, the schema is introspected from the remote schema. The schema is cached in the .cache directory, and refreshing the schema requires deleting the cache (e.g. by restarting gatsby develop).

To control schema consumption, you can alternatively construct the schema definition by passing a createSchema callback. This way you could, for example, read schema SDL or introspection JSON. When the createSchema callback is used, the schema isn’t cached. createSchema can return a GraphQLSchema instance, or a Promise resolving to one.

You can use this method if your schema changes regularly.

const fs = require("fs")
const { buildSchema, buildClientSchema } = require("graphql")

module.exports = {
plugins: [
{
resolve: "gatsby-source-graphql",
options: {
typeName: "Apito",
fieldName: "apito",
url: "https://api.apito.io/secured/graphql",
headers: {
// Learn about environment variables: https://gatsby.dev/env-vars
Authorization: `Bearer ${process.env.SECRET_TOKEN}`,
},
createSchema: async () => {
const json = JSON.parse(
fs.readFileSync(`${__dirname}/introspection.json`)
)
return buildClientSchema(json.data)
},
},
},
{
resolve: "gatsby-source-graphql",
options: {
typeName: "Apito",
fieldName: "apito",
url: "https://api.apito.io/secured/graphql",
headers: {
// Learn about environment variables: https://gatsby.dev/env-vars
Authorization: `Bearer ${process.env.SECRET_TOKEN}`,
},
createSchema: async () => {
const sdl = fs.readFileSync(`${__dirname}/schema.sdl`).toString()
return buildSchema(sdl)
},
},
},
],
}

Network requests can fail, return errors or take too long. Use Apollo Link to add retries, error handling, logging and more to your GraphQL requests.

Use the plugin's createLink option to add a custom Apollo Link to your GraphQL requests.

You can compose different types of links, depending on the functionality you're trying to achieve. The most common links are:

  • @apollo/client/link/retry for retrying queries that fail or time out
  • @apollo/client/link/error for error handling
  • @apollo/client/link/http for sending queries in http requests (used by default)

For more explanation of how Apollo Links work together, check out this Medium article: Productionizing Apollo Links.

Here's an example of using the HTTP link with retries (using @apollo/client/link/retry):

// gatsby-config.js
const { createHttpLink, from } = require(`@apollo/client`)
const { RetryLink } = require(`@apollo/client/link/retry`)

const retryLink = new RetryLink({
delay: {
initial: 100,
max: 2000,
jitter: true,
},
attempts: {
max: 5,
retryIf: (error, operation) =>
Boolean(error) && ![500, 400].includes(error.statusCode),
},
})

module.exports = {
plugins: [
{
resolve: "gatsby-source-graphql",
options: {
typeName: "Apito",
fieldName: "apito",
url: "https://api.apito.io/secured/graphql",
headers: {
// Learn about environment variables: https://gatsby.dev/env-vars
Authorization: `Bearer ${process.env.SECRET_TOKEN}`,
},
// `pluginOptions`: all plugin options
// (i.e. in this example object with keys `typeName`, `fieldName`, `url`, `createLink`)
createLink: pluginOptions =>
from([retryLink, createHttpLink({ uri: pluginOptions.url })]),
},
},
],
}

Refetching data

By default, gatsby-source-graphql will only refetch the data once the server is restarted. It's also possible to configure the plugin to periodically refetch the data. The option is called refetchInterval and specifies the timeout in seconds.

module.exports = {
plugins: [
// Simple config, passing URL
{
resolve: "gatsby-source-graphql",
options: {
// Arbitrary name for the remote schema Query type
typeName: "Apito",
// Field under which the remote schema will be accessible. You'll use this in your Gatsby query
fieldName: "apito",
// Url to query from
url: "https://api.apito.io/secured/graphql",
headers: {
// Learn about environment variables: https://gatsby.dev/env-vars
Authorization: `Bearer ${process.env.SECRET_TOKEN}`,
},
// refetch interval in seconds
refetchInterval: 60,
},
},
],
}

Performance tuning

By default, gatsby-source-graphql executes each query in a separate network request. But the plugin also supports query batching to improve query performance.

Caveat: Batching is only possible for queries starting at approximately the same time. In other words it is bounded by the number of parallel GraphQL queries executed by Gatsby (by default it is 4).

Fortunately, we can increase the number of queries executed in parallel by setting the environment variable GATSBY_EXPERIMENTAL_QUERY_CONCURRENCY to a higher value and setting the batch option of the plugin to true.

Example:

cross-env GATSBY_EXPERIMENTAL_QUERY_CONCURRENCY=20 gatsby develop

With plugin config:

const fs = require("fs")
const { buildSchema, buildClientSchema } = require("graphql")

module.exports = {
plugins: [
{
resolve: "gatsby-source-graphql",
options: {
typeName: "Apito",
fieldName: "apito",
url: "https://api.apito.io/secured/graphql",
batch: true,
},
},
],
}

By default, the plugin batches up to 5 queries. You can override this by passing dataLoaderOptions and set a maxBatchSize:

const fs = require("fs")
const { buildSchema, buildClientSchema } = require("graphql")

module.exports = {
plugins: [
{
resolve: "gatsby-source-graphql",
options: {
typeName: "Apito",
fieldName: "apito",
url: "https://api.apito.io/secured/graphql",
batch: true,
// See https://github.com/graphql/dataloader#new-dataloaderbatchloadfn--options
// for a full list of DataLoader options
dataLoaderOptions: {
maxBatchSize: 10,
},
},
},
],
}

Having 20 parallel queries with 5 queries per batch means we are still running 4 batches in parallel.

Each project is unique so try tuning those two variables and see what works best for you. We've seen up to 5-10x speed-up for some setups.