Calendar for gatsby
Aug 26, 2018 - 2 min read

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


  • 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)


      // ..
      // Create slugs for files.
      // Slug will used for blog page path.
      exports.onCreateNode = ({ node, boundActionCreators, 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] = 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) {
    • 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, boundActionCreators }) => {
    const { createPage } = boundActionCreators
    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(
        // added yearWithMonth to frontmatter
            posts: allMarkdownRemark {
                edges {
                node {
                    fields {
                    frontmatter {
        ).then(result => {
        if (result.errors) {
            return reject(result.errors)
        const posts = => p.node)
        // ...
        // Create months pages
            (mem, post) =>
                cleanArray(mem.concat(get(post, 'frontmatter.yearWithMonth'))),
            .forEach(month => {
                path: `/blog/months/${kebabCase(month)}/`,
                component: slash(templates.monthsPage),
                context: {
Previous & Next
When did we lost it?
14 September, 2018
I just came from a refreshing holiday. It wasn't restful by any means. No, it was quite a job looking after my two-year-old son while… read more…
Retrieving history
25 August, 2018
I decided to dig in my history and find records of my internet activity since the begining. And I've been here for a while, constantly… read more…
For a very long time, I kept using the same set of questions while performing interviews. Even though I created it with Angular in mind… read more…
Let's face it: there are not enough opportunities for people with little commercial experience when at the same time there is massive… read more…
People dealing with rejection often allow their emotions to build new imaginary words. As they drew in denial or simply accept the change… read more…
I just came from a refreshing holiday. It wasn't restful by any means. No, it was quite a job looking after my two-year-old son while… read more…

Powered with by Gatsby 1.0