A couple of months ago I started looking into ergonomical keyboards; mainly split keyboards with much fewer keys, like the 36-key Gergoplex and the 44-key Kyria. I may write another post about the reasons why, but long story short I started getting pain in my thumbs, fingers, wrist and forearm, and I thought it was time to do something about it.
Because my new shiny layout has been unchanged for more than a week, I’ve clearly found my Ultimate Layout™ and it’s time to immortalize it with a blog post!
… Best get comfortable, this is a long post.
(To be completely transparent, I’ve made a few changes to it during the time it has taken me to write this post. And I’m sure, the tweaking will never stop.)
The journey is long and full of peril
They all have their pros and cons, and which one you prefer is highly subjective. At first I chose BEAKL 15, mostly because I liked the discussion on the now defunct BEAKL forums, and I had some strain on my right pinky that I wanted to minimize.
Although the layout felt much better than QWERTY, after trying out a bunch of modifications, I’ve since moved away from BEAKL. At around 50 WPM I got increasingly annoyed at the high same finger usage (called SFU) and I found that I wanted to use my pinkies more than BEAKL was designed for, which could be used to address the high SFU.
The breaking point came when I read an article about the benefits of E on one of the thumb keys, which made me abandon BEAKL and try something else.
The keymap is optimized for me and my quirks:
Comfort above speed.
For me I can comfortably reach 34 keys (2 thumb keys per hand), and I use very light choc keys that makes combos very comfortable.
Minimize pinky movement.
I’ve always used my ring finger to press keys above the home-row pinky. Maybe I have short pinkies, I dunno. It’s also why I use a 5-column layout instead of a 6-column layout.
Optimized for programming and Vim usage.
A vast majority of time is spent programming in Vim.
I type mostly English, but it should work well with Swedish too.
I find it hard to put it in numbers how difficult/easy I think certain keys are, but it’s something like this:
My RSI isn’t that inhibiting. Just going down to 5 columns and two thumb keys fixes most of my issues. Pressing the top outer keys with the ring finger feels good.
Some armchair analysis
Because it gives you the illusion that the layout is backed by science.
The problem with trying to optimize for programming is that it varies a lot depending on the language.
Take for example three of my own projects: a WIP Rust implementation of Git (following the excellent Building Git), a crypto payment processor in Elixir, and the source code for my book (mostly English, but with some Racket and other codey things):
While there’s a general trend here, we see some massive outliers. Like how
- is incredibly overrepresented in the book’s source (because the Racket convention is
kebab-case and I use
--- to represent an em dash
—) or how
; is very common in Rust but almost non-existent in Elixir.
What should we do then? We can try a keylogger to see what symbols we’re typing. Here’s the results, together with a dataset of all my personal projects I could find (labeled “Code”):
It’s not perfect either, as I didn’t run the keylog as long as I should, and I only used a small selection of languages at that time. The big outliers that come from Vim are
: (I save a lot with
. (repeat last action),
/ (regex search) and
$ (end-of-line). I don’t know why
' is overrepresented in the keylog, it’s not something I use a lot in Vim.
One might wonder, where do the symbols appear? Are they mostly next to characters, or next to other symbols? Here’s a table of where the symbols end up, and what symbol bigrams they appear (ignoring double symbols like
||), using the Code source:
|Char||Count||Next to letter||Next to symbol||Common bigrams|
Note that it it tracks letters on both sides of the symbol, which is why
, is only next to a letter 31% of the time (it’s almost always next to a space).
And a plot of how common the bigrams themselves are:
So what observations can we draw from this imperfect dataset? Here are some thoughts I have:
)are very common. I’d expect it if it was Lisp, but they seem very common even in Rust. They’re also neighbours with many other symbols, making them a high priority.
- The symbols
'are almost always next to an alpha character, meaning they don’t have to be placed next to other symbols, and can be optimized to be easily reachable from the base layer. I’ll add
,to this class as well.
]aren’t super common, but they do combine with many other symbols (mostly other types of brackets). If
>are used in a symbol bigram then it’s mostly in arrow form, like
- Computation symbols like
*are mostly surrounded by space, and they’re less used than I would’ve thought.
_have traditionally been on a shift layer, but here they’re much more common than their counterparts
Typically digits follow Benford’s law that says that lower numbers are more common. How does that hold up for us?
Fairly well I’d say. Again, the keylog displays some different results, mainly because I tend to use workspaces
9 more on a traditional keyboard (accessed with
Gui + number). This can be ignored when designing the layout as I can use whatever digit is convenient.
Optimizing letters is an area where layouts have focused a lot of attention on. Some notes from my own data:
- Code basically follows English, which makes sense as you’re mostly typing English words.
- There are some differences with Swedish, most notably
rare more common (and some extra vowels of course).
- My Vim usage makes some unusual keys quite common. Apparently I’m a
kspammer (up/down)—which isn’t a good habit to have as there are more efficient ways to move vertically.
b(forward and backwards a word) and
:w(save) are used a lot. I also seem to mistype a bunch as
uis very common (undo).
On one hand you might want to place these keys in better positions, but on the other hand they’re often typed with a pause, after I’ve had time to think for a second or two, so it might not be important enough to warp the entire layout.
On to the actual layout then. Illustrations are inspired by the darnedest thing.
There are two different ways you can make decisions: you either take a strictly logical approach, using the left half of your brain, or you let your subconscious decide as you go by feeling, letting the right half of your brain run the show.
It’s common to use a program to optimize the layout, letting the computer explore tons of layouts very quickly. I did not go this route, as I found it difficult to write down my exact preferences. Instead I based my layout on RSTHD, which is a well optimized layout, and tweaked it whenever I ran into things that annoyed me.
Feel the force!
These are the most notable changes I’ve made to RSTHD:
eon other thumb. Feels much better to avoid having “here”, “there” and similar combinations on the same hand.
zmoved away to combos in favor of more symbols.
pas I dislike the center column and lower index is good.
lon that good lower index.
kis in a better spot as it’s much more common in Swedish, and I use it a lot with Vim. As a bonus it makes
ckvery nice to type, again common in Swedish.
I really like
e on the thumb and I don’t think I’ll ever want to give it up. The low SFU and the consonant/vowel separations also feels very good to me.
And the rationale for choosing the symbols:
)some of the most common symbols, so they got prime real estate that let’s me type
()quickly. As a bonus I can use them as a prefix for a lot of things in Vim. For instance
)d(next LSP diagnostics),
)q(next quickfix) and
)s(next spellcheck error). (Nah, I never used
()for their original purpose.)
_is also very common, and is almost always next to letters in
snake_case, so having it on base is awesome. And it doubles as a Vim prefix, for example
_d(goto definition) and
_h(show help of thing under cursor).
- Which of
,to prioritize is a good question. I put
.in a better position as it’s used as “repeat last action” in Vim.
- Some of the most common symbols that don’t usually stand next to other symbols are moved to home-row combos. I find they’re easier to type than moving my fingers off home-row, so
;were moved off base.
"is very common. I’ve also had
/here, but I haven’t fully decided which I prefer yet.
=is on base as it makes
=very comfortable, which is the primary usage for it. It also makes it easy to pair with the different symbols, such as
This feels quite good—especially
A combo (sometimes called a chord) is when you press down two keys at the same time to produce something else. For instance if I press
k at the same time I get
q. With the light choc switches I use this feels very nice, even pressing three keys or vertical combos with two keys using a single finger.
I use it for lots of things. For instance:
- Hide the least common chars
- “Big keys” on home-row:
Escape(perfect for Vim!).
- Delete things:
- Symbols like
- Special things, like saving in Vim (
Here’s a table (because I wasn’t happy with the visualization I tried to make):
|Top Left||Res||Top Right||Res|
|Home Left||Res||Home Right||Res|
|Bottom Left||Res||Bottom Right||Res|
The rationale here is that home-row combos are very easy to type, so the common keys like
: go there. Split combos with the index and ring finger are slightly more awkward to type, but still good.
Having related functionality close to each other makes it a little easier to learn, so
^ (goto first non-space char in line) and
$ (goto last char in line) pairs nicely. They, and the other combo-able symbols, are mostly stand-alone so there’s minimal switching between layers to type them.
There are also vertical combos with the common arrow combinations you often see in programming:
Depending on the language, symbols like
-> are common, but often difficult to type. Combos solve this really well.
Also, splitting windows in vim is something I do a lot. Horizontal/vertical splits are laid out to match the split direction, and they’re grouped next to closing a window. (Why is saving vim on the right side then? Because
); is very common. It’s not perfect I know.)
What about shift?
Where to place shift was one of the most difficult decisions for me. I considered these options:
- One-shot shift, where you press and release shift and the next letter will be shifted, is great. But it doesn’t vibe well with
eon the thumb (and no outer column).
- Home-row mods, where you press and hold a regular key to turn it into shift. Many people love it, but I found it difficult to coordinate between left/right (as you often want to hold with the opposite hand).
- Auto Shift, where you just do a long press to get an uppercase letter. It’s convenient for single letters, but many people who have tried it says it messed up their rhythm.
I wanted to use one-shot shift, but I just couldn’t get it to work well with
e on the thumb. I got the fiddly home-row config to work, and I think I could learn to live with it, but for me auto shift felt better.
Sure, it’s harder to type quickly with auto shift, but I want to maximize comfort over speed, and auto shift feels like the option requiring the least amount of effort. I do have one-shot shift keys, but on a separate layer, which I use for some shortcuts (more on that shortly).
Typing multiple uppercase letters in a row does suck. That’s why I also use “CAPSWORD”, which is a smart caps lock that turns itself off after space or some other special characters. It makes it super easy to type variables like
POST_LIMIT for example.
Mods & symbols
I have modifiers combined with the other symbols, across two layers:
Instead of home-row mods, I have mods on a separate layer. (Some refer to it as callum-style mods, from the person who invented/popularized it.) While you need to press one key extra to access
Ctrl for instance, there are no timings here so it’s very quick and it feels surprisingly good. I’ve kept same-side mod activation because that’s what I started with, and I don’t feel a need to change it.
Some shortcuts, like
a, are impossible to press left-handed (when I use the mouse/trackball), so I’ve added them here.
I tried to place the symbols ordered by frequency, in some kind of logical groupings. There are very few symbol bigrams I have trouble typing. I find it’s mostly holding down
LMOD to type
 or similar. I’ve also kept the position of the symbols from base layer, so I don’t have to switch layers if I type bigrams like
]( (but truthfully, it almost never comes up).
While I can use the layer switches as one-shot for the symbols, I also have combos with
<key> to produce symbols from the base layer, for example
[. I now use that exclusively, and relegate the layer switch for the symbol bigrams (because I dislike having to move the thumb).
One last annoyance is double- or triple-tapping symbols, particularly with the pinky, for things like
||. I got around it by adding long press for them, similar to what auto shift does:
Where are the digits?
Here they are:
Yupp, I use numbers on home-row (and the low index, which is the next best key apart from the thumbs). They’re laid out prioritizing lower digits, slightly de-emphasizing index fingers as they’re responsible for two digits. Separating even from odd numbers made sense from an optimization aspect, but it also made it easier to learn.
What makes this special is that the layer switch is smart, similar to CAPSWORD as the layer turns off on space (which I call NUMWORD). So if I want to write
if x == 3 do then I type
if x == <NUMWORD>3 do and the layer turns off after the space.
G? Those are for easy navigation with Vim. So
13k means “13 lines above” and
127G means “line number 127”. Naturally, the layer turns itself off, so it doesn’t interfere with my next commands. I use it all the time and it’s fantastic.
Navigation is the only “hold key down” I have. Vim-like arrows on the right side (but I try not to use them in Vim, as jumping with the NUM layer is more efficient).
Ctrl + arrow is used to switch windows in Vim and
r switches between my three monitors (it’s here because it’s so common).
Navigation on the left hand is great when I have the right hand on the mouse; initially I didn’t have arrows here, but I found myself missing them.
Tab switches tabs in Firefox.
I also have a workspace navigation layer, used exclusively for workspace manipulation:
Gui + number switches to that workspace;
j switches between windows; and if you
Shift (long press) you move the current window there.
Having a separate layer for this isn’t strictly needed, but it feels much more convenient. I tried the regular one-shot mods and home-row mods on the number layer, but I just didn’t like it that much. I also tried a smart layer or a simple layer switch (where I had to exit the layer explicitly), but I prefer having to hold down a key so I know that I’m in the workspace layer.
Nothing special going on with the function keys. Having them on the same positions as numbers makes them easy to learn, which is important for me as I almost never use them.
As a Swede, I do type Swedish from time to time. But I never type code and Swedish at the same time, so it made sense to have a Swedish mode that I can toggle, for example when I need to write an email or similar.
_, as they’re mostly used in code, and
åäö are practically never used next to the vowels, making the layout very pleasant for Swedish as well. The layer is is activated with
) (and deactivated with the same keys). I can still access the symbols with the one-shot layer on the left thumb or with combos like
I have some runtime options I might occasionally want to access:
- On a regular keyboard and on my laptop I’ve had
Caps Lockswapped (to make it easier to press in Vim). I can toggle it on the keyboard so I can use it there as well.
- I don’t currently have anything that differs between Windows and Linux I don’t think, but things like window switching works differently. When I go back to working on Windows I’ll probably make use of this.
NUMtoggles a regular number layer, that don’t deactivate on
Space, which I use when I practice number typing.
There’s plenty of room here for rare, but useful, symbols. Such as the arrow symbols
↑ and dead key modifiers.
The pink keys are called “dead keys”. A dead key is a sort of prefix to modify a symbol, so to type
ã you press
~ (dead) +
^ combo is also turned into a dead key on this layer.
You might say it’s ridiculous to have this kind of layer, but I think it’s very easy to learn with the keys staying in logical positions (dead
` has the same position as the normal
` for instance).
34 keys are plenty
If you’re not into tweaking layouts it might sound crazy with only 34 keys (and maybe it is), but I still think there’s plenty of space here:
- With layers you multiply your available space, making it easy to have arrows, numbers, function keys and symbols right under your fingers.
- Combos will in practice give you access to even more keys than a regular keyboard.
- Multi function keys, with long press or double clicks (which I don’t even use), combined with combos and layers gives you more available space than you’ll ever need.
I could easily fit much more functionality into my layout if I needed to. The constraint isn’t space—it’s your ability to learn and get proficient with a complex layout. (And I don’t think it’s that hard to learn a new layout, but that’s a topic for another day.)
Is this the perfect layout?
Oh, that’s funny…
There are always things that could be done better. Here are some things that currently annoy me:
As I press the outer top keys (
,) with my ring finger, “sys” is terrible to type as it’s three letters in a row with the same finger.
I’ve tried to address this by moving
j, but everything I’ve tried so far has created larger problems. So maybe I’ll shove in a combo to produce “sys” and call it a day?
bjis crazy annoying. It gets worse if I program in a codebase that uses
Objectall over the place.
jis in the worst spot, even though I use it a lot in Vim.
jas combos, but I liked that even less. At first I actually used the
NAVlayer, but I got annoyed at the extra layer switch and I had some misfiring due to timing issues.
I’m not 100% content with the symbols layer, and I’ll probably try to move some symbols around a bit.
And there are a bunch of things that aren’t optimal, but at this point I’m hitting diminishing returns, so I’ll try to avoid changing things unless it’s something that really bothers me.
How did you implement this?
I use QMK and my keymap is on GitHub.