Guide - acgaudette/holojam-node GitHub Wiki


Exactly one relay always needs to be running, which routes messages (updates, events) for the entire Holojam network. The relay can be thought of as a central server, which collects data coming upstream, and broadcasts it back downstream. More than one relay will cause a feedback loop--don't do this!

A network often contains multiple Holojam nodes (endpoints) besides the relay. Endpoints are either emitters, which exclusively send data upstream, sinks, which exclusively accumulate data downstream, and clients (emitter/sink combos), which receive data downstream and send data upstream.

One example of an emitter is a tracking system, which needs to broadcast positional HMD data. A sink may take the form of a remote logger or network visualizer. A client could be Unity3D running on a Vive or WebVR on a phone. It is important to remember that holojam-node is module, and has to be implemented in code somewhere (although the most basic implementation is only one short line).

Both relays and clients can double as emitters or sinks. To this point: it is usually not necessary (for example, when deploying at an event) to hook up lots of separate endpoints. If there's only one tracking system in use for a particular event and all the clients know where to look, it may make more sense to simply run the relay on the machine broadcasting the tracking data, routing the tracking data through the relay. In this manner, the number of connections in the network is minimized, and the setup cost is low. However, for permanent installations, it's often prudent to have a dedicated relay onsite.

In the event that the source or destination of the data being communicated is not JavaScript/Node.js, you will have to write a wrapper (e.g. over a C++ app). This usually isn't overly difficult--and the alternative is implementing the Holojam protocol/conventions from scratch. Additionally, by integrating with holojam-node, both sending and receiving data via the supplied hooks and changing the network layout on the fly are painless. No matter what happens in the underlying protocol, you can update the module and still call the same functions. Doing this with a custom implementation is much more difficult and requires vigilant upkeep.


Requiring holojam-node and passing in ['relay'] as an argument to the constructor will automatically start a relay for you on the default IP address ( Pass in an IP as the second argument if desired.


const holojam = require('holojam-node')(['relay'], '');

Passing no parameters to the constructor will default to a full server with web support.

Emitter nodes send data upstream, but can't process incoming data:

const holojam = require('holojam-node')(['emitter'], '');

Note: the IP specified in this case refers to the address of the (target) relay, presumably running somewhere else.

Sink nodes only receive data from the relay (downstream):

const holojam = require('holojam-node')(['sink']);

Note: specifying an IP here is irrelevant as packets are received via multicast.

"Client" nodes, i.e. combined emitter/sink nodes send data upstream and receive data downstream from the relay:

const holojam = require('holojam-node')(['emitter', 'sink']);


Packets are routed through the Holojam network either as updates or events. An update is essentially an array of "flakes"--generic Holojam objects. An event only has one flake. A notification is an abstraction over an event, which contains just a label (string).

Creating flakes in javascript is as simple as filling out (or not) their optional array parameters. See code examples below for dealing with flakes.

Once you have an array of flakes (or single flake, in the case of an event), pass it to BuildUpdate(scope, flakes), BuildEvent(scope, flake), or BuildNotification(scope, label). The scope argument is a namespace for your data.

The build functions return an object which you can then pass in to Send(nugget) or SendToWeb(nugget).

Running the Examples

See here for working code examples: emitter.js, relay.js, client.js, and sink.js.

Copy these into a separate directory and run npm install holojam-node within that directory. Then, separately run node emitter.js, node relay.js, node client.js, and node sink.js. You should see some contrived data being passed back and forth.