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>{{ message.node.author }}</strong><br />
<small>
<a href="/messages/{{ message.node.id }}"
>{{ message.node.createdAt | date }}</a
>
</small>
</p>
<p>{{ message.node.body }}</p>
</li>
{%- endfor -%}
</ul>
You'll notice above that we link to /messages/{{ message.node.id }}
. 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/{{ message.node.id | slug }}/'
---
<h1>{{ message.node.author }} 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.