Welcome to my space. Let me tell you about some of the stuff I have worked on.

To those visiting hoping to find a resume, be warned this site is more of a narrative than a straightforward resume.

TL;DR

Voting

I have this crazed obsession with voting methods. I just wanted to get the best result when voting on a game for board game night, but maybe I went a bit too far...

Go Vote Tally

2013-2014

All of my side projects are partially rooted in learning something new. At the time, I was learning Go and so I wrote a few different voting algorithms in the Go playground. I started with Borda, then went to instant runoff (IRV) and then eventually landed on a (highly questionable) blend of both.

Indifference Engine

I was tired of sending a survey out and then manually entering the survey data into my program. I started on the Indifference Engine (source; old broken site), so called because it allowed for people's ranked choice votes to have ties in them. It started out based on my earlier IRV / Borda blend but eventually was migrated to the minimax method.

Indifference Engine Screenshot

I spent quite a bit more time on this project and learned about Node.js, Express, publishing packages on npm, MongoDB, Heroku, unit testing in Mocha, test coverage in Coveralls, CI/CD on Travis CI, Bootstrap, and using templates in Dust.js.

No More Voting!

Revonarchy

I got tired of my favorite games never getting picked, so I decided to move away from voting to let people just pick a game and then rotate who picks the game each time. The problem that quickly showed up was that some people would only show up rarely and yet got to pick just as often, Thus Revonarchy was born. (Source; site was never deployed)

Revonarchy was relatively short lived but I still learned some great stuff including Bower, Koa, Less, Gulp, Ramda, and most importantly React.

A Triumphant Return to Voting

Majority Judgment

After a long hiatus, I decided to go back to the drawing board with voting. I had been reading about this new interesting voting method known as Majority Judgement. I implemented a modernized board game night voting site (source; site no longer deployed).

After learning a lot of frontend work in my day job, this project became focused on learning more backend and devops. I used Elixir's Phoenix Framework for the backend and deployed it using CircleCI and Amazon ECS. The frontend was React using nivo for charts, Bulma for CSS, and webpack for bundling.

All The Voting Methods, At Once

Star Judge

With kids and people moving away, I haven't had as many big board game nights as I used to. Plus everyone just defers to me for board game choices anyways. But after years of not thinking about it, I came back to it again curious about advancements in voting methods and curious to get my feet wet with my first foray into vibe coding.

Star Judge takes one set of ratings and runs them through eight different algorithms simultaneously — STAR and Majority Judgment (the two eponymous voting methods), Borda, instant runoff, Condorcet, a couple of "intolerant veto" variants that drop options with too many hard passes before tallying, and, last but not least, the Dictator. The fun part is the mock scenarios: Condorcet cycles, STAR runoff flips, and the classic Tennessee capital example where Memphis wins plurality but loses every single head-to-head, Nashville wins by Condorcet, and IRV somehow elects Knoxville. Deployed at star-judge.willcolton.com (and at the underlying star-judge.pages.dev).

The main thing I wanted to learn was Claude Code. I had already spent a lot of time with Github Copilot at work, but the buzz at the time was that Claude Code was the best-in-class AI coding tool and I wanted to try it for myself.

Star Judge Screenshot

The frontend is SvelteKit 5 with Runes. The API is Hono on Cloudflare Workers, talking to a D1 SQLite database. Linting is Biome. The animated bar charts are pure CSS — no chart library. I learned nothing about Hono or Runes, because the AI just did all that for me. In the end I found the project deeply unsatisfying. Since the point of side-projects is mainly to learn, I plan to rely much less on vibe coding in the future.

Gaming Side Projects

Sensors Are Down

I have always loved designing and programming video games, but the problem is that video games have a lot of art and I do not enjoy making art.

Enter Alexa. I could make an audio only game! I decided to create an Alexa space combat game (source; never published).

In the end, I created something that just wasn't very fun. I fell into the trap of making a system too complex considering you cannot see the current state. I think I had some good ideas and I have follow-up ideas for redesigns but I shelved the game for now.

Sorry for poor audio quality

This project involved mostly learning various AWS technologies that go into making an Alexa skill. I used an AWS Lambda which I deployed to using the Serverless Framework. I also tried typed JavaScript for the first time but picked a losing horse and used flow-typed.

Instantaneous Card Game

Scala.js

2018

I love card games. I could write about that topic alone forever but suffice it to say, I had an idea for a collectible card game where you build the deck and then the game plays itself where the winner is whoever had the better deck.

I made an early prototype in Scala.js (source; site). I stopped mostly because the Scala.js ecosystem was incredibly barren with lackluster tooling and few tutorials which were all broken and out of date.

Over the holidays that year I discussed the idea with my brother and it was rekindled. Conveniently, I got a Humble Bundle with a bunch of card art assets for use in Unity, so I decided to build the game in Unity (backend source; game not released).

The game client was coded in C# and built with Unity. The backend was coded in Python deployed to AWS Lambda with the Serverless Framework.

Making a Real Game

Boats and Bridges

In 2016, I made a couple modified hashi puzzles for my wife and friends to solve. I really enjoyed making the puzzles and thought maybe I could make a puzzle game similar to the Hexcells series except instead of modified minesweeper I would do modified hashi.

The idea evolved over time but eventually I started working on a level solver and accompanying level editor to build some puzzles. (level editor source).

I spent a lot of time on a 3D Unity implementation of the game but every time I developed new visuals they would either not look how I wanted or they would obscure the gameplay elements to the point of being a net negative for the game. After spending a long time on a pencil hatching shader and being disappointed with the results, I took an extended break from the project.

Unlike most of my projects, this project was much more focused on execution rather than learning new technologies. The level solver was built in node with a heavy use of lodash for array manipulation. The level editor was just vanilla ES6 JavaScript using babel to transpile and webpack to bundle. I had a brief diversion where I learned Rust and started migrating the level editor to Rust for performance improvements.

Boats and Bridges, Take Two

After a few years away I came back to the idea, this time as a web game. I figure I can more easily actually finish if it is based on technologies I already know and love. The result is the closest thing in this museum to a "shipped" project: it is live at boatsandbridgesgame.com (source), people actually play it, and the URL still works.

The one thing I regret about it is the art. The board and card illustrations were generated with Midjourney when image generation had just become good enough to be interesting. By the time the game actually shipped, the gamedev community had turned hard against AI art, with good reason, and as a result the art has aged badly. If I rebuilt the visuals today I would do the art myself or partner with an artist.

Stack is SvelteKit (with Svelte 5 runes), TypeScript, hand-written SVG for the puzzle rendering, and Vercel for hosting with their analytics built in so I can see when anybody is playing. Out of all the frontend frameworks I have used, SvelteKit has been one of my favorites. Definitely glad I learned it and I plan to use it more for future projects (even if I could never get work off of React).

Designing My Own Board Game

While Boats and Bridges was on the back burner, I had been quietly designing a different game on the side — a competitive sci-fi card game called Defend the Drill, where each player crews their own drill (an unlicensed copy of a Dune spice harvester) on a hostile planet, fending off threats and racing to be the player who comes out with the most loot. This one was never going to be a video game; the target was a real tabletop game, with Tabletop Simulator as the playtesting environment.

Defend the Drill

The first version was a small Node script that took card definitions written as plain text and rendered them into card-shaped PNGs with Jimp, ready to drop into Tabletop Simulator as a custom deck. Crude but it did the job — I could write a new card during dinner, regenerate the deck, and have it on the table for playtesting that night.

A few years later I did a proper rebuild. Card data now lives in a Google Sheet so I can rebalance numbers between playtest rounds without recompiling anything; a build script pulls the sheet down, runs it through a Svelte component that renders each card, and uses Playwright to screenshot the rendered cards into the sheet-of-cards PNGs that Tabletop Simulator expects for a deck. Sharp does the final image processing.

The whole thing is a board-game asset pipeline pretending to be a Svelte web app.

Prototyping in PuzzleScript

After Boats and Bridges shipped, I wanted to keep doing real game development but without ever opening Unity again. Before committing to an engine I spent a stretch making small puzzle-game prototypes in PuzzleScript, the in-browser puzzle-game engine where the whole game — graphics, rules, levels — fits in a single text file.

PuzzleScript prototypes

2024

PuzzleScript is brilliant for this kind of thing: the iteration loop is essentially "edit the file, hit Run, the game is in your browser." You can have a brand-new mechanic playable in under an hour, which means you find out very quickly whether an idea is fun or whether you've been politely fooling yourself for three weeks. (Details on the specific prototypes coming soon — I will fill this in with the games and screenshots.)

The one that survived the round of prototyping was a sokoban variant about pushing takeout containers around without spilling them. That one I decided was worth building for real in a proper engine.

Soko-Bun (Takeout Containers)

2024-2026

So Soko-Bun is the Bevy version of that prototype. Bevy is interesting to me in a way Unity has not been for a long time — Rust as a games language, ECS as the world model, and a build pipeline that was actually fun to set up: native dev builds with dynamic linking for fast iteration, release builds that target both desktop and WebAssembly in the browser.

The point was as much to learn Bevy and ECS as it was to ship the game.

It is on hold right now. The recent wave of AI tooling pulled my attention away, and I would rather understand what is happening with LLMs while the field is still moving fast than keep grinding on level six of a puzzle game. I will come back to it.

Fun with Family

My family does an annual get-together where we play games and solve puzzles together. For the occasion I decided to make a little quiz game, sort of a cooperative version of sporcle. I used the opportunity to learn Gatsby and sharpen my skills with websockets (backend source; frontend has private source and implementation).

It was my first time using any sort of react based static site generator. I found Gatsby to be annoying to use especially their GraphQL internal api. I had been working with TypeScript at work a bit and so I started developing all side projects in TypeScript starting with this project. I deployed the frontend using CircleCI for CI/CD and Amazon S3 to host. I learned Auth0 for authentication and authorization.

I used an aws official sample for a chat app as the foundation for my backend. I deployed the backend using Serverless and included Lambdas, DynamoDB, and ApiGateway from AWS.

Convention Schedule

Before the 2022 family get-together I decided to make a digital schedule. I added some functionality where attendees could pick which games they were going to join (source; site - use username Will and give it a few minutes for vercel to start the server before refreshing and logging in).

I had the pleasure of building this site using Next.js and deploying using Vercel. It made my life really easy and I ended up switching our frontend to Next.js at work off of this experience. For styling I used Bulma and as a database I used AWS DynamoDB. I continue to update the schedule every year for the family get together and I continue to be happy with it.

The museum is its own exhibit

Next, I want to talk about the very site you are on right now. The plan was always to implement the museum in several different UI frameworks — partly as a low-stakes way to pick up a new framework without inventing a whole new project for it, partly as an apples-to-apples comparison of how those frameworks perform on a simple two-page site. Each of the older versions has more or less become its own side project at this point; they all still live at their own subdomains.

Create React App

2020-2022

The original. Plain React with Tailwind, statically built, deployed to AWS S3 + CloudFront. Lives at cra.willcolton.com (source). It establishes the baseline — everything else gets measured against this one.

Deno Fresh

2022-2023

The first port — same content, run through Deno Fresh with Preact islands hydrating only the bits that need to be interactive. My first taste of the islands architecture, which I would much later come back to with Astro. Lives at fresh.willcolton.com (source).

SvelteKit

2022-2026

The longest-lived implementation; it was the canonical museum URL for years. SvelteKit on Cloudflare Pages, Tailwind for styling. Notably it was my first encounter with Svelte 5 runes, which I liked enough that they're now also driving the islands in this Astro version. Lives at svelte.willcolton.com (source).

Astro

2026

This implementation, updated with the latest projects and content. Astro with a single Svelte 5 island for the lazy-loading video player; everything else is plain static HTML, and the TL;DR page ships literally zero JavaScript. Tailwind for styling, a typed data module for the section content so adding a new project is a content edit rather than a new file, and a Vitest + Playwright test suite that also runs in CI. Deploys as static files on Cloudflare Pages.

The idea was to eventually set up a real comparison across the implementations — bundle sizes, Lighthouse scores, time-to-interactive on identical content. Instead the museum is a casual cross-section of where the JavaScript ecosystem has been over the last several years, with the bonus that I get to learn a new framework every couple of years without having to come up with what to put in it.

Learning Modern AI From Scratch

Rules RAG

2026

Coming off Star Judge, where I had let the AI do most of the work and walked away without really learning anything, I wanted a hands-on project to actually dig into retrieval-augmented generation.

Rules RAG is a board-game-rules chatbot. You ask "how does the auction phase work in Brass" and it answers with a quoted passage from the actual rulebook and a page citation. But, even more than most side projects, I care less about the project itself and more about the underlying technologies I am trying to learn.

The whole thing is a Rust workspace and I am trying to make it as idiomatically Rust as possible. I am using clippy::pedantic to make sure I do as much the "rusty" way as possible. Embeddings and answer generation go through Ollama locally; vector storage and full-text search both live in LanceDB. I built an eval set so that when I add a new technique I can validate the technique and get that satisfying "number go up" reward.

Rules RAG Screenshot

This one I am writing myself, with Claude as a collaborator I can ask questions to rather than as an implementer.

Thanks for stopping by!