Unleashing the Power of Content Sourcing in Gatsby.js
Gatsby.js has taken the web development world by storm as a blazing-fast static site generator with a rich plugin ecosystem. One of Gatsby‘s most powerful features is its flexible content sourcing capabilities. Whether your content lives in local files, a headless CMS, or even a database, Gatsby makes it easy to pull that data into your components and pages.
In this comprehensive guide, we‘ll dive deep into sourcing content with Gatsby.js. You‘ll learn multiple techniques for sourcing various types of content and integrating it into your Gatsby site. By the end, you‘ll be a master at fueling your sites with content from any source imaginable. Let‘s jump in!
Sourcing Content from the Filesystem
One of the simplest ways to source content with Gatsby is to load it directly from your project‘s filesystem. This is a great approach for smaller sites where you want to maintain full control over your content in local files. The gatsby-source-filesystem
plugin makes this process a breeze.
First, install the plugin:
npm install gatsby-source-filesystem
Then add it to your gatsby-config.js
:
module.exports = {
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
name: `content`,
path: `${__dirname}/content`,
},
},
],
}
Here we‘re telling gatsby-source-filesystem
to source files from the content
directory in our project. The name
option allows us to filter the sourced files by the filesystem they came from.
Querying Filesystem Images
Let‘s say we have an image file at content/images/avatar.png
that we want to display on our site. We can query it using GraphQL like this:
query {
file(relativePath: {eq: "images/avatar.png"}) {
childImageSharp {
fixed(width: 200, height: 200) {
...GatsbyImageSharpFixed
}
}
}
}
This queries for a file with the relative path images/avatar.png
and accesses its childImageSharp
field to get a fixed-size, optimized version of the image to display. The ...GatsbyImageSharpFixed
fragment includes all the necessary fields for displaying a fixed image.
You can then use the queried data in a component:
const Avatar = ({ data }) => (
<Img fixed={data.file.childImageSharp.fixed} alt="Avatar" />
);
export default Avatar;
export const query = graphql`
query {
file(relativePath: {eq: "images/avatar.png"}) {
childImageSharp {
fixed(width: 200, height: 200) {
...GatsbyImageSharpFixed
}
}
}
}
`;
Transforming Markdown Content
In addition to images, a common use case is sourcing content from Markdown files. Gatsby has a powerful Markdown processing plugin called gatsby-transformer-remark
that converts Markdown files to HTML and provides additional features like syntax highlighting.
Install the transformer along with gatsby-source-filesystem
:
npm install gatsby-transformer-remark gatsby-source-filesystem
Configure the plugins in gatsby-config.js
:
module.exports = {
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
name: `content`,
path: `${__dirname}/content`,
},
},
`gatsby-transformer-remark`,
],
}
Now any Markdown files in the content
directory will be processed and available to query via GraphQL. For example, let‘s say we have a Markdown file at content/posts/hello-world.md
:
---
title: Hello World
date: 2020-01-01
---
This is my first blog post!
## Nice to meet you
I hope you‘ll enjoy my posts.
We can query the transformed HTML as well as any frontmatter fields like this:
query {
allMarkdownRemark {
nodes {
html
frontmatter {
title
date(formatString: "MMMM D, YYYY")
}
}
}
}
The frontmatter fields become available under the frontmatter
field, while the converted HTML is available under the html
field. This structured data can then be used to programmatically create pages:
// gatsby-node.js
const path = require(`path`);
exports.createPages = async ({ actions, graphql }) => {
const { createPage } = actions;
const result = await graphql(`
query {
allMarkdownRemark {
nodes {
frontmatter {
slug
}
}
}
}
`);
result.data.allMarkdownRemark.nodes.forEach(node => {
createPage({
path: node.frontmatter.slug,
component: path.resolve(`./src/templates/post.js`),
context: {
slug: node.frontmatter.slug,
},
});
});
};
This queries all the Markdown nodes for their slugs and programmatically creates a page for each one using a post template component.
Sourcing from Headless CMSs
While sourcing from local files works great for simple sites, many larger projects opt to use a headless CMS to manage their content. A headless CMS provides a user-friendly interface for content creators while exposing the content via an API for developers to consume.
Gatsby has source plugins for most of the popular CMSs like Contentful, Drupal, Sanity, and more. As an example, let‘s see how to source content from Contentful.
Start by installing the gatsby-source-contentful
plugin:
npm install gatsby-source-contentful
In your gatsby-config.js
, configure the plugin with your Contentful space ID and access token:
module.exports = {
plugins: [
{
resolve: `gatsby-source-contentful`,
options: {
spaceId: `your_space_id_here`,
accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
},
},
],
}
It‘s a good practice to use environment variables for sensitive information like access tokens. You can set these variables locally in a .env
file or configure them in your deployment environment.
With the plugin configured, you can query your Contentful data using GraphQL. The exact query will depend on your content model, but here‘s an example for a generic "post" content type:
query {
allContentfulPost(sort: { fields: publishDate, order: DESC }) {
nodes {
title
slug
publishDate(formatString: "MMMM D, YYYY")
content {
childMarkdownRemark {
html
}
}
}
}
}
This query retrieves all posts sorted by publish date. The title
, slug
, and publishDate
fields are simple text and date fields, but the content
field is a rich text field that is transformed to Markdown using the childMarkdownRemark
field.
You can then use this data to programmatically create pages or display it in components just like with the filesystem data.
Avoiding Sourcing Conflicts
When sourcing content from multiple locations, it‘s important to be specific in your queries to avoid conflicts. For example, if you‘re sourcing Markdown content from both your filesystem and a CMS, you might need to update any allMarkdownRemark
queries to filter by a specific source:
query {
allMarkdownRemark(filter: {
fileAbsolutePath: {regex: "/content/"}
}) {
...
}
}
This query only returns Markdown nodes sourced from the content
directory in your filesystem, ignoring any Markdown from the CMS.
Recap & Further Reading
In this guide, we‘ve explored several powerful techniques for sourcing content with Gatsby.js. Whether your content lives in local files or a headless CMS, Gatsby provides the tools to easily pull that data into your components and pages.
Some key takeaways:
- Use
gatsby-source-filesystem
to source content from local files - Transform and query Markdown files using
gatsby-transformer-remark
- Source content from a headless CMS like Contentful using source plugins
- Filter queries by source to avoid conflicts when using multiple content sources
This just scratches the surface of what‘s possible with Gatsby‘s content sourcing capabilities. To dive deeper, check out the Gatsby docs on sourcing content and working with images. You can also explore the wide world of Gatsby source plugins to find plugins for your favorite CMSs and data sources.
Happy Gatsby-ing! May your content be plentiful and your builds be fast.