{
  description = "Componentware";

  inputs = {
    flake-parts.url = "github:hercules-ci/flake-parts";
    nixpkgs.url = "github:NixOS/nixpkgs";
    wildfly = {
      url = "github:0qln/wildfly";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = inputs @ {flake-parts, ...}:
    flake-parts.lib.mkFlake {inherit inputs;} {
      imports = [];
      systems = ["x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin"];
      perSystem = {
        pkgs,
        system,
        ...
      }:
        with pkgs.lib; let
          latexPackages = with pkgs; [
            latexrun
            (texlive.withPackages
              (ps:
                with ps; [
                  amsmath
                  biber
                  biblatex
                  changepage
                  csquotes
                  enumitem
                  fontaxes
                  latexmk
                  listings
                  minted
                  newtx
                  newtxsf
                  newtxtt
                  scheme-medium
                  textpos
                  times
                  titlesec
                  transparent
                  upquote
                ]))
          ];

          wildfly-fhs = inputs.wildfly.packages.${system}.wildfly-fhs;
        in {
          # Per-system attributes can be defined here. The self' and inputs'
          # module parameters provide easy access to attributes of the same
          # system.
          packages = with pkgs; let
            fmtNum = strings.fixedWidthNumber 2;
            fmtReleaseName = sem: author: chap: "${fmtNum sem} - ${fmtNum chap} - ${author.lastName}, ${author.firstName}.pdf";
            fmtRelease = fmtReleaseName 4 {
              firstName = "Linus";
              lastName = "Nagel";
            };
            mkUebungPdf = n: args:
              stdenvNoCC.mkDerivation rec {
                name = fmtRelease n;
                version = "1.0.0";
                src = ./.;
                buildInputs = latexPackages;
                buildPhase =
                  # sh
                  ''
                    cd docs/uebungen

                    latexmk \
                      -pdf \
                      -l -dir-report -file-line-error -verbose \
                      -interaction=nonstopmode \
                      "uebung-${toString n}.tex"
                  '';
                installPhase =
                  # sh
                  ''
                    mkdir -p $out/share $out/log $out/artifacts
                    cp out/uebung-${toString n}.pdf "$out/share/${name}"
                    cp out/*.log $out/log/
                    cp -r out/* $out/artifacts
                  '';
              }
              // args;
          in {
            "uebung-1" = mkUebungPdf 1 {};
            "uebung-2" = mkUebungPdf 2 {};
            "uebung-3" = mkUebungPdf 3 {};
            "uebung-4" = mkUebungPdf 4 {};
            "uebung-5" = mkUebungPdf 5 {};
            "uebung-6" = mkUebungPdf 6 {};
          };

          devShells.default = with pkgs;
            mkShell {
              buildInputs = [wildfly-fhs pkgs.openjdk21 maven];
              nativeBuildInputs = [];
              packages =
                [
                  mermaid-cli
                  openjdk
                  maven
                  lombok
                ]
                ++ latexPackages;

              shellHook =
                # bash
                ''
                  export PATH="bin/:$PATH"
                  export WILDFLY_BASE_DIR="$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.wildfly-base"
                '';
            };
        };
      flake = {
        # The usual flake attributes can be defined here, including system-
        # agnostic ones like nixosModule and system-enumerating ones, although
        # those are more easily expressed in perSystem.
      };
    };
}
