Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gatsby JS - Multiple pages pulling in markdown files with different categorys

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?

like image 707
J Bullock Avatar asked Jul 29 '18 07:07

J Bullock


1 Answers

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.

like image 80
chmac Avatar answered Nov 14 '22 04:11

chmac