{
  lib,
  optionNames,
}:
/**
  The default `toMenu` function renders a page node into a menu subtree.
*/
{
  page,
  prefix ? [ ],
  indent ? "",
  nested ? true,
}:
let
  inherit (page._page) loc target;
  count = page._page.children;

  # Only add node to the menu if it has content or multiple children
  showInMenu = target != "" || count > 1;
  nextPrefix = if showInMenu then loc else prefix;
  nextIndent = if showInMenu && nested then indent + "  " else indent;

  children = builtins.removeAttrs page optionNames;
  submenu = lib.pipe children [
    builtins.attrValues
    (map (
      subpage:
      page._page.toMenu {
        inherit nested;
        page = subpage;
        indent = nextIndent;
        prefix = nextPrefix;
      }
    ))
  ];

  loc' = if lib.lists.hasPrefix prefix loc then lib.lists.drop (builtins.length prefix) loc else loc;
  menuText = lib.attrsets.showAttrPath loc';
  menuitem = lib.optionals showInMenu [
    (indent + lib.optionalString nested "- " + "[${menuText}](${target})")
  ];
in
builtins.concatStringsSep "\n" (menuitem ++ submenu)
