получилось вывести только элементы первого уровня, но не могу понять, как заставить выводиться дочерние элементы
Рекурсия. Если в элементе есть непустой массив children, то делаете рекурсивный вызов функции, передавая ей этот массив.
Можно самостоятельно создавать элементы:
const createNestedList = data =>
data.reduce((ul, { name, children }) => {
const li = document.createElement('li');
const div = document.createElement('div');
div.textContent = name;
li.appendChild(div);
if (children instanceof Array && children.length) {
li.appendChild(createNestedList(children));
}
ul.appendChild(li);
return ul;
}, document.createElement('ul'));
document.body.appendChild(createNestedList(data));
Или собрать соответствующую разметку:
const createNestedList = data => `
<ul>${data.map(n => `
<li>
<div>${n.name}</div>
${Array.isArray(n.children) && n.children.length ? createNestedList(n.children) : ''}
</li>`).join('')}
</ul>`;
document.body.insertAdjacentHTML('beforeend', createNestedList(data));