Indie web manifesto, and how this site is made
2026-03-23
Long-time followers of this site may have noticed that about a week ago, the whole design changed.
In fact, it wasn't just the theme that changed. While the content here remains largely the same, the entire underlying technology was rewritten from scratch.
The previous iteration of this site used Blazor WebAssembly with the MudBlazor component library. While this was great on the surface level, letting me work quickly in a technology I was familiar with, it came with a lot of issues regarding routing and accessibility.
This post details why this website exist at all, and how its current incarnation came to be.
Motivations
I've lived through a lot of content on the internet disappearing. In the late 2010s, Tumblr and YouTube removed significant amounts of content to appear more friendly to advertisers. Vine and Google+ shut down completely due to competition, and again, monetary concerns. Several big titles in gaming became unplayable — many unnecessarily — because of financial and licensing concerns.
More than that, many major platforms claim excessive rights to user-uploaded content. They use and sell this content to train generative AI.
By keeping the content of this site away from Blogger, Medium, and the like, I can ensure that this content remains online so long as I maintain it, I can choose not to hinder backups by not using any DRM, and I can take measures to prevent its use in training GenAI, which I oppose in many of its current forms because its use threatens the livelihoods of creatives, furthers the destruction of this already-burning planet, and takes all the enjoyment and fulfilment out of the creative process for everyone.
Core Technologies
The primary driving factor behind this was the cost, or rather, lack thereof. Static sites can be hosted for free in many places, which means I save a few dollars and a lot of maintenance time, plus the site can persist at its usual URI for longer if I forget about it for any reason. Combined with the fact that this is largely read-only content (more on that later), there's really no reason to overcomplicate things beyond the intended use of HTTP GET requests.
Another priority for me is to have some level of functionality on mobile browsers. A lot of indie web sites are designed only with a width of around 1920px in mind, which is fair enough for hobbyist devs and those who need the space to properly express their artistic intent. However, as a developer with years of experience and the artistic talent of a stable diffusion model (which, let's be clear, neither you nor I should ever be using), there's really no reason for me not to entertain the idea of someone visiting this site on a phone.
Despite my desire for simplicity, I don't want to have to go through and edit every single file by hand to make a minor change. After much deliberation and extensive experimentation with various technologies, I ended up going with Frozen-Flask, a library that generates a static site using Python's Flask web framework.
I'm using the Markdown package to render blog posts and similar content, and python-frontmatter to work with metadata encoded in YAML format within markdown files (inspired by Microsoft Learn). Sure, I could just write the HTML myself, but this build system lets me abstract away the templating and focus more on the content.
To save some time and effort on the styling side of things, I added in Bootstrap CSS. There's a fair amount of custom CSS too, but I enjoy its layout utilities.
Theming & Rendering
The basic theme of this site is inspired by modern terminal emulators. The colour scheme is primarily Catppuccin Mocha, and the font you'll see the most is Fira Code. Together, these make a pretty good approximation of my Wezterm config.
A lot of pages contain code fences with syntax highlighting. This highlighting is done at compile time using the codehilite markdown renderer extension. Code fences look like this:
#include <iostream>
int main() {
std::cout << "Hello, world!";
return 0;
}
Some also use admonitions (also known as alerts or callouts), a feature of GitHub-flavoured markdown (gfm). Since I prefer the syntax used by GitHub's flavour of markdown, I used the markdown-gfm-admonitions package's extension to add support for it during transpilation, then added some custom styles, including some icons from Octicons. In practice, that looks like this:
Note
This is an admonition.
There's also LaTeX, a markup language for mathematical expressions, which is rendered into SVGs at compile time using mdx_math_svg. Earlier implementations used pymdown-extensions' arithmatex and MathJax 3, but I pivoted because I wanted to minimise the amount of JavaScript on this site. I find that mdx_math_svg also renders some features, like square roots over tall expressions (e.g. \(\sqrt{1\over2}\)) more clearly. In action, LaTeX looks like this:
(Please, don't ask me to explain the position-space Schrödinger equation for a single nonrelativistic particle in one dimension.)
JavaScript (Ew.)
I have a sticker on my laptop that parodies the JavaScript "JS" logo (the one with the black text in the yellow square; not the official one that looks more like the HTML5 and CSS3 logos). It reads, "Maybe you don't need all that JS".
Since the advent of node.js, TypeScript, et cetera, people have started putting JavaScript in everything. I find that in a majority of cases, this is redundant, and only disenfranchises those who sensibly have JavaScript disabled on their browsers.
Below is a list of times I have used JavaScript. If you can imagine an alternative to any of these use cases without JS, please let me know.
The translation feature is fuelled by JavaScript. I feel this one was forgivable, since the alternative would be translating into a variety of different languages at compile time, which would amount to thousands upon thousands of API calls. The "navigation" mode, which takes you to the Google translate webpage, just manipulates window.location.href to put the relevant URI at the start, which is impossible with plain HTML. The "gadget" mode runs a lot more JavaScript on this site, all of it written by Google and released under the Apache software license.
For comments, I'm using giscus, which uses the GitHub discussions APIs to create comment boxes. From this, I get quick notifications, easy moderation, and pretty good spam prevention, without spending a yen or a second myself. JavaScript feels almost necessary here - I think there may be a way to accomplish the same effect with HTMX, but I don't wish to implement it myself.
Other Tech
To test locally, I'm using act, which wraps Docker to allow for the running of GitHub pipelines locally. This way, I can have one process to fully automate the installation of dependencies and the compilation of the static site.