Tom's website

Projects

This is the list of my open source projects. Most are licensed under MPL 2.0, which is my favorite license these days. I've added a short annotation to each project to explain my motivation. Favorite projects are marked with a star.

go-simpler

Link | Source | Stack: Go, HTML, CSS

A collection of Go packages built with โค๏ธ

This is where most of my Go projects live. It started as a few packages hosted on my personal account, but at some point I thought it would be cool to create an organization. The goal is to eventually make it a community of people who share the same love for minimalist Go packages.

As you probably know, Go requires importing packages with the full URL. Given the direction GitHub has taken, I didn't want to depend on it too much. That's why I decided to use vanity imports, so if I ever need to change hosting, it won't affect my users.

env

Source | Documentation | Stack: Go

๐Ÿ” Load environment variables into a config struct

This was one of my first open source projects. I wasn't happy with the mainstream config libraries for Go, because I find them bloated with features (looking at you, Viper). Being a fan of the 12factor methodology, I decided to focus on environment variables.

While the implementation is straightforward, working on it helped me to learn a lot about designing a good library API. During development, the API went through multiple iterations, including functional options. In the end, I decided to keep it as close to the standard library as possible, since that is what all Go developers are familiar with. I kept only essential features, while allowing user-defined extensions via Go interfaces.

I may add some convenience helpers in the future, but for now I consider this library mostly complete.

sloglint

Source | Documentation | Stack: Go

๐Ÿชต Ensure consistent code style when using log/slog

I was super excited when structured logging finally made it into the standard library. I was less excited about some of the API choices made, specifically supporting two argument types behind ...any. I'm actually fine with both styles, but I'd rather have a separate set of functions for each.

It's common to fix Go problems with static analysis (see vet checks), so I decided to take the same approach to make using slog in production a bit more pleasant. That's how sloglint was born, and today, with a lot of checks added, I consider it a good supplement to slog.

Since sloglint is integrated into golangci-lint, which you probably already use (if not, you should), it's super easy to give it a try, especially if you're just getting started with slog.

musttag

Source | Documentation | Stack: Go

๐Ÿš” Enforce field tags in (un)marshaled structs

This linter is a bit more opinionated, but I find it useful in almost any project that has some sort of communication. The idea is that when Go struct tags define a contract between parts of the system (e.g. json for REST API), they should be written explicitly to avoid accidentally breaking the contract.

goversion

Source | Documentation | Stack: Go

๐ŸŽฒ Easily switch between multiple Go versions

I once needed to test a project with multiple Go versions to find a regression bug. Although Go already supported installing multiple goX.Y binaries, the project had the go command hardcoded everywhere, so it was quite inconvenient to test with different versions. The solution I came up with was to temporarily symlink go to goX.Y, so I quickly wrote a script to do just that.

It worked quite well, and based on this script I built goversion, a full-featured Go version manager. Unlike analogues, it's cross-platform (yes, I even tested it on Windows) and depends only on Go itself. Although Go 1.21 later introduced a similar feature, I still use goversion for explicit version management.

sloggen

Source | Documentation | Stack: Go

๐Ÿชต Generate domain-specific wrappers for log/slog

This project was initially born out of the same complaints about the slog API that led to the creation of sloglint. The classic answer to any API problem is to wrap it. sloggen does just that: it generates wrappers from a simple config, so you can easily adjust the slog API to your specific needs, such as allowing only slog.Attr fields or making all functions accept a context.

sloggen is useful even if you're happy with the vanilla slog API: it can be used to generate key constants and custom levels with all the necessary helpers. Also, if multiple services share the same domain, an sloggen config can be used as a single source of truth.

assert

Source | Documentation | Stack: Go

โ˜‘๏ธ Assertions for the standard testing package

I'm not a fan of testify. I find its API clumsy (e.g. want before got) and easy to misuse (to the point that testifylint exists). I get that in the Go community it's the assertion library, but for my personal projects I prefer something simpler.

I used to carry a few useful assertions with me, but after many projects it became harder to keep them up to date in all places. I combined them into this package, although the code is still small enough to just copy and paste, which I find preferable for libraries (I'm a sucker for empty go.mod).

errorsx

Source | Documentation | Stack: Go

๐Ÿงจ Extensions for the standard errors package

This is just a bunch of helper functions for error handling that I used to copy between projects. While I wish some of them were in the standard library, I understand why they are not.

queries

Source | Documentation | Stack: Go

๐Ÿ‘ท Easily build SQL queries and scan the results

The one thing in software development that I have never understood is ORMs. I mean, as a backend developer you have to work with SQL anyway, so why add another abstraction on top of it? On the other hand, I think query builders are almost always useful. This is yet another one, but unlike most query builders, it is based on string formatting. Think of it as the fmt package + special verbs for query arguments. This is probably the closest you can get to writing raw SQL with the benefits of a query builder.

As for the query scanner, in my experience, as soon as you need a query builder, you almost always want to conveniently scan query results into structs, so why not include it in the library as well?

check

Source | Documentation | Stack: Go

โœ”๏ธ Write any validations declaratively

This was a fun little project, sort of a proof of concept. While it helps to save a few lines, it does not necessarily make things more readable, so you should probably not use it.

libds

Source | Stack: C, Make

๐Ÿงฑ Data structures implemented in C

While I feel pretty comfortable with programming in general, I have always struggled with two things: low-level stuff and DSA. I also find that the best way to learn a new technology is to build something with it. So I decided to kill two birds with one stone and learn C by implementing fundamental data structures. I started with a hash table because it's probably my favorite one. I had a lot of fun writing this library, and I'd like to dive deeper into low-level programming in the future.

I also really liked the idea of explicitly passing allocators from Zig, so I added support for custom allocators to this library.

dotfiles

Source | Stack: Lua, Python, Shell

๐Ÿ—ƒ๏ธ My dotfiles for macOS and Linux

I just love it when I can turn a new machine into my own by running a single script. I think it's totally worth the time spent on all these configs.

The main highlight here is probably my Neovim config, as it took the most effort. It's my primary editor these days and the main reason to learn Lua.

It was such a relief when I finally took the time to organize all this stuff properly. Now my precious dotfiles are safe forever!

porkcron

Source | Stack: Python, Docker, systemd

๐Ÿ” Automatically renew SSL certificate for your Porkbun domain

porkcron = Porkbun + cron. As always, it started as a tiny script, but grew quickly with convenient configuration, installation helpers, and support for Docker and systemd. It now handles certificate renewals for all my websites.

Go styleguide

Link | Stack: Markdown

I have always liked Uber's Go styleguide. With a few exceptions, I agree with all of its points. As I gained more experience, I came up with some preferences of my own. I find them a bit too opinionated to be upstreamed, so I wrote this document instead. It serves as general recommendations for contributors to go-simpler.

CI workflows for Go

Source | Stack: GitHub actions

I find the ability to reuse jobs and maintain them in a single place to be a great feature of GitHub actions. I miss something similar in other CI systems. This collection powers up all my Go projects.

Swiftbar plugins

Source | Stack: Python

I like the idea of putting the output of any script in the menu bar, it's simple yet flexible. It works well for me for things like package manager updates or quick access to Docker containers. Swiftbar is only available for macOS, but as I slowly move everything to Linux, I may port my plugins to a similar app as well.

Leetcode solutions

Source | Stack: Go, Python

There are not many solutions here because I quickly lost interest in solving problems without a clear goal. However, I'm going to get back to it after I spend some time improving my DSA skills.

I prefer to write solutions in my local environment, so I also implemented a problem template generator, which grabs everything needed from the LeetCode API.

Personal site

Link | Stack: HTML, CSS, Go

I have always liked coming across personal websites while browsing the web. It feels cozy to navigate hand-crafted pages compared to the corporate web. I also find it a great way to get to know a person: unlike social media profiles, the whole website is yours, not just the content. I wish more people would create personal websites these days.

Mine is built from scratch with vanilla HTML/CSS and Go for static generation. I didn't want to use any fancy frameworks or pre-built themes, just the good old reliable tools. I'm far from frontend development, so this is probably the best I can do for now in terms of developing websites :)

Personal wiki

Link | Stack: Markdown, Go

Not much to add here, see the wiki page.