These are the projects I like to work on, in no particular order. I prefer to open source everything I do, but sometimes the end results is more important than the code, as is the case with We Ride. The code is a bit of a mess, and that’s ok! We Ride is a utility for me to find gravel and mountain bike partners.

Bench, Bicycle Workshop Manager Bench is a SaaS that streamlines managing bicycle workshops A local-first social network for cyclists
neoq A queue-agnostic background job framework for Go
ess (env sample sync) Automatically keep .env files in sync with env.sample
di-tui A terminal UI player for premium
hugo-htmx-go-template A Hugo project template for making dyanmic Hugo sites. It's weird and I love it

Bench, Bicycle Workshop Manager (

Bench is the only business venture that I’m comfortable sharing as one of my “projects”. Primarily because it’s not only a business venture, but adjacent to one of my primary pastimes – cycling. Noticing that bike shops almost universally lack a good online service booking experience, I suspected that most shops lacked good software systems for managing work orders. So I started talking to mechanics and shop owners about how they manage their bike workshops. Eventually those conversations turned into Bench.

We Ride (

We Ride is a local-first “social network” for cyclists to find riding partners and join group rides in their local communities. While “social network” is roughly how I describe it, the end goal is not to have large network effects and claim a large percentage of the world’s cyclists. It’s a tool that I built for myself.

Since I spend a lot of time traveling, I’m often in new places where I don’t know any other riders. So to find new gravel routes, or to safely ride more consequential mountain bike trails, I need to tap into local rider base and knowledge. So what I do is create a We Ride and post about it in the local Strava clubs. Strava clubs tend to not get many posts, even if they’re over 1000 members, so when a new post arrives, a lot of people end up seeing it since by default Strava notifies club members of new posts.

If there are no local Strava clubs, a lot of trail systems have a cork board for posting community information. We Ride has a “Print QR Flier” feature that I can use to print fliers for trailhead cork boards.

We Ride also allows you to upload GPX routes and import them from Strava, which is my preference since I like to build ride routes in Strava.

Neoq (

Neoq is a background job framework for Go. Its central thesis is that background jobs shouldn’t impose any additional infrastructure on projects. Neoq could hardly be simpler to use and has a pleasant API that makes writing background jobs dirt simple.

Does the world need another background job framework? No, but I do. I work on a lot of projects that never see the light of day. I’m ok with that, especially when I haven’t put a lot of time into building infrastructure and code for them.

What does that have to do with Neoq? Since Neoq can be backed by in-memory queues, Postgres queues, or Redis queues – it’s easy to match my application infrastructure with my background job infrastructure. For development/non-critical jobs, I use in-memory queues, and for “production” I use either Postgres or Redis, depending on my needs, without changing a line of application code. This makes it easy for me to get projects off the ground without creating additional infrastructure for background jobs.

Example in-memory job handler code

ctx := context.Background()
nq, _ := neoq.New(ctx)
nq.Start(ctx, "hello_world", handler.New(func(ctx context.Context) (err error) {
  j, _ := jobs.FromContext(ctx)
  log.Println("got job id:", j.ID, "messsage:", j.Payload["message"])

Now, all you have to do is add jobs.

nq.Enqueue(ctx, &jobs.Job{
  Queue: "hello_world",
  Payload: map[string]interface{}{
    "message": "hello world",


ess (

env-sample-sync - automatically keep .env files in sync with env.sample.

Your .env is always in .gitignore, right…right?! So how do you document what goes in it? Easy, add a file named env.sample to your project and check it in to git.

The problem is that env.sample rarely gets updated when new environment variables are added to applications. ess is the solution to that problem.

Users can document .env with comments and extensive details about how env var values should be structured, or where one can get/generate values for them.

Example .env


# I got this FOO from the detailed process documented at: http:://
FOO="My super secret value for foo"

ess converts the above .env example to:


# I got this FOO from the detailed process documented at: http:://

After syncing the sample, it is immediately git added, ensuring that your sample is always up to date with reality.

di-tui (

A terminal UI player for premium.

There’s not much more to say about this one. I use this virtually every day that I’m at my computer. I’m using it as I write this, in fact.

It’s totally unnecessary, and I love it.

hugo-htmx-go-template (

Hugo is a fantastic static site build tool, and there are few things about Hugo that can or should be improved.

The existence of this project template should in no way suggest that static sites should be dynamic. If your site can be static, it should be static.

Yet there are instances in which one might need to add dynamic functionality to static Hugo sites. That is the purpose of this project template. Not to make all static sites dynamic, but to provide a simple solution to add islands of dynamic behavior to static sites.

This allows us to build fast, easily deployable HTML content, but with the added ability of meeting a new class dynamic behavior needs.

Example use cases include

  • Contact forms
  • Comment systems
  • Up/Down vote systems
  • You know … website stuff

You shouldn’t have to reach for a SaaS product to offer dynamic content on your static sites.