I am Apt

Building a website for the long-term

Published on Sat Nov 07 2020 00:00:00 GMT+0000 (Coordinated Universal Time)

After 6 years of neglect, it was time to “refurb” my website. The main objective was to build a website for the long-term. This meant the following:

  1. Without any involvement, the website should remain online. — I should not need to update or patch my site to remain online and secure.
  2. Updating the site’s content is possible, without needing to run it on my local machine.
  3. Its code is simple. Even if I return to the codebase in 10 years, I should be able to pick it up quickly.
  4. Bonus: I want to use AWS products, so I can apply the knowledge learnt to other areas of work.

Based on the above, I concluded my solution should:

  1. Be a static website
  2. Have Continuous Integration / Continuous Deployments (CI/CD)
  3. Run and deploy with AWS products.

Let’s go into each of these parts, and why I wanted these:

Static Website

Instead of managing a server or application, for a static website you only care about the HTML files you serve to users. This is easier than maintaining an application/server which dynamically creates the HTML for each individual request.

A static website does not expose servers or databases which can be attacked or need to be patched. As such, a static website allowed me to meet requirement #1 (Without any involvement, the website should remain online. — I should not need to update or patch my site to remain online and secure.).

The only negative is that you need to re-deploy your site, anytime the HTML file(s) change. If your content updates frequently, this may become a challenge for you to maintain.

Knowing myself, I imagine I will write 2–3 blog posts a month, so frequent updates were rare.

The perks of a slightly more difficult way to release updates is worth the benefit of engineering away the maintenance.

Choosing a static website generator

Now that I was convinced the website should be a static website, I needed to consider which route to go. I considered the following options:

  1. No generator (just hardcoded HTML files)
  2. GatsbyJS
  3. NextJS
  4. Eleventy

HTML files

The simplest static website is to just upload HTML files. Although the simplicity is attractive, the main feature I would miss is templating and content duplication.

From a templating perspective, I would need to hardcode values that are re-used across pages. For example, the code for my page’s navigational header would need to be hardcoded into every file.

In addition, if there is no templating engine, I would need to re-enter a lot of information across different files. As an example, if I had a description, I would need to write the same description in the <meta> tags for Facebook, Twitter and default HTML spec. If I wanted to maintain a sitemap.xml or RSS feed, I would again need to track content both in the sitemap and RSS XML files and keep track of each HTML file I created.

As such, the ease of maintenance would be higher, as I would need to remember which files need to be edited whenever I create a page. As such, I started considering static website frameworks, such as the below:

GatsbyJS

I’m a big fan of React, and GatsbyJS is great if you want to build websites with React. One should however pause for a moment before using it for a website like this (a blog).

React’s super power is handling state, especially state in interactive applications. Now how much state is there in a blog? Hardly any… The closest thing to state in this context is the route, and that can easily be handled with different HTML files themselves. The benefit of handling state (which page you are viewing) is not worth the additional complexity of React.

In addition, GatsbyJS may load static HTML at first, but it afterwards loads 298KB worth of JavaScript to handle the rest of the page. This is JavaScript I don’t need. I’m happy for pages to “just” be loaded as normal HTML pages, without any intelligent preloading offered by Gatsby’s <Link/> component. Despite using GatsbyJS for Adlexicon, I guess I don’t value its features enough for my personal website.

Next.js

I have not used Next.js first-hand, however it is also a React Framework for websites and applications.

I ruled this option out for two reasons:

  1. It again uses React for website rendering, which is something I did not want.
  2. Next.js uses Vercel for its hosting by default. I wanted to use this opportunity to use (and learn more) AWS products. — I realize I could deploy without Vercel, but it did not strike me as a good idea to rely on a framework which will always invest more into its own hosting product (Vercel), over others (AWS, Azure, etc.). Remember, these decisions need to work for the long-term!

Eleventy

Eleventy is the “new kid on the block” for static website generators. Eleventy’s documentation had some great call-outs, that quickly drew me in:

What is not to like? Simplicity, long-term thinking and (out of the box) support for different templating engines.

As Eleventy’s output does not have client-side JavaScript, it gets back to the simplicity of the web: HTML files.

Based on the above, I was convinced to use Eleventy. It also met requirement #3 (Its code is simple. Even if I return to the codebase in 10 years, I should be able to pick it up quickly.).

Continuous Integration / Continuous Deployments (CI/CD)

Normally, CI/CD’s main benefit is the ability to frequently test and release software. Although good benefits, they actually were not my main motivation. Rather, a CI/CD gives you another surprising benefit: it allows you to update a file directly in the (Github) repository and have the change get deployed by your CI/CD pipeline.

Essentially, Github becomes a CMS. If I want to make a content update, I actually don’t need to run anything locally. This allowed me to meet the requirement #2 (Updating the site’s content is possible, without needing to run it on my local machine.).

If you just want the benefits of a CI/CD pipeline, I actually recommend using Netlify. Getting a pipeline set-up takes minutes!

At work the teams I work with need to regularly set-up their own (custom) pipeline, so I wanted to get more first-hand experience setting up a CI/CD pipeline with AWS products.

AWS products

At a high-level, the use of AWS products could be categorized into two parts:

  1. The hosting of the static website
  2. The continuous deployment of the static website

Hosting a static website on AWS

To get a static website on AWS, there are three products you’ll use:

Route53 routing to CloudFront, routing to S3

The continuous deployment of the static website

As long as you are able to run the build script of your Eleventy project, and place its output files into S3, you can create a CI/CD pipeline.

For this, I chose to use AWS CodePipeline. AWS CodePipeline uses AWS CodeBuild and CodeDeploy behind the scenes, however when setting these up via the Console, you don’t really notice this.

At a super high-level, a pipeline has the following stages:

Source
Get the source code and dependencies (from a Github repository)
Build
Use source code and dependencies to build your software into a distributable file(s)
Test
Test your built software. — I am actually skipping this for my blog (and am sure to regret this decision in the future).
Deploy
Take the output of the build and deploy these to an end destination. In this case, an S3 bucket. You can deploy the software across different stages (e.g. a beta stage and production stage).

The build phase is done by CodeBuild. Essentially it runs npm install && npm run build. The deploy phase uses CodeDeploy

Conclusion

I believe I now have a website which is built for the long-term. With the decision made, I hope it will be easy to maintain. I also enjoyed learning about AWS products and will be sharing more learnings in future posts.