diff --git a/keyboards/dztech/dz65rgb/keymaps/haervig/keymap.c b/keyboards/dztech/dz65rgb/keymaps/haervig/keymap.c
new file mode 100644
index 0000000000..6784c14f00
--- /dev/null
+++ b/keyboards/dztech/dz65rgb/keymaps/haervig/keymap.c
@@ -0,0 +1,36 @@
+/*
+Copyright 2021 Jakob Hærvig <jakob.haervig@gmail.com>
+
+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 "haervig.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+    [0] = LAYOUT_65_ansi(
+        KC_GESC,        DK_1,    CU_2,    DK_3,    CU_4,    DK_5,    CU_6,    CU_7,    CU_8,    CU_9,    CU_0,    CU_MINS, CU_EQL,  CU_BSPC, KC_HOME,
+        KC_TAB,         KC_Q,    KC_W,    KC_E,    KC_R,    KC_T,    KC_Y,    KC_U,    KC_I,    KC_O,    KC_P,    CU_LBRC, CU_RBRC, CU_BSLS, KC_PGUP,
+        CTL_T(KC_CAPS), KC_A,    KC_S,    KC_D,    KC_F,    KC_G,    KC_H,    KC_J,    KC_K,    KC_L,    CU_SCLN, CU_QUOT,          KC_ENT,  KC_PGDN,
+        CU_LSFT,                 KC_Z,    KC_X,    KC_C,    KC_V,    KC_B,    KC_N,    KC_M,    CU_COMM, CU_DOT,  CU_SLSH, CU_RSFT, KC_UP,   KC_END,
+        KC_LCTL,        KC_LALT, KC_LGUI,                            KC_SPC,                    MO(1),   KC_RALT,   KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
+    ),
+    [1] = LAYOUT_65_ansi(
+        _______,        KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,  _______,  _______,
+        _______,        _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,   _______,
+        _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,          _______, _______,
+        _______,                 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+        _______,        _______, _______,                            _______,                   _______, _______, _______, _______, _______, _______
+    )
+};
diff --git a/keyboards/dztech/dz65rgb/keymaps/haervig/rules.mk b/keyboards/dztech/dz65rgb/keymaps/haervig/rules.mk
new file mode 100644
index 0000000000..676050bfce
--- /dev/null
+++ b/keyboards/dztech/dz65rgb/keymaps/haervig/rules.mk
@@ -0,0 +1,3 @@
+# Userspace defines
+DANISH_ENABLE = yes # Enable Custom US Ansi Keycodes for PC with Danish set as input language
+RGB_MATRIX_ENABLE = no # Disable the ugly RGB light
\ No newline at end of file
diff --git a/users/haervig/config.h b/users/haervig/config.h
new file mode 100644
index 0000000000..6a7d67737e
--- /dev/null
+++ b/users/haervig/config.h
@@ -0,0 +1,19 @@
+/*
+Copyright 2021 Jakob Hærvig <jakob.haervig@gmail.com>
+
+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 TAPPING_TERM 200
diff --git a/users/haervig/haervig.c b/users/haervig/haervig.c
new file mode 100644
index 0000000000..d03b43edc1
--- /dev/null
+++ b/users/haervig/haervig.c
@@ -0,0 +1,234 @@
+/*
+Copyright 2021 Jakob Hærvig <jakob.haervig@gmail.com>
+
+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 "haervig.h"
+
+#ifdef DANISH_ENABLE
+// These indicate if left and right shift are physically pressed
+bool lshift = false;
+bool rshift = false;
+
+// Interrupt and times for space cadet shift
+bool lshiftp = false;
+bool rshiftp = false;
+uint16_t lshift_timer = 0;
+uint16_t rshift_timer = 0;
+
+// Number of items that are saved in prev_kcs
+uint8_t prev_indx = 0;
+// Used to save the last 6 actual keycodes activated by frankenkeycodes
+uint16_t prev_kcs[6] = {0, 0, 0, 0, 0, 0};
+
+// If true the deadkey characters grave and circonflexe are not automatically escaped
+bool esct = false;
+
+/*
+Used to add a keycode to a prev_kcs to remember it.
+When full the last code gets discarded and replaced by
+the new one.
+*/
+void add_to_prev(uint16_t kc){
+  for (int i=0; i<prev_indx; i++){
+    if (kc == prev_kcs[i])
+      return;
+  }
+  if (prev_indx == 6){
+    for (int i=5; i>0; i--){
+      prev_kcs[i] = prev_kcs[i-1];
+    }
+    prev_kcs[0] = kc;
+  } else {
+    prev_kcs[prev_indx] = kc;
+    prev_indx++;
+  }
+}
+
+/*
+Unregisters all codes saved in prev_kcs and resets prev_indx.
+gets called on multiple occasions mainly when shift is released
+and when frankenkeycodes are pressed. Prevents output of
+wrong characters when really specific key combinations
+that would never occur during normal usage are pressed.
+*/
+void unreg_prev(void){
+  if (prev_indx == 0)
+    return;
+  for (int i=0; i<prev_indx; i++){
+    unregister_code(prev_kcs[i]);
+  }
+  prev_indx = 0;
+}
+#endif
+
+// Interrupt and times for Nav/Esc
+bool navesc = false;
+uint16_t navesc_timer = 0;
+
+// Interrupts all timers
+void timer_timeout(void){
+  #ifdef DANISH_ENABLE
+  lshiftp = false;
+  rshiftp = false;
+  #endif
+  navesc = false;
+  timer_timeout_keymap();
+}
+
+__attribute__((weak))
+void timer_timeout_keymap(void){
+}
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+  switch (keycode) {
+  case KC_LGUI:
+  case KC_RGUI:
+    if (record->event.pressed)
+      timer_timeout();
+    return true;
+  case CU_NAV:
+    if(record->event.pressed) {
+      navesc = true;
+      navesc_timer = timer_read();
+      layer_on(_NAV);
+    } else {
+      if (timer_elapsed(navesc_timer) < TAPPING_TERM && navesc) {
+        tap_code(KC_ESC);
+      }
+      layer_off(_NAV);
+    }
+    return false;
+
+  #ifdef DANISH_ENABLE
+  case CU_LSFT:
+    if(record->event.pressed) {
+      lshiftp = true;
+      lshift_timer = timer_read();
+      unregister_code(KC_LSFT);
+      register_code(KC_LSFT);
+      lshift = true;
+    } else {
+      if (timer_elapsed(lshift_timer) < TAPPING_TERM && lshiftp) {
+        register_code(KC_LSFT);
+        tap_code(KC_8);
+        unregister_code(KC_LSFT);
+      }
+      unreg_prev();
+      if (!rshift)
+        unregister_code(KC_LSFT);
+      lshift = false;
+    }
+    return false;
+  case CU_RSFT:
+    if(record->event.pressed) {
+      rshiftp = true;
+      rshift_timer = timer_read();
+      unregister_code(KC_LSFT);
+      register_code(KC_LSFT);
+      rshift = true;
+    } else {
+      if (timer_elapsed(rshift_timer) < TAPPING_TERM && rshiftp) {
+        register_code(KC_LSFT);
+        tap_code(KC_9);
+        unregister_code(KC_LSFT);
+      }
+      unreg_prev();
+      if (!lshift)
+        unregister_code(KC_LSFT);
+      rshift = false;
+    }
+    return false;
+  case CU_COMM:
+    SHIFT_NO(DK_COMM, KC_GRV)
+  case CU_DOT:
+    SHIFT_NORM(DK_DOT, KC_GRV)
+  case CU_SLSH:
+    SHIFT_ALL(DK_7, KC_MINS)
+  case CU_SCLN:
+    SHIFT_ALL(DK_COMM, DK_DOT)
+  case CU_QUOT:
+    SHIFT_NORM(DK_QUOT, DK_2)
+  case CU_2:
+    NORM_ALGR(DK_2, KC_NUHS)
+  case CU_4:
+    if (record->event.pressed) { \
+      timer_timeout(); \
+      if (lshift || rshift) { \
+        register_code(KC_LSFT); \
+        register_code(KC_ALGR); \
+        unregister_code(KC_3); \
+        tap_code(KC_3); \
+        unregister_code(KC_3); \
+      } else { \
+        unregister_code(KC_4); \
+        tap_code(KC_4); \
+      } \
+      unregister_code(KC_ALGR); \
+      unregister_code(KC_LSFT); \
+    } \
+    return false;
+  case CU_6:
+    SHIFT_NORM(DK_6, KC_RBRC)
+  case CU_7:
+    SHIFT_NORM(DK_7, DK_6)
+  case CU_8:
+    SHIFT_NORM(DK_8, KC_NUHS)
+  case CU_9:
+    SHIFT_NORM(DK_9, DK_8)
+  case CU_0:
+    SHIFT_NORM(DK_0, DK_9)
+  case CU_MINS:
+    SHIFT_NORM(KC_SLSH, KC_SLSH)
+  case CU_EQL:
+    SHIFT_SWITCH(DK_0, DK_PLUS)
+  case CU_BSPC:
+    SHIFT_NO(KC_BSPC, KC_DEL)
+  case CU_LBRC:
+    NORM_ALGRSHIFT(DK_8, DK_8)
+  case CU_RBRC:
+    NORM_ALGRSHIFT(DK_9, DK_9)
+  case CU_BSLS:
+    ALGR_SWITCH(DK_7, DK_I)
+  case KC_LCTL:
+  case KC_RCTL:
+    if(!record->event.pressed) {
+      timer_timeout();
+      unregister_code(KC_Z);
+      unregister_code(KC_Y);
+    }
+    return true;
+  #endif
+
+  default:
+    if(record->event.pressed) {
+      timer_timeout();
+
+      #ifdef DANISH_ENABLE
+      if (lshift || rshift)
+        register_code(KC_LSFT);
+      else
+        unregister_code(KC_LSFT);
+      #endif
+
+    }
+    return process_record_keymap(keycode, record);
+  }
+}
+
+__attribute__((weak))
+bool process_record_keymap(uint16_t keycode, keyrecord_t *record) {
+  return true;
+}
diff --git a/users/haervig/haervig.h b/users/haervig/haervig.h
new file mode 100644
index 0000000000..e0d47e4cc9
--- /dev/null
+++ b/users/haervig/haervig.h
@@ -0,0 +1,297 @@
+/*
+Copyright 2021 Jakob Hærvig <jakob.haervig@gmail.com>
+
+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 "quantum.h"
+#include "keymap_danish.h"
+
+enum userspace_layers {
+  _DEADKEY = 14,            // Change if more than 16 layers are required
+  _NAV
+};
+
+enum userspace_custom_keycodes {
+  //CU_GAME = SAFE_RANGE,     // Toggle game mode on/off
+  CU_NAV = SAFE_RANGE,                   // NAV | ESC
+
+  #ifdef DANISH_ENABLE
+  CU_LSFT,                  // LSFT | (
+  CU_RSFT,                  // LSFT | )
+  CU_COMM,                  // , | <
+  CU_DOT,                   // . | >
+  CU_SLSH,                  // / | ?
+  CU_SCLN,                  // ; | :
+  CU_QUOT,                  // ' | "
+  CU_2,                     // 2 | @
+  CU_4,                     // 4 | $
+  CU_6,                     // 6 | ^
+  CU_7,                     // 7 | &
+  CU_8,                     // 8 | *
+  CU_9,                     // 9 | (
+  CU_0,                     // 0 | )
+  CU_MINS,                  // - | _
+  CU_EQL,                   // = | +
+  CU_BSPC,                  // backspace | delete
+  CU_LBRC,                  // [ | {
+  CU_RBRC,                  // ] | }
+  CU_BSLS,                  // \ | |
+  #endif
+
+  NEW_SAFE_RANGE            // Use for keymap specific keycodes
+};
+
+#ifdef DANISH_ENABLE
+extern bool lshift;
+extern bool rshift;
+extern bool lshiftp;
+extern bool rshiftp;
+extern uint16_t lshift_timer;
+extern uint16_t rshift_timer;
+
+extern uint8_t prev_indx;
+extern uint16_t prev_kcs[6];
+void add_to_prev(uint16_t kc);
+void unreg_prev(void);
+
+extern bool esct;
+#endif
+
+extern bool navesc;
+extern uint16_t navesc_timer;
+
+void timer_timeout(void);
+
+void timer_timeout_keymap(void);
+
+bool process_record_keymap(uint16_t keycode, keyrecord_t *record);
+
+#define CTRLX LCTL(KC_X)
+#define CTRLC LCTL(KC_C)
+#define CTRLV LCTL(KC_V)
+
+#define ALTF4 LALT(KC_F4)
+
+#define GUIU LGUI(KC_UP)
+#define GUID LGUI(KC_DOWN)
+#define GUIL LGUI(KC_LEFT)
+#define GUIR RGUI(KC_RIGHT)
+
+#define CTLENT CTL_T(KC_ENT)
+
+#define EMOJI LWIN(KC_DOT)
+
+/*
+Templates for Keys, with custom shifted and non shifted Characters
+*/
+
+// Normal shift status
+#define SHIFT_NORM(kc1, kc2) \
+if (record->event.pressed) { \
+  timer_timeout(); \
+  if (lshift || rshift) { \
+    register_code(KC_LSFT); \
+    unregister_code(kc2); \
+    register_code(kc2); \
+    add_to_prev(kc2); \
+  } else { \
+    unregister_code(KC_LSFT); \
+    unregister_code(kc1); \
+    register_code(kc1); \
+  } \
+} else { \
+  unregister_code(kc1); \
+  unregister_code(kc2); \
+} \
+return false;
+
+// Inverted shift status
+#define SHIFT_SWITCH(kc1, kc2) \
+if (record->event.pressed) { \
+  timer_timeout(); \
+  if (lshift || rshift) { \
+    unregister_code(KC_LSFT); \
+    unregister_code(kc2); \
+    register_code(kc2); \
+    add_to_prev(kc2); \
+  } else { \
+    register_code(KC_LSFT); \
+    unregister_code(kc1); \
+    register_code(kc1); \
+    add_to_prev(kc1); \
+  } \
+} else { \
+  unregister_code(kc1); \
+  unregister_code(kc2); \
+  unreg_prev(); \
+  if (lshift || rshift) \
+    register_code(KC_LSFT); \
+  else \
+    unregister_code(KC_LSFT); \
+} \
+return false;
+
+// Always shifted
+#define SHIFT_ALL(kc1, kc2) \
+if (record->event.pressed) { \
+  timer_timeout(); \
+  register_code(KC_LSFT); \
+  if (lshift || rshift) { \
+    tap_code(kc2); \
+    add_to_prev(kc2); \
+  } else { \
+    tap_code(kc1); \
+    add_to_prev(kc1); \
+  } \
+} else { \
+  unregister_code(kc1); \
+  unregister_code(kc2); \
+  unreg_prev(); \
+  if (lshift || rshift) \
+    register_code(KC_LSFT); \
+  else \
+    unregister_code(KC_LSFT); \
+} \
+return false;
+
+// Never shifted
+#define SHIFT_NO(kc1, kc2) \
+if (record->event.pressed) { \
+  timer_timeout(); \
+  unregister_code(KC_LSFT); \
+  if (lshift || rshift) { \
+    tap_code(kc2); \
+    add_to_prev(kc2); \
+  } else { \
+    tap_code(kc1); \
+  } \
+} else { \
+  unregister_code(kc1); \
+  unregister_code(kc2); \
+  unreg_prev(); \
+  if (lshift || rshift) \
+    register_code(KC_LSFT); \
+  else \
+    unregister_code(KC_LSFT); \
+} \
+return false;
+
+// Norm AltGr
+#define NORM_ALGR(kc1, kc2) \
+if (record->event.pressed) { \
+  timer_timeout(); \
+  if (lshift || rshift) { \
+    register_code(KC_ALGR); \
+    unregister_code(KC_LSFT); \
+    tap_code(kc2); \
+    unregister_code(KC_ALGR); \
+  } else { \
+    unregister_code(KC_ALGR); \
+    unregister_code(KC_LSFT); \
+    tap_code(kc1); \
+  } \
+} else { \
+  unregister_code(kc1); \
+  unregister_code(kc2); \
+} \
+return false;
+
+// Norm AltGr shift
+#define NORM_ALGRSHIFT(kc1, kc2) \
+if (record->event.pressed) { \
+  timer_timeout(); \
+  register_code(KC_LSFT); \
+  register_code(KC_ALGR); \
+  if (lshift || rshift) { \
+    unregister_code(kc2); \
+    tap_code(kc2); \
+    unregister_code(KC_LSFT); \
+  } else { \
+    unregister_code(KC_LSFT); \
+    unregister_code(kc1); \
+    register_code(kc1); \
+  } \
+  unregister_code(KC_ALGR); \
+} else { \
+  unregister_code(kc1); \
+  unregister_code(kc2); \
+} \
+return false;
+
+// Inverted altgr status
+#define ALGR_SWITCH(kc1, kc2) \
+if (record->event.pressed) { \
+  timer_timeout(); \
+  register_code(KC_ALGR); \
+  if (lshift || rshift) { \
+    unregister_code(KC_LSFT); \
+    unregister_code(kc2); \
+    register_code(kc2); \
+    unregister_code(KC_ALGR); \
+    add_to_prev(kc2); \
+  } else { \
+    register_code(KC_LSFT); \
+    unregister_code(kc1); \
+    register_code(kc1); \
+    unregister_code(KC_ALGR); \
+    add_to_prev(kc1); \
+  } \
+} else { \
+  unregister_code(kc1); \
+  unregister_code(kc2); \
+  unreg_prev(); \
+  if (lshift || rshift) \
+    register_code(KC_LSFT); \
+  else \
+    unregister_code(KC_LSFT); \
+} \
+return false;
+
+// Always AltGr
+#define SHIFT_ALGR(kc1, kc2) \
+if (record->event.pressed) { \
+  timer_timeout(); \
+  unregister_code(KC_LSFT); \
+  register_code(KC_ALGR); \
+  if (lshift || rshift) { \
+    unregister_code(kc2); \
+    tap_code(kc2); \
+    register_code(KC_LSFT); \
+  } else { \
+    unregister_code(kc1); \
+    tap_code(kc1); \
+  } \
+  unregister_code(KC_ALGR); \
+} \
+return false;
+
+// Different keycode when Ctrl is pressed
+#define CTRL(kc1, kc2) \
+if(record->event.pressed) { \
+  timer_timeout(); \
+  if (lshift || rshift) \
+    register_code(KC_LSFT); \
+  else \
+    unregister_code(KC_LSFT); \
+  if (keyboard_report->mods & (MOD_BIT(KC_LCTL) | MOD_BIT(KC_RCTL))){ \
+    register_code(kc2); \
+  } else { \
+    register_code(kc1); \
+  } \
+} else { \
+    unregister_code(kc1); \
+    unregister_code(kc2); \
+} \
+return false;
diff --git a/users/haervig/readme.md b/users/haervig/readme.md
new file mode 100644
index 0000000000..dc2ebbd13c
--- /dev/null
+++ b/users/haervig/readme.md
@@ -0,0 +1,11 @@
+# haervig Userspace
+
+This userspace keeps my userdefined codes. I work on a ANSI keyboard on a Danish macOS system. I believe this code might be relevant for similar users. A big shout out to user spacebarracecar for the ideas on how to map keys, which served as the basis of this code.
+
+## US Layout Keys for Danish PCs
+
+By daily work involves a lot of coding. I find an ANSI layout superior and decided to buy a QMK keyboard. However, all PC's here in Denmark are set to input language Danish. Even though I could simply set input language language to US international, I find this inconvenient. I instead decided to map my keys so the ANSI keyboard would will function as expected when the OS inputn language is Danish.
+
+## More details
+
+Tracking the current state of the shift code is nessesary for it to work. User spacebarracecar has documented the idea thoroughly and should serve you as a starting point if you wish to implement this code. I modified the code to suit Danish input language. Additionally, a couple of functions were added to accomodate the altgr key.
\ No newline at end of file
diff --git a/users/haervig/rules.mk b/users/haervig/rules.mk
new file mode 100644
index 0000000000..e06647ff27
--- /dev/null
+++ b/users/haervig/rules.mk
@@ -0,0 +1,5 @@
+SRC += haervig.c
+
+ifeq ($(strip $(DANISH_ENABLE)), yes)
+    OPT_DEFS += -DDANISH_ENABLE
+endif