Expected you would say that and actually I meant to take out my first para but I was distracted by work. Hopefully you will one day be happy to transfer the Dashboard part over to uibuilder.
Again, thought that might be your thinking - and perfectly fine of course.
The only other thing that I would have probably done would have been to create the baseline HTML in a single output (maybe with empty data or a default data display) and used uib-update nodes to send the data. But it wouldn't really make much difference unless you had hundreds of people accessing the data. It would be slightly more efficient - and therefore elegant.
Notice the orange template node in the box that says "Page HTML". This is an example where the lower flow builds the entire base page structure. That is cached so that any new or reloaded browser tab will always get the latest version. Though it is static really, I only change it if I need to change the base information structure. Here is the template code:
The upper-left flow dynamically creates a set of MQTT subscriptions. The control data is structure such that the HTML element ID to be updated matches the MQTT topic which is then used in the uib-update node so that only a single node is required.
Obviously, this does take a bit more thinking through to get it right and it does need you to be able to put together the Mustache code for the base HTML if you are wanting to have a really flexible output where you don't necessarily know how many entries there are.
If you know the full structure of the output then, of course, you can simply use straight HMTL in the template. Just make sure that you have a way that you can identify what element to update based on your data outputs.
Looks like in your case, you could use a simple msg.topic property set manually in each part of the flow. So you wouldn't need anything anywhere near as complex as this example that has 2 levels of structure that could both have any number of entries that can't be predicted in advance.