{
  inputs ? import ./inputs.nix {},
  selfPath ? ./.
}:

let

lib = (import "${inputs.nixpkgs}/lib").extend (import ./lib/overlays/version-info-fixup.nix { revision = inputs.lock.nixpkgs.revision; });

systems = [
  "x86_64-linux"
  "aarch64-linux"
];

# (system -> x) -> { [system] := x }
forEachSystem = lib.genAttrs systems;

self = {
  inherit inputs lib self;
  outPath = selfPath;
  modifiedNixpkgs     = import ./pkgs/top-level/impure.nix;
  modifiedNixpkgsPure = import ./pkgs/top-level/default.nix;
  packagesForSystem = system: self.modifiedNixpkgsPure { localSystem = system; };
  packages = forEachSystem (system: let
    nixpkgs = import "${inputs.nixpkgs}/pkgs/top-level/default.nix" { localSystem = system; };
    attrnames = builtins.attrNames nixpkgs;
  in
    builtins.removeAttrs (self.packagesForSystem system) attrnames
  );
  overlays = {
    cosmicPackages = import ./pkgs/overlays/cosmic-packages.nix { inherit inputs; };
    selfExpr = import ./pkgs/overlays/selfExpr.nix { nixpkgsPath = inputs.nixpkgs; };
    unstableWithMeta = import ./pkgs/overlays/unstable-with-meta.nix { unstableSource = inputs.nixpkgs-unstable; revision = inputs.lock.nixpkgs-unstable.revision; };
    versionInfoFixup = import ./pkgs/overlays/version-info-fixup.nix { inherit inputs; };
  };
  nixosConfigurations = let
    nixosSystem = import "${inputs.nixpkgs}/nixos/lib/eval-config.nix";
    mkNixosSystem = path: nixosSystem {
      inherit lib;
      modules = [
        path
        {
          config.nixpkgs.overlays = [
            ( import ./pkgs/overlays/selfExpr.nix { nixpkgsPath = "${self}/pkgs/top-level/impure.nix"; } )
            ( import ./pkgs/top-level/by-name-overlay.nix "${self}/pkgs/by-name" )
            self.overlays.versionInfoFixup
          ];
        }
      ];
      specialArgs = { inherit self inputs; };
    };
  in
    # mapped attrset of nix file paths to attrSet with initialized NixOS configurations,
    # whose names are derived from file names
    lib.pipe ./hosts [
      builtins.readDir
      # filter out files that are not .nix files, directories with default.nix or starting with . (dot, hidden files)
      ( lib.filterAttrs (name: type:
        (
          (type == "regular" && lib.hasSuffix ".nix" name)
          || (type == "directory" && builtins.pathExists "${./.}/hosts/${name}/default.nix")
        )
        && !lib.hasPrefix "." name
      ))
      (builtins.mapAttrs (name: type: {
        # remove .nix extension
        name = if type == "directory" then name else builtins.substring 0 (builtins.stringLength name - 4) name;
        # initialize NixOS configuration
        value = mkNixosSystem ./hosts/${name};
      }))
      builtins.attrValues
      builtins.listToAttrs
    ];
};

in self