Here's a curated list of some of the more interesting and fun projects that I've worked on over the years.
After a summer internship working directly with Kubernetes, I became interested in trying to host some of my own services within a Kubernetes cluster. After exploring managed options like EKS, GKE, DOKS, and more, I decided that the cost of a multi-node, highly-available cluster was not justifiable with my simple ambition of "just run it in Kubernetes". After looking around at possible solutions, I decided to set up a single-node K3s cluster on an $18/month DigitalOcean droplet.
Also mirroring some techniques I picked up over the prior summer, I decided to try and provision the underlying infrastructure using Terraform under an infrastructure-as-code model. This Terraform module includes the DigitalOcean droplet, the DNS records for the cluster, the public/private network configuration, and firewall rules.
To secure/isolate my cluster, I opted to set up Wireguard on the Kubernetes node and configured the control plane to bind to the Wireguard interface. I was also able to set up my home server as a peer via Wireguard, which I then configured as a sort of "metrics replicator". I'm running VictoriaMetrics in the k8 cluster while my home server exports metrics to its own Prometheus/Grafana monitoring stack.
I'm currently running only one or two services in my Kubernetes cluster, so the value add of running an entire Kubernetes node
is perhaps questionable at the moment. Nonetheless, I think the whole ordeal of transforming a bare-metal (OK, it's a DO droplet, but whatever)
machine into a functioning cluster complete with metrics, Traefik routing, etc. was very valuable and a fun challenge. It's also very
nice to deploy rolling, validated updates to the few services running in the cluster with a single command compared to my prior method
of SSHing into my home server and running a bunch of docker compose
commands.
During the winter semester of my junior year at the University of Michigan, I enrolled in EECS 498-007 Game Engine Architecture. This course focused on building a multipurpose 2D game engine with Lua scripting and a component-based architecture.
This game engine was the single largest project I've worked on for University (and close to some of my other projects) and I learned a lot about designing a performance-critical, developer-facing piece of software.
Throughout the development of my "Sage Game Engine" (or sge
for short), I integrated several third-party dependencies
and made use of tools like:
At the end of the course, our final assignment was to design and implement a completely new feature of our choosing into our existing game engine. Because I mostly play multiplayer games, and because I thought it would pose an interesting technical challenge (it certainly did!), I chose to add multiplayer capabilities to my engine.
To make multiplayer "just work" for the game developer, I added the idea of a component existing in a certain "realm". A component can run
on the server, on the client, on the owner client, or be "server replicated", in which case it exists across all clients and the server.
Below, I show the message flow for replicating a Transform
component representing the position of an actor in the scene.
If you're interested in learning more about the multiplayer capabilities of sge
and how they came to be, I recommend you watch the
following two videos I recorded for my class:
I maintain an open-source framework for connecting your Go application to Twitch's EventSub API. The main goal is to enable simple dispatching of EventSub Webhook requests to your application code, letting the framework deal with the HMAC verification, unmarshalling, routing, etc.
// Create my handler with no secret key verification handler := eventsub.NewHandler(nil) // Process channel.update EventSub notifications handler.HandleChannelUpdate = func(h bindings.NotificationHeaders, sub bindings.Subscription, event bindings.EventChannelUpdate) { fmt.Println("Got a channel.update notification!") fmt.Printf("Channel = %s, Title = %s\n", event.BroadcasterUserName, event.Title) } // Listen for HTTP requests from Twitch EventSub servers http.ListenAndServe("127.0.0.1:8080", handler)
Recently, in a v2 redesign of the framework API, I've moved to a code generation method for dealing with the ever-growing number of EventSub events and bindings. Reproducible code generation based on simpler Go struct definitions allow for a more maintainable and stable framework.
Tired of standing around waiting for other University of Michigan bus tracking apps to load, I decided to create my own arrival times viewer in the form of an Apple Watch app. MBus Arrival Times, available here, uses your GPS to determine which bus stop you are standing at and displays data about the next arriving busses.
I've also published the source code for interacting with the University of Michigan's BusTime API at https://github.com/dnsge/mbus-ltp-api.
Note: There are many talented people that also work on Chatterino! I am just one contributor.
I've been contributing to the 3rd party Twitch chat client Chatterino since early 2020. Over the years, I've worked on multiple parts of the application. For example, one feature I'm particularly proud of is message filtering using a custom programming language (unfortunately, I designed the filtering language before taking a theory of programming languages course).
Another feature that has greatly improved the Chatterino chatting experience is layered emotes. Certain custom emotes in Twitch chat can be layered on top of each other, leading to great combinations (pictured below). I worked on making layered emotes a first-class entity within our message rendering pipeline and greatly improved the accessibility around viewing them.