{
  description = "Forge - A Blazor Git Forge";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
        dotnet-sdk = pkgs.dotnetCorePackages.dotnet_9.sdk;
        dotnet-runtime = pkgs.dotnetCorePackages.dotnet_9.aspnetcore;
        flyctl = pkgs.flyctl;

        forge = pkgs.buildDotnetModule rec {
          name = "forge";
          src = ./.;
          projectFile = "src/Forge.Web/Forge.Web.csproj";
          nugetDeps = ./deps.json;
          dotnet-sdk = pkgs.dotnetCorePackages.dotnet_9.sdk;
          dotnet-runtime = pkgs.dotnetCorePackages.dotnet_9.aspnetcore;
          executables = [ "Forge.Web" ];
          
          # Only build for linux-x64
          runtimeId = "linux-x64";
          buildType = "Release";
          selfContainedBuild = false;
        };

        runForge = pkgs.writeShellApplication {
          name = "run-forge";
          runtimeInputs = [ dotnet-runtime ];
          text = ''
            password_file="''${FORGE_ADMIN_PASSWORD_FILE:-''${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/agenix/forge-admin-password}"
            if [ ! -f "$password_file" ]; then
              echo "Forge admin password file not found: $password_file"
              exit 1
            fi
            export Auth__PasswordFile="$password_file"
            export WEBROOT="${forge}/lib/wwwroot"
            
            data_dir="''${FORGE_DATA_DIR:-''${XDG_DATA_HOME:-$HOME/.local/share}/forge}"
            export Database__Path="$data_dir/forge.db"
            export Repositories__Root="$data_dir/repositories"
            
            mkdir -p "$Repositories__Root"
            echo "Forge starting at: http://localhost:5128"
            echo "Data directory: $data_dir"
            exec ${forge}/bin/Forge.Web --urls "http://localhost:5128" "$@"
          '';
        };

        deployFly = pkgs.writeShellApplication {
          name = "deploy-fly";
          runtimeInputs = [ flyctl ];
          text = ''
            # shellcheck source=/dev/null
            if [ -f .env ]; then
              set -a
              source .env
              set +a
            fi

            if [ -z "''${FLY_APP:-}" ]; then
              echo "Error: FLY_APP not set. Create a .env file with FLY_APP=<your-app-name>"
              exit 1
            fi

            fly deploy -a "$FLY_APP"
          '';
        };
      in
      {
        packages.default = runForge;
        packages.forge = forge;
        packages.run-forge = runForge;
        packages.deploy-fly = deployFly;

        apps.run-forge = {
          type = "app";
          program = "${runForge}/bin/run-forge";
        };

        apps.deploy-fly = {
          type = "app";
          program = "${deployFly}/bin/deploy-fly";
        };

        devShells.default = pkgs.mkShell {
          packages = with pkgs; [
            dotnet-sdk
            git
            flyctl
            sqlite
            just
          ];

          shellHook = ''
            # shellcheck source=/dev/null
            if [ -f .env ]; then
              set -a
              source .env
              set +a
            fi

            echo "Forge dev shell"
            echo "Commands:"
            echo "  nix run .#run-forge        Start the dev server using a decrypted password file"
            echo "  dotnet test                Run tests"
            echo "  dotnet build               Build the project"
            echo "  nix run .#deploy-fly       Deploy to Fly.io using a decrypted password file"
            echo ""
            echo "Git clone/push URLs:"
            echo "  git clone http://localhost:5128/{owner}/{repo}.git"
            echo "  git push http://localhost:5128/{owner}/{repo}.git main"
          '';
        };

      }
    );
}
An unhandled error has occurred. Reload 🗙