diff --git a/.travis.yml b/.travis.yml
index 45b66d72ad320b823262d910d36d8af081724788..7a150b62901a166ecd1551937b0d141c62d03a03 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,12 +1,8 @@
 language: node_js
 before_install:
   - "npm install -g bower"
-  - "bower install"
 node_js:
   - "0.12"
-  - "0.11"
-  - "0.10"
 branches:
   only:
     - master
-    - 0.6
diff --git a/README.md b/README.md
index c618007beef4b8f73a1a3478a2d8555b404bb293..34b41376b98509aad02ca5e0a451204e5ee31004 100644
Binary files a/README.md and b/README.md differ
diff --git a/gulpfile.js b/gulpfile.js
index 317ac0a81959b679f5edb12867f9fdc1c05725e6..5e02ceab203dfa11fd6a15d1d0a8f12190c3d05a 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -28,8 +28,8 @@
     Specify which specs to use!
 
   Commands:
-    - build
-        Build this library
+    - build:deploy
+        Build this library for deployment (es6->es5, minified)
     - dev:browser
         Watch the ./src directory.
         Builds the library on changes.
diff --git a/src/Connector.js b/src/Connector.js
index 017b1156a72b4ebbc6781afa8cd248ac11d07d02..88ca708de5cc6803406e72c38afef62468406761 100644
--- a/src/Connector.js
+++ b/src/Connector.js
@@ -130,7 +130,7 @@ class AbstractConnector {
   }
   send (uid, message) {
     if (this.debug) {
-      console.log(`send ${this.userId} -> ${uid}: ${message.type}`, m);// eslint-disable-line
+      console.log(`send ${this.userId} -> ${uid}: ${message.type}`, m) // eslint-disable-line
     }
   }
   /*
@@ -141,7 +141,7 @@ class AbstractConnector {
       return
     }
     if (this.debug) {
-      console.log(`receive ${sender} -> ${this.userId}: ${m.type}`, m);// eslint-disable-line
+      console.log(`receive ${sender} -> ${this.userId}: ${m.type}`, m) // eslint-disable-line
     }
     if (m.type === 'sync step 1') {
       // TODO: make transaction, stream the ops
@@ -212,17 +212,19 @@ class AbstractConnector {
       this.y.db.apply(m.ops)
     }
   }
-  // Currently, the HB encodes operations as JSON. For the moment I want to keep it
-  // that way. Maybe we support encoding in the HB as XML in the future, but for now I don't want
-  // too much overhead. Y is very likely to get changed a lot in the future
-  //
-  // Because we don't want to encode JSON as string (with character escaping, wich makes it pretty much unreadable)
-  // we encode the JSON as XML.
-  //
-  // When the HB support encoding as XML, the format should look pretty much like this.
-  //
-  // does not support primitive values as array elements
-  // expects an ltx (less than xml) object
+  /*
+    Currently, the HB encodes operations as JSON. For the moment I want to keep it
+    that way. Maybe we support encoding in the HB as XML in the future, but for now I don't want
+    too much overhead. Y is very likely to get changed a lot in the future
+
+    Because we don't want to encode JSON as string (with character escaping, wich makes it pretty much unreadable)
+    we encode the JSON as XML.
+
+    When the HB support encoding as XML, the format should look pretty much like this.
+
+    does not support primitive values as array elements
+    expects an ltx (less than xml) object
+  */
   parseMessageFromXml (m) {
     function parseArray (node) {
       for (var n of node.children) {
@@ -256,14 +258,16 @@ class AbstractConnector {
     }
     parseObject(m)
   }
-  // encode message in xml
-  // we use string because Strophe only accepts an "xml-string"..
-  // So {a:4,b:{c:5}} will look like
-  // <y a="4">
-  //   <b c="5"></b>
-  // </y>
-  // m - ltx element
-  // json - Object
+  /*
+    encode message in xml
+    we use string because Strophe only accepts an "xml-string"..
+    So {a:4,b:{c:5}} will look like
+    <y a="4">
+      <b c="5"></b>
+    </y>
+    m - ltx element
+    json - Object
+  */
   encodeMessageToXml (msg, obj) {
     // attributes is optional
     function encodeObject (m, json) {
diff --git a/src/Notes.md b/src/Notes.md
new file mode 100644
index 0000000000000000000000000000000000000000..f9d2236e0435d106ed94efa6b8d03acb638fc6b8
--- /dev/null
+++ b/src/Notes.md
@@ -0,0 +1,12 @@
+
+# Notes
+
+### Terminology
+
+* DB: DataBase that holds all the information of the shared object. It is devided into the OS, DS, and SS. This can be a persistent database or an in-memory database. Depending on the type of database, it could make sense to store OS, DS, and SS in different tables, or maybe different databases.
+* OS: OperationStore holds all the operations. An operation is a js object with a fixed number of name fields.
+* DS: DeleteStore holds the information about which operations are deleted and which operations were garbage collected (no longer available in the OS).
+* SS: StateSet holds the current state of the OS. SS.getState(username) refers to the amount of operations that were received by that respective user.
+* Op: Operation defines an action on a shared type. But it is also the format in which we store the model of a type. This is why it is also called a Struct/Structure.
+* Type and Structure: We crearly distinguish between type and structure. Short explanation: A type (e.g. Strings, Numbers) have a number of functions that you can apply on them. (+) is well defined on both of them. They are *modeled* by a structure - the functions really change the structure of a type. Types can be implemented differently but still provide the same functionality. In Yjs, almost all types are realized as a doubly linked list (on which Yjs can provide eventual convergence)
+*
\ No newline at end of file
diff --git a/src/OperationStore.js b/src/OperationStore.js
index 6bbba9a3f45ec56fde35ba0c078bc51a1b5b1ec8..37031f6acd9adae5b6195e461433de3d23bdb770 100644
--- a/src/OperationStore.js
+++ b/src/OperationStore.js
@@ -3,6 +3,9 @@
 
 /*
   Partial definition of a transaction
+  
+  A transaction provides all the the async functionality on a database.
+  
   By convention, a transaction has the following properties:
   * ss for StateSet
   * os for OperationStore
@@ -75,6 +78,10 @@ class AbstractTransaction {
   constructor (store) {
     this.store = store
   }
+  /*
+    Get a type based on the id of its model.
+    If it does not exist yes, create it.
+  */
   * getType (id) {
     var sid = JSON.stringify(id)
     var t = this.store.initializedTypes[sid]
@@ -87,12 +94,11 @@ class AbstractTransaction {
     }
     return t
   }
-  * createType (model) {
-    var sid = JSON.stringify(model.id)
-    var t = yield* Y[model.type].initType.call(this, this.store, model)
-    this.store.initializedTypes[sid] = t
-    return t
-  }
+  /*
+    Apply operations that this user created (no remote ones!)
+      * does not check for Struct.*.requiredOps()
+      * also broadcasts it through the connector
+  */
   * applyCreatedOperations (ops) {
     var send = []
     for (var i = 0; i < ops.length; i++) {
@@ -108,24 +114,13 @@ class AbstractTransaction {
     }
   }
   /*
-    Delete an operation from the OS, and add it to the GC, if necessary.
-
-    Rulez:
-    * The most left element in a list must not be deleted.
-      => There is at least one element in the list
-    * When an operation o is deleted, then it checks if its right operation
-      can be gc'd (iff it's deleted)
+    Mark an operation as deleted, and add it to the GC, if possible.
   */
   * deleteOperation (targetId) {
     var target = yield* this.getOperation(targetId)
 
     if (target == null || !target.deleted) {
       this.ds.markDeleted(targetId)
-      var state = yield* this.getState(targetId[0])
-      if (state.clock === targetId[1]) {
-        yield* this.checkDeleteStoreForState(state)
-        yield* this.setState(state)
-      }
     }
 
     if (target != null && target.gc == null) {
@@ -143,23 +138,16 @@ class AbstractTransaction {
       var left = target.left != null ? yield* this.getOperation(target.left) : null
       var right = target.right != null ? yield* this.getOperation(target.right) : null
 
-      this.store.addToGarbageCollector(target, left, right)
+      this.store.addToGarbageCollector(target, left)
 
       // set here because it was deleted and/or gc'd
       yield* this.setOperation(target)
 
-      if (
-        left != null &&
-        left.left != null &&
-        this.store.addToGarbageCollector(left, yield* this.getOperation(left.left), target)
-      ) {
-        yield* this.setOperation(left)
-      }
-
+      // check if it is possible to add right to the gc (this delete can't be responsible for left being gc'd)
       if (
         right != null &&
         right.right != null &&
-        this.store.addToGarbageCollector(right, target, yield* this.getOperation(right.right))
+        this.store.addToGarbageCollector(right, target)
       ) {
         yield* this.setOperation(right)
       }
@@ -176,31 +164,45 @@ class AbstractTransaction {
       yield* this.deleteOperation(id)
       o = yield* this.getOperation(id)
     }
+    
+    // check to increase the state of the respective user
+    var state = yield* this.getState(id[0])
+    if (state.clock === id[1]) {
+      // also check if more expected operations were gc'd
+      yield* this.checkDeleteStoreForState(state)
+      // then set the state
+      yield* this.setState(state)
+    }
 
+    // remove gc'd op from the left op, if it exists
     if (o.left != null) {
       var left = yield* this.getOperation(o.left)
       left.right = o.right
       yield* this.setOperation(left)
     }
+    // remove gc'd op from the right op, if it exists
     if (o.right != null) {
       var right = yield* this.getOperation(o.right)
       right.left = o.left
       yield* this.setOperation(right)
     }
+    // remove gc'd op from parent, if it exists
     var parent = yield* this.getOperation(o.parent)
-    var setParent = false
+    var setParent = false // whether to save parent to the os
     if (Y.utils.compareIds(parent.start, o.id)) {
+      // gc'd op is the start
       setParent = true
       parent.start = o.right
     }
     if (Y.utils.compareIds(parent.end, o.id)) {
+      // gc'd op is the end
       setParent = true
       parent.end = o.left
     }
     if (setParent) {
       yield* this.setOperation(parent)
     }
-    yield* this.removeOperation(o.id)
+    yield* this.removeOperation(o.id) // actually remove it from the os
     yield* this.ds.markGarbageCollected(o.id)
   }
 }
@@ -272,10 +274,9 @@ class AbstractOperationStore {
     var os = this.os
     var self = this
     os.iterate(null, null, function (op) {
-      if (op.deleted && op.left != null && op.right != null) {
+      if (op.deleted && op.left != null) {
         var left = os.find(op.left)
-        var right = os.find(op.right)
-        self.addToGarbageCollector(op, left, right)
+        self.addToGarbageCollector(op, left)
       }
     })
   }
@@ -283,25 +284,21 @@ class AbstractOperationStore {
     Try to add to GC.
 
     TODO: rename this function
-
-    Only gc when
-       * creator of op is online
-       * left & right defined and both are from the same creator as op
-
+    
+    Rulez:
+    * Only gc if this user is online
+    * The most left element in a list must not be gc'd.
+      => There is at least one element in the list
+    
     returns true iff op was added to GC
   */
-  addToGarbageCollector (op, left, right) {
+  addToGarbageCollector (op, left) {
     if (
       op.gc == null &&
       op.deleted === true &&
       this.y.connector.isSynced &&
-      // (this.y.connector.connections[op.id[0]] != null || op.id[0] === this.y.connector.userId) &&
       left != null &&
-      right != null &&
       left.deleted &&
-      right.deleted &&
-      left.id[0] === op.id[0] &&
-      right.id[0] === op.id[0]
     ) {
       op.gc = true
       this.gc1.push(op.id)
@@ -343,23 +340,25 @@ class AbstractOperationStore {
     }
     return [this.userId, this.opClock++]
   }
+  /*
+    Apply a list of operations.
+    
+    * get a transaction
+    * check whether all Struct.*.requiredOps are in the OS
+    * check if it is an expected op (otherwise wait for it)
+    * check if was deleted, apply a delete operation after op was applied
+  */
   apply (ops) {
     for (var key in ops) {
       var o = ops[key]
-      if (o.gc == null) { // TODO: why do i get the same op twice?
-        if (o.deleted == null) {
-          var required = Y.Struct[o.struct].requiredOps(o)
-          this.whenOperationsExist(required, o)
-        } else {
-          throw new Error('Ops must not contain deleted field!')
-        }
-      } else {
-        throw new Error("Must not receive gc'd ops!")
-      }
+      var required = Y.Struct[o.struct].requiredOps(o)
+      this.whenOperationsExist(required, o)
     }
   }
-  // op is executed as soon as every operation requested is available.
-  // Note that Transaction can (and should) buffer requests.
+  /*
+    op is executed as soon as every operation requested is available.
+    Note that Transaction can (and should) buffer requests.
+  */
   whenOperationsExist (ids, op) {
     if (ids.length > 0) {
       let listener = {
@@ -390,7 +389,7 @@ class AbstractOperationStore {
     this.listenersByIdRequestPending = true
     var store = this
 
-    this.requestTransaction(function *() {
+    this.requestTransaction(function * () {
       var exeNow = store.listenersByIdExecuteNow
       store.listenersByIdExecuteNow = []
 
@@ -421,6 +420,13 @@ class AbstractOperationStore {
       }
     })
   }
+  /*
+    Actually execute an operation, when all expected operations are available.
+    If op is not yet expected, add it to the list of waiting operations.
+      
+    This will also try to execute waiting operations
+    (ops that were not expected yet), after it was applied
+  */
   * tryExecute (op) {
     if (op.struct === 'Delete') {
       yield* Y.Struct.Delete.execute.call(this, op)
@@ -439,6 +445,7 @@ class AbstractOperationStore {
           yield* this.addOperation(op)
           yield* this.store.operationAdded(this, op)
 
+          // Delete if DS says this is actually deleted
           if (this.store.ds.isDeleted(op.id)) {
             yield* Y.Struct['Delete'].execute.call(this, {struct: 'Delete', target: op.id})
           }
@@ -479,21 +486,5 @@ class AbstractOperationStore {
       yield* t._changed(transaction, Y.utils.copyObject(op))
     }
   }
-  removeParentListener (id, f) {
-    var ls = this.parentListeners[id]
-    if (ls != null) {
-      this.parentListeners[id] = ls.filter(function (g) {
-        return (f !== g)
-      })
-    }
-  }
-  addParentListener (id, f) {
-    var ls = this.parentListeners[JSON.stringify(id)]
-    if (ls == null) {
-      ls = []
-      this.parentListeners[JSON.stringify(id)] = ls
-    }
-    ls.push(f)
-  }
 }
 Y.AbstractOperationStore = AbstractOperationStore
diff --git a/src/OperationStores/IndexedDB.js b/src/OperationStores/IndexedDB.js
index f219779a8590153083157fe23acfd142b8188b82..ca36f678ec746a2a1c434736bdd4728e0e9fb0c3 100644
--- a/src/OperationStores/IndexedDB.js
+++ b/src/OperationStores/IndexedDB.js
@@ -122,7 +122,7 @@ Y.IndexedDB = (function () { // eslint-disable-line
         }
       })()
 
-      function handleTransactions (t) { // eslint-disable-line no-unused-vars
+      function handleTransactions (t) {
         var request = t.value
         if (t.done) {
           return
diff --git a/src/Types/Array.js b/src/Types/Array.js
index f34e75a519ade9a8169cae3b66b24f6246c2255c..f20593433a2a93e78fe7333fdfd773ad747547f6 100644
--- a/src/Types/Array.js
+++ b/src/Types/Array.js
@@ -167,15 +167,16 @@
   Y.Array = new Y.utils.CustomType({
     class: YArray,
     createType: function * YArrayCreator () {
+      var modelid = this.store.getNextOpId()
       var model = {
         struct: 'List',
         type: 'Array',
         start: null,
         end: null,
-        id: this.store.getNextOpId()
+        id: modelid
       }
       yield* this.applyCreatedOperations([model])
-      return yield* this.createType(model)
+      return modelid
     },
     initType: function * YArrayInitializer (os, model) {
       var valArray = []
diff --git a/src/Types/Map.js b/src/Types/Map.js
index e2f73092893a7c325d8eb47ab537e5c2f967b6d8..cb769b111d1d38f2c13d65c92f6e4e6df5477aeb 100644
--- a/src/Types/Map.js
+++ b/src/Types/Map.js
@@ -134,8 +134,9 @@
         if (value instanceof Y.utils.CustomType) {
           // construct a new type
           this.os.requestTransaction(function *() {
-            var type = yield* value.createType.call(this)
-            insert.opContent = type._model
+            var typeid = yield* value.createType.call(this)
+            var type = yield* this.getType(typeid)
+            insert.opContent = typeid
             insert.id = this.store.getNextOpId()
             yield* this.applyCreatedOperations([insert])
             resolve(type)
@@ -212,14 +213,15 @@
   Y.Map = new Y.utils.CustomType({
     class: YMap,
     createType: function * YMapCreator () {
+      var modelid = this.store.getNextOpId()
       var model = {
         map: {},
         struct: 'Map',
         type: 'Map',
-        id: this.store.getNextOpId()
+        id: modelid
       }
       yield* this.applyCreatedOperations([model])
-      return yield* this.createType(model)
+      return modelid
     },
     initType: function * YMapInitializer (os, model) { // eslint-disable-line
       return new YMap(os, model)
diff --git a/src/Types/TextBind.js b/src/Types/TextBind.js
index 77262bf0d6f4b97566673b8e82976f6c6b392c55..378061774f3fe4610cc97eff991a248064fbfbbd 100644
--- a/src/Types/TextBind.js
+++ b/src/Types/TextBind.js
@@ -267,15 +267,16 @@
   Y.TextBind = new Y.utils.CustomType({
     class: YTextBind,
     createType: function * YTextBindCreator () {
+      var modelid = this.store.getNextOpId()
       var model = {
         start: null,
         end: null,
         struct: 'List',
         type: 'TextBind',
-        id: this.store.getNextOpId()
+        id: modelid
       }
       yield* this.applyCreatedOperations([model])
-      return yield* this.createType(model)
+      return modelid
     },
     initType: function * YTextBindInitializer (os, model) {
       var valArray = []
diff --git a/src/y.js b/src/y.js
index 81a3089b4f96c2ec10f358c1a7eb1241c97608fb..0008f941fd0fdb6336a0753bae174e2c4cb945a3 100644
--- a/src/y.js
+++ b/src/y.js
@@ -37,14 +37,6 @@ class YConfig {
   }
   reconnect () {
     this.connector.reconnect()
-    /* TODO: maybe do this..
-    Promise.all([
-      this.db.garbageCollect(),
-      this.db.garbageCollect()
-    ]).then(() => {
-      this.connector.reconnect()
-    })
-    */
   }
   destroy () {
     this.connector.disconnect()