I am using GatsbyJS to build a personal webpage. I have multiple pages, the two relevant ones are a projects/portfolio page and a blog page.
I have setup gatsby so on the blog page, it pulls in markdown files from a specific folder, and displays them using a template on the blog page. I wanted to display my projects in a similar fashion on the projects/portfolio page. My folder structure is as follows:
-src
-pages
-BlogPostOne
-BlogPostTwo
projects.js
blog.js
-templates
BlogPostTemplate.js
ProjectTemplate.js
-projects
-project1
-project2
I want the projects page to grab the project markdown files from the projects folder and display them using the project template
The blog page grabs the blog post markdown files from the pages folder and displays them using the blog post template, this works fine.
I basically used the same code as I did to grab the blog post files with different variable names and paths but it doesn't work. Is it possible to even do this with Gatsby? I have searched through their documentation and can't find anything similar to what I am trying to do. Does anyone have any experience doing a similar thing with Gatsby?
Yes, this is totally possible.
The solution is actually very simple, but requires a little understanding of Gatsby's internals to figure out. See this snippet on GatsbyCentral if you already know Gatsby a bit.
Otherwise, here's a more verbose explanation.
In your gatsby-node.js
file, you need to add this code:
exports.onCreateNode = ({ node, boundActionCreators, getNode }) => {
const { createNodeField } = boundActionCreators;
if (_.get(node, "internal.type") === `MarkdownRemark`) {
// Get the parent node
const parent = getNode(_.get(node, "parent"));
// Create a field on this node for the "collection" of the parent
// NOTE: This is necessary so we can filter `allMarkdownRemark` by
// `collection` otherwise there is no way to filter for only markdown
// documents of type `post`.
createNodeField({
node,
name: "collection",
value: _.get(parent, "sourceInstanceName")
});
}
};
Ensure you also have the required require()
statement for lodash:
const _ = require("lodash")
Now ensure that you have two plugin sections in gatsby-config.js
for both blog posts and projects. Ensure that each one has a name
option, something like:
plugins: [
{
resolve: "gatsby-source-filesystem",
options: {
name: "pages",
path: `${__dirname}/src/pages`
}
},
{
resolve: "gatsby-source-filesystem",
options: {
name: "projects",
path: `${__dirname}/src/projects`
}
},
Then you can query on the allMarkdownRemark
collection and filter for the field collection
. It will either be pages
or projects
.
An example query might look like:
query {
allMarkdownRemark(filter: {fields: {collection: {eq: "pages"}}}) {
...
Hope that's helpful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With