Simone Silvestroni

Minutes to Midnight - Official website

Why Minutes to Midnight’s new website eclipses the previous on IA, performance, sustainability and maintenance.

Skills

Jekyll Liquid Markdown HTML CSS Netlify Git Bash Microformats Webmentions Indieweb

Controlling the source

Starting out in the Nineties, I could write HTML code with a simple text editor. Anything that could go wrong was under my hands:

Then, the idea of a CMS seduced me. I’d been using WordPress since version 1.5. I can honestly say I know my way around it. Either on my own or with my former UI Farm team, I designed and coded custom themes and plug-ins for a large number of clients.

There won’t be criticism directed at WordPress in this case study. It’s a personal account of a change of direction that was beneficial to me. I will note similarities and a way to maintain a sort of continuity between then and now. The rationale behind the choice of leaving the CMS is quite simple in the end — to gain unconditional control over the workflow:

Sustainability

WordPress can serve websites with optimal performance; however, as a database-driven system it needs time to communicate with a remote server in order to return the page requested by the browser. I don’t need that. Even if this is solved with an aggressive cache policy, the way it works inevitably leads to files and database swelling over time, requiring constant maintenance and several chores that I wanted to rid of.

When my simple WordPress site ballooned to an unreasonable 740 MB over a a couple of years — despite my relentless maintenance — I wanted a change. Following the principle of pre-rendering and decoupling,1 I dropped both WordPress and my hosting service SiteGround, switching to Jekyll and Netlify.

Jekyll takes content written either in Markdown or HTML, organized in Liquid templates, and builds a static website ready to be uploaded to any web server. I wasn’t interested in pre-built themes, so I built the whole system from scratch.

Moving the content

The change carried the possibility of rethinking the information architecture. Before importing anything from my old site, Silvia helped me reorganizing and refocusing the content, putting my multi-disciplinary skills back together. I realized the importance of this stage later in the project, when I saw how convoluted was my previous navigation and how much material I decided to remove.

I then imported posts and pages.

To avoid too many SEO issues, I used a redirection feature provided by Netlify in the form of a simple plain text _redirects file. It also supports wildcards:

https://blog.minutestomidnight.co.uk/* https://minutestomidnight.co.uk/blog/:splat 301!

Liquid template language

Liquid is an open source template language written in Ruby. It was created by Shopify and is now used in Jekyll, Salesforce, Zendesk, 500px and more.2 Coming from PHP, I’ve found Liquid incredibly intuitive: a simpler programming language, yet powerful enough to let me build complex component that fuels the static site.

Layouts

I built specific layouts for pages, projects, posts, archives and landing pages. The functionality is vaguely similar to templates in WordPress. I love how layouts in Jekyll can be nested, thus the possibility to build powerful and complex structures. Key to this are:

For example, after creating the default.html layout containing a general structure and all the basic inclusions like header, main and footer, a second layout called page.html can inherit. It’s just a matter of adding a declaration in the second layout:

---
layout: default
---

The above instruction allows the page layout to be entirely included in the {{ content }} variable of default.html.

Modularity

An array of components are collected in an _includes/ folder. They can be site-wide, such as footer and header, or embeddable modules. The latter type (i.e. images, videos etc.) is recurringly added to posts and pages.

Embeddable modules works in a similar fashion as shortcodes3 in WordPress.

Module example: YouTube

This is a simple module to embed YouTube videos, through the open source front-end Invidious, called pattern-video.html:

<div class="video iframe-container">
  <iframe loading="lazy" src="https://yewtu.be/embed/{{ include.id }}" frameborder="0" allowfullscreen title="{{ include.title | default: "Video" }}"></iframe>
</div>

Whenever I need to embed a video, I just call a snippet, passing a video ID parameter and an optional title:

{% include pattern-video.html id="N0Sa-1Vqn6g" title="Berlin 91 official music video" %}

Automating the embed

I’ve been using Alfred on macOS for many years. Among other things, it offers access to clipboard history and creation of custom text snippets. A keyword for each snippet can be set. For example, to embed my include code for adding a <figure> tag, I type /figure and then complete the missing data where 000 is present:

Short animation of how I embed a figure tag
Embedding a figure tag using Alfred

Like the block editor in WordPress, I associated keywords such as /image, /video and so on. All modules, whether simple or complex, work the same way. I can also recall Alfred’s snippets window with my shortcut ⌥ ⌘ C, select the one I need and hit enter.

Alfred's snippets recall window
Alfred's snippets recall window

Markdown

Posts, notes, pages and projects are written in Markdown. Jekyll’s Kramdown implementation includes footnotes, code highlighting and more. Projects are particular content types outside the posts loop, created using collections. Not too different from custom post types in WordPress.

Design

The theme is handcrafted by applying styles to the layouts. I’m using Simple CSS as a base, with my custom components built in plain CSS on top of it. I only load a minified stylesheet on production:

{% if jekyll.environment == "production" -%}
<link rel="stylesheet" href="/assets/css/m2m.min.css">
{% else -%}
<link rel="stylesheet" href="/assets/css/m2m.css">
{%- endif -%}

Meta content

First, I check upon the existence of a variable called robots, used to exclude the page from search crawling.

{%- if page.robots %}
<meta name="robots" content="{{ page.robots }}" />
{% endif %}

The page title is rendered based on a few checks:

{%- if page.url == "/" -%}
{{ site.title | append: ' – ' }}{{ site.tagline }}
{%- elsif page.type == 'tag' -%}
{{ page.type | capitalize }}: {{ page.title | capitalize | append: ' – ' }}{{ site.title }}
{%- else -%}
{{ page.title | append: ' – ' }}{{ site.title }}
{%- endif -%}

Things I added next:

Without the need of external plug-ins, all benchmarks gives optimal results with all audits fully passed.

File management

Since I don’t need any setup for Apache, PHP or MySQL, file management is extremely easy. Using GitHub as a versioning system, my local website directory is a perfect mirror of the remote repository. Again, all my images, CSS or other assets are kept together with the source code. No external database to be backed up, no extra maintenance.

Build process

I use Bash to run Jekyll’s internal build tasks, using appropriate aliases in my bash_profile for regular localhost preview, serving drafts and future posts.

Javascript

I don’t compile nor minify Javascript because I only use it for the search engine and webmentions, which I never need to edit.

Performance, accessibility and sustainability

I’ve been treating performance as a design feature for more than ten years. The complete size of the website source code is currently 1.1 MB, reaching a root total of 23 MB including images and a 13 MB PDF file. It’s a sensible reduction from the previous 800 MB.

What contributes to my Pagespeed and Lighthouse score of 100 on performance, accessibility and SEO?

I also took care of removing files that are not needed on the live server, by adding a second config-production.yml which is called in my build command on Netlify. After validating the markup with the W3C, the final benchmarks shows a 100 on all grades for Google Pagespeed and also 100 on Gtmetrix.

The homepage weighs 56 KB uncompressed and loads in 0.4 seconds. Only 0.01g of CO2 is produced every time someone visits the homepage. Cleaner than 99% of web pages tested.

About accessibility:

As a static site generator, Jekyll lacks two features: a search functionality and a comment system. I solved the first by including a clever vanilla Javascript solution supported by Liquid syntax to indicize the content. A script-free solution using DuckDuckGo is provided.

Integrations: Webmentions, Indieweb

After deciding to avoid third-party commenting systems, I turned to webmentions, a decentralized way to interact with other websites’ posts, notes, likes and reposts.6

I’ve been out of mainstream social networks since 2020, so putting my website at the center of my online presence seemed perfect.

Visit the live site


Footnotes

  1. Decoupling is the process of creating a clean separation between systems or services. By decoupling the services needed to operate a site, each component part can become easier to reason about, can be independently swapped out or upgraded, and can be designated the purview of dedicated specialists either within an organization, or as a third party. 

  2. https://github.com/Shopify/liquid/wiki#who-uses-liquid 

  3. A shortcode is akin to a shortcut to add features to your website that would typically require lots of complicated computer code and technical ability. Read more

  4. https://developers.google.com/search/docs/advanced/crawling/consolidate-duplicate-urls 

  5. https://developers.google.com/search/docs/advanced/appearance/snippet?hl=en 

  6. A Webmention is a notification that one URL links to another. For example, Alice writes an interesting post on her blog. Bob then writes a response to her post on his own site, linking back to Alice’s original post. Bob’s publishing software sends a Webmention to Alice notifying that her article was replied to, and Alice’s software can show that reply as a comment on the original post.