This repository provides a Debian trixie base image plus a Compose workflow for building QMK firmware for the Framework 16 RGB macropad, with an editable keymap source tree kept outside the QMK checkout so it stays in your own git history.
The initial keymap demonstrates a "cycle through N modes" key: pressing the top-left key steps through five layers, each with a distinct per-key RGB colour pattern defined in a single readable table in keymap/keymap.c.
HOST_UID="$(id -u)" HOST_GID="$(id -g)" docker compose run --rm build-macropadOn first run the container clones FrameworkComputer/qmk_firmware (branch fl16-2025) into ./workspace/qmk_firmware and initialises submodules — this takes a few minutes. Subsequent runs reuse the cached checkout.
The compiled firmware lands in ./out/:
./out/framework_macropad_phlax.uf2
The Framework 16 macropad uses an RP2040 MCU with a UF2 drag-and-drop bootloader. Automatic flashing from inside the container is not supported — follow these steps on the host:
- Double-tap the reset button on the back of the macropad.
It appears as a USB mass-storage device named RPI-RP2. - Copy the firmware file onto the drive:
(or drag-and-drop in your file manager)
cp ./out/framework_macropad_phlax.uf2 /run/media/$USER/RPI-RP2/ - The macropad reboots automatically — done.
Tip: setting
FLASH=1prints a reminder of these steps rather than attempting anything automatic.
| Path | Container mount | Purpose |
|---|---|---|
./workspace |
/workspace |
QMK firmware checkout (cloned on first run) |
./out |
/out |
Compiled firmware (.uf2, .bin, .hex) |
./cache |
/cache |
Build cache (pip, ccache, …) |
./keymap |
/repo/keymap (read-only) |
Your editable keymap source |
./scripts |
/repo/scripts (read-only) |
Build entrypoint script |
All three writable directories (workspace, out, cache) are automatically chown-ed to HOST_UID:HOST_GID at the end of every run, so files are never left root-owned on the host.
These directories are listed in
.gitignore— onlykeymap/is tracked.
Everything you iterate on lives in keymap/:
| File | Purpose |
|---|---|
keymap/keymap.c |
Layer definitions, CYCLE_MODE handler, mode_colors table |
keymap/palette.h |
Named {R,G,B} macros (RGB_RED, RGB_GRN, …) |
keymap/config.h |
Per-keymap hardware overrides (brightness, tapping term, …) |
keymap/rules.mk |
Feature flags (RGB_MATRIX_ENABLE, MIDI_ENABLE, …) |
Open keymap/keymap.c and find the mode_colors table. Each entry is one comment + one colour macro:
/* LED 3: Bksp */ RGB_RED,Swap RGB_RED for any macro from palette.h (or a literal {R, G, B} triple) and rebuild.
- Increment
NUM_MODES(currently5). - Add a new
enum layersentry and a matchingLAYOUT(…)block in the keymaps array. - Add a new row to
mode_colors.
The mode_colors table uses LED indices 0–23 in the order defined by the IS31FL3741 driver in keyboards/framework/macropad/macropad.c (g_led_config.matrix_co). The approximate mapping is documented in a comment at the top of the table. If a colour appears on the wrong physical key, compare with that file and swap the table entries to match.
All parameters are settable as environment variables (with the defaults shown):
| Variable | Default | Description |
|---|---|---|
QMK_REPO |
https://github.com/FrameworkComputer/qmk_firmware.git |
QMK fork to clone |
QMK_REF |
fl16-2025 |
Branch, tag, or commit SHA to check out |
KEYBOARD |
framework/macropad |
Keyboard path within keyboards/ |
KEYMAP |
phlax |
Keymap name |
FLASH |
(empty) | Set to any non-empty value to print flash instructions |
Example — pin to a specific commit and use a different keymap name:
QMK_REF=11c49db KEYMAP=mine \
HOST_UID="$(id -u)" HOST_GID="$(id -g)" \
docker compose run --rm build-macropadHow
KEYBOARDwas determined: the Framework QMK fork keeps the macropad definition onfl16-*branches (notmaster, which is upstream QMK). Branchfl16-2025(commit11c49db) containskeyboards/framework/macropad/— a 24-key IS31FL3741 RGB pad on an RP2040. If Framework releases a newer branch, updateQMK_REFto point to it.
Rebuild the image from scratch (e.g. after changing the Dockerfile):
docker compose build --no-cache build-macropadRe-clone the QMK source (e.g. to switch branches):
rm -rf ./workspace/qmk_firmware
HOST_UID="$(id -u)" HOST_GID="$(id -g)" docker compose run --rm build-macropadKEYBOARD path not found / compile error about missing keyboard:
Make sure QMK_REF points to a Framework branch, not upstream master:
QMK_REF=fl16-2025 HOST_UID="$(id -u)" HOST_GID="$(id -g)" \
docker compose run --rm build-macropadFlashing is not automated:
The RP2040 UF2 bootloader mounts as a USB drive — qmk flash inside a container cannot access it. Use the manual drag-and-drop steps in the Flashing section above.