Only the top level is fetched at first. Opening a folder fetches its
children from api/nodes/<id>.json. The dev server
answers these from vite.config.ts, and the build contains
them as static files. Watch the log, or the network tab. While a folder
loads, its node has aria-busy="true", which draws the
spinner.
The children of Fails to load don't exist on the server.
Opening it makes one request, which fails: the folder stays closed and
tree.load_failed is dispatched. Open it again to retry.