{"componentChunkName":"component---src-templates-blog-post-js","path":"/posts/multiple-gatsby-content-types/","result":{"data":{"markdownRemark":{"html":"<p>So you've created a site on gatbsy with a blog format that draws from markdown files.\nGreat, its looking good and life is now a lot easier when you want to add new content. Just\nopen up a new markdown file, add, save, boosh; its there automatically. However, what if you want to add a different content type for your site? Have blog posts and projects for instance (hint hint, look to the bar on the left) well it turns out that's a bit more complicated.</p>\n<p>After scanning the gatsby docs, which are actually pretty damn good, I had no luck. So cut to Google and this <a href=\"https://desktopofsamuel.com/gatsby-website-with-multiple-post-types\">article</a> by Samuel W. which is excellent. I followed along for the majority of it however, the site its adding to has a few more bells and whistles than mine. So here is a bit of a bare bones example of how you would get this working.</p>\n<p>As Samuel suggests, point you gastby config to the folders were you want to store your two forms of markdown file.</p>\n<pre><code class=\"language-js\">{\n    resolve: `gatsby-source-filesystem`,\n    options: { path: `${__dirname}/src/project_posts`, name: \"projects\" },\n},\n{\n    resolve: `gatsby-source-filesystem`,\n    options: { path: `${__dirname}/src/blog_posts`, name: \"posts\" },\n},\n</code></pre>\n<p>Here I have pointed mine to folders were I want to store blog posts and posts about the projects I have been working on. Make sure that in the markdown files in your folders you create some metadata and specifically include a category for differentiating your content type. For instance in this very blog post the metadata looks like:</p>\n<pre><code>title: \"Generating Multiple Content Types for Gatsby\"\ndate: \"2020-06-22\"\nposttype: \"blog\"\ntagline: \"Running two types of markdown genre on gatsby is a little complicated...\"\n</code></pre>\n<p>Notice the posttype, while in my project section this would be set to project. This is important for generating the correct nodes for the GraphQl queries in a sec.</p>\n<p>The steps for creating the slugs for your markdown are the same as the ones found in Gatsby basic tutorial but the section you do change is the create page function. Samuel's adapted fuction is an if statement that creates the page based on the posttype defined in the markdown.</p>\n<pre><code>result.data.allMarkdownRemark.edges.forEach(({ node }) => {\n    if (node.frontmatter.posttype === \"project\") {\n    createPage({\n        path: `/projects${node.fields.slug}`,\n        component: path.resolve(`./src/templates/projectPost.js`),\n        context: {\n        slug: node.fields.slug,\n        },\n    })\n    } else {\n    // blog post\n    createPage({\n        path: `/posts${node.fields.slug}`,\n        component: path.resolve(`./src/templates/blogPost.js`),\n        context: {\n        slug: node.fields.slug,\n        },\n    })\n    }\n})\n</code></pre>\n<p>To get the posttype available for this function make sure you include it in your GraphQl query in the gatsby node file:</p>\n<pre><code>query {\n    allMarkdownRemark {\n        edges {\n            node {\n                frontmatter {\n                    posttype\n                }\n            fields {\n                slug\n            }\n        }\n        }\n    }\n}\n</code></pre>\n<p>Now, next Samuel suggests you should create your queries in the same section and filter them using regex, to search for posts under blog and project. If you fire up <code>gatsby develop</code> you can navigate to <em>localhost:8000/\\</em>__graphql_ and try the query out yourself. For instance if you want to find just your projects (remember to change project_posts to whatever folder name you store the markdown files in) you can put in:</p>\n<pre><code>{\n    allMarkdownRemark(\n    filter: { fileAbsolutePath: { regex: \"/project_posts/.*\\\\.md$/\" } }\n    ) {\n    edges {\n        node {\n        fields {\n            slug\n        }\n        frontmatter {\n            date(formatString: \"DD MMMM, YYYY\")\n            title\n        }\n        }\n    }\n    }\n}\n</code></pre>\n<p>And so appears the projects. Now if you were to copy this query over to your project index page and give it a go. Oh no! That regex is now throwing a weird error. Seems you can't escape characters in regex queries which is what we need for finding all the files in our folder. According to stack overflow you would need to create a big query in your gatsyb-node file (minging). Luckily, if you traipse through the gatsby docs you come across a small line about escaping characters and if you add two extra back slashes (I know, weird) you can keep your query were you had it:</p>\n<pre><code>export const query = graphql`\n{\n    allMarkdownRemark(\n    filter: { fileAbsolutePath: { regex: \"/project_posts/.*\\\\\\\\.md$/\" } }\n    ) {\n    edges {\n        node {\n        fields {\n            slug\n        }\n        frontmatter {\n            date(formatString: \"DD MMMM, YYYY\")\n            lang\n            title\n            featuredImage {\n            childImageSharp {\n                fluid(maxWidth: 600) {\n                ...GatsbyImageSharpFluid\n                }\n            }\n            }\n        }\n        }\n    }\n    }\n}\n`\n</code></pre>\n<p>So you can now grab the data as needed for building out seperate index pages and creating template pages for both content types. This the one I use for the blog style page that you are reading (very meta):</p>\n<pre><code>import React from \"react\"\nimport Navbar from \"../components/navbar\"\nimport ContentContainer from \"../components/contentcontainer\"\nimport { graphql, Link } from \"gatsby\"\nimport style from \"./blog_post.module.css\"\nimport SEO from \"../components/seo\"\n\nexport default function BlogPost({ data }) {\nconst post = data.markdownRemark\nreturn (\n    &#x3C;Navbar>\n    &#x3C;ContentContainer>\n        &#x3C;SEO title={post.frontmatter.title} description={post.excerpt} />\n        &#x3C;article>\n        &#x3C;h1 className={style.title}>{post.frontmatter.title}&#x3C;/h1>\n        &#x3C;div\n            className={style.blogtext}\n            dangerouslySetInnerHTML={{ __html: post.html }}\n        />\n        &#x3C;br />\n        &#x3C;p>Posted {post.frontmatter.date}&#x3C;/p>\n        &#x3C;div>\n            &#x3C;Link to=\"/posts/\" className={style.backlink}>\n            &#x26;#8592; Back\n            &#x3C;/Link>\n        &#x3C;/div>\n        &#x3C;/article>\n    &#x3C;/ContentContainer>\n    &#x3C;/Navbar>\n)\n}\nexport const blogQuery = graphql`\nquery BlogPostBySlug($slug: String!) {\n    markdownRemark(fields: { slug: { eq: $slug } }) {\n    html\n    frontmatter {\n        title\n        date(fromNow: true)\n    }\n    }\n}\n`\n</code></pre>\n<p>The last thing you need to get this fully working if you have included an index page for your two types of content, is linking to them correctly. Now you have different content types you need to account for which one you are looking for. So now this file is called <em>multiple-gatsby-content-types</em> and this slug is found at <em>/posts/multiple-gatsby-content-types</em>. Our link to this has to be:</p>\n<pre><code>&#x3C;Link to={`/posts${node.fields.slug}`} />\n</code></pre>\n<p>That should be it all working, but if you want the full example, just head to the <a href=\"https://github.com/CodyAbb/cody-abbott-dev\">repository</a> for this site. Yet again, the article by Samuel W. has done all the heavy lifting and I just modified a few queries at the end but hopefully this is helpful.</p>","frontmatter":{"title":"Generating Multiple Content Types for Gatsby","date":"2 months ago"}}},"pageContext":{"slug":"/multiple-gatsby-content-types/"}}}