Software Development & Management

Calendar for gatsby

2 min min read - August 26, 2018

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()
    })
    })
    }

Previous article

6 min min read - August 25, 2018