A typical use case for a photo gallery blog is to have posts with a set of images, each post would be contained within it's own folder with it's images and markdown file:
-src
--posts
---my-first-post
----index.md
----photo-1.jpg
----photo-2.jpg
----photo-3.jpg
[...]
---my-second-post
----index.md
----photo-1.jpg
----photo-2.jpg
[...]
I have followed along the gatsbyjs.org tutorial and tried to keep my code as close to this as possible. I have paid special attention to the allFile part but I am still struggling to get gatsby to display the set of images for each post. Most of the examples around the web just use one featured image per post which is referenced in frontmatter. Please don't confuse this with what I'm trying to achieve here.
Perhaps the solution could be added to this incomplete docs page which feels like it's meant for what I'm trying to do.
I'm using gatsby-image also for all the benefits it brings. I think where I'm going wrong is in my post template post.js which I've included below.
Can anyone help?
This is my gatsby-config.js
module.exports = {
siteMetadata: {
title: `My Photo Site`
},
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
name: `posts`,
path: `${__dirname}/src/posts`
}
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
`gatsby-transformer-remark`,
`gatsby-plugin-emotion`
]
};
This is my gatsby-node.js
const path = require("path");
const { createFilePath, createFileNode } = require(`gatsby-source-filesystem`);
exports.createPages = ({ actions, graphql }) => {
const { createPage } = actions;
const blogPostTemplate = path.resolve(`src/templates/post.js`);
return new Promise((resolve, reject) => {
resolve(
graphql(`
{
allMarkdownRemark(
sort: { order: DESC, fields: [frontmatter___date] }
limit: 1000
) {
edges {
node {
fields {
slug
}
frontmatter {
title
}
}
}
}
}
`).then(result => {
if (result.errors) {
console.log(result.errors);
return reject(result.errors);
}
const blogTemplate = path.resolve("./src/templates/post.js");
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.fields.slug,
component: blogTemplate,
context: {
slug: node.fields.slug
} // additional data can be passed via context
});
});
return;
})
);
});
};
exports.onCreateNode = ({ node, getNode, actions }) => {
const { createNodeField } = actions;
if (node.internal.type === `MarkdownRemark`) {
const slug = createFilePath({ node, getNode, basePath: `posts` });
createNodeField({
node,
name: `slug`,
value: slug
});
}
};
And finally this is my post template post.js
import React from "react";
import { graphql } from "gatsby";
import Img from "gatsby-image";
import Layout from "../components/layout";
export default ({ data }) => {
const post = data.markdownRemark;
return (
<Layout>
<div>
<h1>{post.frontmatter.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
</div>
<div>
{data.allFile.edges.map(({ node }, index) => (
<Img key={index} fluid={node.childImageSharp} />
))}
</div>
</Layout>
);
};
export const query = graphql`
query($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
html
frontmatter {
title
}
}
allFile(
filter: {
extension: { regex: "/(jpg)|(png)|(tif)|(tiff)|(webp)|(jpeg)/" }
relativeDirectory: { eq: $slug }
}
) {
edges {
node {
childImageSharp {
fluid(maxWidth: 1920, quality: 80) {
...GatsbyImageSharpFluid_withWebp
}
resize(width: 600, quality: 80) {
src
}
}
}
}
}
}
`;
Gatsby info:
System:
OS: macOS High Sierra 10.13.6
CPU: (8) x64 Intel(R) Core(TM) i7-3615QM CPU @ 2.30GHz
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 10.13.0 - /usr/local/bin/node
Yarn: 1.9.4 - /usr/local/bin/yarn
npm: 6.6.0 - /usr/local/bin/npm
Languages:
Python: 2.7.10 - /usr/bin/python
Browsers:
Chrome: 71.0.3578.98
Firefox: 61.0.1
Safari: 12.0.3
npmPackages:
gatsby: ^2.0.93 => 2.0.93
gatsby-image: ^2.0.27 => 2.0.27
gatsby-plugin-emotion: ^4.0.1 => 4.0.1
gatsby-plugin-sharp: ^2.0.18 => 2.0.18
gatsby-source-filesystem: ^2.0.17 => 2.0.17
gatsby-transformer-remark: ^2.2.0 => 2.2.0
gatsby-transformer-sharp: ^2.1.10 => 2.1.10
npmGlobalPackages:
gatsby-cli: 2.4.8
Hey @gmossong
Sorry about the confusion! If I understand correctly, the GraphQL query filtering out the images with the current directory is not working?
I tried this out and it seems to work fine!

Could you link to a minimal reproduction of this?
If I understand you correctly my starter https://github.com/LekoArts/gatsby-starter-portfolio-emilia does exactly that.
I pass the directory as regex and then filter by this in my template
@sidharthachatterjee Yes the graphql query works as expected, see below. What I don't understand is how to use this with gatsby-image and loop through all the images displaying them in my post.

@LekoArts Looks like your starter does a similar thing, though I'm not sure I follow your code as well as the tutorial. Is your method best practice? Being new to react I'm not sure how to correctly map through what allFile is returning and use gatsby-image with it.
It'd be great if we could work on some documentation for this: https://www.gatsbyjs.org/docs/dropping-images-into-static-folders/
@gmossong _Dropping images into static folders_ actually refers to a different use case and wouldn't cover this if I understand correctly
Just took a look at @LekoArts example repository
{images.map(image => (
<Img
key={image.node.childImageSharp.fluid.src}
fluid={image.node.childImageSharp.fluid}
style={{ margin: '3rem 0' }}
/>
))}
This is pretty standard and looks like best practice to me
Closing this issue for now but please feel free to reopen or comment if we haven't answered your question completely!
Hi, I seem to be having a similar issue with doing this. My issue however appears to be that my slugs include a backslash before and after the string, but in order to query them I need to use the string without the backslashes. Any ideas why this might be happening?
Many thanks
This was the graphql query I ended up with, in src/templates/post.js. I have all my posts in their own folders within src/posts/. Each post folder would contain a markdown index file and then all the images for the post.
query($slug: String!, $absolutePathRegex: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
html
frontmatter {
title
date
modified
caption
description
cover {
publicURL
childImageSharp {
fluid(maxWidth: 915, quality: 70) {
...GatsbyImageSharpFluid_withWebp
}
}
}
}
fields {
slug
}
}
allFile(
filter: {
extension: { regex: "/(jpg)|(png)|(tif)|(tiff)|(webp)|(jpeg)/" }
absolutePath: { regex: $absolutePathRegex }
}
) {
totalCount
edges {
node {
name
childImageSharp {
fluid(maxWidth: 915, quality: 70) {
aspectRatio
...GatsbyImageSharpFluid_withWebp
}
}
}
}
}
}
niw web
The real issue is why relativeDirectory does not work:
query($slug: String!) {
allFile(filter: {relativeDirectory: { eq: $slug }}) {
...
}
}
Always produces empty array.
And @gmossong's solution does work.
@LekoArts thanks for the example, here are correct links btw: https://github.com/LekoArts/gatsby-starter-portfolio-emilia/blob/0ef63139538f85eede922282cc444e0509b446d0/src/templates/project.js#L82 and https://github.com/LekoArts/gatsby-starter-portfolio-emilia/blob/0ef63139538f85eede922282cc444e0509b446d0/gatsby-node.js#L67
The real issue is why
relativeDirectorydoes not work:
@kirill-konshin Did you check to make sure the slug matches the relativeDirectory name? In the links you gave above the slug has been transformed to kebab case with slug = /${_.kebabCase(node.frontmatter.slug)} so it no longer matches.
The real issue is why
relativeDirectorydoes not work:@kirill-konshin Did you check to make sure the
slugmatches therelativeDirectoryname? In the links you gave above the slug has been transformed to kebab case withslug = /${_.kebabCase(node.frontmatter.slug)}so it no longer matches.
It does matches. The code above is not mine, I did not do any transformations with the slugs.
Most helpful comment
If I understand you correctly my starter https://github.com/LekoArts/gatsby-starter-portfolio-emilia does exactly that.
I pass the directory as regex and then filter by this in my template