{
  stdenvNoCC,
  mdbook,
  nixdoc,
  lib,
  excluded ? [
    ".*flake\\.nix$"

    "^docs/.*"
  ]
}:
stdenvNoCC.mkDerivation {
  name = "SkyOS-book";
  src = ./.;
  nativeBuildInputs = [
    mdbook
    nixdoc
  ];
  patchPhase =
    let
      relPath = file: lib.removePrefix (toString ../. + "/") (toString file);
      nixFiles =
        with lib.fileset;
        lib.filter (file: !(lib.any (pattern: builtins.match pattern (relPath file) != null) excluded)) (
          toList (fileFilter (f: f.hasExt "nix") ../.)
        );

      chapters = lib.sort (a: b: a.sortKey < b.sortKey) (
        map (
          file:
          let
            mdPath =
              (
                if baseNameOf file == "default.nix" then
                  lib.removeSuffix "/" (dirOf (relPath file))
                else
                  lib.removeSuffix ".nix" (relPath file)
              )
              + ".md";

            orderMap = {
              docs = 0;
              flake = 1;
              devShells = 2;
              hosts = 3;
              users = 4;
            };
            order = orderMap.${lib.head (lib.splitString "/" (relPath file))};

            category = lib.removeSuffix ".md" (lib.replaceStrings [ "/" ] [ "." ] mdPath);
            title =
              let
                head = builtins.head (lib.splitString "\n" (builtins.readFile file));
              in
              if builtins.match "^# (.*)" head != null then
                lib.trim (lib.removePrefix "#" head)
              else
                lib.removeSuffix ".nix" (baseNameOf file);

            depth =
              let
                dirPart = dirOf mdPath;
              in
              if dirPart == "." then 0 else lib.length (lib.splitString "/" dirPart);
            indent = lib.concatStringsSep "" (lib.genList (x: "    ") depth);
          in
          {
            script = ''
              mkdir -p "src/${dirOf mdPath}"
              nixdoc \
                --prefix "" \
                --category "${category}" \
                --description "${title}" \
                --anchor-prefix "" \
                --file "${file}" > "src/${mdPath}"
            '';
            summaryLine = "${indent}- [${title}](${mdPath})";
            sortKey = toString order + mdPath;
          }
        ) nixFiles
      );

      summaryContent =
        "# Summary\n\n"
        + ''
          [Introduction](README.md)

          - [Features]()
            - [Evaluation time secrets](evalSecrets.md)
            - [Documentation generation](docGen.md)

        ''
        + builtins.concatStringsSep "\n" (map (c: c.summaryLine) chapters)
        + "\n";

      nixdocScripts = builtins.concatStringsSep "\n" (map (c: c.script) chapters);
    in
    ''
      cp ${../README.md} src/README.md
      cp -r ${../assets} src/assets
      cp src/assets/logo.png theme/favicon.png

      ${nixdocScripts}

      cat > src/SUMMARY.md <<EOF
      ${summaryContent}
      EOF
    '';

  buildPhase = ''
    runHook preBuild
    mdbook build
    runHook postBuild
  '';

  postBuild = ''
    mkdir -p $out $out/theme
    cp -r book/* $out
    cp theme/catppuccin.css $out/theme
  '';
}
