Modifying permalinks in Gatsby depending on content type

Whilst migrating my personal website to Gatsby.js, I was faced with an issue of my own making around how to organise the project, and how this would impact on permalink structure.

Folder structure

My plan for the Gatsby folder structure was:

content/
  pages/
    about.md
  posts/
    2019-01-01-test-post.md
  projects/
    fulhamish.md

src/
  components
  pages
  templates

Out of the box, Gatsby appends the folder name to the permalink for each page, post or project. This would lead to the following links:

  • tomodwyer.com/posts/2019-01-01-test-post/ – ✅
  • tomodwyer.com/projects/fulhamish/ – ✅
  • tomodwyer.com/pages/about/ – ❌

I wanted to figure out a way to remove the /pages/ from the URL, without needing to add a custom parameter to each page’s markdown files.

Collections

My solution was to create a collection field at the same time the permalink was being created in the gatsby-node.js file. This way I could check if the page was inside the pages folder and if so, not add the folder name to the permalink. It would also make sure that all the other posts and pages had the folder name added.

The code from my gatsby-node.js file is:

if (type === `MarkdownRemark`) {
  const collection = getNode(node.parent).sourceInstanceName;
  const isPage = collection === `pages`;

  const slug = createFilePath({
    node,
    getNode,
    basePath: `content`,
  });

  createNodeField({
    node,
    name: `collection`,
    value: collection,
  });

  createNodeField({
    node,
    name: `slug`,
    value: isPage ? slug : `/${collection}${slug}`,
  });
}

I set collection to a constant for use later in the file, when selecting what type of page template I want to use.

Hopefully this helps you if you need to make permalink adjustments in Gatsby.