This repository contains the ZMK user configuration for all my keyboards that use the ZMK firmware.
The way I organize the keyboards' layouts is to have a single master layout, with more keys defined than any keyboard I have. Then, each individual Keyboard configuration would define a “layer adapter” mapping the keys in the layout that it uses to its physical position.
Every keyboard layout has its layout documentation (located under the docs
directory), but since they all share the majority of my layout, you should
expect plenty of repeating texts between them.
My suggestion is to read the layout documentation for the keyboard you're looking for, then, when you understand it, go check out the other docs. This way, you won't have to read the same text twice, or explanations for things you aren't concerned with in the first place.
Currently, in this repository, I have layout for:
If you did not click on any of the layout links yet, there is some general information I would like you to have to help you understand them better.
Inside the keymap files and on the layout map images, you'll see a series of symbols that are not well-used in ZMK configurations out there, so to understand the layout easily, here is a table with all the symbols I use:
When looking at the layout map images, you'll see that some keys have their background highlighted with different colors than the rest; many of them, also have more than one symbol as their labels.
To understand what all those symbols mean, let's first, look at how a key that has a single purpose is represented:
This key has nothing special about it. When I tap it, it will output a
, and if
I hold it down, it will output a
repeatedly, until I release it.
My layouts, like virtually every other keyboard layout in the world (including the standard ones that most people use), have keys that are used exclusively to alter what other keys output when held-down. When that happens, we say that the key caused the keyboard to “switch layers”, for instance:
This is the Shift key, which forces other keys to output the uppercase version of itself, or in certain cases, it can force the key to output an entirely different symbol than the normal one (e.g., the number keys in most standard keyboards).
When a key outputs a different symbol than the uppercase version of the normal output while holding down the Shift key, it has the extra symbol drawn above the normal one, for instance:
When tapped while no other hey is held-down, it will output 2
, but if the
Shift key is held-down while tapping it, it will output @
.
Now, there is a special type of key that you don't find in standard keyboards easily. Those keys output their normal value when tapped, and a different one when held-down. These keys are called “Hold-Tap” keys. Most custom layouts use them, specially layouts for keyboards with less than 50 keys.
When those keys are shown in my layout maps, they have the “hold-down” value displayed below the normal symbol. For instance:
This key is a normal F
key that output f
when tapped, and F
when tapped
while holding down the “Shift” key. However, when I hold this key down, it
behaves like the “Shift” key, meaning that if I hold it down, and then press
the key for number 2
, the keyboard will output a @
character.
Note
Unfortunately, Keymap Drawer does not support representations of Mod-Morph or Tap-Dance, so I had to come up with a syntax to represent them:
When you see a symbol followed by :
, followed by another symbol on either,
the shifted symbol or held symbol positions, it is indicating a morph
behavior, meaning: <morph trigger>: <output symbol>
. In the example above,
when the A
key is tapped while holding down the Command key, the result
output will be the `
key.
When you see a counter in the form of <N>x
, followed by :
, followed by a
symbol on either the held symbol or shifted symbol positions, it indicates
a tap-dance behavior, meaning: <tap count>x: <output symbol>
. In the
example above, when the A
key is tapped twice, it will output a CAPS_LOCK
.
When we put all this together, and we see the following key in a layout map:
We know that this key is a normal “Delete Backwards” when tapped by itself, and a “Forward Delete” when tapped while holding down “Shift”. But when I hold it down, it will be like I'm holding down the “Command” key on my macOS.
Usually, a tap and hold key goes into the “hold” mode when the key is held-down, which prevents the user from holding the key down and having its output repeated until the key is released.
To solve this issue, I used a (relatively new) feature of ZMK called
quick-tap-ms
, which
always produces the “tap” behavior when the key is pressed twice in quick
succession. This allows me to have repeatable keys, even when they're a
“tap-hold” type of key.
For instance, let's assume the F
tap-hold key shown in the previous section.
The sequence of taps and their output would be:
F
down,F
up :: it will output a singlef
;F
down :: it will output a “Shift” key;F
down,F
up,F
down :: it outputsffffffffff…
until the key is released.
Around 2021, Apple made the (FN)/Globe
key a standard key on all its
keyboards, so as an Apple user, I wanted to have the same ability to access some
features using my keyboard as I can using a standard Apple keyboard.
ZMK has partial support for the Globe key (check issue #937 for details on the mater), it can only be used as a “holding” key.
I think CAPS_LOCK
is evil. No keyboard should ever have that key available.
That being said, I admit that sometime is very convenient to type a fully
capitalized word without having to hold down the Shift key.
Fortunately, ZMK solved this by allowing us to use the
CAPS_WORD
behavior, where, when
tapped, it will turn on the CAPS_LOCK
just to the next word typed. Thereafter,
the keyboard will put you on a normal typing mode again.
In this layout configuration, the CAPS_WORD
feature is triggered when I press
both “Shift” keys together.
You may be asking yourself (probably not, but I'll pretend you are) what is my process to choose where keys go in all these layouts?
In all honesty, I don't have one. I usually use the keyboard and try to note repetitive mistakes or things that require a bigger effort to accomplish. When they become somewhat highly noticeable, I think about where the keys causing this issue should be for me to have less of these mistakes happening. Then, I change the layout to match my new hypothesis, flash the keyboard, and use the layout as if nothing happened.
Over time, the fixes that worked will fade in the background while new issues that deserve my attention, as well as the fixes that did not work, will show up again and again. When that happens… Rinse and repeat.
If you want to build this configuration locally, first, follow ZMK's instructions to be able to build the firmware itself.
Then, get a Python environment ready (you can use your OS Python, or you can create a virtual environment just for the project), and install the required dependencies to it:
$ pip install -r support/requirements.txt
You can build the firmware for all keyboards I have with the following command:
$ west build -p -d build/corne-left -b nice_nano_v2 -- \
-DSHIELD=corne_left \
-DDTS_EXTRA_CPPFLAGS="-DUSE_MOLOCK=1" \
-DZMK_CONFIG="$TOWNK_ZMK_CONFIG_DIR/config" \
&& west build -p -d build/corne-right -b nice_nano_v2 -- \
-DSHIELD=corne_right \
-DDTS_EXTRA_CPPFLAGS="-DUSE_MOLOCK=1" \
-DZMK_CONFIG="$TOWNK_ZMK_CONFIG_DIR/config" \
&& west build -p -d build/lily-left -b nice_nano_v2 -- \
-DSHIELD="lily58_left nice_view_adapter nice_view" \
-DDTS_EXTRA_CPPFLAGS="-DUSE_MOLOCK=1" \
-DZMK_CONFIG="$TOWNK_ZMK_CONFIG_DIR/config" \
&& west build -p -d build/lily-right -b nice_nano_v2 -- \
-DSHIELD="lily58_right nice_view_adapter nice_view" \
-DDTS_EXTRA_CPPFLAGS="-DUSE_MOLOCK=1" \
-DZMK_CONFIG="$TOWNK_ZMK_CONFIG_DIR/config" \
&& west build -p -d build/settings-reset -b nice_nano_v2 -- \
-DSHIELD="settings_reset" \
-DZMK_CONFIG="$TOWNK_ZMK_CONFIG_DIR/config"
After the first build, you can simplify the build command to the following:
$ west build -d build/corne-left \
&& west build -d build/corne-right \
&& west build -d build/lily-left \
&& west build -d build/lily-right \
&& west build -d build/settings-reset
And if you make any modifications to the keymap, make sure you update the assets
used in the documentation, by running the update-layout-maps.sh
script from
the support
directory:
$ cd "$TOWNK_ZMK_CONFIG_DIR"
$ ./support/update-layout-maps.sh
Layout map images are all generated with Keymap-Drawer from Cem Aksoylar. If you have your custom ZMK or QMK configuration, I highly recommend you to check it out.
My homerow mod configuration is based on the fantastic “timeless homerow mods” from Robert U (@urob)'s ZMK Configuration. You should absolutely check this configuration for examples.
The pattern I used to share my layout across multiple keyboards was a suggestion from Rafael Romão (@rafaelromao) and Cem Aksoylar (@caksoylar) on the ZMK Discord server, so I spent some time digging through their ZMK configurations to learn, and copy the pattern into my layout.
Unfortunately, due to the nature of my layout, you cannot use this configuration with Nick Coutsos Keymap-Editor.