I have two markdown collection routes which I want to apply to two different sets of markdowns separated by subfolders.
My folder structure is as follows
appfolder
content
projects
project1.md
project2.md
article
article1.md
article2.md
src
pages
projects
{MarkdownRemark.frontmatter__slug}.js
articles
{MarkdownRemark.frontmatter__slug}.js
The content of projects/{MarkdownRemark.frontmatter__slug}.js is as follows
import React from 'react';
import Layout from "../../components/Layout";
import Nav from "../../components/Nav";
import PageHeader from "../../components/PageHeader";
import Footer from "../../components/Footer";
import SimpleReactLightbox from 'simple-react-lightbox'
import { graphql } from 'gatsby'
const ProjectPage = ({data}) => {
const fm = data.markdownRemark.frontmatter;
const html = data.markdownRemark.html;
return (
<SimpleReactLightbox>
<Layout pageTitle={fm.title}>
<Nav />
<PageHeader title={fm.title} />
<Footer />
</Layout>
</SimpleReactLightbox>
);
};
export const query = graphql`
query($id: String!) {
markdownRemark(id: { eq: $id },fileAbsolutePath: {regex: "/(projects)/" }) {
html
frontmatter {
slug
title
summary
icon
}
}
}
`
export default ProjectPage;
But GraphiQL shows that the pages are generated for all md files. How do I restrict each collection route to respective subfolder.
I just ran into the same problem. It seems like there are no ready-made solutions for your current organization of src/pages
. But after running through the discussions on Gatsby, I found there are some workarounds, though I think it's a bit inconvenient.
Like this comment said:
If your source nodes contain something like
category: "article" | "blog"
, you could generate separate routes with file nested incategory
directory like/{SourceNode.category}/{SourceNode.slug}.tsx
.If your source node does not contain such a category field, then you can append it to the nodes in onCreateNode hook, or create entirely new nodes for your purposes
In your case, if you can add a category
field to the frontmatter in your .md
files, you can change your organization of src
to
appfolder
content
projects
project1.md
project2.md
article
article1.md
article2.md
src
templates
project-template.js
article-template.js
pages
{MarkdownRemark.frontmatter__category}
{MarkdownRemark.frontmatter__slug}.js
Then projects/{MarkdownRemark.frontmatter__slug}.js
goes to templates/project-template.js
and the article one is similar.
Now in your {MarkdownRemark.frontmatter__slug}.js
file, you can forward the data queried by GraphQL to the corresponding template.
// {MarkdownRemark.frontmatter__slug}.js
const GeneratedPage = ({ data }) => {
const templates = {
project: <ProjectTemplate data={data} />,
article: <ArticleTemplate data={data} />,
};
return templates[data.MarkdownRemark.frontmatter.category];
};
If it's not possible to add the category
field into the .md
file, make use of the createNodeField
API to programmatically add it to MarkdownRemark
nodes in gatsby-node.js
. It maybe something like this:
// gatsby-node.js
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions;
if (node.internal.type === `MarkdownRemark`) {
const value = ...; // something mapping the directory of node to certain catecory
createNodeField({
name: 'category',
node,
value,
});
}
};
Hope this can be helpful to you.