Reproducible QMK firmware builds for my keyboards using QMix and the vial-qmk fork.
QMix provides two helper functions used here:
fetchQmkFirmwareβ Fetches a pinned version of a QMK firmware repo and primes it so QMK won't warn or crash during buildbuildQmkFirmwareβ Builds firmware for a specific keyboard, injecting custom keymap source viasrc/srcMount
This project fetches vial-qmk (QMK fork with Vial support) at a specific commit, then builds each keymap by injecting local source into the firmware tree.
Corne Keyboard β split 3x6 + 3 thumb layout based on Helix, for Kailh Choc v1/v2 switches.
- MCU: RP2040 ProMicro (
CONVERT_TO=promicro_rp2040) - Firmware: vial-qmk (Vial-compatible QMK fork)
- Layout:
LAYOUT_split_3x6_3β 36 main keys + 3 thumb keys per half - Features:
- RGB Matrix with typing heatmap, alphas mods, band pinwheel/spiral, gradient effects
- RGB layer/color indicators per active layer
- Caps Lock indicator (rainbow or accent color)
- Idle dimming (fades after 60s, full off after 30min)
- Vial combos (10 entries), key overrides (10 entries), tap dance (10 entries)
- 10 dynamic macros
- Leader sequences, combos, key overrides, tap dance
- Unicode input (common + full)
- Auto-shift, retro shift, space cadet (sticky shift/ctrl on double-tap)
- NKRO
- Split sync: layer state, LED state, mods, transaction mirror
- USB auto-detect master/slave
Build:
nix build .#crkbd-choc-v2The UF2 firmware files are at result/share/qmk/firmware/{left,right}/.
Flash (RP2040 UF2 bootloader):
# Flash left half β double-tap reset when prompted:
nix run nixpkgs#qmk -- flash result/share/qmk/firmware/left/*.uf2 -bl uf2-split-left
# Flash right half β double-tap reset when prompted:
nix run nixpkgs#qmk -- flash result/share/qmk/firmware/right/*.uf2 -bl uf2-split-rightCorne Keyboard β same split 3x6 + 3 thumb layout, for Cherry MX compatible switches.
- MCU: AVR
- Firmware: vial-qmk (Vial-compatible QMK fork)
- Layout:
LAYOUT_split_3x6_3β 36 main keys + 3 thumb keys per half - Features:
- Vial combos (4 entries), tap dance (10 entries), key overrides (4 entries)
- 6 dynamic macros
- NKRO
- Split sync (layer/LED/mods)
- USB auto-detect master/slave
Build:
nix build .#crkbd-classic-v3The hex firmware files are at result/share/qmk/firmware/{left,right}/crkbd_rev1_classic-v3.hex.
Flash (Caterina bootloader, avrdude):
# Flash left half β double-tap reset when prompted:
nix run nixpkgs#qmk -- flash result/share/qmk/firmware/left/crkbd_rev1_classic-v3.hex -bl avrdude-split-left
# Flash right half β double-tap reset when prompted:
nix run nixpkgs#qmk -- flash result/share/qmk/firmware/right/crkbd_rev1_classic-v3.hex -bl avrdude-split-rightThese keymaps are designed for the EurKey layout β a multilingual layout based on QWERTY that provides Western European accented characters (French, Spanish, German, Portuguese, etc.) via Alt Gr combos, while keeping the familiar QWERTY base for coding and ASCII symbols.
TapDance keys produce different actions based on tap vs. hold timing. All slots use TD(...) in the keymap. These tap-dance keys replicate EurKey accented characters that are normally accessed via Alt Gr on the OS level.
| Slot | Tap | Hold/Double | Term | EurKey Char | Description |
|---|---|---|---|---|---|
| 0 | KC_A |
RALT(KC_X) |
200ms | Γ‘ | Tap: A Β· Hold: AltGr+X β Γ‘ |
| 1 | KC_E |
RALT(KC_G) |
200ms | Γ© | Tap: E Β· Hold: AltGr+G β Γ© |
| 2 | KC_I |
RALT(KC_B) |
200ms | Γ | Tap: I Β· Hold: AltGr+B β Γ |
| 3 | KC_O |
RALT(KC_DOT) |
200ms | Γ³ | Tap: O Β· Hold: AltGr+. β Γ³ |
| 4 | KC_U |
RALT(KC_J) |
200ms | ΓΊ | Tap: U Β· Hold: AltGr+J β ΓΊ |
| 5 | KC_N |
RALT(KC_N) |
200ms | Γ± | Tap: N Β· Hold: AltGr+N β Γ± |
| 6 | KC_C |
RALT(KC_C) |
200ms | Γ§ | Tap: C Β· Hold: AltGr+C β Γ§ |
| 7 | KC_LEFT_GUI |
KC_LEFT_ALT |
350ms | β | Tap: GUI (Win) Β· Hold: AltGr |
| 8 | KC_LEFT_SHIFT |
double tap β KC_CAPS_LOCK |
180ms | β | Tap: LShift Β· Double: CapsLock |
QWERTY Layer (0)
ββββ ββββ
βββββE βββββββββ βββββββββI βββββ
βββββββββW ββ ββR ββT β βY ββU ββ ββO βββββββββ
ββ ββQ ββ ββββββ ββ β β ββ ββββββ ββP βββ« β
β ββ βββββββββββββββββ βββββββββββββββββ ββ β
βββββββββββββD βββββββββ βββββββββK βββββββββββββ
βββββββββS ββ ββF ββG β βH ββJ ββ ββL βββββββββ
ββ₯ ββA ββ ββββββ ββ β β ββ ββββββ ββ; βββ β
β ββ βββββββββββββββββ βββββββββββββββββ ββ β
βββββββββββββTDβββββββββ βββββββββ, βββββββββββββ
βββββββββX ββ6 ββV ββB β βTDββM ββ ββ. βββββββββ
βTDββZ ββ ββββββ ββ β β5 ββ ββββββ ββ/ ββ' β
β8 ββ βββββ ββββββββ ββββββββ βββββ ββ β
ββββββββ ββββ ββββ ββββ ββββ ββββ ββββ ββββββββ
βLββ βTDβ ββ£ β ββ£ β βMOβ βMOβ
β β β7 β β β β β β2 β β1 β
ββββ ββββ β β β β ββββ ββββ
β β β β
ββββ ββββ
Navigation Layer (1)
Layer 1 provides navigation keys (arrows, page up/down, home/end) and macros on the left, plus media/print keys on the right.
ββββ ββββ
βββββ3 βββββββββ βββββββββ*1βββββ
βββββββββ2 ββ ββ4 ββ5 β ββΈ ββ ββ βββ¦ βββββββββ
β~ ββ1 ββ ββββββ ββ β β ββ ββββββ ββINSββ½ β
β ββ βββββββββββββββββ βββββββββββββββββ ββ β
βββββββββββββM βββββββββ ββββββββββ± βββββββββββββ
βββββββββM ββ2 ββM ββM β β ββ ββ βββ βββββββββ
ββ½ ββM ββ1 ββββββ3 ββ4 β β ββ ββββββ βββ βββ β
β ββ0 βββββββββββββββββ βββββββββββββββββ ββ β
ββββββββββββββ½ βββββββββ ββββββββββ² βββββββββββββ
ββββββββββ½ ββ βββ½ ββ β β ββ ββ βββ βββββββββ
ββ½ βββ½ ββ ββββββ ββ β β ββ ββββββ βββ βββ β
β ββ βββββ ββββββββ ββββββββ βββββ ββ β
ββββββββ ββββ ββββ ββββ ββββ ββββ ββββ ββββββββ
ββ½ β βMOβ ββ½ β ββ½ β βMOβ β β
β β β4 β β β β β β5 β β β
ββββ ββββ β β β β ββββ ββββ
β β β β
ββββ ββββ
*1 - KC_PRINT_SCREEN
| Symbol | Keycode | Description |
|---|---|---|
| MO | MO(4) / MO(5) |
Momentary layer switch to layer 4 or 5 |
Symbol Layer (2)
Layer 2 provides symbols via LSHIFT (left hand) and EurKey Alt Gr combos (right hand), with navigation on thumbs.
ββββ ββββ
βββββLβ§βββββββββ βββββββββLβ§βββββ
βββββββββLβ§ββ3 ββLβ§ββLβ§β βLβ§ββLβ§ββ8 ββLβ§βββββββββ
βLβ§ββLβ§ββ2 ββββββ4 ββ5 β β6 ββ7 ββββββ9 ββLβ§βββ½ β
β~ ββ1 βββββββββββββββββ βββββββββββββββββ0 ββ β
βββββββββββββ βββββββββ βββββββββ( βββββββββββββ
βββββββββ ββ ββ*1ββ β β- ββ= ββ ββ) βββββββββ
ββ½ ββ ββ ββββββ ββ β β ββ ββββββ ββLβ§ββ~ β
β ββ βββββββββββββββββ βββββββββββββββββ\ ββ β
βββββββββββββ βββββββββ βββββββββLβ§βββββββββββββ
βββββββββLβ§ββ ββ ββ β βLβ§ββLβ§ββ( ββLβ§βββββββββ
ββ½ ββ*2ββ. ββββββ ββ β β- ββ= ββββββ) ββ\ ββLβ§β
β ββ βββββ ββββββββ ββββββββ βββββ ββ~ β
ββββββββ ββββ ββββ ββββ ββββ ββββ ββββ ββββββββ
ββ½ β βMOβ ββ½ β ββ½ β β β βMOβ
β β β3 β β β β β β β β5 β
ββββ ββββ β β β β ββββ ββββ
β β β β
ββββ ββββ
*1 - RALT(KC_5)
*2 - Lβ§,,
| Symbol | Keycode | Description |
|---|---|---|
| Lβ§ | KC_LSFT |
Left Shift (for symbol access) |
| MO | MO(3) / MO(5) |
Momentary layer switch to layer 3 or 5 |
| *1 | RALT(KC_5) |
AltGr + 5 β β¬ |
| *2 | KC_LSFT(KC_COMMA) |
Left Shift + comma β < |
F-keys / Number Layer (3)
Layer 3 provides F1-F12 on the left hand and a numpad-like layout on the right.
ββββ ββββ
βββββF3βββββββββ βββββββββ8 βββββ
βββββββββF2ββ ββF4ββF5β βK*ββ7 ββ ββ9 βββββββββ
ββ½ ββF1ββ ββββββ ββ β β ββ ββββββ ββ βββ½ β
β ββ βββββββββββββββββ βββββββββββββββββ ββ β
βββββββββββββF8βββββββββ βββββββββ5 βββββββββββββ
βββββββββF7ββ ββF9ββF β βK+ββ4 ββ ββ6 βββββββββ
β ββF6ββ ββββββ ββ10β β ββ ββββββ ββK=ββKββ
β ββ βββββββββββββββββ βββββββββββββββββ ββ β
βββββββββββββ βββββββββ βββββββββ2 βββββββββββββ
βββββββββF ββ ββ ββ β βK-ββ1 ββ ββ3 βββββββββ
β ββF ββ12ββββββ ββ β β ββ ββββββ ββ/ ββ β
β ββ11βββββ ββββββββ ββββββββ βββββ ββ β
ββββββββ ββββ ββββ ββββ ββββ ββββ ββββ ββββββββ
β β β β β β β0 β β. β β, β
β β β β β β β β β β β β
ββββ ββββ β β β β ββββ ββββ
β β β β
ββββ ββββ
Alt-F / Extended Symbols Layer (4)
Layer 4 maps to Alt+F (left hand) and Alt+Number (right hand) for media/number shortcuts.
ββββ ββββ
βββββ*1βββββββββ βββββββββ*2βββββ
βββββββββ*3ββ ββ*4ββ*7β β*8ββ*5ββ ββ*6βββββββββ
ββ½ ββ*9ββ ββββββ ββ β β ββ ββββββ ββ*10ββ½ β
β ββ βββββββββββββββββ βββββββββββββββββ ββ β
βββββββββββββ*11ββββββββ βββββββββ*12ββββββββββββ
βββββββββ*13β ββ*14β*17 β*18β*15β ββ*16ββββββββ
ββ½ ββ*19β ββββββ ββ β β ββ ββββββ ββ*20ββ½ β
β ββ βββββββββββββββββ βββββββββββββββββ ββ β
βββββββββββββ βββββββββ βββββββββ βββββββββββββ
βββββββββ*21β ββ ββ β β ββ ββ ββ βββββββββ
ββ½ ββ*22β ββββββ ββ β β ββ ββββββ ββ ββ β
β ββ βββββ ββββββββ ββββββββ βββββ ββ β
ββββββββ ββββ ββββ ββββ ββββ ββββ ββββ ββββββββ
ββ½ β ββ½ β ββ½ β ββ½ β β β β β
β β β β β β β β β β β β
ββββ ββββ β β β β ββββ ββββ
β β β β
ββββ ββββ
| Ref | Keycode | Description |
|---|---|---|
| *1 | LALT(KC_F3) |
AltGr + F3 |
| *2 | RALT(KC_3) |
AltGr + 3 |
| *3 | LALT(KC_F2) |
AltGr + F2 |
| *4 | LALT(KC_F4) |
AltGr + F4 |
| *5 | RALT(KC_2) |
AltGr + 2 |
| *6 | RALT(KC_4) |
AltGr + 4 |
| *7 | LALT(KC_F5) |
AltGr + F5 |
| *8 | RALT(KC_1) |
AltGr + 1 |
| *9 | LALT(KC_F1) |
AltGr + F1 |
| *10 | RALT(KC_5) |
AltGr + 5 |
| *11 | LALT(KC_F8) |
AltGr + F8 |
| *12 | RALT(KC_8) |
AltGr + 8 |
| *13 | LALT(KC_F7) |
AltGr + F7 |
| *14 | LALT(KC_F9) |
AltGr + F9 |
| *15 | RALT(KC_7) |
AltGr + 7 |
| *16 | RALT(KC_9) |
AltGr + 9 |
| *17 | LALT(KC_F10) |
AltGr + F10 |
| *18 | RALT(KC_6) |
AltGr + 6 |
| *19 | LALT(KC_F6) |
AltGr + F6 |
| *20 | RALT(KC_0) |
AltGr + 0 |
| *21 | LALT(KC_F12) |
AltGr + F12 |
| *22 | LALT(KC_F11) |
AltGr + F11 |
Media / System (5)
Layer 5 provides media controls (volume, playback) on the left hand and system/magic keys on the right.
ββββ ββββ
βββββ βββββββββ βββββββββ βββββ
βββββββββV+ββ ββ ββ β β*2ββ*1ββ ββ βββββββββ
β ββ ββ ββββββ ββ β β ββ ββββββ ββ ββ*3β
β ββ βββββββββββββββββ βββββββββββββββββ ββ β
βββββββββββββ>>βββββββββ βββββββββ βββββββββββββ
βββββββββV-ββ ββ ββ β β ββ ββ ββ βββββββββ
β ββ<<ββ ββββββ ββ β β ββ ββββββ ββ ββ β
β ββ βββββββββββββββββ βββββββββββββββββ ββ β
βββββββββββββ βββββββββ βββββββββ βββββββββββββ
βββββββββ ββ ββ ββ β β ββ ββ ββ βββββββββ
β ββ ββ ββββββ ββ β β ββ ββββββ ββ ββ β
β ββ βββββ ββββββββ ββββββββ βββββ ββ β
ββββββββ ββββ ββββ ββββ ββββ ββββ ββββ ββββββββ
β β β β ββ― β βMut β β β β
β β β β β β β β β β β β
ββββ ββββ β β β β ββββ ββββ
β β β β
ββββ ββββ
*1 - QK_MAGIC_EE_HANDS_RIGHT
*2 - QK_MAGIC_EE_HANDS_LEFT
*3 - QK_BOOTLOADER
| Symbol | Keycode | Description |
|---|---|---|
| V+ | KC_VOLUME_UP |
Volume up |
| V- | KC_VOLUME_DOWN |
Volume down |
| << | KC_PREVIOUS |
Previous track |
| >> | KC_NEXT |
Next track |
| β― | KC_PLAY_PAUSE |
Play/pause toggle |
| Mut | KC_MUTE |
Mute audio |
| *1 | QK_MAGIC_EE_HANDS_RIGHT |
Magic: sync EEPROM to right hand |
| *2 | QK_MAGIC_EE_HANDS_LEFT |
Magic: sync EEPROM to left hand |
| *3 | QK_BOOTLOADER |
Reboot into bootloader (for flashing) |
# Corne Chocolate v2 (RP2040, UF2)
nix build .#crkbd-choc-v2
# Corne Classic v3 (AVR, hex)
nix build .#crkbd-classic-v3The compiled firmware is in result/share/qmk/firmware/{left,right}/.
The -bl avrdude-split-left / -bl uf2-split-left bootloaders wait interactively for you to double-tap reset, then flash and set EEPROM handedness.
Corne Classic v3 (AVR):
nix run nixpkgs#qmk -- flash result/share/qmk/firmware/left/crkbd_rev1_classic-v3.hex -bl avrdude-split-left
nix run nixpkgs#qmk -- flash result/share/qmk/firmware/right/crkbd_rev1_classic-v3.hex -bl avrdude-split-rightCorne Chocolate v2 (RP2040):
nix run nixpkgs#qmk -- flash result/share/qmk/firmware/left/*.uf2 -bl uf2-split-left
nix run nixpkgs#qmk -- flash result/share/qmk/firmware/right/*.uf2 -bl uf2-split-rightRender the keyboard layout from a connected keyboard:
nix run path:.#vitaly -- layers -n <layer-number>fetchQmkFirmwarefetches vial-qmk at a pinned commit and primes the repobuildQmkFirmwareinjects local keymap source (src) into the firmware tree at the mount path (srcMount), then runs the QMK build- Each keymap is a separate package, built independently
See the QMix docs for full details on fetchQmkFirmware and buildQmkFirmware.
To update the vial-qmk source, change rev and hash in flake.nix:
vialQmkFirmware = pkgs.fetchQmkFirmware {
url = "https://github.com/vial-kb/vial-qmk.git";
origin = "https://github.com/vial-kb/vial-qmk.git";
rev = "..."; # new commit hash
hash = "sha256-..."; # compute with `nix-prefetch-git` or let nix suggest it
};- Create a directory under
keyboards/crkbd/keymaps/<name>/ - Add
keymap.c,config.h,rules.mk, andvial.json - Add a package entry in
flake.nix:
my-keymap = pkgs.buildQmkFirmware {
keyboard = "crkbd";
keymap = "my-keymap";
split = true;
src = ./keyboards/crkbd/keymaps/my-keymap;
srcMount = "keyboards/crkbd/keymaps/my-keymap";
qmkFirmware = vialQmkFirmware;
};