Just about a month ago, for some unknown and undoubtedly a sleep deprived reason, I began building my own static site generator (SSG).
And I did it entirely wrong. This is that story.
A sensible person would have first looked at the available static site generators and tried them first. I didn't. In fact, I have only a limited amount of experience with a few SSGs. That same sensible person should have made a comprehensive feature matrix to figure out what these products offered and, perhaps, pick out the features I would need. I didn't do that either.
Instead, I wanted to see how I would solve the problem rather than looking at prior art. By doing so, perhaps I would come up with some different (and, maybe, better?) ways of doing some of the things that SSGs do. Now that I'm about a month into development I'm ready to share what I've accomplished so far. Spoiler: I don't think I came up with anything new or better. But I have had fun.
I named my SSG Tuff, the type of rock formed from volcanic ash. My mind is like a volcano spewing nonsense and Tuff is what puts it all together.
Here is how Tuff works today.
The directory structure so far:
- _lib - For external code libraries.
- dist - For the output that is the website itself
- website/assets (multiple directories for images, css)
- website/content - for markdown files
- website/content/blog - blog posts (directories by YYYY/MM)
- website/content/pages - pages e.g. about
- website/content/podcast - podcast episodes
- website/content/portfolio - portfolio entries
- website/feeds - templates for syndication feeds
- website/layouts - HTML template files
My main objective with Tuff was to avoid a complicated technology stack and keep dependencies to a minimum. As it stands, there is but 1 code dependency and that is Parsedown. I wasn't about to rebuild a Markdown parser in PHP. Parsedown is extensible with add-ons but I don't currently use any.
Other dependencies related to the stack are that you need to be able to run PHP. I'm currently using PHP 8.1 on my Mac to run Tuff locally.
There is no magic to how Tuff works. I've set up various commands that will chew through the markdown files and spew the content out combined with the HTML in the layouts folder. Each section of the site is able to be built on its own.
For example, to build the entire website I run
tuff build all from the command line. This deletes the previous build of the site and rebuilds it from scratch. Now that my website has reached a point of some sort of solid footing, I shouldn't need to rebuild the entire site very often. Most of the pages on the site do not change often so there is no need to rebuild them. However, whenever I make a change to one of the core layout files (like, say, the footer) I need to. Rebuilding the entire website, with over 15,000 files, takes less than 10 seconds. This has nothing to do with my skills as an efficient programmer and more to do with the awesome raw power under our fingertips with computers.
Other commands I have include
tuff build recent which only builds the most recent posts,
tuff build portfolio which rebuilds the portfolio. Of course, other commands include building the podcast pages, the other pages like the about page, etc. And, I have a command to move assets (images, CSS files) around.
I plan to make Tuff's build routine even more efficient over time. I do not agonize over every millisecond of build time, but I like the idea of touching just the files that are necessary. By doing so it will keep things like file created dates and modified times more accurate.
The built website is able to be viewed on my local computer and network so that I can test the site on other devices. For this I'm using Docker, though on a Mac I obviously don't need to do that. I just to like Docker Compose. I'm using a dead simple Apache container and that's it.
Once I've verified that my updated content has been built correctly, it is time to deploy the changes to the public site.
To deploy Tuff uses
rsync. This has proven to be extremely fast. I can first request a "dry run" deploy which lists the files that will be updated during a real live deploy. I sometimes do this if I'm curious how many files will be impacted. But most often I just shoot from the hip. The deploy routine can be broken apart into smaller chunks to just deploy things like assets. I plan to break this part even more to conincide with Tuff's other build commands. This way I can deploy just a single page, just a single blog post, etc.
Backing up my website's content has never been easier. In fact, I currently have 4 copies of my website's content that are fairly up-to-date. Tuff's built-in backup command will take the local copy and push it out to OneDrive and local hard drives. This too I would like to improve to daisy chain commands together so that I don't need to run this manually. I'd also like to set up a Shortcut on macOS to either alert me when a backup is out of date or run the routine when it is.
Tuff's current featureset includes, but is not limited to:
- Home page
- Pages like about or projects
- Blog index, and pagination, posts, titleless posts
- Blog post tag indexes, examples photography, wis
- Blog date indexes, example January 2018
- Portfolio index and entries
- Podcast index and entries
- Mastodon favorites (gathers Mastodon faves at build time)
- RSS feed
- Social media redirects, example cdevroe.com/yt redirects to YouTube
- Featured images for portfolio and podcast post types, including image counts
- And text files. Each page or post has a corresponding text file. Here is the one for this post. Append .text to most URLs and you'll find the content. I stole this idea from Daring Fireball.
Of course, there is still much to do. I'd like to make it easier to share a photo from my phone to my website. Right now there are a number of steps to do so. Most of those steps can be eliminated with a few Shortcuts automations. I'd also like to bring back the comments that had been left on my site over the decades. I have a lot of server maintenance to do to pair down the services that run there that I no longer need (such as mySQL). I'm also going to take that opportunity to upgrade a bunch of the software there. And of course, just improvements overall.
My website has never been faster or used less compute cycles to deliver a page. I'm super happy with how things are today and I'm looking forward to continuing to whittle away at making more improvements to Tuff. And I may end up using it to rebuild all of my other websites including The Watercolor Gallery.