About This Site

I've written a custom static site generator in Python for this website, that intentionally does as little as possible. I used to use PHP inclusions to do templating, and a lot of my clients had too. But ultimately, the website was static in nature. PHP just happened to be there.

Static site generators are all the rage these days, and for good reason. They endeavour to reduce the complexity (in compute and architecture) of websites that never needed complexity in the first place. They stand as a great, cheaper, simpler alternative to big ol' content-management systems like WordPress or Django anywhere the information flows predominately one-way. At this point, I've tried a few - namely Jekyll, Hugo, and Makesite which was my inspiration for rolling my own.

Web Development Should Be Simple

Ultimately, a website is just HTML, CSS, and maybe JavaScript - in that order. Even the fanciest of websites have to fit that bill to be presented. They're the formats/languages that can not be changed regardless of tooling, and ultimately the output of any tool that works with the web. They're the sane default and they should remain that way, the stable known-ground for anything built on the web.

But they do have problems, because they're almost as old as I am and had to adapt like I did. These problems inspired some developers to invent some new problems to solve those problems.

HTML

HTML is a mark-up language used to describe a document hierarchy. That hierarchy is muddied in practice. It is prone to repetition - a mixture of website layout, styling, and content; it often ends in a lot of redundancy for the average document.

It is needed both to construct the layout shared across all pages, the content contained within them, and occasionally the emphasis/stylization of the content itself. There is no distinction between these intended functions as far as HTML is concerned, and HTML from one page can't be used identically in another without additional work.

This results in a lot of copy-paste effort if used purely. Templating languages (Mustache, Jinja, Liquid, etc.) and web components (custom HTML elements) were developed and introduced to alleviate that. They are tools to aid in development by eliminating repetition. These and state synchronization (in more dynamic web applications, anyway) are the exact problems that the big names - Vue, Angular, and React endeavour to solve. For a massive web application, they are a vital tool to separate representation from state, while presevering both in a compartmentalized way.

My personal website is decidedly not a massive web application. So this website uses no virtual DOM library. Only a templating language (Mustache) rendered in a one-off build step which had to happen anyway given my preferred authoring medium. For this use case, those frameworks are mostly bloat.

CSS

CSS is there for stylization. It's constantly facing inconsistencies in browser implementations. It is used to style the content. Font choices, sizes, spacing, weights, colors, state presentation (actively loading, focused, hovering, clicking, clicked), etc. That should be its only job. It's often not these days in practice, but that is its intended purpose.

This website uses one of the many CSS preprocessors, SASS. While CSS is growing into its own and now natively offering a lot of the features we used to require preprocessors for, it's still a bit lacking in some areas. I took some care to bridge the gap between SASS and CSS so I can remove it later if possible. I already have a build step, so SASS isn't a big addition to the toolchain. Its nature as a preprocessor means it is also a small addition during the build step, and doesn't impact page load time at all. It's a tool to aid development, not (just) a library.

JavaScript

JavaScript is where the dynamics come into play. It's a moving target itself that has a love/hate following as it's often over-used. Its sole job, ideally, is to respond to user interactions that don't simply communicate or transition state of interaction or content, but do something. It's where the logic comes in. If, then, else. Send a form, load some info.

There's a JavaScript library for everything, which is and is not a good thing. It leads to dependencies being thrown in for convenience rather than reason, and those dependencies generally have dependencies of their own. These libraries are often a compiled and a community effort leaving them vulnerable to supply-chain attacks. This problem scales out of hand quickly.

If your website is a massive web application, you have to balance the risks with the rewards of dependencies and maybe tango a bit with the dependency hell. Sometimes a longer build time and risk assessment is worth it, and with careful consideration the risks can be mitigated.

This website is not a massive web application. So I use no libraries that I haven't written myself, reviewed myself, or at least isolated to a single page and responsibility.

Keep It Simple

I mentioned earlier that I used to use PHP for templating. Often in PHP, you'll see something along these lines:

<?php include 'header.php'; ?>
Hello world!
<?php include 'footer.php'; ?>

This is what I consider to be a 'page shell.' It's a pattern that has come up time and time again in my experience, and often effectively does a very simple job - poorly: Encapsulate HTML content mark-up inside a styled layout and page. Functionally a division between HTML layout and content.

PHP is itself a sort of over-powered templating language, introducing 'back-end' logic to rendered HTML, directly from the HTML (after some server-side work). It has been used that way for at least 20 years. There is nothing wrong with this, it does the job. But when your website is functionally static (as in, it doesn't change per-user, and users don't tend to send data back to the server), it's a lot like taking a jackhammer to a roofing nail. Each page load spins up an entire process dedicated to running the compiled code that renders each page.

Computation time costs money.

Introducing SSSSS, in Python

This is where Stupid Simple Static Site Shells (SSSSS) comes in. It's written in Python, hence the name. No, I couldn't resist the (fitting) alliteration. My reasoning was straightforward: a static site generator, at its core, should be a stupid-simple conversion tool. It should take an input directory of documents media, and templates - then output a fully-formed website. Nothing more, nothing less - really nothing fancy.

SSSSS is intentionally minimalist. It doesn't dictate your CSS framework, layout, toolchain, or preprocessors. Nor does it offer a built-in solutions for any of them. Pick your own poisons. It doesn't optimize your images, or manage your JavaScript dependencies - those are jobs best left to package managers, bash scripts, and Makefiles.

It has one job: to take the documents in your inherently hierarchical filesytem, in your preferred authoring medium, and convert/wrap it in your designed HTML "shells" using a templating engine (like Mustache, which is my preference), to serve over URLs which reflect the whole process of dividing up the presentation logic anyway.

Inherently Hierarchical Filesystem?

Yes, it uses cascading directories/folders to produce a website incrementally from big (e.g. whole layout, navigation) to small (e.g. subnavigation, individual pages).

The root is the site layout, but inside of that site layout it's up to the subfolder/subsection how it divides the space up. This is consistent with what you see in the wild on the web, with the URLs reflecting the layouts of content and subcontent by section. It's just done statically and ahead-of-time. If the web has folders anyway in their URLs, why not leverage them structurally in the code and representation?

Version Control

Version control is fantastic, and databases don't do it well. By removing databases from the mix, and expressing everything as flat files, you allow yourself to leverage version control tooling for your entire website. You have the entire capacity of git at your disposal, and it is truly a first-class citizen.

Again, one tool doing one thing well. All it takes is reflection in the very file system we all have to use anyway.

As an added bonus, you now have access to hooks to complete an entire build and publish pipeline. This is a perfectly valid CI/CD workflow, in DevOps parlance. Most people just lean on Github Actions or derivatives for this, which happily over-engineers dependencies into the problem to charge for the solution - despite being built on hooks anyway. A relatively simple bash script that checks out the repository, runs make exactly as I would on my local dev copy, and moves some folders into public view when complete does fine in this case.

Function and Form

In essence, SSSSS is the result of a belief that function should be separated from form. Your content and its basic structure should be easily convertible, and the stylistic choices and more complex build steps should be handled by tools specifically designed for those purposes.

A file system is a tree, a document hierarchy is a tree, a URL points to a node in a tree.

Might as well leverage the overlap. For me, this "stupid simple" approach offers more creative freedom in the process.

That Sounds Inconvenient

Because it is. Ultimately, web design and development is a craft just as much as a job. If all websites took the same approach to all problems we'd end up with a lot of the same websites, and it'd be that much harder to sever the wheat from the chaff in terms of information. It's obvious at a glance to anyone with experience which websites are AI-generated these days. I'd argue taking a different approach is worth it if only for the contrast.

When I first got started in this field, HTML, CSS, and maybe JavaScript was exactly what every developer had to work with. While it led to a lot of poorly-developed websites, it made up for that in its pure and expressive humanity and creative freedom.

I strive to strike a balance. I like that humanity. While it might look good to potential employers that I know and use virtual DOM libraries, that I am willing to use AI assistance, and that I know and use the toolchain of the day - I would simply prefer to craft my own website. It can honestly take less effort than the modern alternatives to anyone proficient enough.

I can and do know how to work with all of those tools too, by the way. I just don't use them in my own personal work. The hard way offers its own rewards.

I'm Sold! Where Is It?

It's on my hard-drive, predominately. Currently it's a domain-specific tool and will remain that way. It's an "it works for me" sort of project.

However, its entire source code is about 337 lines of Python, including documentation.

It is not a large project, by design, just a large idea. I was never seeking to change the face of web development forever. In fact, quite the opposite - I wanted to bring it back to its basics. I enjoy those, I enjoy simplicity, and I enjoy building on that foundation myself as needed.

If you're a determined developer looking to implement this - it's actually quite simple to do, and a great exercise. If we never reinvented the wheel, our tires wouldn't have treads. Go get that practice in - and do it your way.

If you're an employer looking for an expert that can work in any environment - well, I suppose I've made my case by working at an even more foundational level than you need.

Happy trails to all.