DEV Community

Pacharapol Withayasakpunt
Pacharapol Withayasakpunt

Posted on • Edited on

My first Gatsby Page, with Transformed GraphQL Query

Continuing from https://dev.to/patarapolw/non-root-gatsby-blog-in-a-monorepo-created-from-scratch-1l2f with I try to convert a Nuxt blog, powered by custom markdown with YAML front matter, to a Gatsby blog.

When I play with GraphQL, I realize that my frontmatter.date is actually a custom format.

  • Sometimes 2019-01-01
  • Sometimes 2019-01-01 01:00 (which in non-UTC)
  • Sometimes 2020-01-16T12:40:18.101Z

So, it is hard to query using

allMarkdownRemark(
  sort: {fields: frontmatter___date, order: DESC},
  filter: {frontmatter___date: {lt: ${new Date().toISOString()}}},
  limit: 5
)
Enter fullscreen mode Exit fullscreen mode

Also, another problem is GraphQL template string doesn't allow string interpolation.

So, what is the solution?

https://www.gatsbyjs.org/docs/schema-customization/

Now, I need gatsby-node.js.

  • Convert custom date string to Epoch using Moment.js.
  let m = moment(dateString, [
    'YYYY-MM-DD HH:MM ZZ',
    'YYYY-MM-DD ZZ',
    'YYYY-MM-DD HH:MM',
    'YYYY-MM-DD',
  ])
Enter fullscreen mode Exit fullscreen mode
  • Creating custom fields
exports.createSchemaCustomization = ({ actions, schema }) => {
  actions.createTypes([
    schema.buildObjectType({
      name: 'MarkdownRemark',
      interfaces: ['Node'],
      fields: {
        correctedDateEpoch: {
          type: 'Float',
          resolve: (s) => customDateStringToEpoch(s.frontmatter.date),
        },
        isPast: {
          type: 'Boolean!',
          /**
           * `s.correctedDateEpoch` failed, no matter how I tried
           */
          resolve: (s) => {
            const epoch = customDateStringToEpoch(s.frontmatter.date)
            return epoch ? epoch < now : false
          },
        },
      },
    }),
  ])
}
Enter fullscreen mode Exit fullscreen mode

Now, now, I have one more problem, YAML front matter sometimes convert Date String without quotes to Date object. This is also solvable by setting gray-matter's options.engines.yaml -- which is also settable in gatsby-transformer-remark

gatsby-config.js

const yaml = require('js-yaml')

module.exports = {
  plugins: [
    {
      resolve: 'gatsby-transformer-remark',
      options: {
        engines: {
          yaml: {
            parse: (s) => yaml.safeLoad(s, {
              schema: yaml.JSON_SCHEMA,
            }),
          },
        },
      },
    },
  ]
}
Enter fullscreen mode Exit fullscreen mode

Actually, I have also created src/pages/index.jsx but it isn't really magic.

Bonus

I replace gatsby-plugin-static-folders with

// gatsby-node.js

exports.onPostBuild = () => {
  rimraf.sync(
    path.join(process.env.ROOT, 'dist'),
  )
  fs.copySync(
    path.join(__dirname, 'public'),
    path.join(process.env.ROOT, 'dist'),
  )
  fs.copySync(
    path.join(process.env.ROOT, 'media'),
    path.join(process.env.ROOT, 'dist/media'),
  )
}

exports.onCreateDevServer = ({ app }) => {
  app.use('/media', require('express').static(path.join(process.env.ROOT, 'media')))
}
Enter fullscreen mode Exit fullscreen mode

And also deleted postbuild.js.

I found the original source code for gatsby-plugin-static-folders here -- https://github.com/imdaveead/plugins/tree/master/gatsby-plugin-static-folders.

Next Episode

I will attempt dynamic page creation, with fallback to 404.html or 200.html next time.

I also have qualms on optimizing local images in Markdown..., but I will find answers to that!

GitHub logo patarapolw / non-root-gatsby-blog

An attempt to create a Gatsby blog as a part of Monorepo, with /data and /dist (output-dir) directories sticking out, instead of being inside the Gatsby repo.

Top comments (0)