diff --git a/keyboards/crkbd/keymaps/ollyhayes/config.h b/keyboards/crkbd/keymaps/ollyhayes/config.h
new file mode 100644
index 0000000000..b7653e1c9a
--- /dev/null
+++ b/keyboards/crkbd/keymaps/ollyhayes/config.h
@@ -0,0 +1,96 @@
+/* Copyright 2022 Olly Hayes (@ollyhayes)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#define EE_HANDS
+
+#define TAPPING_FORCE_HOLD
+#define TAPPING_TERM 100
+
+#define NO_ACTION_ONESHOT
+
+#define OLED_FONT_H "keyboards/crkbd/lib/glcdfont.c"
+
+#define UNICODE_SELECTED_MODES UC_LNX
+
+#ifdef RGB_MATRIX_ENABLE
+#   define RGB_MATRIX_KEYPRESSES // reacts to keypresses
+// #   define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
+// #   define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
+#   define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
+#   define RGB_MATRIX_FRAMEBUFFER_EFFECTS
+// #   define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
+// #   define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
+#    define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash.
+#    define RGB_MATRIX_HUE_STEP 8
+#    define RGB_MATRIX_SAT_STEP 8
+#    define RGB_MATRIX_VAL_STEP 8
+#    define RGB_MATRIX_SPD_STEP 10
+
+
+// RGB Matrix Animation modes. Explicitly enabled
+// For full list of effects, see:
+// https://docs.qmk.fm/#/feature_rgb_matrix?id=rgb-matrix-effects
+#    define ENABLE_RGB_MATRIX_SOLID_COLOR
+// #    define ENABLE_RGB_MATRIX_ALPHAS_MODS
+// #    define ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN
+// #    define ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
+// #    define ENABLE_RGB_MATRIX_BREATHING
+// #    define ENABLE_RGB_MATRIX_BAND_SAT
+// #    define ENABLE_RGB_MATRIX_BAND_VAL
+// #    define ENABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
+// #    define ENABLE_RGB_MATRIX_BAND_PINWHEEL_VAL
+// #    define ENABLE_RGB_MATRIX_BAND_SPIRAL_SAT
+// #    define ENABLE_RGB_MATRIX_BAND_SPIRAL_VAL
+// #    define ENABLE_RGB_MATRIX_CYCLE_ALL
+// #    define ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
+// #    define ENABLE_RGB_MATRIX_CYCLE_UP_DOWN
+// #    define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
+// #    define ENABLE_RGB_MATRIX_CYCLE_OUT_IN
+// #    define ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
+// #    define ENABLE_RGB_MATRIX_CYCLE_PINWHEEL
+// #    define ENABLE_RGB_MATRIX_CYCLE_SPIRAL
+// #    define ENABLE_RGB_MATRIX_DUAL_BEACON
+// #    define ENABLE_RGB_MATRIX_RAINBOW_BEACON
+#    define ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS
+// #    define ENABLE_RGB_MATRIX_RAINDROPS
+// #    define ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
+// #    define ENABLE_RGB_MATRIX_HUE_BREATHING
+// #    define ENABLE_RGB_MATRIX_HUE_PENDULUM
+// #    define ENABLE_RGB_MATRIX_HUE_WAVE
+// #    define ENABLE_RGB_MATRIX_PIXEL_RAIN
+// #    define ENABLE_RGB_MATRIX_PIXEL_FLOW
+// #    define ENABLE_RGB_MATRIX_PIXEL_FRACTAL
+// enabled only if RGB_MATRIX_FRAMEBUFFER_EFFECTS is defined
+#    define ENABLE_RGB_MATRIX_TYPING_HEATMAP
+#    define RGB_MATRIX_TYPING_HEATMAP_DECREASE_DELAY_MS 200
+// #    define ENABLE_RGB_MATRIX_DIGITAL_RAIN
+// enabled only of RGB_MATRIX_KEYPRESSES or RGB_MATRIX_KEYRELEASES is defined
+#    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
+// #    define ENABLE_RGB_MATRIX_SOLID_REACTIVE
+// #    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
+// #    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
+// #    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
+// #    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
+// #    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
+// #    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
+// #    define ENABLE_RGB_MATRIX_SPLASH
+// #    define ENABLE_RGB_MATRIX_MULTISPLASH
+// #    define ENABLE_RGB_MATRIX_SOLID_SPLASH
+// #    define ENABLE_RGB_MATRIX_SOLID_MULTISPLASH
+
+#endif
diff --git a/keyboards/crkbd/keymaps/ollyhayes/keymap.c b/keyboards/crkbd/keymaps/ollyhayes/keymap.c
new file mode 100644
index 0000000000..80ce41df49
--- /dev/null
+++ b/keyboards/crkbd/keymaps/ollyhayes/keymap.c
@@ -0,0 +1,112 @@
+/* Copyright 2022 Olly Hayes (@ollyhayes)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include QMK_KEYBOARD_H
+#include "ollyhayes.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+  [BASE] = LAYOUT_split_3x6_3(
+// +------------+------+------+---------+----------+---------+--------+----------+---------+--------+---------+---------+
+     NUM_SWITCH , KC_Q , KC_W , KC_F    , KC_P     , KC_G    , KC_J   , KC_L     , KC_U    , KC_Y   , KC_SCLN , KC_BSPC ,
+     KC_ESC     , KC_A , KC_R , KC_S    , KC_T     , KC_D    , KC_H   , KC_N     , KC_E    , KC_I   , KC_O    , KC_ENT  ,
+     KC_LSFT    , KC_Z , KC_X , KC_C    , KC_V     , KC_B    , KC_K   , KC_M     , KC_COMM , KC_DOT , KC_SLSH , KC_RSFT ,
+                                KC_LCTL , MO(PUNC) , MO(ARR) , KC_SPC , MO(PUNC) , KC_RCTL
+// +------------+------+------+---------+----------+---------+--------+----------+---------+--------+---------+---------+
+  ),
+
+  [QWERTY] = LAYOUT_split_3x6_3(
+// +---------+------+------+---------+---------+---------+---------+---------+---------+--------+---------+---------+
+     KC_TRNS , KC_Q , KC_W , KC_E    , KC_R    , KC_T    , KC_Y    , KC_U    , KC_I    , KC_O   , KC_P    , KC_TRNS ,
+     KC_TRNS , KC_A , KC_S , KC_D    , KC_F    , KC_G    , KC_H    , KC_J    , KC_K    , KC_L   , KC_SCLN , KC_TRNS ,
+     KC_TRNS , KC_Z , KC_X , KC_C    , KC_V    , KC_B    , KC_N    , KC_M    , KC_COMM , KC_DOT , KC_SLSH , KC_TRNS ,
+                             KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS
+// +---------+------+------+---------+---------+---------+---------+---------+---------+--------+---------+---------+
+  ),
+
+  [GAMES] = LAYOUT_split_3x6_3(
+//  +---------+------+------+---------+---------+----------+---------+---------+---------+--------+---------+---------+
+	  KC_TRNS , KC_Q , KC_W , KC_E    , KC_R    , KC_T     , KC_Y    , KC_U    , KC_I    , KC_O   , KC_P    , KC_TRNS ,
+	  KC_TRNS , KC_A , KC_S , KC_D    , KC_F    , KC_G     , KC_H    , KC_J    , KC_K    , KC_L   , KC_SCLN , KC_TRNS ,
+	  KC_TRNS , KC_Z , KC_X , KC_C    , KC_V    , KC_B     , KC_N    , KC_M    , KC_COMM , KC_DOT , KC_SLSH , KC_TRNS ,
+							  KC_TRNS , KC_LALT , KC_SPACE , MO(ARR) , KC_TRNS , KC_TRNS
+//  +---------+------+------+---------+---------+----------+---------+---------+---------+--------+---------+---------+
+  ),
+
+  [NUM] = LAYOUT_split_3x6_3(
+//  +---------+---------------+------+--------+---------+-----------+-----------+------+--------+------+---------+---------+
+	  KC_TRNS , MO(FUNCTIONS) , KC_1 , KC_2   , KC_3    , DF(BASE)  , C(KC_GRV) , KC_7 , KC_8   , KC_9 , KC_TRNS , KC_TRNS ,
+	  KC_TRNS , MO(MEDIA)     , KC_4 , KC_5   , KC_6    , DF(GAMES) , KC_NO     , KC_4 , KC_5   , KC_6 , KC_TRNS , KC_TRNS ,
+	  KC_TRNS , KC_0          , KC_7 , KC_8   , KC_9    , DF(QWERTY), KC_NO     , KC_1 , KC_2   , KC_3 , KC_TRNS , KC_TRNS ,
+									   KC_DOT , KC_TRNS , KC_TAB    , KC_TRNS   , KC_0 , KC_DOT
+//  +---------+---------------+------+--------+---------+-----------+-----------+------+--------+------+---------+---------+
+  ),
+
+  [FUNCTIONS] = LAYOUT_split_3x6_3(
+//  +---------------+---------+---------+---------+---------+---------+---------+---------+---------+-------+---------+---------+
+	  KC_TRNS       , KC_TRNS , KC_TRNS , KC_F8   , KC_F9   , KC_F12  , KC_F12  , KC_F7   , KC_F8   , KC_F9 , KC_TRNS , KC_TRNS ,
+	  TG(FUNCTIONS) , KC_TRNS , KC_F4   , KC_F5   , KC_F6   , KC_F11  , KC_F11  , KC_F4   , KC_F5   , KC_F6 , KC_TRNS , KC_TRNS ,
+	  KC_TRNS       , KC_TRNS , KC_F1   , KC_F2   , KC_F3   , KC_F10  , KC_F10  , KC_F1   , KC_F2   , KC_F3 , KC_TRNS , KC_TRNS ,
+										  KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS
+//  +---------------+---------+---------+---------+---------+---------+---------+---------+---------+-------+---------+---------+
+  ),
+
+  [ARR] = LAYOUT_split_3x6_3(
+//  +---------+---------+-----------+---------+---------+------------+-----------+---------+---------+-----------+---------+---------+
+	  KC_TRNS , KC_TRNS , KC_HOME   , KC_PGUP , KC_PGDN , KC_END     , KC_HOME   , KC_PGDN , KC_PGUP , KC_END    , KC_TRNS , KC_TRNS ,
+	  KC_ENT  , KC_DEL  , KC_LEFT   , KC_UP   , KC_DOWN , KC_RGHT    , KC_LEFT   , KC_DOWN , KC_UP   , KC_RGHT   , KC_DEL  , KC_TRNS ,
+	  KC_TRNS , KC_INS  , C(KC_LEFT), KC_LGUI , KC_LALT , C(KC_RGHT) , C(KC_LEFT), DOWN4   , UP4     , C(KC_RGHT), KC_INS  , KC_TRNS ,
+								      KC_TRNS , KC_F12  , KC_TRNS    , KC_TRNS   , KC_F12  , KC_TRNS
+//  +---------+---------+-----------+---------+---------+------------+-----------+---------+---------+-----------+---------+---------+
+  ),
+
+  [PUNC] = LAYOUT_split_3x6_3(
+//  +---------+------------+-----------+-----------+-------------+------------+------------+-------------+------------+------------+-----------+---------+
+	  ALTTAB  , S(KC_1)    , S(KC_2)   , UC(0x20ac), S(KC_4)     , S(KC_5)    , S(KC_6)    , S(KC_7)     , S(KC_8)    , S(KC_9)    , S(KC_0)   , KC_TRNS ,
+	  KC_TRNS , S(KC_NUBS) , S(KC_GRV) , KC_LBRC   , KC_RBRC     , S(KC_NUHS) , KC_QUOT    , S(KC_LBRC)  , S(KC_RBRC) , KC_MINS    , S(KC_EQL) , KC_TRNS ,
+	  KC_TRNS , KC_NUBS    , KC_GRV    , KC_LGUI   , KC_LALT     , KC_NUHS    , S(KC_QUOT) , KC_LALT     , KC_LGUI    , S(KC_MINS) , KC_EQL    , KC_TRNS ,
+										 KC_TRNS   , MO(DUBPUNC) , KC_MPLY    , KC_TRNS    , MO(DUBPUNC) , KC_TRNS
+//  +---------+------------+-----------+-----------+-------------+------------+------------+-------------+------------+------------+-----------+---------+
+  ),
+
+  [MEDIA] = LAYOUT_split_3x6_3(
+//  +------------+-----------+---------+---------+---------+----------------+----------------+---------+---------+---------+----------+---------+
+	  RESET      , RGB_RMOD  , RGB_MOD , RGB_TOG , RGB_HUD , RGB_HUI        , RGB_HUD        , RGB_HUI , RGB_TOG , RGB_RMOD, RGB_MOD  , KC_SLEP ,
+	  KC_TRNS    , KC_TRNS   , KC_TRNS , KC_VOLD , KC_VOLU , RGB_MODE_PLAIN , RGB_MODE_PLAIN , KC_VOLD , KC_VOLU , KC_TRNS , KC_TRNS  , KC_TRNS ,
+	  KC_TRNS    , KC_TRNS   , RGB_VAD , RGB_VAI , RGB_SAD , RGB_SAI        , RGB_SAD        , RGB_SAI , RGB_VAD , RGB_VAI , KC_TRNS  , KC_TRNS ,
+										 KC_TRNS , KC_TRNS , KC_TRNS        , KC_TRNS        , KC_TRNS , KC_TRNS
+//  +------------+-----------+---------+---------+---------+----------------+----------------+---------+---------+---------+----------+---------+
+  ),
+
+  [DUBPUNC] = LAYOUT_split_3x6_3(
+//  +---------+----------+-----------+-----------+------------+---------+-----------+---------+----------+---------+----------+---------+
+	  KC_TRNS , KC_TRNS  , KC_TRNS   , UC(0x00a3), KC_TRNS    , KC_TRNS , KC_TRNS   , KC_TRNS , U_UMLAUT , KC_TRNS , KC_TRNS  , KC_TRNS ,
+	  KC_TRNS , A_UMLAUT , KC_TRNS   , UC(0x00df), UC(0x2713) , KC_TRNS , UC(0x00b0), KC_TRNS , KC_TRNS  , KC_TRNS , O_UMLAUT , KC_TRNS ,
+	  KC_TRNS , KC_TRNS  , UC(0x2717), KC_TRNS   , KC_TRNS    , KC_TRNS , KC_TRNS   , KC_TRNS , KC_TRNS  , KC_TRNS , KC_TRNS  , KC_TRNS ,
+									   KC_TRNS   , KC_TRNS    , KC_TRNS , KC_TRNS   , KC_TRNS , KC_TRNS
+//  +---------+----------+-----------+-----------+------------+---------+-----------+---------+----------+---------+----------+---------+
+  )
+};
+
+/*
+[TEMPLATE] = LAYOUT_split_3x6_3(
+//  +--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+
+    KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      ,
+    KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      ,
+    KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      ,
+                                                 KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS      , KC_TRNS
+//  +--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+
+),
+*/
diff --git a/keyboards/crkbd/keymaps/ollyhayes/oled.c b/keyboards/crkbd/keymaps/ollyhayes/oled.c
new file mode 100644
index 0000000000..33db85fbb7
--- /dev/null
+++ b/keyboards/crkbd/keymaps/ollyhayes/oled.c
@@ -0,0 +1,112 @@
+/* Copyright 2022 Olly Hayes (@ollyhayes)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include QMK_KEYBOARD_H
+#include "ollyhayes.h"
+
+oled_rotation_t oled_init_user(oled_rotation_t rotation) {
+  if (!is_keyboard_master()) {
+    return OLED_ROTATION_180;  // flips the display 180 degrees if offhand
+  }
+  return rotation;
+}
+
+#define L_BASE 0
+#define L_NUM 8
+#define L_FUNCTIONS 16
+#define L_ARR 32
+#define L_PUNC 64
+#define L_DUBPUNC 128
+#define L_MEDIA 256
+
+#define DL_COLEMAK 1
+#define DL_QWERTY 2
+#define DL_GAMES 4
+
+void oled_render_layer_state(void) {
+    oled_write_P(PSTR("Layer: "), false);
+    switch (layer_state) {
+        case L_BASE:
+            switch (default_layer_state) {
+                case DL_QWERTY:
+                    oled_write_ln_P(PSTR("Qwerty"), false);
+                    break;
+                case DL_GAMES:
+                    oled_write_ln_P(PSTR("Games"), false);
+                    break;
+                case DL_COLEMAK:
+                default:
+                    oled_write_ln_P(PSTR("Colemak"), false);
+                    break;
+            }
+            break;
+        case L_NUM:
+            oled_write_ln_P(PSTR("Numbers"), false);
+            break;
+        case L_FUNCTIONS:
+        case L_FUNCTIONS|L_NUM:
+            oled_write_ln_P(PSTR("Functions"), false);
+            break;
+        case L_ARR:
+            oled_write_ln_P(PSTR("Navigation"), false);
+            break;
+        case L_PUNC:
+            oled_write_ln_P(PSTR("Punctuation"), false);
+            break;
+        case L_MEDIA:
+        case L_MEDIA|L_NUM:
+            oled_write_ln_P(PSTR("Media"), false);
+            break;
+        case L_DUBPUNC:
+        case L_DUBPUNC|L_PUNC:
+            oled_write_ln_P(PSTR("Specials"), false);
+            break;
+    }
+}
+
+void oled_render_timer(void) {
+    static uint16_t microticks = 0;
+    static uint16_t ticks = 0;
+
+    if (microticks++ % 1000 == 0) {
+        ticks++;
+    }
+
+    oled_write_P(PSTR("Ticks:   "), false);
+    oled_write_ln(get_u16_str(ticks, ' '), false);
+}
+
+void oled_render_presses(void) {
+    oled_write_P(PSTR("Presses: "), false);
+    oled_write_ln(get_u16_str(key_presses, ' '), false);
+}
+
+void oled_render_rgb_mode(void) {
+    oled_write_P(PSTR("Animation: "), false);
+    oled_write_ln(get_u8_str(rgb_matrix_get_mode(), ' '), false);
+}
+
+bool oled_task_user(void) {
+    if (is_keyboard_master()) {
+        oled_render_layer_state();
+    }
+    oled_render_timer();
+    if (is_keyboard_master()) {
+        oled_render_presses();
+    }
+    oled_render_rgb_mode();
+    return false;
+}
diff --git a/keyboards/crkbd/keymaps/ollyhayes/readme.md b/keyboards/crkbd/keymaps/ollyhayes/readme.md
new file mode 100644
index 0000000000..9e63f780ff
--- /dev/null
+++ b/keyboards/crkbd/keymaps/ollyhayes/readme.md
@@ -0,0 +1,67 @@
+# ollyhayes's keymap for [Corne Keyboard (crkbd)](https://github.com/foostan/crkbd)
+
+## Keymap
+
+After many years of changing my keymap often and reperatedly, I finally came to a stable version. I've been using this for a while now with only small tweaks every so often.
+
+All layers are activated only whilst the layer key is held, except the default layers.
+
+Lots of keys are repeated on both sides. I find this really useful for two reasons:
+
+* I like to have the option to use the opposite hand to hold modifiers shift/ctrl etc as the hand pressing the key, I find this really comfortable.
+* When using the mouse, I like to be able to do common things with just my left hand.
+
+### Colemak
+
+The base layer:
+
+![colemak](https://i.imgur.com/uxLJzul.png)
+
+### Navigation
+
+All things for moving the cursor around, inspired by vim.
+
+* `c←` is ctrl+left
+* `↓↓↓↓` is ↓ pressed four times
+
+![navigation](https://i.imgur.com/xfkA0ze.png)
+
+### Symbols
+
+The shifted number row and all brackets and other symbols.
+
+* `a/t` is alt-tab for window switching in windows/linux. Using some special code to release alt when the punc key is released, this works quite nicely.
+
+![symbols](https://i.imgur.com/t9Jygs1.png)
+
+### Specials
+
+Some extra symbols (linux only for now) that work by sending UTF sequences. Layer activated by holding both punctuation layer keys.
+
+![specials](https://i.imgur.com/AtPWKrA.png)
+
+### Numbers
+
+Numbpads (left version is reversed so 1, 2, 3 are easy to reach with one hand (like on a regular keyboard).
+
+Also the keys to switch the default layer are here.
+
+![numbers](https://i.imgur.com/9XXcAXK.png)
+
+### Functions
+
+Function keys, nothing too interesting.
+
+![functions](https://i.imgur.com/ttrw3FJ.png)
+
+### Games (default layer)
+
+Used for some games, qwerty with space bar and alt for the left hand.
+
+![games](https://i.imgur.com/zVvHWKd.png)
+
+### Qwerty (default layer)
+
+Mostly for guests.
+
+![qwerty](https://i.imgur.com/Bqs1bjV.png)
diff --git a/keyboards/crkbd/keymaps/ollyhayes/rules.mk b/keyboards/crkbd/keymaps/ollyhayes/rules.mk
new file mode 100644
index 0000000000..2dcd9007e5
--- /dev/null
+++ b/keyboards/crkbd/keymaps/ollyhayes/rules.mk
@@ -0,0 +1,17 @@
+SRC += oled.c
+
+OLED_ENABLE = yes
+OLED_DRIVER = SSD1306
+
+EXTRAKEY_ENABLE = yes
+UNICODE_ENABLE = yes
+
+RGBLIGHT_ENABLE = no
+RGB_MATRIX_ENABLE = yes
+# RGB_MATRIX_CUSTOM_USER = yes
+
+VIRTSER_ENABLE = yes
+
+LTO_ENABLE = yes
+
+MOUSEKEY_ENABLE = no
diff --git a/users/ollyhayes/ollyhayes.c b/users/ollyhayes/ollyhayes.c
new file mode 100644
index 0000000000..6dfd61b263
--- /dev/null
+++ b/users/ollyhayes/ollyhayes.c
@@ -0,0 +1,153 @@
+/* Copyright 2022 Olly Hayes (@ollyhayes)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ollyhayes.h"
+
+#ifdef VIRTSER_ENABLE
+#   include "virtser.h"
+#endif
+
+layer_state_t default_layer_state_set_kb(layer_state_t state) {
+    if (layer_state_cmp(state, BASE)) {
+        rgb_matrix_mode(3);
+    } else if (layer_state_cmp(state, GAMES)) {
+        rgb_matrix_mode(1);
+    }
+    return state;
+}
+
+uint16_t key_presses = 0;
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+    // for tab/number layer switch
+    static bool key_pressed_since_switch = false;
+    static uint16_t switch_down_time = 0;
+
+    // for alt-tab on punc layer
+    static bool alt_tab_used = false;
+
+    // for capital umlauts
+    static bool shift_held = false;
+
+#ifdef VIRTSER_ENABLE
+    if (record->event.pressed) {
+        uint8_t key_index = 40 + record->event.key.col + record->event.key.row * 6;
+        virtser_send(key_index);
+    } else {
+        uint8_t key_index = 90 + record->event.key.col + record->event.key.row * 6;
+        virtser_send(key_index);
+    }
+#endif
+
+    if (record->event.pressed) {
+        key_pressed_since_switch = true;
+        key_presses++;
+    }
+
+    switch (keycode) {
+        case UP4:
+            if (record->event.pressed) {
+                tap_code(KC_UP);
+                tap_code(KC_UP);
+                tap_code(KC_UP);
+                tap_code(KC_UP);
+                return false;
+            }
+            break;
+
+        case DOWN4:
+            if (record->event.pressed) {
+                tap_code(KC_DOWN);
+                tap_code(KC_DOWN);
+                tap_code(KC_DOWN);
+                tap_code(KC_DOWN);
+                return false;
+            }
+            break;
+
+        case NUM_SWITCH:
+            if (record->event.pressed) {
+                layer_on(NUM);
+                key_pressed_since_switch = false;
+                switch_down_time = timer_read();
+            } else {
+                layer_off(NUM);
+
+                if (!key_pressed_since_switch && timer_elapsed(switch_down_time) < 200) {
+                    tap_code(KC_TAB);
+                }
+            }
+            return false;
+
+        case MO(PUNC):
+            if (!record->event.pressed) {
+                if (alt_tab_used) {
+                    unregister_code(KC_LALT);
+                    alt_tab_used = false;
+                }
+            }
+            return true;
+
+        case MO(FUNCTIONS):
+            if (!record->event.pressed) {
+                // if NUM_SWITCH has been lifted first, toggle to that layer
+                // (4 = 2^NUM)
+                if ((layer_state & 4) != 0) {
+                    layer_on(FUNCTIONS);
+                    return false;
+                }
+            }
+            return true;
+
+        case ALTTAB:
+            if (record->event.pressed) {
+                alt_tab_used = true;
+                register_code(KC_LALT);
+                tap_code(KC_TAB);
+            }
+            return false;
+
+        case KC_LSFT:
+        case KC_RSFT:
+            shift_held = record->event.pressed;
+            break;
+
+        case A_UMLAUT:
+            if (record->event.pressed) {
+                if (shift_held)
+                    register_unicode(0x00c4);
+                else
+                    register_unicode(0x00e4);
+            }
+            break;
+        case O_UMLAUT:
+            if (record->event.pressed) {
+                if (shift_held)
+                    register_unicode(0x00d6);
+                else
+                    register_unicode(0x00f6);
+            }
+            break;
+        case U_UMLAUT:
+            if (record->event.pressed) {
+                if (shift_held)
+                    register_unicode(0x00dc);
+                else
+                    register_unicode(0x00fc);
+            }
+            break;
+    }
+    return true;
+}
diff --git a/users/ollyhayes/ollyhayes.h b/users/ollyhayes/ollyhayes.h
new file mode 100644
index 0000000000..c65422937c
--- /dev/null
+++ b/users/ollyhayes/ollyhayes.h
@@ -0,0 +1,41 @@
+/* Copyright 2022 Olly Hayes (@ollyhayes)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include QMK_KEYBOARD_H
+
+enum layers {
+    BASE,
+    QWERTY,
+    GAMES,
+    NUM,
+    FUNCTIONS,
+    ARR,
+    PUNC,
+    DUBPUNC,
+    MEDIA,
+};
+
+enum custom_keycodes {
+  DOWN4 = SAFE_RANGE,
+  UP4,
+  NUM_SWITCH,
+  ALTTAB,
+  A_UMLAUT,
+  O_UMLAUT,
+  U_UMLAUT,
+};
+
+extern uint16_t key_presses;
diff --git a/users/ollyhayes/rules.mk b/users/ollyhayes/rules.mk
new file mode 100644
index 0000000000..27752a5dee
--- /dev/null
+++ b/users/ollyhayes/rules.mk
@@ -0,0 +1 @@
+SRC += ollyhayes.c