Mozilla Hubs is a web based stack of applications which provide multiple interfaces to online WebXR multi user meeting/presentation spaces. To quote the documentation, “Hubs is a virtual collaboration platform that runs in your browser. With Hubs you can create your own 3D spaces with a single click. Invite others to join using a URL. No installation or app store required”. The ‘Stack’ of applications required to provide Hubs is large. It includes Node.js, Three.js, Aframe.js, React, Reticulum, Janus and several other APIs as well. Considering it’s complexity, it is a daunting task to ‘customize’ hubs in non-trivial ways that involve modifying the source code. The documentation for this process as of late 2020 when I'm writing this article is almost non-existent. So I’m creating documentation on the methods I’ve used to create a custom client for Mozilla hubs, including explanations for how to create your own custom Hubs components.
This documentation should not be considered complete or even sanctioned by Mozilla since many of the techniques I’m describing involve DOM manipulation in the browser using script injection after the client is loaded. This is also known as a hack. Since the client is hosted from the server that provides the content at the same URL the client is reached through, this may not seem like a “nefarious process”. However, hosting Hubs involves accessing interfaces on the User’s computer, including the microphone, the video camera, and even screen sharing the desktop. Pairing this type of client access with JavaScript code injection from outside repositories without providing the users some information about the process, should be considered ‘inconsiderate’ at best and ‘sneaky’ or ‘illegal’ at worst depending your application. So my recommendation is to proceed with a large amount of respect for the User of your application and use some caution in how you modify their ‘experience’ in Hubs.
Where to start? You can find a ‘technical’ description of Hubs at [ System Overview · Hubs by Mozilla ]. It provides a high level description of what you are playing with when you modify Hubs. I suggest checking it out before you proceed with the rest of this article. Once you’ve read that you will probably want to check out [ Introduction to A-FRAME ] in order to understand what Hubs wraps itself around. I say "wraps itself", because technically this is exactly what Hubs does. It operates as a communication layer between several different browsers with the same A-frame scene loaded into each user's browser. A-frame is a WebXR entity component system that creates new DOM elements in standard HTML. These DOM elements leverage another, more powerful, API for WebGL called Three.js. So in some ways Hubs is actually a wrapper of a wrapper around Three.js. Once you learn something about A-frame, especially things like creating your own components, you will find yourself needing to know more about Three.js. You can learn more about Three.js at Three.js Documentation. All of these APIs are just JavaScript designed to make it easier to create WebGL applications. As I mentioned above the amount of information you CAN learn is daunting, but if you know JavaScript already, in particular Node.js, then you may find you can do a lot with a little.
The approach we are going to take in customizing Hubs is to ‘modify’ or ‘touch’ the Hubs source code as little as possible. This accomplishes several key things, not least of which is to make it easier to keep up with Hubs changes as the developers modify and fix issues with it. Here is a graphic showing what our final application modifications should look like.
The Orange Hubs client part with the hub.html and hub.js are the only files we will actually modify in the Hubs stack. Actually, we really only put a small script into the hub.js file which will then modify the hub.html once it knows which scripts to inject. The green ‘top level node server’ is a simple express server with one route which receives a query parameter for a ‘hub_id’ and replies with a string of URLs for A-frame components and Networked A-frame templates which can be stored on a CDN or in this case Github using the GHpages feature to serve as a CDN. That’s it. The code to do all of this is tricky, since you need to know where to ‘put’ things and how to determine when it’s Ok to put them there. First I’ll share information on how to get the Mozilla Hubs custom client up and running and then I’ll go through the ‘load sequence’ Hubs uses to get everything synced up across the server.
Index | Installing a Custom Client for Hubs |