I have been following the beginner tutorial on Gatsby's website and have a question regarding the use of multiple blog post templates.
If there is a need for two or more templates to be used for the blog, for example:
How is it possible to achieve this in Gatsby when programmatically generating pages within the same URL structure, for example:
/blog/post-title-1 (using template 1) /blog/post-title-2 (using template 2)
Thanks.
Of course, it's doable but keep in mind that you need to provide that information (the chosen layout) to your code. If you've followed the tutorial using a File System Route API you'll need to swap to the "classical" version of create dynamic pages, using the gatsby-node.js
since that kind of logic needs to be provided somewhere to let Gatsby be aware of that.
You can just add a Contentful field called layout
which in this case can be an integer or something like that, then in your gatsby-node.js
:
const path = require("path")
exports.createPages = async ({ graphql, actions, reporter }) => {
const { createPage } = actions
const result = await graphql(
`
{
allContentfulBlogPost {
edges {
node {
layout
slug
}
}
}
}
`
)
if (result.errors) {
reporter.panicOnBuild(`Error while running GraphQL query.`)
return
}
const blogPostTemplate1 = path.resolve(`src/templates/blog-post-1.js`)
const blogPostTemplate2 = path.resolve(`src/templates/blog-post-2.js`)
const posts = result.data.allContentfulBlogPost.edges
posts.forEach((post, index) => {
createPage({
path: `/blog/${post.node.slug}/`,
component: post.node.layout === "1" ? blogPostTemplate1 : blogPostTemplate2,
context: {
slug: post.node.slug
},
})
})
})
}
The File System Route API saves you from adding this kind of query + logic for standard approaches in your gatsby-node.js
but since it doesn't support filtering (yet) as soon as you need to add some logic you'll need to go back to the "standard" approach.
Basically, you are getting your Contentful data, querying for the slug
and the layout
(the new field), and create dynamic pages based on that criteria.
Note that in the component
, you are choosing one template or another based on the layout field using a ternary condition. Of course, tweak it as you wish. Ideally, in complex approaches (more than 2 layouts) it should be a function for readability.
The rest of your legacy code (your template queries) will work alone since you are providing the slug (as you did before) using the context in:
context: {
slug: post.node.slug
},