diff --git a/common/base-hardware.nix b/common/base-hardware.nix
index bee29ba..4283273 100644
--- a/common/base-hardware.nix
+++ b/common/base-hardware.nix
@@ -15,10 +15,11 @@
 
   # Bluetooth
   hardware.bluetooth.enable = true;
-  hardware.bluetooth.extraConfig = "
-    [General]
-    Enable=Source,Sink,Media,Socket
-  ";
+  hardware.bluetooth.config = {
+    General = {
+      Enable = "Source,Sink,Media,Socket";
+    };
+  };
 
   # Sound.
   sound.enable = true;
diff --git a/common/gpu-bumblebee.nix b/common/gpu-bumblebee.nix
index a775ec0..ff6bcb1 100644
--- a/common/gpu-bumblebee.nix
+++ b/common/gpu-bumblebee.nix
@@ -4,4 +4,13 @@
   # Graphics drivers
   hardware.bumblebee.enable = true;
   hardware.opengl.driSupport32Bit = true;
+
+  hardware.opengl = {
+    driSupport32Bit = true;
+    extraPackages = with pkgs; [
+      vaapiIntel
+      vaapiVdpau
+      libvdpau-va-gl
+    ];
+  };
 }
diff --git a/common/system.nix b/common/system.nix
index b05a4a9..11b281b 100644
--- a/common/system.nix
+++ b/common/system.nix
@@ -8,12 +8,26 @@
     neovim
   ];
 
-  fonts.enableDefaultFonts = true;
   fonts.fonts = with pkgs; [
     hasklig
   ];
-  fonts.fontconfig.defaultFonts.sansSerif = [ "Noto Color Emoji" ];
-  fonts.fontconfig.defaultFonts.serif = [ "Noto Color Emoji" ];
+  fonts.fontconfig.localConf = ''
+    <fontconfig>
+      <alias binding="weak">
+        <family>sans-serif</family>
+        <prefer>
+          <family>emoji</family>
+        </prefer>
+      </alias>
+      <alias binding="weak">
+        <family>serif</family>
+        <prefer>
+          <family>emoji</family>
+        </prefer>
+      </alias>
+    </fontconfig>
+  '';
 
   services.printing.enable = true;
+  services.fwupd.enable = true;
 }
diff --git a/home/common/.direnvrc b/home/common/.direnvrc
new file mode 100644
index 0000000..3df1010
--- /dev/null
+++ b/home/common/.direnvrc
@@ -0,0 +1,62 @@
+use_nix() {
+  local path="$(nix-instantiate --find-file nixpkgs)"
+
+  if [ -f "${path}/.version-suffix" ]; then
+    local version="$(< $path/.version-suffix)"
+  elif [ -f "${path}/.git" ]; then
+    local version="$(< $(< ${path}/.git/HEAD))"
+  fi
+
+  local cache=".direnv/cache-${version:-unknown}"
+
+  local update_drv=0
+  if [[ ! -e "$cache" ]] || \
+    [[ "$HOME/.direnvrc" -nt "$cache" ]] || \
+    [[ .envrc -nt "$cache" ]] || \
+    [[ default.nix -nt "$cache" ]] || \
+    [[ shell.nix -nt "$cache" ]];
+  then
+    [ -d .direnv ] || mkdir .direnv
+    nix-shell --show-trace --pure "$@" --run "\"$direnv\" dump bash" > "$cache"
+    update_drv=1
+  else
+    log_status using cached derivation
+  fi
+  local term_backup=$TERM path_backup=$PATH
+  if [ -n ${TMPDIR+x} ]; then
+    local tmp_backup=$TMPDIR
+  fi
+
+  eval "$(< $cache)"
+  export PATH=$PATH:$path_backup TERM=$term_backup TMPDIR=$tmp_backup
+  if [ -n ${tmp_backup+x} ]; then
+    export TMPDIR=${tmp_backup}
+  else
+    unset TMPDIR
+  fi
+
+  # `nix-shell --pure` sets invalid ssl certificate paths
+  if [ "${SSL_CERT_FILE:-}" = /no-cert-file.crt ]; then
+    unset SSL_CERT_FILE
+  fi
+  if [ "${NIX_SSL_CERT_FILE:-}" = /no-cert-file.crt ]; then
+    unset NIX_SSL_CERT_FILE
+  fi
+
+  # This part is based on https://discourse.nixos.org/t/what-is-the-best-dev-workflow-around-nix-shell/418/4
+  if [ "$out" ] && (( $update_drv )); then
+    local drv_link=".direnv/drv"
+    local drv="$(nix show-derivation $out | grep -E -o -m1 '/nix/store/.*.drv')"
+    local stripped_pwd=${PWD/\//}
+    local escaped_pwd=${stripped_pwd//-/--}
+    local escaped_pwd=${escaped_pwd//\//-}
+    ln -fs "$drv" "$drv_link"
+    ln -fs "$PWD/$drv_link" "/nix/var/nix/gcroots/per-user/$LOGNAME/$escaped_pwd"
+    log_status renewed cache and derivation link
+  fi
+
+  if [[ $# = 0 ]]; then
+    watch_file default.nix
+    watch_file shell.nix
+  fi
+}
diff --git a/home/common/direnv.nix b/home/common/direnv.nix
new file mode 100644
index 0000000..ee3d9a2
--- /dev/null
+++ b/home/common/direnv.nix
@@ -0,0 +1,15 @@
+{ config, pkgs, ... }:
+
+with pkgs;
+{
+  programs.direnv = {
+    enable = true;
+    enableBashIntegration = true;
+    enableFishIntegration = true;
+    stdlib = builtins.readFile ./.direnvrc;
+  };
+
+  home.file.".envrc".text = ''
+    dotenv
+  '';
+}
diff --git a/home/common/dotnet.nix b/home/common/dotnet.nix
index 478cc7f..b471aa5 100644
--- a/home/common/dotnet.nix
+++ b/home/common/dotnet.nix
@@ -2,23 +2,58 @@
 
 with pkgs;
 let
-  dotnet-sdk_3 = pkgs.callPackage (import (pkgs.fetchFromGitHub {
-    name = "nixos-pr-dotnet-sdk_3";
-    owner = "juselius";
+  nixpkgs-dotnet-repo = fetchFromGitHub {
+    name = "nixos-pr-dotnet-combined";
+    owner = "NixOS";
     repo = "nixpkgs";
-    rev = "077f44d84b390a29af7abf7ebbb573b1bbd1a3c1";
-    sha256 = "01isr2sh5m0bav7gach53rxbnn10lrrzz3j4mrz30prs4n0ww16r";
-  } + /pkgs/development/compilers/dotnet/sdk/3.nix )) {};
+    rev = "34ec6d3d11797031df3b488953a0c82c60865f90";
+    sha256 = "0mdmzxx67wyckp7813f8k900ip3s3bi27y0chv71qqklmba72dyp";
+  };
+  nixpkgs-dotnet = (import nixpkgs-dotnet-repo {});
+  dotnetCorePackages = nixpkgs-dotnet.dotnetCorePackages;
+  buildDotnet = attrs: callPackage (import (nixpkgs-dotnet-repo + /pkgs/development/compilers/dotnet/buildDotnet.nix) attrs) {};
+  buildNetCoreSdk = attrs: buildDotnet (attrs // { type = "sdk"; } );
+  sdk_3_1 = buildNetCoreSdk {
+    version = "3.1.100";
+    sha512 = "0hvshwsgbm6v5hc1plzdzx8bwsdna2167fnfhxpysqs5mz7crsa4f13m4cxhrbn64lasqz2007nhdrlpgaqvgll6q8736h884aaw5sj";
+  };
+  dotnet-combined = with dotnetCorePackages; combinePackages {
+    cli = sdk_3_1;
+    withSdks = [ sdk_2_1 sdk_3_0 sdk_3_1 ];
+    withRuntimes = [ sdk_2_1 sdk_3_0 sdk_3_1 ];
+  };
 in
 {
+  nixpkgs.overlays = [
+    (self: super: {
+      omnisharp-roslyn = super.omnisharp-roslyn.overrideAttrs (oldAttrs: rec {
+          version = "1.34.9";
+          src = fetchurl {
+            url = "https://github.com/OmniSharp/omnisharp-roslyn/releases/download/v${version}/omnisharp-mono.tar.gz";
+            sha256 = "1b5jzc7dj9hhddrr73hhpq95h8vabkd6xac1bwq05lb24m0jsrp9";
+          };
+      });
+    })
+  ];
+  
   home.packages = [
-    # dotnet-sdk
-    dotnet-sdk_3
+    dotnet-combined
     omnisharp-roslyn
   ];
 
   home.sessionVariables = {
-    DOTNET_ROOT = "/tmp/dotnet-sdk/3.0.100";
-    MSBuildSDKsPath = "/tmp/dotnet-sdk/3.0.100/sdk/3.0.100/Sdks";
+    DOTNET_ROOT = "${dotnet-combined}/bin";
+    MSBuildSdksPath = "${dotnet-combined}/sdk/3.1.100/Sdks";
+    MSBUILD_EXE_PATH = "${dotnet-combined}/sdk/3.1.100/MSBuild.dll";
+  };
+
+  home.file.".omnisharp/omnisharp.json" = {
+    text = ''
+      {
+        "RoslynExtensionsOptions": {
+          "EnableAnalyzersSupport": true
+        }
+      }
+    '';
   };
 }
diff --git a/home/common/neovim.nix b/home/common/neovim.nix
index 7d31af8..d08aeca 100644
--- a/home/common/neovim.nix
+++ b/home/common/neovim.nix
@@ -1,12 +1,130 @@
 { config, pkgs, ... }:
 
+let
+  buildVimPluginFrom2Nix = pkgs.vimUtils.buildVimPluginFrom2Nix;
+
+  omnisharp-vim = buildVimPluginFrom2Nix {
+    pname = "omnisharp-vim";
+    version = "master";
+    src = pkgs.fetchFromGitHub {
+      owner = "FelschR";
+      repo = "omnisharp-vim";
+      rev = "7a11d9cfb414c14b87efddeadfad4b9a9fc09cfa";
+      sha256 = "03q5lbp9z1xblfn8yr3z6hvky45mfzwf54hjysvyz2hz9yxl92g4";
+    };
+  };
+  nvim-lsp = buildVimPluginFrom2Nix {
+    pname = "nvim-lsp";
+    version = "master";
+    src = pkgs.fetchFromGitHub {
+      owner = "neovim";
+      repo = "nvim-lsp";
+      rev = "bf657b837ee0aad20afd812ea14d73108bb30093";
+      sha256 = "192175fkxdki5damxj0z1bna1qdpsc2di4df7i5mzyw2qikj9y0m";
+    };
+  };
+  # coc-omnisharp = buildVimPluginFrom2Nix {
+  #   pname = "coc-omnisharp";
+  #   version = "master";
+  #   src = pkgs.fetchFromGitHub {
+  #     owner = "coc-extensions";
+  #     repo = "coc-omnisharp";
+  #     rev = "9c062bbae5692b69b5cf918131a972405b2582b9";
+  #     sha256 = "1phjnzgh8918cb915jn92i5vv23lki95q9x0nsjddna3gz3c9k0w";
+  #   };
+  # };
+in
 {
+  nixpkgs.overlays = [
+    (self: super: {
+      neovim-unwrapped = super.neovim-unwrapped.overrideAttrs (oldAttrs: rec {
+        version = "master-lsp";
+        src = pkgs.fetchFromGitHub {
+          owner = "neovim";
+          repo = "neovim";
+          rev = "ed424655bef3169dc5452c5a8212e250dc483f9e";
+          sha256 = "0ri31nxs3lcx9x1gwwx6ch5b5nddqvg5n1gdzskyfwffvg3wwrl3";
+        };
+        nativeBuildInputs = oldAttrs.nativeBuildInputs ++ [
+          pkgs.utf8proc
+        ];
+      });
+    })
+  ];
+
+  home.packages = with pkgs; [
+    fzf
+    nodejs-12_x
+    # haskellPackages.ghcide
+  ];
+
+  home.sessionVariables = {
+    EDITOR = "vim";
+  };
+
   programs.neovim = {
     enable = true;
     viAlias = true;
     vimAlias = true;
     plugins = with pkgs.vimPlugins; [
+      gruvbox
+      editorconfig-vim
+      fzf-vim
+      lightline-vim
+      lightline-ale
+      nerdtree
+      vim-polyglot
+      vim-multiple-cursors
+      vim-surround
+      vim-commentary
+      vim-easymotion
+      # vim-gitgutter
+      camelcasemotion
+
+      # nvim-lsp # nixos-rebuild currently fails
+
+      ale
+      vim-orgmode
       vim-nix
+
+      coc-nvim
+      coc-emmet
+      coc-html
+      coc-css
+      coc-tsserver
+      coc-json
+      coc-yaml
+      # coc-omnisharp # not really maintained
+
+      omnisharp-vim
     ];
+    extraConfig = ''
+      colorscheme gruvbox
+      let g:gruvbox_number_column = 'bg1'
+
+      let mapleader=" "
+      let g:camelcasemotion_key = '<leader>'
+
+      " omnisharp-vim config:
+      let g:OmniSharp_server_stdio = 1
+      let g:OmniSharp_server_path = '/home/felschr/.nix-profile/bin/omnisharp'
+      let g:OmniSharp_selector_ui = 'fzf'
+      let g:OmniSharp_highlight_types = 3
+      let g:ale_linters = {
+      \ 'cs': ['OmniSharp']
+      \}
+      inoremap <silent><expr> <c-space> coc#refresh()
+      
+      " call nvim_lsp#setup("tsserver", {})
+      " call nvim_lsp#setup("ghcide", {})
+
+      set relativenumber
+      set wildmenu
+      set wildmode=longest,list,full
+
+      map ; :Files<CR>
+      map <C-o> :NERDTreeToggle<CR>
+      map <Leader> <Plug>(easymotion-prefix)
+    '';
   };
 }
diff --git a/home/felschr-work.nix b/home/felschr-work.nix
index 33bb5e0..e3ae731 100644
--- a/home/felschr-work.nix
+++ b/home/felschr-work.nix
@@ -4,6 +4,7 @@ with pkgs;
 {
   imports = [
     ./common/sh.nix
+    ./common/direnv.nix
     ./common/mimeapps.nix
     ./common/gui.nix
     ./common/gnome.nix
@@ -30,10 +31,32 @@ with pkgs;
     enableFishIntegration = true;
   };
 
+  programs.ssh = {
+    enable = true;
+  };
+
+  services.gpg-agent = {
+    enable = true;
+    extraConfig = ''
+      pinentry-program ${pkgs.pinentry-gnome}/bin/pinentry-gnome3
+    '';
+  };
+
+  programs.gpg.enable = true;
+
   programs.git = {
     enable = true;
     userName = "Felix Schroeter";
     userEmail = "fs@upsquared.com";
+    ignores = [".direnv"];
+    signing = {
+      key = "6DA1 4A05 C6E0 7DBE EB81  BA24 28ED 46BC B881 7B7A";
+      signByDefault = true;
+    };
+    extraConfig = {
+      pull = { rebase = true; };
+      rebase = { autoStash = true; };
+    };
   };
 
   programs.firefox.enable = true;
@@ -45,18 +68,25 @@ with pkgs;
   home.packages = with pkgs; [
     # system
     gparted
+    gnome-firmware-updater
 
     # productivity
     discord
     libreoffice
     skypeforlinux
+    pinta
+    inkscape
 
     # development
     unzip
+    openssl
     kubectl
     kubernetes-helm
+    google-cloud-sdk
     awscli
     postman
+    jq
+    dos2unix
   ];
 
   home.stateVersion = "19.09";
diff --git a/work-pc.nix b/work-pc.nix
index 8700b36..2dd23e0 100644
--- a/work-pc.nix
+++ b/work-pc.nix
@@ -22,6 +22,12 @@
 
   virtualisation.virtualbox.host.enable = true;
 
+  hardware.enableAllFirmware = true;
+  hardware.cpu.intel.updateMicrocode = true;
+  services.tlp.enable = true;
+
+  programs.adb.enable = true;
+
   users.users.felschr = {
     isNormalUser = true;
     extraGroups = [ "wheel" "audio" "docker" "disk" "vboxusers" ];