Home Reference Source

Yjs

Yjs is a framework for offline-first p2p shared editing on structured data like text, richtext, json, or XML. It is fairly easy to get started, as Yjs hides most of the complexity of concurrent editing. For additional information, demos, and tutorials visit y-js.org.

Extensions

Yjs only knows how to resolve conflicts on shared data. You have to choose a ..

Connectors, Databases, and Types are available as modules that extend Yjs. Here is a list of the modules we know of:

Connectors
Name Description
webrtc Propagate updates Browser2Browser via WebRTC
websockets Set up a central server, and connect to it via websockets
xmpp Propagate updates in a XMPP multi-user-chat room (XEP-0045)
ipfs Connector for the Interplanetary File System!
test A Connector for testing purposes. It is designed to simulate delays that happen in worst case scenarios
Database adapters
Name Description
memory In-memory storage.
indexeddb Offline storage for the browser
leveldb Persistent storage for node apps
Types
Name Description
map A shared Map implementation. Maps from text to any stringify-able object
array A shared Array implementation
xml An implementation of the DOM. You can create a two way binding to Browser DOM objects
text Collaborate on text. Supports two way binding to the Ace Editor, CodeMirror, Monaco, textareas, input elements, and HTML elements (e.g. <h1>, or <p>)
richtext Collaborate on rich text. Supports two way binding to the Quill Rich Text Editor
Other
Name Description
y-element Yjs Polymer Element

Use it!

Install Yjs, and its modules with bower, or npm.

Bower

bower install --save yjs y-array % add all y-* modules you want to use

You only need to include the y.js file. Yjs is able to automatically require missing modules.

<script src="./bower_components/yjs/y.js"></script>

CDN

<script src="https://cdn.jsdelivr.net/npm/yjs@12/src/y.js"></script>
<script src="https://cdn.jsdelivr.net/npm/y-array@10/dist/y-array.js"></script>
<script src="https://cdn.jsdelivr.net/npm/y-websockets-client@8/dist/y-websockets-client.js"></script>
<script src="https://cdn.jsdelivr.net/npm/y-memory@8/dist/y-memory.js"></script>
<script src="https://cdn.jsdelivr.net/npm/y-map@10/dist/y-map.js"></script>
<script src="https://cdn.jsdelivr.net/npm/y-text@9/dist/y-text.js"></script>
// ..
// do the same for all modules you want to use

Npm

npm install --save yjs % add all y-* modules you want to use

If you don't include via script tag, you have to explicitly include all modules! (Same goes for other module systems)

var Y = require('yjs')
require('y-array')(Y) // add the y-array type to Yjs
require('y-websockets-client')(Y)
require('y-memory')(Y)
require('y-map')(Y)
require('y-text')(Y)
// ..
// do the same for all modules you want to use

ES6 Syntax

import Y from 'yjs'
import yArray from 'y-array'
import yWebsocketsClient from 'y-webrtc'
import yMemory from 'y-memory'
import yMap from 'y-map'
import yText from 'y-text'
// ..
Y.extend(yArray, yWebsocketsClient, yMemory, yArray, yMap, yText /*, .. */)

Text editing example

Install dependencies

bower i yjs y-memory y-webrtc y-array y-text

Here is a simple example of a shared textarea

  <!DOCTYPE html>
  <html>
    <body>
      <script src="./bower_components/yjs/y.js"></script>
      <!-- Yjs automatically includes all missing dependencies (browser only) -->
      <script>
        Y({
          db: {
            name: 'memory' // use memory database adapter.
            // name: 'indexeddb' // use indexeddb database adapter instead for offline apps
          },
          connector: {
            name: 'webrtc', // use webrtc connector
            // name: 'websockets-client'
            // name: 'xmpp'
            room: 'my-room' // clients connecting to the same room share data
          },
          sourceDir: '/bower_components', // location of the y-* modules (browser only)
          share: {
            textarea: 'Text' // y.share.textarea is of type y-text
          }
        }).then(function (y) {
          // The Yjs instance `y` is available
          // y.share.* contains the shared types

          // Bind `y.share.textarea` to `<textarea/>`
          y.share.textarea.bind(document.querySelector('textarea'))
        })
      </script>
      <textarea></textarea>
    </body>
  </html>

Get Help & Give Help

There are some friendly people on Gitter who are eager to help, and answer questions. Please join!

Report any issues to the Github issue page! I try to fix them very soon, if possible.

API

Y(options)

Instantiated Y object (y)

Y(options) returns a promise that is fulfilled when..

The promise returns an instance of Y. We denote it with a lower case y.

Logging

Yjs uses debug for logging. The flag y* enables logging for all y- components. You can selectively remove components you are not interested in: E.g. The flag `y,-y:connector-messagewill not log the longy:connector-message` messages.

Enable logging in Node.js
DEBUG=y* node app.js

Remove the colors in order to log to a file:

DEBUG_COLORS=0 DEBUG=y* node app.js > log
Enable logging in the browser
localStorage.debug = 'y*'

Contribution

I created this framework during my bachelor thesis at the chair of computer science 5 (i5), RWTH University. Since December 2014 I'm working on Yjs as a part of my student worker job at the i5.

License

Yjs is licensed under the MIT License.

[email protected]