Open-source project
jsfiddle/togetherjs avatar
jsfiddle/togetherjs

TogetherJS: real-time co-browsing for your own site, and what it costs to run

A service for your website that makes it surprisingly easy to collaborate in real-time.

6,999 stars830 forksJavaScriptMPL-2.0

At a glance

What is it?
TogetherJS is a drop-in client that shows two people the same page with shared cursors and edits, relayed through a hub server you host yourself. The client is the product; the hub is the part you now have to own.
Who is it for?
Adopt TogetherJS when you already have a page whose DOM you can load it into and you are willing to run the relay: the hub-worker port is the recommended path, and a local build is a matter of npm install, grunt build and node devserver.js. Do not adopt it if you need a hosted service, a documented upgrade path between versions, or an automated test runner, because the README offers none of the three.
Can I use it commercially?
Yes, with conditions. MPL-2.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • jsfiddle/togetherjs6,999 ★ · +0
Star history
Repository2026-09-282026-11-14
jsfiddle/togetherjs7k7k

0 Stars in the last 47 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The problem TogetherJS solves, and the page it assumes you already have

Two people looking at the same URL are not looking at the same thing. One has scrolled, one has typed into a form, one is pointing at a paragraph the other cannot find. TogetherJS is aimed at that gap: the README describes it as a service you include on your site so that two people can interact on the same page, seeing each other's cursors, edits, and browsing a site together. The site owner adds it, and the site owner configures it.

That framing matters more than the feature list. TogetherJS is not a collaboration product you sign into. It is a script you embed in a page that already exists, so that people on that page see each other's cursors and edits. The README is explicit that the client in togetherjs/ "does all the real work", while the server "doesn't do much" beyond echoing messages back and forth. So the useful question is not whether the idea is good, but whether your page is the kind of page its mirroring can hold together.

It suits teams building support tools, pair-debugging surfaces, or teaching pages where a second person needs to follow along.

Client does the work, hub relays the messages

The repository is split down the middle. togetherjs/ holds the browser client. hub/ holds the relay, and hub/server.js is named as the package main and as the start script, which tells you how little logic sits there. The server's own commit history is described in the README, with some understatement, as "incredibly boring".

That division has a consequence worth stating plainly: there is no shared hub server anymore. The README says so directly, and points to "Hosting the Hub Server" in site/docs/index.md. The recommended route is hub-worker/, described as a Cloudflare Workers plus Durable Objects port of the relay logic that runs on Cloudflare's free plan. So the architecture is client plus your relay, and the relay is now your operational responsibility.

The client is built from source rather than consumed as a package. Styles come from LESS, and the README notes that "a couple files are generated", which is why Grunt is in the loop at all. The build also emits a site copy: grunt build buildsite produces the whole togetherjs.com site under build/, and devserver.js serves it. There is a real distinction between building the site for development and building a static client for distribution, and the README treats them as separate commands with separate flags.

Building TogetherJS locally and pointing it at your own hub

Start by cloning and installing. The README gives these commands verbatim, and notes that most of what lands in node_modules/ is development-only, with WebSocket-Node as the single server-side dependency.

bash
git clone git://github.com/mozilla/togetherjs.git
cd togetherjs
npm install
npm install -g grunt-cli

Build the site and serve it. The --no-hardlink flag turns off hard linking, which the README explains is on by default so edits in togetherjs/ show up under build/togetherjs/ without a rebuild.

bash
grunt build buildsite --no-hardlink
node devserver.js

The README says devserver.js starts a server on port 8080, so the built site should be reachable at http://localhost:8080. If you are changing the hub and want a local build to talk to it, the README shows the HUB_URL environment variable being set at build time:

bash
HUB_URL=http://localhost:8080 grunt devwatch

For a deployable client rather than a site copy, build with a base URL and a destination directory. The README's example uses --base-url https://myapp.com and --dest static-myapp, and states that static-myapp/togetherjs.js and static-myapp/togetherjs-min.js end up in place with the rest of the code under static-myapp/togetherjs/.

bash
grunt build --base-url https://myapp.com --no-hardlink --dest static-myapp

One constraint to carry into deployment: the README states that if you include TogetherJS on an https site, you must use an https or wss hub server, and that Cloudflare Workers handle this automatically. A plain http hub behind an https page will not do.

Testing is manual, and the README says so

This is the weakest part of the project as documented. Tests live in togetherjs/tests/ and are doctest.js tests. To run them you build TogetherJS, serve it, and open http://localhost:PORT/togetherjs/tests/, where the tests are linked from the top of the page. Unit-style files are named test_*.js and functional ones func_*.js.

The README then states the limitation without softening it: "There is unfortunately no automated runner for these tests." It floats Karma plus doctest.js as something that might be nice, and notes that it has not been done. For anyone evaluating TogetherJS as a dependency, that is the sentence that decides the integration cost. You are not wiring a test suite into CI. You are opening a browser and clicking links, or using the "Manual testing" page that the README describes as a way to simulate conditions without a second browser.

There is also a toolchain signal in package.json worth reading before you commit. The engines field pins node to ~0.12.7 and npm to ^2.11.3, and the dependency list carries express ~3.0.6, less ~1.3.1 and grunt ~0.4.1. Those are old ranges. If your build environment runs a current Node release, expect to spend time on the toolchain before you spend any on collaboration features.

Where TogetherJS is the wrong tool

The clearest failure mode is the one the README implies rather than states: a hub you do not run is a hub that does not exist. There is no shared hub server anymore. Anyone who reads the project's one-line description, "A service for your website that makes it surprisingly easy to collaborate in real-time", and expects to add a script tag and be finished will be surprised by the hosting step. The relay is not optional infrastructure you can defer.

A second boundary is documentation: the README does not document rollback, version compatibility between a deployed client and a changed hub, or a migration path between releases. The repository has no published releases, so there is no changelog to consult either.

A third is testing. With no automated runner, a team that requires a green pipeline before deploy has to build that harness itself. That is not a flaw in the collaboration feature. It is a cost that lands on whoever owns the integration.

TogetherJS against a CRDT library such as Yjs

The obvious alternative people search for is Yjs, and the difference is architectural rather than a matter of feature checklists. TogetherJS is a client included on the page that relays messages through a hub, so people share cursors, edits and browsing on that page. Yjs is a CRDT library: shared data structures that merge concurrent edits, with the application deciding what to render from them. It is not a co-browsing layer, and it does not give you a stranger's cursor on your page for free.

That difference sets the integration shape. With TogetherJS you add a built client to a page you already have, and the README's static build produces togetherjs.js and togetherjs-min.js for exactly that. With Yjs you change how the application stores state, and the collaboration behaviour follows from the data model. If your page is a form or a support screen you cannot restructure, mirroring is the shorter path.

One practical asymmetry: Yjs does not require you to operate a relay built from this repository. It still needs a transport, but the README's hosting burden, the Cloudflare Workers hub-worker/ recommendation and the HUB_URL build variable, is specific to how TogetherJS is packaged.

Licence and the cost of keeping a fork current

TogetherJS is under MPL-2.0. The README states that the source code form is subject to the terms of the Mozilla Public License, v. 2.0, and that a copy can be obtained at mozilla.org/MPL/2.0/. MPL-2.0 is file-level copyleft: modifications to covered files carry obligations when distributed, and the licence text is the authority, not this summary. If you patch files under togetherjs/ and ship the result, read the licence rather than assuming a permissive outcome. Nothing here is legal advice.

Upgrade cost is the harder question, and the documentation is thin. package.json carries version 0.4.0a, which reads as a pre-release, and the engines pin is node ~0.12.7. The repository has no published releases to consult and no documented upgrade procedure. The last push to the default branch was on 2026-10-30, so the code is moving, but movement is not the same as a supported upgrade path. Budget for reading diffs in togetherjs/ yourself, and for rebuilding the client with the same grunt build --base-url invocation you used before, because the generated files are build output rather than source you can merge.

Editorial conclusion

Adopt TogetherJS when you already have a page whose DOM you can load it into and you are willing to run the relay: the hub-worker port is the recommended path, and a local build is a matter of npm install, grunt build and node devserver.js. Do not adopt it if you need a hosted service, a documented upgrade path between versions, or an automated test runner, because the README offers none of the three. Before committing, build a static copy with grunt build --base-url and confirm the generated togetherjs.js points at a wss hub, since the README states an https page requires an https or wss hub.

Frequently asked questions

Does TogetherJS still work without running my own server?

No. The README states there is no shared hub server anymore and that you will need to host your own, pointing to the Hosting the Hub Server section of site/docs/index.md. The recommended route is hub-worker/, a Cloudflare Workers and Durable Objects port of the relay logic that runs on Cloudflare's free plan.

How do I build TogetherJS for my own site instead of the demo site?

The README shows grunt build with --base-url, --no-hardlink and --dest, for example grunt build --base-url https://myapp.com --no-hardlink --dest static-myapp. It states that static-myapp/togetherjs.js and static-myapp/togetherjs-min.js end up in place, with the rest of the code under static-myapp/togetherjs/.

Is there an automated test runner for TogetherJS?

No. Tests are doctest.js files under togetherjs/tests/, and the README says you build TogetherJS, serve it, and open the tests page in a browser. It states there is unfortunately no automated runner, and mentions Karma with doctest.js as something that might be nice but has not been done.

Can I use TogetherJS on an https site?

Yes, but the hub must match. The README states that if you include TogetherJS on an https site you must use an https or wss hub server, and notes that Cloudflare Workers handle this automatically.

Official sources

  1. Issues
  2. jsfiddle/togetherjs on GitHub
  3. License: MPL-2.0
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/jsfiddle-togetherjs.svg)](https://hysenlabs.com/projects/jsfiddle-togetherjs)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/jsfiddle-togetherjs.svg)](https://hysenlabs.com/projects/jsfiddle-togetherjs)

Was this useful?