Now, we're able to write full-blown applications inside the main function, because I can declare what events we're interested in, and how to use those events to create new elements on the DOM. We can still improve this code.
One thing that annoys my eyes, at least. Is this object here to describe those elements. This is essentially creating the view. Usually, we use template languages like Handlebars, JSX, or Pug. One simple way we can achieve that is to write a function that returns those objects for us.
I'm going to call that function H as a shortcut to HTML. It takes the tag name and the children as arguments. It just returns the object that has those two and children. Then I can replace the usage here instead of creating the object directly.
I'm just going to call H with span and that array there like that, as well as for the outer element, I'm going to use H of H1 as the tag name, and then the children array. That simplified our code even more. It looks a bit better, starting to look like something like a template language.
We can take this idea even further by writing a function called H1 that now takes only the children. This will just return an object that has tag name, is already H1. We don't need to specify the tag name as an argument. We just pass the children.
Then something similar for span, and this will improve our code even further. Can write that and this. This is looking much nicer. You can see the hierarchical structure here, just like you usually have in HTML or Pug.