I'm using GraphQL from within a Gatsby project. I have a set of markdown files for a blog-like section of the site. In the frontmatter of each markdown file, there's an image
property.
What I'd like to do is use Gatsby's fine image api to load the image in the frontmatter. When viewing an individual post (the ones created via createPage api), this works just fine because I can provide the frontmatter.image in the context. Here's what that query looks like.
export const pageQuery = graphql`
query($slug: String!, $image: String) {
markdownRemark(frontmatter: { slug: { eq: $slug } }) {
html
frontmatter {
date(formatString: "MMMM DD, YYYY")
slug
title
image
}
}
coverImage: file(relativePath: { eq: $image }) {
childImageSharp {
fluid(maxWidth: 1440) {
...GatsbyImageSharpFluid
}
}
}
}
`
On my index page where I'm displaying all these posts though, I want to display a smaller version of this image. I can get the image
from the front matter easy enough, but I'm not sure how to integrate that into the query.
export const pageQuery = graphql`
query {
allMarkdownRemark(sort: { order: DESC, fields: [frontmatter___date] }) {
edges {
node {
id
excerpt(pruneLength: 250)
frontmatter {
date(formatString: "MMMM DD, YYYY")
slug
title
image # <--- want to use this in a file query
}
}
}
}
}
`
As far as I understand, I can't use string interpolation in a static query in the component where the image is actually used, so I need to get it here in the page query. Is what I'm trying to do possible? Is there a better way to handle this?
This "link" between your frontmatter's image
string and an actual image file node (processed with Sharp) is called a foreign-key relationship.
There are two ways of doing this:
gatsby-config.js
@link
directive through Gatsby's schema customization (from v2.2)I recommend the second option, since it's a more GraphQL way of doing things, and happens in gatsby-node.js
where most node operations are taking place. However, if you're starting out with Gatsby and GraphQL, the first option might be easier to set up.
In your case, using the @link
GraphQL directive, you would probably end up with something like this in your gatsby-node.js
:
exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions
const typeDefs = [
`type MarkdownRemark implements Node { frontmatter: Frontmatter }`,
`type Frontmatter {
# you may need to adapt this line depending on the node type and key
# that you want to create the relationship for
image: File @link(by: "relativePath")
}`
]
createTypes(typeDefs)
}
Finally, you'll be able to query like this:
{
allMarkdownRemark {
edges {
node {
frontmatter {
date
slug
title
# image now points to the image file node
image {
childImageSharp {
fluid(maxWidth: 1024) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
}
}