diff --git a/README.md b/README.md
index e6dcacea6fec87377990f89e6bce1f2c836433ac..b9fedbbad5d8c06629d1e7d92c5b4a14a7c0f50c 100644
--- a/README.md
+++ b/README.md
@@ -31,6 +31,11 @@ CRDT-based p2p Drawing Application
 ### Open in browser
 
 Using a modern browser that supports WebRTC, like a recent version of Chrome or Firefox, open several windows of [http://localhost:12345](http://localhost:12345).
+Open the developer console to find out your client's ID. To connect to another peer, call the following function from the console with their ID:
+
+```
+>> window.connectToPeer("peer-id")
+```
 
 ## License
 
diff --git a/src/app.js b/src/app.js
index 146a1515152e150e88fec9a7821a98c2c336fa1b..9361101c8b7e5adea27958553d70521252259a9d 100644
--- a/src/app.js
+++ b/src/app.js
@@ -19,4 +19,8 @@ Y({
   }
 }).then(y => {
   y.share.textfield.bind(document.getElementById("textfield"))
+
+  global.connectToPeer = function(uid) {
+    y.connector.connectToPeer(uid)
+  }
 })
diff --git a/src/y-webrtc/index.js b/src/y-webrtc/index.js
index ea663607d3bc41d9556332c9abc8e852ea1f8fd8..c6ba4b566e6dbb279d3f44eea9fb87e86d722042 100644
--- a/src/y-webrtc/index.js
+++ b/src/y-webrtc/index.js
@@ -16,32 +16,101 @@ function extend(Y) {
       super(y, options)
       this.webrtcOptions = options
 
-      this.connect()
+      this.initialiseConnection()
     }
 
-    connect() {
+    initialiseConnection() {
       var peer = new Peer({
         host: this.webrtcOptions.host,
         port: this.webrtcOptions.port,
         path: this.webrtcOptions.path
       })
 
+      this.peer = peer
+      var self = this
+      this.peers = new Map()
+
       peer.on("open", function(id) {
         console.log("My peer ID is: " + id)
+
+        self.setUserId(id)
+      })
+
+      peer.on("connection", function(dataConnection) {
+        self.initialiseChannel(dataConnection)
+      })
+    }
+
+    connectToPeer(uid) {
+      this.initialiseChannel(this.peer.connect(uid))
+    }
+
+    initialiseChannel(dataConnection) {
+      var self = this
+
+      dataConnection.on("open", function() {
+        console.log("Connected to peer " + dataConnection.peer)
+
+        self.peers.set(dataConnection.peer, dataConnection)
+        self.userJoined(dataConnection.peer, "master")
+      })
+
+      dataConnection.on("data", function(data) {
+        console.log("Message from peer " + dataConnection.peer + ":", data)
+
+        self.receiveMessage(dataConnection.peer, data)
+      })
+
+      dataConnection.on("close", function() {
+        console.log("Disconnected from peer " + dataConnection.peer)
+
+        self.peers.delete(dataConnection.peer)
+        self.userLeft(dataConnection.peer)
       })
     }
 
     disconnect() {
+      this.peer.destroy()
+      this.peers = new Map()
+
       super.disconnect()
     }
 
     reconnect() {
+      this.initialiseConnection()
+
       super.reconnect()
     }
 
-    send(/*uid, message*/) {}
+    send(uid, message) {
+      console.log("Sending message", message, "to " + uid)
+
+      var self = this
+
+      var send = function() {
+        // check if the clients still exists
+        var peer = self.peers.get(uid)
+
+        if (peer) {
+          try {
+            peer.send(message)
+          } catch (error) {
+            setTimeout(send, 500)
+          }
+        }
+      }
+
+      // try to send the message
+      send()
+    }
+
+    broadcast(message) {
+      console.log("Broadcasting message", message)
 
-    broadcast(/*message*/) {}
+      for (const uid of this.peers.keys()) {
+        this.send(uid, message)
+      }
+    }
 
     isDisconnected() {
       return false