thomas howells is online

Building thomashowellsis.online v1.0

Adventures in static site generation
(2026-07-18)

I think it's fun to have a personal website. And it's even more fun to build it yourself!

I've tried to use static site generators before. I used NextJS (configured for static export) for a fish-and-stream themed single page application social media site that I still haven't finished despite starting over a year ago. However, I got frustrated with just how complex everything is, and decided that for a personal site, I would build my own, since I don't need a virtual DOM, React features, Tailwind CSS, etc. I also wanted full control over the workflow, file structure, and output formats, which are not possible without a custom solution.

Personal website features

I wanted my personal website to be simple, readable, and quick, with basic information about myself on the front page and a blog section. This was the setup for which I wanted to write the SSG, knowing that I could always add more features.

Building the SSG

I wanted a few features for my SSG: - Write blogposts in markdown, keep in a single folder - HTML templates to populate with content - Command line operation, with commands to create new blogpost templates and compile all or some of the blogposts - Embed metadata in posts - Simple and easy development

I ended up choosing Python with a few different packages to achieve this: python-markdown, jinja2, argparse, and frontmatter. While researching other peoples' SSGs, I found that this "stack" was fairly common.

The only roadblock I hit during the development process was fairly early on: the mess that is Python version and package management. I recently switched to MacOS (after using Windows for most of my life, and various Linux distros over the past few years), and my unfamiliarity with some of its particularities also contributed to this confusion. Eventually, after messing about with Homebrew, pyenv, pip, pip3, uv, and MacOS's built-in Python 3.9 interpreter for an embarrassingly long time, I learned that I could embed a shebang line pointing to uv run --quiet and a script that instructs uv which version and packages to use (which would be installed on the fly!).

After getting my development environment setup, the rest of the project went well. I have experience writing Python from high school and undergrad, a computer science degree, and I know how to RTFM.

I ended up with tomblog.py, a few template files, a styles.css file, and a favicon (which I'm reusing from one of my old projects called cursorparty). All of this code is hosted in GitLab.

Creating a personal website

Honestly, the most difficult part of creating the site was the theming. I am very inexperienced in front end design, and usually find it very fiddly and frustrating. Thankfully, in undergrad I partnered with incredibly talented front end designers for our fullstack development projects, so our final submissions always looked good.

Right now, the theming on this site is pretty bare-bones (as you can tell), but this will improve with time.

As for the content on the site: I want this site to eventually serve as a replacement for my LinkedIn (since I hate that platform with a burning passion). Unfortunately, as of now LinkedIn serves as a necessary evil for springboarding and navigating a white-collar career, even if every single person who uses it acknowledges how terrible it is (the idea that middlemen companies like LinkedIn and Indeed can essentially act as arbiters of your professional success frustrates me to no end).

Hosting the site that it outputs

To host the site, I knew I would need three things: - A domain name - DNS records for that domain name - A static site host

For the domain name, I debated for an eternity whether to use my real name or my pseudonym. I know that truly anonymous digital privacy is basically dead at this point anyway (thanks bills C-22 and C-34), LLMs are making it easier than ever to compile and cross reference tiny pieces of data to build a profile on someone, and online advertising tracking and social media recommendation algorithms know more about us than we do, but I still had a big debate with myself on what to do. My pseudonym is not obviously connected to my real name, but it's not professional, so I won't be able to use it in academia (if that's a route I choose to go down after graduating from my MPP).

I eventually bit the bullet and did some brainstorming before eventually settling on thomashowellsis.online. I am a big fan of the "fun" TLDs, and I thought this was a pretty good domain name given my interests.

I did a bit of shopping around for registrars before eventually settling on Spaceship, which had WHOIS privacy and the cheapest fees for the domain I picked. They are headquartered in the US but I don't plan on using this site to do anything that could get me in trouble, so I don't mind. Their web management UI is really terrible, though, and the DNS propagation took a very long time (especially when compared to Cloudflare). Thankfully, all I needed to do was set a CNAME record and a TXT record.

For static site hosting, I went with GitLab pages, since the code was already on there. It's just a bunch of HTML and CSS files as of now, so I don't need anything crazy. Setting up the .gitlab-ci.yml for the deployment was pretty easy because I have experience with GitLab CI/CD from work and my fish-and-stream-based social media site that still has not been launched.

Conclusion

Wow! I did something fun! And made something useful!

I am very happy that I made this site. The theming is in a pretty rough state right now, but that will improve! And I'll gradually add more features to my SSG. The source code is available here if you want to take a look!