Reinventing the wheel! AGAIN!

Why fix something that wasn't broke? Our previous homepage was certainly not broken, but it wasn't perfect either.
11.09.2018
Sam Clulow
Tags

We refurbished, refreshed and modernised our homepage! Again!

Why fix something that wasn’t broke? Our previous homepage was certainly not broken, but it wasn’t perfect either.

We were using a static site generator called waffel. In order to deploy new content someone needed to push content to a specific branch on github. There’s absolutely nothing wrong with this workflow, many developers had been comfortable with this process, and many (including myself) had used it personally.

But over the past several months I started noticing some issues with both the tech stack and the process. As the company is growing, we’re producing more content, our business units all want to have some features added to the site, content changes, or updates that better reflect who we are and what we do.

Beyond the common editorial processes that include validating features, planning, designing, creating and proofreading, many of the smaller day-to-day tasks started to take up a considerable amount of time. The deployment process described earlier may seem straight forward when it includes only a handful of developers who know the framework. But this isn’t realistically maintainable when an editorial team want to easily push content without having to get involved with git, the command line or the framework. I’ll not mention the hassle that emerges if ever anything goes wrong somewhere along the line.

The other issue was more directly linked with the tech stack. waffel uses a mix of coffeeScript, jQuery, Nunjucks, and Brunch. A nice way to describe this stack would be to call it “Esoteric” or “Niche”. I’ll state this again, there is nothing wrong here, but there’re a couple of potential bottlenecks:

  • The first being that quickly adding new features requires quite some understanding of the technologies used, or having the framework be well documented and maintained. Unfortunately the framework isn’t exactly active, and the technologies used aren’t really “mainstream”.

  • The second is that many front-end developers are comfortable with more modern frameworks and don’t really want to invest time into libraries or frameworks that are losing popularity.

Briefly put: publishing content and implementing changes to the site required the involvement of the one remaining front-end Dev that was somewhat familiar with the framework and the process (that’d be me, Hi!).

In order to solve these issues, we decided to decouple code from content and use a new framework.

JAMstack to the rescue!

What does that mean exactly?

JAMstack: Modern web development architecture based on client-side JavaScript, reusable APIs, and prebuilt Markup.

In our case that means that we’re going to use:

  • a Headless Content Management System(CMS) to access all our content via API;
  • a Static Site Generator to create our site;
  • a lot of Javascript along the way.

Let’s start talking about Content!

With our previous system, content and code were hosted in the same file system coupling it tightly to each other. If you’re familiar with Wordpress or Drupal, then you’re probably familiar with your content being bound to your code.

A Headless CMS allows us to completely separate our content from the site. Our content is written and resides in one place and can be distributed to various endpoints regardless of the platform or tech stack. We could have built or hosted our own instance of Wordpress and accessed content using the REST API. but that solution is… well… potentially a good amount of maintenance. We decided to go with Contentful as they offer a user friendly CMS with the flexibility that we needed without managing the service stack ourselves.

Migrating several years worth of blog posts was pretty straight forward. We created a small script to copy our existing YAML blog posts, reformate them to JSON, and tweak it to fit the content model we specified in Contentful. There’re many scripts to support content migration from Wordpress or Jekyll to Contentful, but we couldn’t really benefit from them. For the the dozen remaining pages of content, we manually migrated the content. Admittedly this proved tedious when it came to migrating the image assets used in our blog posts, but this process only needs to be done once.

Now let’s dig into the Front End!

We wanted to use a Static Site Generator with a modern tech stack that has an active community, and that is easily maintainable by other front-end developers. There are some amazing projects out there that meet all these requirements. We’ve already used Hugo for a larger project and were satisfied with the results. We also considered using a more React focused framework like Next.js or GatsbyJS.

In the end, we decided to go with Nuxt.js for several reasons:

  • Nuxt.js is a Universal Vue.js Framework;
  • I personally LOVE Vue.js;
  • Both projects have a friendly and active communities, and with that comes a nice ecosystem of plugins and solutions for common issues;
  • The documentation is extensive without being overwhelming;
  • There’s an active community and responsive maintainers;
  • It’s very approachable as frameworks go, with a low barrier to entry.

I really want to stress that last point. For me this is Nuxt.js’ (and Vue.js’) selling point. Let’s have a quick look at a basic example of a component:

//pages/blog/_slug.vue

<template lang="pug">
 article.blog
   .intro
     img(:src="post.image.src" :alt="post.image.title")
     h1.hot-pink {{post.title}}
     .author {{post.author}}
   .content
     Vue-Markdown {{post.content}}
</template>

<script>
import Vue-Markdown from 'vue-markdown'
import axios from 'axios'
export default {
 async asyncData ({ params, payload }) {
   if (payload) {
     post: payload
   }else {
     let { post } = await axios.get(`https://my-api/posts/${params.id}`)
     return { post }
   }
 },
 components: {
 VueMarkdown,
 }
}
</script>

<style lang="stylus">
.blog
 width: 80%
 .intro
   margin-bottom: 2rem
   .hot-pink
     color: #ff69b4
</style>

The first thing that we can see here is the separation of logic and content. We have the template of the component, the script that deals with fetching data and components, and finally the styles.

In my opinion, this is quite approachable for a developer who is new to the project or framework. A basic component is understandable, self contained and easy to maintain. Thus, fixing issues or adding new features doesn’t require a profound understanding of the framework.

Nuxt.js is a Universal Javascript Framework providing three different deployment options. We can build it as a server-side rendered app, as a Single page application, or generate it as a static site without needing to create three different apps!

With this in mind, let’s look at fixing our deployment issue.

Different builds for different needs

At the start of this post, I mentioned how our content publishing process became quite time consuming. The problem was twofold: no quick or automatic way of deploying fresh content, and no possibility to review changes before going live.

We can now solve the second issue with relative ease as we can have our Production environment be generated as a static site and our Preview environment operating as a Single Page Application pulling content directly from Contentful! This gives us the possibility of previewing our future content without the need to either wait for a full build of the site or setup a local development environment.

The Preview environment can be deployed and hosted on a large selection of services in a matter of minutes and is completely independent of of Staging and Production environment. Nuxt.js’ documentation has a whole section on deployments.

Automating the deployment process would be trickier, and might not be the best option. Contentful has the option to set webhook endpoints that can be triggered if certain conditions are met. Unfortunately the webhooks couldn’t be configured to suit our needs exactly as the standard webhooks are triggered each time content is “published”, “unpublished” or “deleted”. This is fine when changing one file, but making multiple changes across multiple files would send out dozens of callback piling up in a queue of dozens of builds. To make it even worse, builds running in parallel would produce several strange errors when rendering the site.

There’s one tool that everyone in our office uses everyday and that comes with several integrations: Slack.

Slack provides an option to send post request to specific endpoints in the form of slash commands (/giphy). There’re a bunch of different ways of hooking up slack with various services to automate tasks, including building your own serverless functions, but we decided to use the easy option of using zapier as a middleman between Slack and or deployment environment. Now anyone who needs to publish content can do that when it suits them without needing to rely on a developers availability! 🎉

Wrapping up

In a relatively short time we were able to migrate all our content to Contentful, completely rebuilt our site and more importantly we managed to streamline our publishing process, saving us hours/days of effort down the line. The separation of concern, content from code, will allow all involved parties to focus on the task at hand without interrupting the others workflow. Getting familiar with Nuxt.js was also a pleasure, it’s really a versatile and powerful framework. It’s still quite new and has some quirks, but overall it was a a great tool with a lot of potential. We also now have a platform that we can seamlessly add features to and extend!

Cover photo by Aaron Mello on Unsplash