Gatsby: Multiple Content Types
Adding my answer in which is based on @nicokant but seems to have changed a bit. I also use mdx here but just swap out for MarkdownRemark
if that is what you use:
Give each source a name option:
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/src/posts`,
name: 'post',
},
},
Then when the node is created, assign it a custom field:
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark` || node.internal.type === `Mdx`) {
createNodeField({
name: `collection`,
node,
value: getNode(node.parent).sourceInstanceName
});
})
};
Then you can query it based on a custom field:
query {
allMdx(filter: { fields: { collection: { eq: "post"}}}) {
edges {
node {
fields {
collection
}
frontmatter {
title
}
}
}
}
}
Define different sources in gatsby-config
and place your contents in different directories like src/projects
and scr/blog-posts
{
resolve: `gatsby-source-filesystem`,
options: {
name: `project`,
path: `${__dirname}/src/project/`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `posts`,
path: `${__dirname}/src/blog-posts/`,
},
},
then you can create a field type based on the source name in gatsby-node
exports.onCreateNode =({ node, getNode, boundActionCreators }) => {
if (node.internal.type === 'MarkdownRemark') {
const { createNodeField } = boundActionCreators;
node.collection = getNode(node.parent).sourceInstanceName;
}
}
now you can filter your graphql query for collection of contents and you can generate specific templates based on content type.
query postsOnly {
allMarkdownRemark(filter: { collection: { eq: "posts" } }) {
edges {
node {
id
collection
}
}
}
}
code is based on this comment on github issue tracker
note: you should not directly mutate node instance in gatsby-node
, but instead use createNodeField
. If you know how to filter in graphql using custom fields please add to this answer!