Adding estimated reading time to my blog posts

September 15th 2018 by Mads Rasmussen - 3 min. read

When visiting different blogs, I like the small estimation of how long time it will take to read a blog post. It gives me an idea whether the post is something I want to read now or save for later.

I know the reading time is not precise. People read at different speed, and various content takes different time to digest. Blog posts with images, presentations, videos, pdf's, code examples, etc. take a longer time to read than blog posts with text only. Despite this, I want to add the reading time both for fun but hopefully also to give a little value to the reader in the end.

I built my blog on Vue.js, Nuxt.js, and Umbraco Headless (more on that in a later blog post) so I want to make a small Vue component which I can reuse on my blog posts and in my blog post lists.

The challenge

My website gets all its content from a REST API. Therefore all the content of a blog post is in a complex JSON object including metadata that isn't part of the final presentation (sections metadata, image metadata, etc.). How do I best estimate the reading time with this extra data?

The process

My first idea is to strip out all of the metadata I don't want from the JSON. The solution quickly feels cumbersome and a bit overkill for what I am doing. This is not the direction I want to go in for this small project.

My second idea is to render the full blog post and get all the text from the rendered markup. This way I am sure that I don't get any of the metadata from the JSON but only what is presented to the reader. The problem with the solution is I also want to show the reading time in the lists where I am not able to render the full post. So this solution won't work.

I have been back and forth a couple of times with various solutions but have decided to surrender to just passing all the post content, including metadata, to my component and allowing the extra words to be part of the reading time. After all, it is an estimation. I have also predefined the reading speed to be 200 words per minute which can be even more off than the extra words in the metadata.

The solution

The final solution is a Vue component where I pass in the content of my blog post. The component finds how many words the text consists of and gets the reading time based on a reading speed of 200 words per minute. Again, I am not interested in a 100% precise time, so I round the time up to the nearest minute.

In BlogPost.vue
<reading-time :content="article.body"></reading-time>
ReadingTime.vue
<template>
  <span>{{readingTime}} min read</span>
</template>

<script>
export default {
  name: 'readingTime',
  props: ['content'],
  computed: {
    readingTime () {
      let minutes = 0;
      const contentString = JSON.stringify(this.content);
      const words = contentString.split(" ").length;
      const wordsPerMinute = 200;
      minutes = Math.ceil(words / wordsPerMinute);
      return minutes;
    }
  }
}
</script>