{
  inputs = {
    utils.url = "github:numtide/flake-utils";
    nixpkgs.url = "github:NixOS/nixpkgs/master";
    nix-filter.url = "github:numtide/nix-filter";
  };

  outputs = {
    self,
    nixpkgs,
    utils,
    nix-filter,
  }:
    utils.lib.eachDefaultSystem
    (system: let
      pkgs = import nixpkgs {
        inherit system;
      };

      filter = nix-filter.lib;

      nodejs = pkgs.nodejs-18_x;

      node_modules = pkgs.stdenv.mkDerivation {
        name = "node_modules";

        src = filter {
          root = ./.;
          include = [
            ./package.json
            ./package-lock.json
          ];
        };

        __noChroot = true;

        configurePhase = ''
          export HOME=$TMP
        '';

        buildInputs = [ nodejs ];

        buildPhase = ''
          ${nodejs}/bin/npm ci
        '';

        installPhase = ''
          mkdir $out
          mv node_modules $out/node_modules
        '';
      };
    in {
      packages = {

        default = pkgs.stdenv.mkDerivation {
          name = "tempest.dev";

          src = filter {
            root = ./.;
            exclude = [
              ./.next
              ./node_modules
            ];
          };

          nativeBuildInputs = [ nodejs ];

          buildPhase = ''npm run build'';

          configurePhase = ''
            ln -sf ${node_modules}/node_modules node_modules
            export HOME=$TMP
          '';

          installPhase = ''
            # Use the standalone nextjs version
            mv .next/standalone $out

            # Copy non-generated static files
            if [ -d "public" ]; then
              cp -R public $out/public
            fi

            # Also copy generated static files
            mv .next/static $out/.next/static

            # Re-link the node_modules
            rm $out/node_modules
            mv node_modules $out/node_modules

            # Link cache directory
            ln -s /tmp $out/.next/cache

            # Wrap the script
            cat <<ENTRYPOINT > $out/entrypoint
            #!${pkgs.stdenv.shell}
            exec "$(type -p node)" "$out/server.js" "$$@"
            ENTRYPOINT
            chmod +x $out/entrypoint
          '';
        };
      };
    }) // {
      nixosModule = {config, lib, pkgs, ...}:
        with lib;
        let cfg = config.ashe.services."tempest.dev";

        in {
          options.ashe.services."tempest.dev" = {
            enable = mkEnableOption "Enables the tempest.dev HTTP service";

            port = mkOption rec {
              type = types.int;
              default = 8000;
              example = default;
              description = "The port for this service to listen on";

            };

            domain = mkOption rec {
              type = types.str;
              default = "tempest.dev";
              example = default;
              description = "The domain name for tempest.dev";
            };
          };

          config = mkIf cfg.enable {
            systemd.services."ashe.tempest.dev" = {
              wantedBy = [ "multi-user.target" ];

              serviceConfig = let pkg = self.packages.${pkgs.system}.default;
              in {
                Restart = "on-failure";
                ExecStart = "${pkg}/entrypoint";
                DynamicUser = "yes";
                PrivateTmp = "yes";
                Environment = [
                  "PORT=${toString cfg.port}"
                ];
              };
            };

            services.nginx.virtualHosts.${cfg.domain} = {
              locations."/" = { proxyPass = "http://127.0.0.1:${toString cfg.port}"; };
              forceSSL = true;
              enableACME = true;
            };
          };
        };


    };
}
