Prelude
Summer was coming to a close and after a laborous six month foray in the construction business, I was coming to the realization my body was conspiring to betray me. It had been over a year since I had abandoned my Seattle tech startup lifestyle in search of something more emotionally sustainable. My mind weighed heavy with the care of my chronically ill partner, my vision for our future, and navigating the increasingly insurmountable road ahead of us. It had been a while since I written any code but lately I had become obsessed with the concept of ownership in technology. Accepting the fact that we are dependent on information technology for our basic survival and freedom, I sought some way to reframe my relationship with it.
Healthy relationships have healthy boundaries. They are built from communication, interdependence, and comprimise. As suspicions about the invasivness of Windows 11 loomed on the horizon, I had already begun migrating to a Linux work station. The developers I know don't talk about C anymore but Linux is a C utopia. I first learned to program with QBasic in DOS but I consider C to be my native toungue. C makes me feel close to the machine and the operating system. To be fluent in C is to understand how computing machines work. It feels so far away from the Agile-AI-Big-Data-Cloud-Native world I was running away from that it felt like coming home.
I have come to rely on Evernote as my second brain. I ask anyone I interview for a job about their note taking habits because I feel this is one of the most powerful practices you can cultivate to become more effective in work. In tech, I find it to be essential but I also find note taking and journaling to be indespensible practices in all disciplines of life. My problem with Evernote came from a lack of Linux support, coupled with a need to own my data. It occurred to me I could start to blog as an alternative way to catalog my ideas while also breaking my isolation and giving back to the world in some small way.
I considered a content management system. Wordpress and Drupal both come to mind. I've setup both in the past but I found the prospect of running a database, PHP, and all that javascript with all the plugins and themes and what nots, just felt like a whole lot of bloated non sense for a blog. However, maintaining a thousand HTML files by hand is also an untennable task. The clear comprimise is static HTML site generation. There are lots of tools out there but so many are written in Javascript or Python and require so many extra packages and dependencies, not to mention the scripting engines themselves. I wanted something cleaner, lighter, simple, pure. I wanted something that fit my tiny lifestyle. I set about writing my own in C.
Enter Tiny Site Generator
My Tiny Site Generator is written completely in C with no external dependencies beyond the C standard library. It uses a system of embedded directives and template injection to automate building all the boiler plate of an HTML page so you can focus on content. The content itself is still HTML. There's no markdown translator. What you put in is what you get out. The tool is so basic as to almost do nothing at all, except the tedious part of applying uniform structure, navigation, and theme across the entire site. It runs from the command line as tinysg
and builds with standard tooling on many Linux distros. tinysg
takes an input path, output path, and a theme path. When no theme is given, it uses an internal default theme. The theme does most of the heavy lifting for generating a cohesive structure. Themes are a collection of CSS stylesheets and HTML snippets that form templates the TSG engine can piece together to build the page.
A TSG site is divided into sections or contexts. Each context has a space on the nav bar and represents either a static page, like Home or About, or enumerated content, like blog articles. At the project level, static contexts are represented by single HTML files, while an enumerated context is a folder with multiple HTML files. A site.conf
holds the configuration that tells TSG how to interpret the site structure. Static pages are rendered as is, though theme CSS classes are available for use. Enumerated content is handled in a more sophisticated way. Each HTML file in the enumerated context is considered the content of an article and will be fit into an article template formatted by the theme. Metadata at the top of an article file will tell TSG how to fill out the various values available in the template such as the article title or publish date.
TSG iterates through the contexts and associated files, reading in special directive tags that tell it how to process certain sections and what values to fill into the templates. Template files from the theme are formatted in the same way. TSG reads these HTML snippets and the directives tell it where content and values should be injected. As TSG iterates over the files, it builds each full HTML page and writes them to the output directory. It also packages a copy of the theme's stylesheet and any other static resources. The result is a pure HTML site, ready to be served by any web server you like. No databases, no build automation tools, no package managers, no server side scripting engines, just HTML files.
At the date of writing, tinyplace.net is fully built using Tiny Site Generator. It is easily deployed with lighttpd and a letsencrypt certificate.
Where to go from here...
While initially limited in scope and capability, there are many features I want to add to Tiny Site Generator. It is truly a labor of love and has been an absolute joy reconnecting to C through a project like this. I think TSG fills a certain niche and I hope others will agree and find it as liberating as I have. To that end, I have decided to release Tiny Site Generator under the GNU GPLv3 license so that it will remain free and open to the world. After a long engineering career working under NDA, this is the first project I have ever contributed to the open source community, but I don't believe it will be my last.
Please give Tiny Site Generator for yourself and let me know what you think.