Back to Blog

Calendar for gatsby

Posted by

I've just updated my blog by adding something that is essential for traditional blogging: chronological indexing.

Won't spend much time explaining as you may see this messy blog source code on my GitHub

Idea

  • Need to added field frontmatter.yearWithMonth to the page

    • That can be done by various plugins or simply in onCreateNode of /gatsby-node.js (see on GitHub)

    gatsby-node.js

    // .. // Create slugs for files. // Slug will used for blog page path. exports.onCreateNode = ({ node, actions, getNode }) => { // ... // exptract date elements for indexing // yearWithMonth allows concatenation otherwise difficult/impossible while // graphql aggregation/filtering if (node.frontmatter && node.frontmatter.updatedDate) { const parts = node.frontmatter.updatedDate.split('-') node.frontmatter.year = parts[0] node.frontmatter.month = parts[1] node.frontmatter.day = parts[2] node.frontmatter.yearWithMonth = parts.slice(0, 2).join('-') } // ... }
  • Can query by that field to show year/month pages

    • You can add that query to any page you want to show calendar on (see on GitHub)
    # Get calendar calendar: allMarkdownRemark { group(field: frontmatter___updatedDate) { fieldValue totalCount } }
    • Also you can create component printing list of months like categories (see on GitHub)
  • You can build pages for each month by groupingby newly created field

    • That can be done using createPages of /gatsby-node.js (Example on GitHub)
    exports.createPages = ({ graphql, actions }) => { const { createPage } = actions return new Promise((resolve, reject) => { // added monthsPage to the templates const templates = ['blogPost', 'tagsPage', 'blogPage', 'monthsPage'].reduce( (mem, templateName) => { return Object.assign({}, mem, { [templateName]: path.resolve( `src/templates/${kebabCase(templateName)}.jsx` ), }) }, {} ) // added yearWithMonth to frontmatter graphql( ` { posts: allMarkdownRemark { edges { node { fields { slug } frontmatter { tags yearWithMonth } } } } } ` ).then(result => { if (result.errors) { return reject(result.errors) } const posts = result.data.posts.edges.map(p => p.node) // ... // Create months pages posts .reduce( (mem, post) => cleanArray(mem.concat(get(post, 'frontmatter.yearWithMonth'))), [] ) .forEach(month => { createPage({ path: `/blog/months/${kebabCase(month)}/`, component: slash(templates.monthsPage), context: { month, }, }) }) resolve() }) }) }