# Write your own static site generator
Published 2024-12-29
I've been meaning to write a blog post about why you should write your own static site generator for your blog. After reading Julia's post on Some notes on upgrading Hugo, I now feel even more compelled. Julia's post is a perfect example of why I chose to write my own SSG. Julia writes about what she learned and the process of upgrading Hugo version 0.40 to 0.135, and all I can say is that it looks like it was a complete nightmare.
When I set out to create a blog, one of my primary goals was simplicity. I wanted a way to write blog articles so that it was easy and enjoyable. Writing in markdown seemed like a good option. I also wanted something that would preferably compile into pure HTML with no JavaScript. I began to research and test various open source SSGs, but as I ventured down this path I realised things were not as simple as they seemed. It felt like I was spending way too much time learning about the SSG I had selected, trying to figure out how to configure a particular plugin, or find the perfect theme. In the end I gave up because it no longer met my primary goal of simplicity, and partly because I wasn't happy with any of the available themes. The problem with using an open source SSG is that it was developed by someone else, and many have become so bloated it requires a significant amount of reading just to get started. And that's before you've made any customisations. God forbid you want to upgrade to the latest version. Need I say more.
After spending way too much time trying to find the perfect SSG I decided I would go maximum simplicity and just write my blog in HTML, but this turned out to be a terrible idea, because writing blog articles in HTML was horrible. It took away the element of creatively when bound to writing HTML syntax.
One of the great things about writing your own SSG is that you fully understand how the SSG works from top to bottom, and you can tailor it exactly to your requirements. You're also not held hostage to someone else making breaking changes to the code, resulting in hours of refactoring if you decide to upgrade to the latest version. Of course that's not to say you won't introduce your own breaking changes, but you at least have some control over your own destiny.
So I decided to write my own SSG in Python. The entire program fits inside 94 lines of code (if we're not counting the imported packages). You can check out Layla on Github. It doesn't come with bells and whistles, and this is exactly what I wanted. There are also no configuration files, so if I want to modify the blog title or theme, I do that by modifying the HTML directly in the templates directory.
Here's a quick overview of my workflow when using Layla.
To initialise a new blog site I run the init sub-command. This only needs to be run once when creating a new blog site.
layla init
This will create directories content, html and templates.
A blog post is created by placing markdown files in the content directory. Layla uses front matter in the markdown files to define title, date and status (published or draft). Here's what a markdown file looks like.
---
title: Demo blog post
date: 29/12/2024
status: published
---
This is a demo blog post.
Title and date should hopefully be obvious. They set the title and date on a blog post.
Running the build sub-command will render the markdown files in the content directory and publish them to the html directory.
layla build
Any markdown files with status set to published will be added to index.html. Setting the status to draft will render the page, but it won't be added to index.html. This is useful when writing a blog post, because I can see how the article looks in my browser without worrying about publishing it to live.
A great reason for writing your own SSG is that you can customise it exactly to your workflow. I'm a huge fan of Obsidian for taking notes and managing my digital life, and since it uses markdown files, I wanted to use Obsidian to write my blog posts. The build sub-command takes a --md parameter for defining the location of your markdown files. In this case I set the path to where my blog posts are in my Obsidian directory.
layla build --md ~/obsidian/g9h/posts
I absolutely love being able to write my blog posts in Obsidian, and because I subscribe to Obsidian Sync, I can write my blog posts on my phone whilst on the go, and they'll be sync'ed up to my computer when I get home where I can build and publish the site.
There's only one final piece of the puzzle, and that is how I get the html files to the web server.
scp -r html/* ovh:/usr/share/caddy/g9hio/
It's that simple. I just scp the files directly to the web server which runs Caddy. By the way, Caddy is awesome. It's super simple to setup and it automatically configures and renews my LetsEncrypt certificate.
For a while I thought thought about how I could commit the markdown files to github and have an automated pipeline build and publish the site, but I decided this would just add additional complexity and goes against my principal of keeping things simple. In the future i'd like to write some automation that would allow me to publish a blog article by simply setting the status to published in Obsidian, as this would allow me to publish blog article from my phone, but for now, i'm really happy with my workflow.
This covers absolutely everything about Layla. There are no other options or settings, and there's no documentation site that requires hours of reading to get started.
I hope this inspires you to write your own SSG.