Working with Eleventy and GraphQL

Working with Eleventy and GraphQL

Eleventy is a simple static site generator. It turns templates and data into HTML.

In this guide we will explore fetching data from Grafbase using GraphQL.

Make sure you have an Eleventy site up and running. You can follow the getting started guide if you haven't already.

Now make sure you install Grafbase CLI and run the following command inside of the grafbook directory created previously:

npx grafbase@latest init

This will generate the file grafbase/schema.graphql. Open this file and replace the contents with a simple @model:

type Message @model { author: String! body: String! }

This is all we need to create a backend for our Eleventy app! Run the Grafbase CLI to generate a GraphQL backend:

npx grafbase@latest dev

We will use the library @11ty/eleventy-fetch to handle requests to the Grafbase backend.

Inside the _data directory in the root of our project you will want to create the file messages.js and import @11ty/eleventy-fetch:

const EleventyFetch = require('@11ty/eleventy-fetch')

Next set the url value we will make requests to.

const EleventyFetch = require('@11ty/eleventy-fetch') const url = process.env.GRAFBASE_API_URL || 'http://localhost:4000/graphql'

Here we fallback to localhost when the environment variable GRAFBASE_API_URL is missing. You should set this value and GRAFBASE_API_KEY with your deployment platform before you deploy.

Next add the following query to the messages.js file:

const EleventyFetch = require('@11ty/eleventy-fetch') const url = process.env.GRAFBASE_API_URL || 'http://localhost:4000/graphql' const GetAllMessagesQuery = /* GraphQL */ ` query GetAllMessagesQuery($first: Int, after: String) { messageCollection(first: $first, after: $after) { edges { cursor node { id body author createdAt } } } } `

Inside of _data/messages.js you will want to finish by exporting a new async function that invokes EleventyFetch to execute the GraphQL query.

If you've used fetch with GraphQL previously you will be familiar with the request POST body:

{ body: JSON.stringify({ query: GetAllMessagesQuery, variables: { first: 100, after: null, }, }) }

Make sure to set the headers and method inside fetchOptions:

module.exports = async function () { const { data } = await EleventyFetch(url, { duration: '2s', type: 'json', fetchOptions: { headers: { 'content-type': 'application/json', 'x-api-key': process.env.GRAFBASE_API_KEY, }, method: 'POST', body: JSON.stringify({ query: GetAllMessagesQuery, variables: { first: 100, after: null, }, }), }, }) return data?.messageCollection?.edges || [] }

If you have more than 100 messages you will want to update the query to loop through all pages to populate the Eleventy cache.

So we can display a formatted createdAt date in our list of messages you can add a custom filter.

Inside your .eleventy.js configuration file use addFilter to configure the date filter:

module.exports = config => { config.addFilter('date', date => new Intl.DateTimeFormat('en-GB', { dateStyle: 'medium', timeStyle: 'short', }).format(Date.parse(date)), ) return { dir: { input: 'src', output: 'public', }, } }

Create the src/index.njk file and loop through messages. The messages value is populated globally using the _data/messages.js file we created previously.

<h1>Grafbook</h1> <ul> {%- for message in messages -%} <li> <p> <strong>{{ }}</strong><br /> <small> <a href="/messages/{{ }}" >{{ message.node.createdAt | date }}</a > </small> </p> <p>{{ message.node.body }}</p> </li> {%- endfor -%} </ul>

You'll notice above that we link to /messages/{{ }}. You also create individual per message too.

Create the file that matches the path above src/messages/id.njk and add the following:

--- pagination: data: messages size: 1 alias: message permalink: '/messages/{{ | slug }}/' --- <h1>{{ }} says</h1> <p>{{ message.node.body }}</p>

That's it! You have now created a static site using Eleventy with data from your Grafbase backend.

Build a backend for your static frontend with Grafbase

Get early access to the Grafbase beta.