Skip to content

Featured Images in Frontmatter with Nested Properties

Trang Le edited this page Dec 12, 2020 · 1 revision

Assume that you have a featuredImage field in the frontmatter of your Markdown or Mdx files following this Gatsby's tutorial.

Sometimes, you many want to add more nested properties to this featuredImage field like: path to the image file, attribution, photographed date etc.

First off, don't delete the existing featuredImage field. Having too much data in the frontmatter is not the problem. We can always fetch data selectively with GraphQL.

Create a new field called titledImage whose value is an object with properties path and credit.

title: "What's the deal with static site?"
featuredImage: "network.jpg"
titledImage: {
  path: "network.jpg"
  credit: '<span>Photo by <a href="https://unsplash.com/@dulgier?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Nastya Dulhiier</a> on <a href="https://unsplash.com/s/photos/network?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></span>'
}

The credit information was copied as HTML snippet from Unsplash.

Now, inside the post template, change the query for sourcing the titled image.

export const query = graphql`
  query($slug: String!) {
    mdx(fields: { slug: { eq: $slug } }) {
      frontmatter {
        titledImage {
          path {
            childImageSharp {
              fluid(maxWidth: 800) {
                ...GatsbyImageSharpFluid
                presentationWidth
              }
            }
          }
          credit
        }
      }
    }
  }
`

Still in the post template, pass the result of the GraphQL query into an <Img /> component.

import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import Img from "gatsby-image"
export default function BlogPost({ data }) {
  const post = data.mdx
  const { titledImage } = post.frontmatter
  const { path, credit } = titledImage.path
  return (
    <Layout>
      <div>
        <h1>{post.frontmatter.title}</h1>
        {titledImage && (
          <>
           <Img fluid={path.childImageSharp.fluid} />
           {credit && <span dangerouslySetInnerHTML={{ __html: credit }} />
          </>
        )}
        <div dangerouslySetInnerHTML={{ __html: post.html }} />
      </div>
    </Layout>
  )
}

Do the same thing for your blog archive page, or any page that queries the titled image.

Now, every time you download an image from Unsplash, don't forget to copy the attribution link, and paste it into the credit field in the frontmatter. Tada.

Clone this wiki locally