I built a keyboard this week. Not bought, built: a 60% hotswap kit, a bag of switches, stabilisers that needed lubing, and a PCB that arrived with a slightly worrying note about "check the diodes" on the listing. The soldering was the easy part. The firmware is where I lost an evening.
The hardware first, because it's the satisfying bit. The plate goes on, the stabilisers clip in (clip them in before you regret not clipping them in, they do not go in afterwards without removing keycaps), and then it's just switches into sockets. A hotswap board means no soldering the switches themselves, which is the modern luxury. The stabiliser lube is the fiddly job: a thin smear of dielectric grease on the wire ends and the housing, and suddenly the spacebar doesn't sound like a stapler.
Then QMK. The idea is lovely: your layout is C, you compile it, you flash it, the board is exactly what you tell it to be. The reality on a fresh machine is forty minutes of toolchain.
qmk setup
qmk compile -kb my_board -km default
The first command wants to clone a large repo and install a pile of AVR and ARM toolchain bits. The second failed because I'd guessed the keyboard name and it wasn't quite right; qmk list-keyboards | grep -i myboard sorted that out. Then it compiled, produced a .hex, and I flashed it by shorting the reset pads and running qmk flash.
The actual customisation is where it earns its keep. I wanted a layer for arrows under the right hand, because reaching for a dedicated arrow cluster on a 60% is the whole point of not having one. A few lines in keymap.c:
[1] = LAYOUT_60_ansi(
KC_GRV, KC_F1, /* ... */,
/* HJKL as arrows on the function layer */
MO(1), KC_TRNS, /* ... */ KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT
)
MO(1) is momentary layer one: hold it, the layer is live, release it, you're back. That single concept is most of what makes these boards worth the bother. Caps lock became a layer toggle and I haven't missed caps lock once.
What surprised me is how much of the time went into things that aren't typing. Debouncing, tap-hold timing, the exact TAPPING_TERM that decides whether a key counts as a tap or a hold. Set it too low and fast typing triggers your hold actions; too high and the board feels sticky. I landed on 180ms after a few rounds of typing the same paragraph and swearing.
Was it worth it? For the keyboard, marginally; you can buy a perfectly good board for the money and the hours. For understanding what's actually happening between a keypress and a character on screen, completely. The matrix scan, the diodes that stop ghosting, the firmware that turns a grid of switches into something that knows the difference between a tap and a hold. I knew all of that abstractly. Now I've soldered it.