Eben Gilkenson

Motorcyclists admiring a view of mountains

Programmatic Featured Images

Most of the tutorials I’ve seen use a front matter field to specify a featured image. And while it’s not a big deal to type that one line for each post, it seems like something that could be automated. Just naming an image the same as the post and having it assigned as a featured image would be ideal.

It just so happens that the slug field generated by my gatsby-node.js setup works as a regex to find a similarly named image with the imageSharp query in GraphQL. If you’re not familiar with creating a slug field with onCreateNode(), check out how to programmatically create pages from data in Gatsby tutorial.

I’m currently only passing the id field as context, but it’s easy to add the slug, since it’s already in the query to use as the page path.

/* gatsby-node.js */

const path = require('path')
exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions
  const result = await graphql(`
    {
      allMarkdownRemark {
        edges {
          node {
            id
            fields {
              slug
            }
          }
        }
      }
    }
  `)
  result.data.allMarkdownRemark.edges.forEach(({ node }) => {
    createPage({
      path: `/posts${node.fields.slug}`,
      component: path.resolve('./src/templates/post.js'),
      context: {
        id: node.id,
        slug: node.fields.slug,
      },
    })
  })
}

Then it’s just a matter of adding it to the query in the post template.

*/ post.js */

export const query = graphql`
  query postQuery($id: String!, $slug: String!) {
    markdownRemark(id: { eq: $id }) {
      html
      frontmatter {
        title
        date
      }
    }

    featured_image: file(
      absolutePath: { regex: $slug }
      internal: { mediaType: { regex: "/image/" } }
    ) {
      childImageSharp {
        fluid {
          ...GatsbyImageSharpFluid
        }
      }
    }
  }
`

You can put the image anywhere that you’ve specified in a gatsby-source-filesystem plugin.

This will have collisions if you have two posts with the same filename, of course.

← Learning Gatsby