UpWeb.

DISPATCHESARCHIVE

I brought KeyEcho back, and got my first paying customer

Two years ago, I left KeyEcho at 0.0.5. The code stopped. The issues didn't.

KeyEcho is a desktop app that makes any keyboard sound like a mechanical one. Put on headphones and the sound stays in your ears. Nobody around you hears it, and it's easier to get into a flow. I open-sourced it two years ago, and after it passed 800 GitHub stars, I stopped updating it.

This past week I shipped 1.0. The first thing I did after shipping was go back to issue #40. For two years, someone had been waiting there for the IBM Model M sound. I told him Model M is in the recording queue now, and I put up a $9.99 Founding Bundle. He paid the same day. KeyEcho's first paying customer.

One $9.99 order doesn't prove KeyEcho has a business model. But it's a real signal. Through those two quiet years, the person who asked never left and the need didn't go away. The product came back, and he was still there to pay.

The sale wasn't the only signal. In the first days after 1.0, the auto-update channel that had sat quiet for two years got pulled more than 80 times. The old users were there the whole time. Nobody had said anything to them in two years.

To get KeyEcho to 1.0, I merged one PR across 130 files: 11,405 lines added and 9,292 removed. It included the Tauri 1 to 2 migration, Windows signing, macOS notarization, Linux x64 and ARM64 builds, and a rewrite of the audio hot path.

After the rewrite, the cached-lookup microbenchmark dropped from 1184.07 ns/op to 43.50 ns/op. That's 27.2x faster on average, and 38x on the largest audio slice. The number only covers the lookup path. It isn't the end-to-end delay from keypress to sound.

I wrote the whole thing up as a technical recap. It covers how the hot-path rework actually works (predecoding, shared buffers, dropping the global mutex), what the AI agent did across those 130 files, and the one fix it suggested that passed CI clean and would have quietly broken a feature. I rejected that one, and it's the best part of the story.

Read the KeyEcho 1.0 technical recap

Want to hear it? You don't need to download anything. Open keyecho.app, type in the browser, and the sound comes out. You can vote for the keyboard you want to hear next. IBM Model M already moved up the queue because of him, and an early preview build went out to him yesterday.


There's a second thread this week.

upweb.dev moved from Nuxt 4 to SolidStart, and keyecho.app is built with SolidStart too. Both sites use vanilla-extract for styling.

I care more and more about whether AI can read and respect the constraints a project already has. AI writes Tailwind and UnoCSS fast, and it rarely produces something that won't compile. The trouble shows up later. The project has its own design tokens, but the model reaches for the default classes it knows best, or it keeps adding arbitrary values. The page looks fine. Underneath, the design system is slowly coming apart.

Next issue I want to write about choosing a frontend architecture in the AI era, why I use SolidStart for upweb.dev and keyecho.app, and why TailwindCSS and UnoCSS are no longer my default.

As always, hit reply and tell me what you're building right now. I read every one.

Zach