Don't include root directory in HTML tree
Let's separate it by responsibilities into renderKids, renderName, traverseTree so that:


the main function can start explicitly from where you want
functions become immutable, free of side-effects
less repeated code
a single return is used
hopefully, the intent and flow become more obvious


function renderTree(json) {

  function renderKids(kids) {
    const ul = document.createElement('ul');
    for (const kid of kids) {
      ul.appendChild(traverseTree(kid))
    }
    return ul;
  }

  function renderName(name) {
    const span = document.createElement('span');
    span.textContent = name;
    return span;
  }

  function traverseTree(node) {
    const li = document.createElement('li');
    if (node.kids) {
      li.appendChild(renderName(node.name));
      li.appendChild(renderKids(node.kids));
    } else {
      li.textContent = node.name;
    }
    return li;
  }

  return renderKids(json.kids || []);
}


Usage: const output = renderTree(await readJson('./tree.json'))

Note, traverseTree is not asynchronous so there's no need for async keyword.