Eleventy + VS Code + GitLab + Cloudways (and a basic CLI)

= My Favourite Ever Blogging Setup


When I initially setup a site at this URL I did it the way I've done a hundred times before: with WordPress. But as fantastic as WordPress is for making almost any kind of site creation accessible for almost anyone, I really didn't want to use it in this case.

What I wanted was:

  • A simpler code base with no bloat
  • A practical content editing workflow over which I had more control
  • Static files for fast load speeds and simplified hosting / server requirements
  • And ideally, ease of storage on a git repository.

After a good bit of fussing around trying & evaluating different things I've settled on a setup that I'm extremely happy with.

Favourite Blog Stack

Okay so here's a quick rundown of the stack I'm using for this site:

The blog itself uses the Eleventy static site generator

  • Eleventy takes a bunch of Markdown and template files and turns them into a static website
  • Eleventy needs only NodeJS
  • No specific frameworks are required
  • Templates are written using Nunjucks, (though you can use basically any engine, like Handlebars, Pug, whatever you like)

The front end is just good old vanilla code

  • All files are static
  • No database
  • No JS framework
  • No CSS framework
  • Only a single CSS file, 506 lines, 8.8kb

Built locally, deployed via GitLab, hosted on Cloudways

I didn't really want to have to use Netlify or another comparable service to handle builds / deployment / hosting - it didn't seem necessary because:

  1. Builds are fast enough that I'm good doing them locally, and
  2. For hosting I'm already very happy with Cloudways

However I also didn't want to have upload the entire lot of static files manually after every build. So here's what I did instead.

First, I organised everything into two repos:

  • src, housing the source files and Eleventy
  • site, housing the built site files

While I'm editing content Eleventy watches and automatically generates the site. There's no waiting, by the time I'm done finished writing an article the static site files are already built.

When I'm done I push the site to a GitLab repo. I use VSCode, (or actually VSCodium in my case), to do this given its interface makes this a simple process of:

  • Type a commit message
  • Hit CTRL + ENTER
  • Click the push button

This solves my problem of wanting to avoid uploading every file of the site when I add an article, because through using git I only have to upload changed / new files.

From there, I have a GitLab webhook setup to fire off a message to Cloudways. Cloudways gets this message and uses its git deploy functionality to pull in the changed / new files, and my site is automatically transferred on my hosting space.

I also have the source repo on GitLab as well, meaning I can pull it down to any device and work on the site anywhere.

Practical content editing through VSCode, snippets, extensions, and a basic CLI

No matter how convenient my site building, deploying and hosting process is, it would all be worthless if writing and organising content was slow or painful. I set myself up a smooth, efficient environment for creating articles by using a combination of:

  • VSCode Plugins
  • VSCode Snippets
  • VSCode Terminal
  • Eleventy Plugins
  • Markdown-it Plugins

Here's how I solved several issues that needed to be handled to make this whole setup a good way to work.

Creating new posts & pages

I didn't want to have to worry about manually creating directories to organise my posts properly, or correctly reproducing front page matter to ensure I had the necessary fields and template paths etc. I wanted this whole process to be just as easy, and minimally error prone, as it would be using a regular CMS backend.

To achieve this I created a very simple CLI, comprised of only four functions and designed to take just one command:

site new <type> <filename>

If you want a post you run something like site new post my-post-title.md and the CLI will:

  1. Create the appropriate directory to house the post within the content directory of my src repo, if it doesn't already exist. The folder structure is organised in a YEAR/MONTH/DATE format so directories will sort themselves chronologically regardless of when they were created or modified
  2. Make a copy of a post.md template file, place it in the directory, and rename it according to the filename parameter given in the command
  3. Insert the date and title into the front matter. The title is a sanitised version of the file name.
  4. Opens the file up for editing in VSCode. This is achieved through using the open-editor npm module.

New post created with CLI

The command is running using VSCode's inline terminal so everything can be done in one place.

Running site new page my-page-title.md does basically the same thing, only it creates the new markdown file in the top level of the content directory and works with different front matter in the page.md template.

Editing markdown

Zen mode markdown editing

For markdown editing I looked at a few options, including MarkText and Typora, both of which are extremely nice editing experiences. In the end I settled on editing inside VSCode, even though MarkText or Typora are arguably nicer environments for writing. The main reasons for this is that in VSCode I can create custom snippets, which are pretty integral to my process, as I'll discuss shortly.

Markdown preview

VSCode has built in markdown support with handy features like linking stylesheets to control your previews. I used this to load my site's stylesheet so previews look more like the real thing. The path to the project's stylesheet is saved in the VSCode workspace settings file so the whole thing can be duplicated and reused easily.

I use zen mode most of the time while writing, activated with keyboard shortcut CTRL+K Z, and use CTRL+SHIFT+V to go in and out of previewing the article.

Formatting & spell check

I'm also using the Markdown All in One VSCode extension which makes it easy to do things like bolding text or creating lists.

For spell checking I'm using the Code Spell Checker extension for VSCode.

Organising tags

Tag management

In a regular CMS you have a database to keep track of your tags or categories. I was concerned that by handling everything manually I'd lose track of exactly what collection of tags I had out there among my articles.

To enable me to maintain a list of tags I created a custom VSCode snippet. I type tg then hit TAB and I'm given a dropdown with a list of tags to choose from. The tags are defined by a comma separated list inside the snippet, and I will add to this list as time goes on with the site. I may look at a more robust solution in the future but for now this is all good.

This VSCode snippet, as well as the others I'll describe, are all stored in the project's workspace so they'll be available for any other sites I build using this setup.

Adding images

Easy insert image snippet

I created another VSCode snippet to make adding images easier. I type img, hit TAB and it expands into ![]() with tab stops where the alt and src info needs to go. I can use VSCode's file path completion prompts to easily browser for images I've copied into my src directory.

Make image previews work

At first I faced an issue where the location the image needed to be in order to appear in the Markdown preview was different to where it needed to be to work in the site. I solved this by creating a symlink to the location needed for the Markdown preview to work.

Adding links

Easy insert link snippet

I created a VSCode snippet for this too: lk then hit TAB to get [](). There are tab stops where the link text and URL need to be entered.

Open links in new tab

I also use the Markdown It Link Attributes plugin to automatically set external links to open in a new tab.

Aligning text and images

I'm using the Markdown It Attrs plugin to allow me to add attributes for text and image alignment by appending the notation {attribute=value}. For text alignment I just use Text to align {align=center} and for images I have right and left aligning classes I invoke using ![imagealt](image.jpg) {class=imgright}

Lazy loading images

To speed up page loading and prevent reflow load I'm using the LazyImages plugin for Eleventy.

Adding videos

Easy video inserting

I'm using the Markdown It Block Embed plugin so all I need to add a YouTube video is its URL.

I also created the VSCode snippet yt to make it even easier, which expands to @[youtube](). The cursor is automatically placed between the brackets where I can paste the video URL in order to embed the video.

Responsive iFrames

The Markdown It Block Embed plugin allows me to wrap my iFrames in a container element. This in turn allows me to use Ben Marshall's technique to make iFrames responsive using only CSS.

Load speed test

Emulated load speed test

On an emulated load speed test with cache disabled, simulating regular 3G connection speeds, this article has a DOMContentLoaded speed of under a second, i.e. 651ms and a total load speed of 1.30s.

These are speeds I'm super happy to be achieving out of the gate.

Very pleased so far

It took some time to get this all constructed the way I wanted it, but I'm super pleased with where it's at.

I don't have to deal with any of the points of irritation that have bothered me with previous sites I've run, and I have a system that's custom made for me just the way I like it. And because I have all the code for the site right at my fingertips, inside my src repo, I have the confidence of knowing I can easily make changes and additions whenever I need to.

Thanks to Eleventy I have a static site built with vanilla code.

Thanks to VSCode / VSCodium I have a very practical and efficient way to edit content.

And thanks to GitLab and Cloudways I have a nearly hands-free, low cost way to deploy and host it all.

All four of these things come highly recommended from me!

Wanna chat about this post? @ me on Twitter

Tags: | blogging | hosting | stacks | coding | site systems

<- Home