Gatsby: [1.0] Dynamically inserting images defined in frontmatter

Created on 6 Jul 2017  Â·  9Comments  Â·  Source: gatsbyjs/gatsby

In Gatsby 0.X, I would add a featuredImage reference to my frontmatter in my blog posts and then in my blog-post template, I would display the featured image. I would include the featuredImage in the same folder. For clarity, please see the below.

Front matter:

title: "Some title"
...
featuredImage: "Octocat.png"
...
---

Directory Structure

- some-blog-post-folder
-- index.md
-- Octocat.png

Ultimately, I want to:

  1. Add an image to the same folder as the blog post in the source
  2. Reference that image in the frontmatter
  3. Use that reference to display the image in places like the blog archive and the individual blog pages. See this as a reference.
  4. When all is said and done, everything needed for a blog post should be containable within one folder and easily transferrable to other sites simply by dragging and dropping.

Is there some obvious way to do this with Gatsby 1.0 that I'm missing?

Most helpful comment

That's what we do for gatsbyjs.org — any file you reference in frontmatter can be queried

https://github.com/gatsbyjs/gatsby/blob/master/www/src/templates/template-blog-post.js#L184

All 9 comments

That's what we do for gatsbyjs.org — any file you reference in frontmatter can be queried

https://github.com/gatsbyjs/gatsby/blob/master/www/src/templates/template-blog-post.js#L184

Dude you rock. Worked like a charm.

I've been struggling with this - I have the same front matter and directory structure as above but still running into issues.

In my templates/post.js file, I have the following line:
<img src={ post.frontmatter.indexImage }></img>
thinking this would pull in the source listed in the front matter. My post.js query is:

export const postQuery = graphql`
  query BlogPostByPath($path: String!) {
    markdownRemark(frontmatter: { path: { eq: $path } }) {
      html
      frontmatter {
        path
        title
        indexImage
      }
    }
  }
`;

Below is the error message:
GraphQL Error Field "indexImage" of type "File" must have a selection of subfields. Did you mean "indexImage { ... }"?

Any thoughts on why this isn't working? I'm still new to Gatsby, so it may be an issue that is over my head. Thanks in advance.

ahlbet, I was having trouble too but this issue helped me https://github.com/gatsbyjs/gatsby/issues/2054
I'm pretty new to this too but it seems like the solution is that the file field needs some kind of renderer which the gatsby-plugin-sharp provides?

@chiedo what was your solution—with respect to your example—which made this work? (I'm currently still wrestling with this challenge, not finding success.)

Hey @sgriffey!

I don't remember doing anything special other than what Kyle mentioned above. Make sure you have all the plugins he's using in that example installed as well though.

The plugins were the gotcha for me.

hmmmm...similar issue...I have a .mdx file with the following front matter:

---
date: 2018-09-02
title: Hipster
subtitle: Can I have that affogato with some sasssss?
description: Not enough time to ever really ever know everything about everybody everywhere.
image: pic-1.jpg
---

and I query it in my component, like so:

export const query = graphql`
  query GetMdxTemplate($slug: String!) {
    mdx(fields: { slug: { eq: $slug }}) {
      frontmatter {
        title
        subtitle
        date(formatString: "MMMM Do, YYYY")
        image {
          childImageSharp {
            fluid(maxWidth: 1920) {
            ...GatsbyImageSharpFluid
          }
        }
      }
      tableOfContents
      code {
        scope
        body
      }
    }
  }
`

and then use it my template like so:

<Heading>
  <h1>{frontmatter.title}</h1>
  <h2>{frontmatter.subtitle}</h2>
  <h3>{frontmatter.date}</h3>
  <img src={frontmatter.image} alt="cool stuff." />
</Heading>

which returns this in the console log:

Object
  childImageSharp: Object
    fluid: Object
      aspectRatio: 1.7777777777777777
      base64: "data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQ…"
      sizes: "(max-width: 1920px) 100vw, 1920px"
      src: "/static/3853b39b9bfc900e2e30fb4ab4cc8039/ae05c/pic-1.jpg"
      srcSet: "/static/3853b39b9bfc900e2e30fb4ab4cc8039/263e2/pic-1.jpg
      480w,↵/static/3853b39b9bfc900e2e30fb4ab4cc8039/6de71/pic-1.jpg 960w…"
````

and get the following errors in the constructor function, which I'm thinking might be part of the issue:

```console
constructor: function()
  arguments: TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context.
  caller: TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context.

soooooooo...dunno what to do for this image to work...

@jlengstorf, did you do something like this with your blog using mdx? Did you run into any mdx related issues putting images in front matter and querying them?

@rchrdnsh first of all, it should be

<img src={frontmatter.image.childImageSharp.fluid.src} alt="cool stuff." />

Alternatively, you can use gatsby-image like so:

import Img from "gatsby-image"

<Img fluid={frontmatter.image.childImageSharp.fluid} alt="cool stuff." />

However, I don't think your error is related to that. It complains about arguments and/or caller properties being used in your constructor. These are deprecated and should not be used anymore.

ok, so I wasn't fetching as deep down as I needed to do. I get that now, and it has worked for me, thank you @jgierer12 XD

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ferMartz picture ferMartz  Â·  3Comments

ghost picture ghost  Â·  3Comments

KyleAMathews picture KyleAMathews  Â·  3Comments

mikestopcontinues picture mikestopcontinues  Â·  3Comments

rossPatton picture rossPatton  Â·  3Comments