Cotonic is a Javascript library which makes it possible to split the javascript code of your page into truly isolated components. By doing this a crash in one component can never affect another component.

Cotonic provides tools to make it possible for these components to cooperate by providing an MQTT publish/subscribe bus. This makes it possible for components to communicate via topics.


Cotonic uses Web Workers which all run in separate calling context. This means that they will not block the main user interface thread. They are also truly isolated from each other. This means that a crash or another kind of problem in worker A can crash worker B.

You can run whatever code you like in workers, with some exceptions. You can't access the DOM, and a lot of things from the window object. This also makes them more secure because you don't have to worry that worker code from an external resource can steal the a credit-card number entered somewhere in the DOM tree.

Cotonic adds a MQTT like publish subscribe mechanism to the standard javascript web worker api. This makes it easy for web workers to communicate with each other.

// worker-a
"use strict";

self.subscribe("some/topic", function(message) {
    self.publish("model/ui/update", "<p>Worker A got message</p>")

self.publish("model/ui/insert", "<p>Worker A started</p>");
// worker-b
"use strict";

self.subscribe("some/topic", function(message) {
    self.publish("model/ui/update", "<p>Worker B got message</p>")

self.publish("model/ui/insert", "<p>Worker B started</p>");
let worker_a = cotonic.spawn("worker-a.js");
let worker_a = cotonic.spawn("worker-b.js");"some/topic", "hello workers!");


Cotonics main functions are available in the cotonic namespace. The functions are mostly used to control and allow messaging between workers.

spawn cotonic.spawn(worker_src_url, [args])
Spawn a new worker. Returns the worker-id of the process.

let worker_id1 = cotonic.spawn("/js/example-worker.js");
let worker_id2 = cotonic.spawn("/js/another-worker.js", ["Arg1", 1]);

spawn_named cotonic.spawn_named(name, worker_src_url, [base], [args])
Spawn a new named worker. Named workers are unique. Use "" or undefined for a nameless worker. Return the worker_id of the newly spawned worker. If the worker was already running, the existing worker_id is returned.

cotonic.spawn_named("example", "example-worker.js");

send cotonic.send(worker_id, message)
Send a message to a worker.

cotonic.send(worker_id1, "hello");

receive cotonic.receive(handler)
Receive messages from workers. The handler should be a function which takes two parameters, the message, and the worker_id.

cotonic.receive(function(message, worker_id) {
    console.log("Received", message, "from worker", worker_id);

set_worker_base_src cotonic.set_worker_base_src(baseUrl)
Set the base url to load additional importable cotonic modules from. This is used to locate the base worker script which is needed to communicate with the other workers.
By default the location is /lib/cotonic/cotonic-worker-bundle.js . It is also possible to configure this via the script via which cotonic itself is loaded on the page. Note: When this is not setup correctly, it will not be possible to spawn workers.

=> Cotonic will now use the '/lib/js/cotonic-worker.js' when workers are spawned.
<script data-worker-base-src="/lib/cotonic-worker.js" src="/lib/cotonic.js"></script>
=> Cotonic will use '/lib/cotonic-worker.js' when new workers are spawned.


The broker module handles all local publish subscribe connections. The subscriptions are stored in a trie datastructure allowing quick action. They are available in the namespace.

Find all subscribers below a certain topic. Used by the bridge to collect all subscriptions after a session restart."/my/topic/#");

Collect all subscribers which match the topic."/a/test"
    function(msg) {
        console.log("test topic a");
    function(msg) {
        console.log("test topic b");

publish, payload, [options])
Publish the message <payload on a topic. The possible options are:

Quality of service. Can be 0, 1, or 2. 0 means at most once, 1 at least once, and 2 exactly once.
When retain is true, the last message sent will be stored, and delivered immediately when a new client subscribes to the topic.
Extra properties which can be attached to the message"truck/001/temperature", 88);
=> All subscribers receive the message 88 on the topic."truck/001/speed", 74, {retain: true});
=> All subscribers receive the message 74. New subscribers will immediately receive 74.

subscribe, callback, [options])
Subscribe to the topics. The callback will be called when a message which matches one of the topics is published.

// [TODO];

unsubscribe, [options])
Unsubscribe from the topics.

// [TODO];

call, payload, [options])
Call a topic, returns a promise for the response.

// [TODO];


matches cotonic.mqtt.matches(pattern, topic)

// [TODO]

extract cotonic.mqtt.extract(pattern, topic)

// [TODO]

exec cotonic.mqtt.exec(pattern, topic)

// [TODO]

fill cotonic.mqtt.fill(pattern, params)

// [TODO]

fill cotonic.mqtt.remove_named_wildcards(pattern)

// [TODO]


insert cotonic.ui.insert(targetId, isInner, initialHTML, [priority])
Insert a new html snippet into the user interface composer. The snippet will be stored under the given targetId. The element will not be placed in the dom-tree immediately. This will happen when one of the render functions is called. The isInner boolean flag indicates if only innerHTML of the target element must be updated, or the outerHTML. The optional priority parameter indicates the render order of the elements. Elements with a high priority are rendedered before lower priorities. This makes it possible to nest elements.

cotonic.ui.insert("root", false, "<p>Hello World!</p>");

get cotonic.ui.get(id)
Retrieve the current html snippet registered at id.

let currentHTML = cotonic.ui.get("root");

remove cotonic.ui.remove(id)
Remove the html snippet registered at id. Note that this will not remove the element from the dom-tree, it will only remove it from the user interface composer. When the element must be removed it should first be updated and set to a blank string and a render operation should be done.


update cotonic.ui.update(id, htmlOrTokens)
Update the registered snippet for the registered element with the given id. The new snippet will be visible after a render operation.

cotonic.ui.update("root", "<p>Hello Everybody!</p>");

render cotonic.ui.render()
Render all registered elements.


renderId cotonic.ui.renderId(id)
Just render the element with the given id.


updateStateData cotonic.ui.updateStateData(model, states)

// [TODO]

updateStateClass cotonic.ui.updateStateClass(model, classes)

// [TODO]

on cotonic.ui.on(topic, msg, event, [options])

// [TODO]




key = "all"


key = "intl"




"model/location/event" ping, search (q), pathname, hash

User Interface Composer

Service Worker

Local Storage

Session Storage