Sandro Turriate

Coder, cook, explorer

My own (kinda weird) Static Site Generator

Oct 26, 2020

How I built my own static site generator for the relaunch of which blurs the lines between dynamic and static.

Did i say static ? Well, strictly speaking, it’s not.

Then why call it a static site generator? Because that’s in the zeitgeist for what is essentially a dumb website. And the thing I built does in fact generate the entire site at once—it compiles a handful of html fragments together once into full html pages. But what I built is also a dynamic tool, pretty similar to the myriad of CMS’s I built in high school and college. It’s more flexible, speedier, and more feature-full than past projects, while providing a long sought-after solution to the problem of being overwhelmed and confused by oh-too-many files. My tool, that is, this website, is a dynamic one, consisting of only two files: a database and an executable, with an output that resembles a static site.

Static sites are fast, straight-forward, and easy to deploy. So why not use a static site generator? Well, I have. I’ve probably used a dozen over the last decade, and there’s a few things that bug me: for one, they’re static, which can be creatively crippling. Second, there’s a huge amount of tools that all basically do that same thing, but you have to try to them to really understand if they’re well suited for your site. A problem with not being easily satisfied is having to learn one tool after another, hopping around from Ruby to Go to Node, then relearning a tool when switching back or finding that the tool had a major update and requires relearning. This hopping around leads to a host of different environment setups with loads of different dependencies, all seeming to break after a minor node update, or a bad python3 symlink.

I’m tired of coding via YAML, or Front Matter, or pretending that Markdown can replace html. When a page needs to look and feel just a little bit different from the rest, I could either fight the framework, or just write some plain ol’ html. My tool does some of the heavy lifting for me, like rendering a page in a layout, routing and serving assets, but for the most part, I’m free to make each page as diverse and varied as I wish.

So I’m making a tool written in Go with SQLite for storage. All assets like images, css, javascript, webfonts are stored in the database and served directly out of the database for every HTTP request. Roughly the equivalent of reading the file from the filesystem. There’s an admin interface for adding assets, pages, entries, javascript, layouts, etc. All of the code that’s shown on the website is edited on my website, using CodeMirror as the text editor. Every time I update a resource, I store a rolling backup of it in the database. When a page is saved, the template is only compiled once, and a minified version of it is stored in the database, ready for fast retrieval. Uploaded images are automatically resized and compressed. The Contact form and the Email Sign Up form save to the same database that stores the website. Because the pages are only compiled once, I have some of the speed of a static site, while also having the benefits of a dynamic site. I can making live changes from anywhere without needing a terminal with the stack set up. I don’t need to worry about trying to remember the magical steps involved in deploying a simple fix to a typo. I can accept form submissions and add new pages or JS on the fly.

It’s effectively a CMS with page caching, but I like to think it blurs the lines between static and dynamic.

Now I’ve known for a long time that database blobs aren’t the best way to store flat files. The data isn’t replicated among CDNs, reads can be slow as the memory gets spread out amongst the database, it adds extra contention to the database, there’s a single point of failure…but when I read the grabby headline that SQLite is “35% Faster Than The Filesystem”, I decided to toss my limiting beliefs aside and try the damn thing already!

After a good amount of testing, I sadly concede that SQLite is not as fast as the filesystem for my use case (large files), but for some reason, I still love that my entire site is just one SQLite file. No symlinks, no Finder window, no ls -G, no git, no scp or rsync, just one SQL table.

I’m happy with what I’ve made thus far, but as with anything, now that I’m using it seriously, I can see all of the improvements I’d like to make for myself, and hopefully one day, for others too. I think I can do more page-building in the browser: just provide a SQL interface to the JS client, and get almost all of my opinions out of the way. It’s absolutely not no-code but more affectionately some-code or maybe enough-code.