Side projects, mostly: a design system I published to npm, an app that tells you when it isn't sure, and five thousand years of civilization wound into a single turning sky. I keep making them because I genuinely love this part of the work, and because I have never really understood something until I have built it and watched where it breaks.

Understory · React + TypeScript · On npm
Understory is a typed React component library I built and shipped to npm. I wanted to find out whether I could still author components myself instead of handing someone a spec and hoping, and the answer turned out to be yes: polymorphic components, accessibility wired in properly rather than bolted on afterwards, a full Storybook, and a CI check that stops a broken release going out.
The most useful part was rediscovering how many decisions a spec quietly leaves to whoever implements it. Writing the code changed how I write the spec.
View the Storybook ↗Source on GitHub ↗
Mobile app · React Native · Claude + iNaturalist
I have loved mushrooms for years, as food, as an aesthetic, and mostly for the sheer strength of what they are capable of. Fantastic Fungi tipped that into something more deliberate, so I took classes and learned to forage properly, and what I kept wanting was a companion for it: a Pokédex for the forest floor, where you find them, learn them, and slowly come to understand them. Sporeprint identifies mushrooms from a photo, and the design challenge turned out to be the opposite of what I expected: the hard part was not making the AI feel confident, it was making it honest.
Getting an identification wrong can genuinely hurt someone, and that stake changed how I approached every screen. The whole interface is built around showing uncertainty instead of hiding it, and it has taught me more about designing for AI than most of my product work has.
Read the case study →
Data visualization · 331 civilizations · Live
An interactive astrolabe charting 331 civilizations across five thousand years. I built it to find out whether deep time could be felt rather than only read about, and the first time the rings filled in and five millennia sat in front of me at once, I had my answer.
It became a long argument with myself about how much data a single view can hold before it stops meaning anything, which is a question I run into at work constantly, just with dashboards instead of dynasties.
Open the astrolabe ↗