Mercury.js is not opinionated about your application architecture - it's components can be used independendently, with the mercury library adding a small amount of bootsrapping and event wiring sugar. The notes given here are just one example of how you could architect an application built with Mercury.js, and will hopefully address some of the questions you may have about implementations that are more complex than the documented examples.
This article will cover some of the key components you need to create a fully featured app and gives an example of how to structure those components in such a way as to keep your app clearly understandable and maintainable for humans.
Create a core app state object that contains top level paramaters. Child data stores are generated by individual 'store' scripts that create the store and wire up appropriate channels and methods for updating data in that store.
Each child store is initialised using mercury.state so that channels will be attached to the individual store, not the overall app state, allowing data stores to be modular and easier to reason about in a large application.
Renderers should return a thunk, or an array of thunks for optimisation. Pass in only the required data stores to renderers.
Use delegated event listeners in renderers to trigger channel updates in your data stores. By attaching channels to individual data stores you can conveniently access the update methods for the data stores you are working with in your renderer.
Need to do something directly with the DOM utside of virtual-hyperscript? Widgets allow you to 'cross over' between virtual-dom components and items in the actual DOM. Useful when you need to work with external code that needs to be inserted or manipulated directly in the DOM.
Remember, widgets will be re-rendered on any relevant store updates - an update method is essential to tell the widget what to change on updates after the initial render.
Widgets are loaded as the content of a virtual-hypertext node so in practice they will be required in their parent renderer.
Utilities handle any state updates that do not originate from the client side user. This is essential where any data or state is being updated from a server, a browser API or another store. At Coviu, our app needs to respond to updates that are pushed to the client via WebRTC data channels - we use utilities to update our data stores based on the new data provided by the data channel.
We seperate these utilities from stores so that they are not tightly coupled to the app state data structure. They are loaded at the top level of the app and therefore have direct access to all of the app state. This prevents confusion and eliminates unecessary complexity. Utilities ahould trigger update methods on the data store rather than updating the store directly to maintain a single point of update for each store.
Require all store initilaisers and utilities at the top level index.js, create the application state object and pass it into a top level view renderer.