diff --git a/nix/esp-idf/default.nix b/nix/esp-idf/default.nix
new file mode 100644
index 0000000000000000000000000000000000000000..29f6a88fc0a4956b612cc02220b88b9f46ee958a
--- /dev/null
+++ b/nix/esp-idf/default.nix
@@ -0,0 +1,105 @@
+# Based on https://github.com/mirrexagon/nixpkgs-esp-dev/
+
+{ rev ? "v4.4.5"
+, sha256 ? "sha256-Jz9cbTYoourYYNo873kLt4CQXbE704zc9Aeq9kbNdPU="
+, stdenv
+, python3Packages
+, fetchFromGitHub
+}:
+
+let
+  src = fetchFromGitHub {
+    owner = "espressif";
+    repo = "esp-idf";
+    rev = rev;
+    sha256 = sha256;
+    fetchSubmodules = true;
+  };
+in
+stdenv.mkDerivation rec {
+  pname = "esp-idf";
+  version = rev;
+
+  inherit src;
+
+  # This is so that downstream derivations will have IDF_PATH set.
+  setupHook = ./setup-hook.sh;
+
+  propagatedBuildInputs = with python3Packages; [
+    setuptools click future pyelftools urllib3
+    jinja2 itsdangerous
+
+    (pyparsing.overrideAttrs (oa: rec {
+      version = "2.3.1";
+      src = fetchFromGitHub {
+        owner = "pyparsing";
+        repo = "pyparsing";
+        rev = "pyparsing_${version}";
+        hash = "sha256-m4mvPUXjDxz77rofg2Bop4/RnVTBDBNL6lRDd5zkpxM=";
+      };
+    }))
+
+    (kconfiglib.overrideAttrs (oa: rec {
+      version = "13.7.1";
+      src = fetchPypi {
+        inherit (oa) pname;
+        inherit version;
+        hash = "sha256-ou6PsGECRCxFllsFlpRPAsKhUX8JL6IIyjB/P9EqCiI=";
+      };
+    }))
+
+    (construct.overrideAttrs (oa: rec {
+      version = "2.10.54";
+      src = fetchFromGitHub {
+        owner = "construct";
+        repo = "construct";
+        rev = "v${version}";
+        hash = "sha256-iDAxm2Uf1dDA+y+9X/w+PKI36RPK/gDjXnG4Zay+Gtc=";
+      };
+    }))
+
+    ((python-socketio.overrideAttrs (oa: rec {
+      version = "4.6.1";
+      src = fetchFromGitHub {
+        owner = "miguelgrinberg";
+        repo = "python-socketio";
+        rev = "v${version}";
+        hash = "sha256-hVNH0086mo17nPcCmVMkkCyuCkwo4nQv2ATtE56SsZE=";
+      };
+      disabledTests = [
+        "test_logger"
+      ];
+    })).override {
+      python-engineio = python-engineio.overrideAttrs (oa: rec {
+        version = "3.14.2";
+        src = fetchFromGitHub {
+          owner = "miguelgrinberg";
+          repo = "python-engineio";
+          rev = "v${version}";
+          hash = "sha256-xJDlbxzy6HSQL1+1NQgFa3IjDg0t9n3NAHvZmX/cb+Q";
+        };
+      });
+    })
+
+    (pygdbmi.overrideAttrs (oa: rec {
+      version = "0.9.0.2";
+      src = fetchFromGitHub {
+        owner = "cs01";
+        repo = "pygdbmi";
+        rev = version;
+        hash = "sha256-bZQYcT5lA8xkG2YIK7P7fxkbVJhO6T5YpWo1EdLpOgY=";
+      };
+    }))
+  ];
+
+  patches = [
+    # Can't be bothered to package gdbgui and idf-component-manager and we
+    # don't need them.
+    ./fixup-requirements.patch
+  ];
+
+  installPhase = ''
+    mkdir -p $out
+    cp -r * $out/
+  '';
+}
diff --git a/nix/esp-idf/fixup-requirements.patch b/nix/esp-idf/fixup-requirements.patch
new file mode 100644
index 0000000000000000000000000000000000000000..f229541c5120adb95f1a4fc35c906825dc0ebdc3
--- /dev/null
+++ b/nix/esp-idf/fixup-requirements.patch
@@ -0,0 +1,17 @@
+diff --git a/requirements.txt b/requirements.txt
+index 9769f8d933..c1126df3fb 100644
+--- a/requirements.txt
++++ b/requirements.txt
+@@ -17,12 +17,8 @@ cryptography>=2.1.4
+ 
+ pyparsing>=2.0.3,<2.4.0
+ pyelftools>=0.22
+-idf-component-manager~=1.2
+ urllib3<2
+ 
+-gdbgui==0.13.2.0; python_version < "3.11"
+-# 0.13.2.1 supports Python 3.6+ only
+-# Windows is not supported since 0.14.0.0. See https://github.com/cs01/gdbgui/issues/348
+ pygdbmi<=0.9.0.2; python_version < "3.11"
+ # The pygdbmi required max version 0.9.0.2 since 0.9.0.3 is not compatible with latest gdbgui (>=0.13.2.0)
+ # A compatible Socket.IO should be used. See https://github.com/miguelgrinberg/python-socketio/issues/578
diff --git a/nix/esp-idf/setup-hook.sh b/nix/esp-idf/setup-hook.sh
new file mode 100755
index 0000000000000000000000000000000000000000..59a5106323fdc65479d5fb530a3714af173aeb96
--- /dev/null
+++ b/nix/esp-idf/setup-hook.sh
@@ -0,0 +1,12 @@
+# Export the necessary environment variables to use ESP-IDF.
+
+addIdfEnvVars() {
+    # Crude way to detect if $1 is the ESP-IDF derivation.
+    if [ -e "$1/tools/idf.py" ]; then
+        export IDF_PATH="$1"
+        export IDF_COMPONENT_MANAGER=0
+        addToSearchPath PATH "$IDF_PATH/tools"
+    fi
+}
+
+addEnvHooks "$hostOffset" addIdfEnvVars
diff --git a/nix/esp32s3-toolchain-bin.nix b/nix/esp32s3-toolchain-bin.nix
new file mode 100644
index 0000000000000000000000000000000000000000..b8d69a84e0037e2df35f374dbfad6ab0c6ed50f8
--- /dev/null
+++ b/nix/esp32s3-toolchain-bin.nix
@@ -0,0 +1,52 @@
+# Based on https://github.com/mirrexagon/nixpkgs-esp-dev/
+
+{ version ? "2021r2-patch5"
+, hash ? "sha256-iqF6at8B76WxYoyKxXgGOkTSaulYHTlIa5IiOkHvJi8="
+, stdenv
+, lib
+, fetchurl
+, makeWrapper
+, buildFHSUserEnv
+}:
+
+let
+  fhsEnv = buildFHSUserEnv {
+    name = "esp32s3-toolchain-env";
+    targetPkgs = pkgs: with pkgs; [ zlib ];
+    runScript = "";
+  };
+in
+
+assert stdenv.system == "x86_64-linux";
+
+stdenv.mkDerivation rec {
+  pname = "esp32s3-toolchain";
+  inherit version;
+
+  src = fetchurl {
+    url = "https://github.com/espressif/crosstool-NG/releases/download/esp-${version}/xtensa-esp32s3-elf-gcc8_4_0-esp-${version}-linux-amd64.tar.gz";
+    inherit hash;
+  };
+
+  buildInputs = [ makeWrapper ];
+
+  phases = [ "unpackPhase" "installPhase" ];
+
+  installPhase = ''
+    cp -r . $out
+    for FILE in $(ls $out/bin); do
+      FILE_PATH="$out/bin/$FILE"
+      if [[ -x $FILE_PATH ]]; then
+        mv $FILE_PATH $FILE_PATH-unwrapped
+        makeWrapper ${fhsEnv}/bin/esp32s3-toolchain-env $FILE_PATH --add-flags "$FILE_PATH-unwrapped"
+      fi
+    done
+  '';
+
+  meta = with lib; {
+    description = "ESP32-S3 compiler toolchain";
+    homepage = "https://docs.espressif.com/projects/esp-idf/en/stable/get-started/linux-setup.html";
+    license = licenses.gpl3;
+  };
+}
+
diff --git a/nix/niv/sources.json b/nix/niv/sources.json
new file mode 100644
index 0000000000000000000000000000000000000000..60c24b7b39a6e5fd3e05feb0105a55408cc070d9
--- /dev/null
+++ b/nix/niv/sources.json
@@ -0,0 +1,14 @@
+{
+    "nixpkgs": {
+        "branch": "master",
+        "description": "Nix Packages collection",
+        "homepage": "",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "c11d08f02390aab49e7c22e6d0ea9b176394d961",
+        "sha256": "017jdga9j0qkdplly8pypxxcsski0h9galzaf9qsvpq0j50x86cv",
+        "type": "tarball",
+        "url": "https://github.com/NixOS/nixpkgs/archive/c11d08f02390aab49e7c22e6d0ea9b176394d961.tar.gz",
+        "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
+    }
+}
diff --git a/nix/sources.nix b/nix/niv/sources.nix
similarity index 100%
rename from nix/sources.nix
rename to nix/niv/sources.nix
diff --git a/nix/openocd-esp32-bin.nix b/nix/openocd-esp32-bin.nix
new file mode 100644
index 0000000000000000000000000000000000000000..b9866502e127bb15c65fd5feaaa1f3757b9984ee
--- /dev/null
+++ b/nix/openocd-esp32-bin.nix
@@ -0,0 +1,42 @@
+# Based on https://github.com/mirrexagon/nixpkgs-esp-dev/
+
+{ stdenv, lib, fetchurl, makeWrapper, buildFHSUserEnv }:
+
+let
+  fhsEnv = buildFHSUserEnv {
+    name = "esp32-openocd-env";
+    targetPkgs = pkgs: with pkgs; [ zlib libusb1 ];
+    runScript = "";
+  };
+in
+stdenv.mkDerivation rec {
+  pname = "openocd";
+  version = "0.12.0-esp32-20230419";
+
+  src = fetchurl {
+    url = "https://github.com/espressif/openocd-esp32/releases/download/v${version}/openocd-esp32-linux-amd64-${version}.tar.gz";
+    hash = "sha256-UUTnUWzXWiFSs17K4KQA99PUQkwkiPusxJQzVk9Uxw0=";
+  };
+
+  buildInputs = [ makeWrapper ];
+
+  phases = [ "unpackPhase" "installPhase" ];
+
+  installPhase = ''
+    cp -r . $out
+    for FILE in $(ls $out/bin); do
+      FILE_PATH="$out/bin/$FILE"
+      if [[ -x $FILE_PATH ]]; then
+        mv $FILE_PATH $FILE_PATH-unwrapped
+        makeWrapper ${fhsEnv}/bin/esp32-openocd-env $FILE_PATH --add-flags "$FILE_PATH-unwrapped"
+      fi
+    done
+  '';
+
+  meta = with lib; {
+    description = "ESP32 toolchain";
+    homepage = https://docs.espressif.com/projects/esp-idf/en/stable/get-started/linux-setup.html;
+    license = licenses.gpl3;
+  };
+}
+
diff --git a/nix/shell.nix b/nix/shell.nix
index 031f9748d5d4d34cd599e36aec62e0f77fda4be5..a86191682d489024240c41300e61d7de1ff77d70 100644
--- a/nix/shell.nix
+++ b/nix/shell.nix
@@ -1,13 +1,17 @@
 let
-  sources = import ./sources.nix;
+  sources = import ./niv/sources.nix;
   nixpkgs = import sources.nixpkgs {
     overlays = [
-      (import "${sources.nixpkgs-esp-dev}/overlay.nix")
+      (self: super: {
+        gcc-xtensa-esp32s3-elf-bin = super.callPackage ./esp32s3-toolchain-bin.nix {};
+        openocd-esp32-bin = super.callPackage ./openocd-esp32-bin.nix {};
+        esp-idf = super.callPackage ./esp-idf {};
+      })
     ];
   };
 
 in with nixpkgs; pkgs.mkShell {
-  name = "badg23-shell";
+  name = "flow3r-shell";
   buildInputs = with pkgs; [
     gcc-xtensa-esp32s3-elf-bin
     openocd-esp32-bin
diff --git a/nix/sources.json b/nix/sources.json
deleted file mode 100644
index 69aba976b54912563e52af02a720f59b51792a94..0000000000000000000000000000000000000000
--- a/nix/sources.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-    "nixpkgs": {
-        "branch": "master",
-        "description": "Nix Packages collection",
-        "homepage": "",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "c11d08f02390aab49e7c22e6d0ea9b176394d961",
-        "sha256": "017jdga9j0qkdplly8pypxxcsski0h9galzaf9qsvpq0j50x86cv",
-        "type": "tarball",
-        "url": "https://github.com/NixOS/nixpkgs/archive/c11d08f02390aab49e7c22e6d0ea9b176394d961.tar.gz",
-        "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
-    },
-    "nixpkgs-esp-dev": {
-        "branch": "master",
-        "description": "Nix flake and overlay for ESP8266 and ESP32 development.",
-        "homepage": "",
-        "owner": "mirrexagon",
-        "repo": "nixpkgs-esp-dev",
-        "rev": "48413ee362b4d0709e1a0dff6aba7fd99060335e",
-        "sha256": "1n0m1nr39ngff6px9gdm9hkgzqq7imdcakpgz9md7fmm5c7b309f",
-        "type": "tarball",
-        "url": "https://github.com/mirrexagon/nixpkgs-esp-dev/archive/48413ee362b4d0709e1a0dff6aba7fd99060335e.tar.gz",
-        "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
-    }
-}