{
  inputs = {
    flake-parts.url = "github:hercules-ci/flake-parts";
    devenv.url = "github:cachix/devenv";
    devenv.inputs.nixpkgs.follows = "nixpkgs";

    nixpkgs-python.url = "github:cachix/nixpkgs-python";
    nixpkgs-python.inputs.nixpkgs.follows = "nixpkgs";
    esp-dev.url = "github:mirrexagon/nixpkgs-esp-dev";
    esp-dev.inputs.nixpkgs.follows = "nixpkgs";

    rootdir = {
      url = "file+file:///dev/null";
      flake = false;
    };
  };

  outputs = inputs@{ nixpkgs, flake-parts, devenv, esp-dev, rootdir, ... }:
    flake-parts.lib.mkFlake { inherit inputs; } {
      imports = [
        devenv.flakeModule

        ./firmware
        ./controller
      ];
      systems = [ "x86_64-linux" ];

      perSystem = { inputs', system, lib, pkgs, config, ... }:
      let
        inherit (lib) mkMerge;

        rootdirOpt =
          let
            rootFileContent = builtins.readFile rootdir.outPath;
          in
          pkgs.lib.mkIf (rootFileContent != "") rootFileContent;
      in
      {
        _module.args = {
          pkgs = import nixpkgs {
            inherit system;
            overlays = [
              esp-dev.overlays.default
            ];
          };

          libMy = {
            withRootdir = c: mkMerge [
              c
              { devenv.root = rootdirOpt; }
            ];
          };
        };
      };
    };
}