{
  description = "Thor system configuration";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/release-22.05";
    nixpkgs-u.url = "github:NixOS/nixpkgs/nixos-unstable";

    home-manager = {
      url = "github:nix-community/home-manager/release-22.05";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    # home-manager-u = {
    #   url = "github:nix-community/home-manager";
    #   inputs.nixpkgs.follows = "nixpkgs-u";
    # };

    flake-utils.url = "github:numtide/flake-utils";
    nixos-hardware.url = "github:NixOS/nixos-hardware";

    nix-rice = {
      url = "github:bertof/nix-rice";
      inputs = { nixpkgs.follows = "nixpkgs-u"; flake-utils.follows = "flake-utils"; };
    };
    pre-commit-hooks = {
      url = "github:cachix/pre-commit-hooks.nix";
      inputs = { nixpkgs.follows = "nixpkgs-u"; flake-utils.follows = "flake-utils"; };
    };
    tex2nix = {
      url = "github:Mic92/tex2nix";
      inputs = { nixpkgs.follows = "nixpkgs-u"; flake-utils.follows = "flake-utils"; };
    };
  };

  outputs =
    { self
    , nixpkgs
    , home-manager
    , nixpkgs-u
      # , home-manager-u
    , flake-utils
    , nixos-hardware
    , tex2nix
    , nix-rice
    , pre-commit-hooks
    }:
    let

      config = {
        allowUnfree = true;
        extraOptions = "experimental-features = nix-command flakes";
        permittedInsecurePackages = [ "electron-9.4.4" ]; # authy dependency
      };

      overlaysBuilder = { system }: [
        # Packages
        (_: _: { stable = pkgs { inherit system; }; unstable = pkgs-u { inherit system; }; })

        # Nix rice
        (nix-rice.overlays.default)
        (import ./rice.nix)

        # Flakes packages
        (final: _: {
          inherit (tex2nix.packages.${system}) tex2nix;
          clipedit = final.callPackage ./custom/clipedit { };

          update-background = final.callPackage ./custom/update-background {
            backgrounds_directory = "$HOME/Immagini/Sfondi/1080+/1440+";
          };
          lockscreen = final.callPackage ./custom/lockscreen {
            palette = final.rice.colorPalette;
            font = final.rice.font.normal;
          };
          sddm-theme-clairvoyance = final.callPackage ./custom/sddm-theme-clairvoyance {
            wallpaper = ./wallpapers/comfy_waves.jpg;
          };
        })
      ];

      modulesBuilder = { system }:
        let overlays = overlaysBuilder { inherit system; }; in
        [
          # Nix configuration
          ({ pkgs, ... }: {
            nixpkgs = { inherit system overlays config; };
            nix = {
              package = pkgs.nixVersions.stable;
              extraOptions = "experimental-features = nix-command flakes";
            };
          })

          # Home manager configuration
          home-manager.nixosModules.home-manager
          ({ home-manager = { useGlobalPkgs = true; useUserPackages = true; }; })

          # Common modules
          ./nixos_modules/bertof_user.nix
          ./nixos_modules/automatic-garbage-collection.nix
          ./nixos_modules/zerotier.nix
        ];

      pkgs = { system }:
        let overlays = overlaysBuilder { inherit system; }; in
        import nixpkgs { inherit system config overlays; };
      pkgs-u = { system }:
        let overlays = overlaysBuilder { inherit system; }; in
        import nixpkgs-u { inherit system config overlays; };

      odinBaseModules = [
        ./odin/hardware-configuration.nix
        nixos-hardware.nixosModules.common-cpu-intel
        nixos-hardware.nixosModules.common-pc-laptop
        nixos-hardware.nixosModules.common-pc-laptop-ssd
        ./odin/common_configuration.nix

        # ./nixos_modules/pro_audio.nix
        ./nixos_modules/sesar.nix
      ];
      odinIntelModules = [ ./odin/configuration-intel.nix ];
      odinNvidiaModules = [ ./odin/configuration-nvidia.nix ];

      odinIntelBuilder = { extraModules ? [ ] }:
        nixpkgs.lib.nixosSystem rec {
          system = "x86_64-linux";
          modules = (modulesBuilder { inherit system; })
            ++ odinBaseModules ++ odinIntelModules
            ++ [{ home-manager.users.bertof = import ./odin/hm.nix; }]
            ++ extraModules;
        };
      odinNvidiaBuilder = { extraModules ? [ ] }:
        nixpkgs.lib.nixosSystem rec {
          system = "x86_64-linux";
          modules = (modulesBuilder { inherit system; })
            ++ odinBaseModules ++ odinNvidiaModules
            ++ [{ home-manager.users.bertof = import ./odin/hm.nix; }]
            ++ extraModules;
        };

      thorBaseModules = [
        ./thor/hardware-configuration.nix
        nixos-hardware.nixosModules.common-cpu-amd
        nixos-hardware.nixosModules.common-pc-ssd
        ./thor/configuration.nix

        ./nixos_modules/pro_audio.nix
        ./nixos_modules/sesar.nix
        ./nixos_modules/pentablet.nix
      ];
      thorBuilder = { extraModules ? [ ] }:
        nixpkgs.lib.nixosSystem rec {
          system = "x86_64-linux";
          modules = (modulesBuilder { inherit system; })
            ++ thorBaseModules
            ++ [{ home-manager.users.bertof = import ./thor/hm.nix; }]
            ++ extraModules;
        };

      lokiBaseModules = [
        ./loki/hardware-configuration.nix
        nixos-hardware.nixosModules.common-cpu-intel
        nixos-hardware.nixosModules.common-pc-ssd
        ./loki/configuration.nix
      ];
      lokiBuilder = { extraModules ? [ ] }:
        nixpkgs.lib.nixosSystem rec {
          system = "x86_64-linux";
          modules = (modulesBuilder { inherit system; })
            ++ lokiBaseModules
            ++ [{ home-manager.users.bertof = import ./loki/hm.nix; }]
            ++ extraModules;
        };

      freyaBaseModules = [
        # ./freya/hardware-configuration.nix
        nixos-hardware.nixosModules.raspberry-pi."4"
        ./freya/configuration.nix
      ];
      freyaBuilder = { extraModules ? [ ] }:
        nixpkgs.lib.nixosSystem rec {
          system = "x86_64-linux";
          modules = (modulesBuilder { inherit system; })
            ++ freyaBaseModules
            ++ [{ home-manager.users.bertof = import ./freya/hm.nix; }]
            ++ extraModules;
        };

      baldurBaseModules = [ ./baldur/configuration.nix ];
      balurBuilder = { extraModules ? [ ] }:
        nixpkgs.lib.nixosSystem rec {
          system = "x86_64-linux";
          modules = (modulesBuilder { inherit system; })
            ++ baldurBaseModules
            ++ [{ home-manager.users.bertof = import ./baldur/hm.nix; }]
            ++ extraModules;
        };
    in
    (flake-utils.lib.eachDefaultSystem (system: rec {
      packages = pkgs-u { inherit system; };

      checks = {
        pre-commit-check = pre-commit-hooks.lib.${system}.run {
          src = ./.;
          hooks = {
            nixpkgs-fmt.enable = true;
            nix-linter.enable = true;
          };
        };
      };

      devShells.default = packages.mkShell {
        shellHook = ''
          ${self.checks.${system}.pre-commit-check.shellHook}
        '';
      };
    })) // {
      nixosConfigurations = rec {

        thor = thorBuilder { };

        odin = odin-intel;
        odin-intel = odinIntelBuilder { };
        odin-nvidia = odinNvidiaBuilder { };

        loki = lokiBuilder { };
        # loki-stable = lokiStable [ ./nixos_modules/dnsmasq.nix ];
        # loki-k3s = lokiStable [ ./nixos_modules/k3s.nix ];
        # loki-unstable = lokiUnstable [ ];

        freya = freyaBuilder { };
        baldur = balurBuilder { };
      };
    };
}
