
DVD Screensaver
With the boring parts taken out.
2026 · JavaScript, Canvas, Web Audio
I make art with code, paint and hardware, for the space between artists and engineers.
The early web was homemade pages, built by amateurs for each other, and I think money crushed most of it. I still work in that spirit, on a site I host myself. I paint too, and every scribble here started as one of those drawings. Plenty of artists still find code scary, and plenty of engineers think the humanities are a waste of time. I want each of them to see the other side, to come away wanting to make something, and to feel a little freer of the idea that everything they make has to earn money.
The early web was full of people who hosted their own sites, linked to each other and gave away what they knew. Olia Lialina called it the vernacular web: homemade pages, built by amateurs for each other. I think money crushed most of it, and what people picture when they hear "tech" now is what came after: startups, crypto and AI, each with a plan to make money.
I host this site myself, on my own hardware, because that early web is still what I love about the medium. Code is easy to share, it bends into almost any shape, and almost nothing made with it lasts. I love that, even though I just rebuilt three of my old apps after they died on Heroku. Some ideas only work on the web. linger is a set of poems that fill in only if you scroll slowly, because a page knows how fast you're reading and paper doesn't.
A lot of my work isn't code at all. I've started painting, mostly subconscious scribbling and color field work, and it's where I chase what I'm drawn to most: the strange, the surreal and the unexplained. Every scribble on this site started as one of those drawings. Now that AI can generate almost anything, I think a person's hand and taste are the most important things they have to offer.
In 1959, C. P. Snow warned that scientists and literary intellectuals had split into two cultures that could barely talk to each other. Plenty of artists still find code and math scary, and plenty of engineers think the humanities are a waste of time. I want each of them to see what's on the other side, and to come away wanting to make something, whether it's a painting, a web page or a piece of hardware. Most of all, I want people to leave a little freer of the idea that everything they make has to earn money.
Data, objects and the homelab

With the boring parts taken out.
2026 · JavaScript, Canvas, Web Audio
A 32x32 LED pixel art frame behind a two-way mirror, driven by a Raspberry Pi. It plays seasonal pixel art, and Home Assistant pushes to it: ON AIR when my camera turns on, the doorbell, the weather. It's open source, and every scene is a plugin.
2026 · Python, Raspberry Pi, LED matrix

A small collection of poems that only finish for readers who slow down. Each line starts as a few words floating in white space. Hold still and the blanks fill in. Scroll fast and they drain away again. Plain HTML, CSS, and about a hundred lines of JavaScript, with no analytics and no share button.
2026 · HTML, CSS, JavaScript

A macOS screen recorder that drafts the edit for me, because editing is the part of video I hate. I talk through a demo once, and it keeps the talking at real time, speeds up the typing, cuts the dead air, zooms on clicks and adds captions. Then I fix it on a timeline or ask an AI model to change it.
2026 · Swift, macOS, ScreenCaptureKit

A voice-following teleprompter that runs in the browser and listens with a local whisper.cpp model. Read your script out loud and the highlight follows you, through flubs, skips, and ad-libs. You pick the model, the audio never leaves your machine, and the column centers over the camera lens so nobody can see your eyes reading. I built it because I can't memorize lines.
2026 · JavaScript, whisper.cpp, Whisper

A CLI tool for generating [adult swim]-style pre-roll bumpers for your personal media server. Define bumpers in YAML, drop in background video clips and music, and render MP4s ready to load into Tunarr. White text cards, fading audio, your server name in brackets at the end - the whole bit.
2026 · Python, ffmpeg, Plex

A Netflix-style intro for your own Plex, Jellyfin or Emby server, made from its name: pick a style, and you get a title card that moves, ready to play before every movie.
2026 · TypeScript, Runway ML, Plex
A from-scratch Python implementation of MikroTik's proprietary binary API protocol. Handles variable-length encoding, authentication, and sentence-based messaging for programmatic control of network infrastructure - bonding, DHCP, firewall rules, and more.
2026 · Python, Binary Protocol, MikroTik
A production subtitle generation pipeline using GPU-accelerated Whisper (faster-whisper) with NVIDIA CUDA. Features parallel workers, automatic language detection and translation, VRAM-aware scheduling, and time-of-day worker scaling to share GPU resources across services.
2026 · Python, Whisper AI, CUDA
The video years
I spent most of these years making short videos on TikTok.
Conference talks and the internet of toilets
An interactive art installation where audience members draw on a shared digital canvas that displays their creations in real-time on a physical RGB LED grid. Uses MongoDB Realm for instant cross-client data sync. Since retired and replaced by PixelPane.
2020 · JavaScript, MongoDB Realm, RGB LEDs

Welcome to the Internet of Toilets. An IoT-connected cat litter box built with a Raspberry Pi, weight sensors, and Node.js. Monitors usage patterns and sends notifications.
2019 · 25 stars · Raspberry Pi, Node.js, MongoDB

A real-time Spotify player built with React. My most starred open source project. Integrates with the Spotify Web API for custom playback. Accompanied a popular tutorial.
2019 · 131 stars · React, Spotify API, JavaScript
Two-day shipping too slow for you? A Chrome extension that tells you if the product you're browsing on Amazon, Walmart or Target is at a Best Buy near you for pickup today.
2018 · React, styled-components, Chrome Extension

A race for two people on one keyboard, set on an 80s sunset grid. You both ride a white wave that never stops rolling, and the first one to dive through the checkered gate scores.
2018 · 5 stars · JavaScript, Phaser, Arcade physics
A Node CLI and npm package that downloads movie scripts by genre from the Internet Movie Script Database. Tim Kendall started it in 2014; I rewrote it and published it to npm in 2018, and it's where Bechdel.io's scripts came from.
2018 · 14 stars · Node.js, Cheerio, npm
Humanities questions, answered in code

Joseph Cornell's 1936 collage film, with the tint, the speed and the music back in your hands while it plays.
2017 · 2 stars · Astro, TypeScript, WebGL2

An augmented reality scavenger hunt. Scan a printed marker and a 3D arrow points you toward a hidden checkpoint.
2017 · Node.js, Express, A-Frame

A one-day hackathon in Honolulu for projects with no value whatsoever.
2017 · HTML, CSS, JavaScript

Schedule apologies to go out once a month, once a week or every day. Never be sorry you weren't sorry again.
2017 · Node.js, Express, Nodemailer

A text-only social network with the usual levers taken out: no like counts, no follower counts, no trending topics and no images.
2016 · React, Node.js, Express
Every way a client and server communicate - HTTP, WebSockets, SSE, GraphQL, gRPC, and more. A complete reference guide with examples.
2016 · 43 stars · Node.js, HTTP, WebSockets
Common data structures and algorithms implemented in JavaScript. Created as teaching material when I was an instructor at DevLeague. Covers linked lists, trees, graphs, sorting, and more.
2016 · 185 stars · JavaScript, Algorithms

A tanuki who works, drinks and goes home, every night. Fly him home through the dark and grab sake on the way. The drunker he gets, the higher you score, and the faster everything comes at you.
2016 · 2 stars · JavaScript, Phaser, Arcade physics

Vote with your friends on where to go tonight. It finds the bars near you, you pick the ones in the running, and everyone votes from a shared link.
2015 · Meteor, MongoDB, Vite
A small web app that turns any photo into big square pixels. Pick a photo, drag the slider to set the block size, and save it as a PNG. Nothing gets uploaded.
2015 · 15 stars · JavaScript, HTML5 Canvas
Generates unique Sudoku boards across 4 difficulty levels with a built-in solver using backtracking.
2015 · 90 stars · Python, Algorithms, Backtracking