website: Draft of Data Flow doc

https://screenshot.googleplex.com/aKWe5M5JYfu.png
https://screenshot.googleplex.com/AVp1sHqLfPi.png

Change-Id: Ie8ba107b0f7c777a5b8a17e6a1c710953b7f415b
diff --git a/content/syncbase/first-app.md b/content/syncbase/first-app.md
index ed05137..0981269 100644
--- a/content/syncbase/first-app.md
+++ b/content/syncbase/first-app.md
@@ -152,7 +152,7 @@
 UI in a single place, regardless of whether the new value is local or was synced
 from a remote device.
 
-<img src="/images/syncbase-dice-data-flow.png" alt="Unidirectioanl Data Flow using Watch API">
+<img src="/images/syncbase-dice-data-flow.png" alt="Unidirectional Data Flow using Watch API">
 
 Now let's hook up this model to our code.
 
diff --git a/content/syncbase/guides/data-flow.md b/content/syncbase/guides/data-flow.md
index de03f53..3490be8 100644
--- a/content/syncbase/guides/data-flow.md
+++ b/content/syncbase/guides/data-flow.md
@@ -4,3 +4,104 @@
 sort: 2
 toc: true
 = yaml =
+
+# Introduction
+
+Syncbase API is designed to encourage writing reactive applications where the app
+updates its UI as data in Syncbase changes. Since Syncbase is a synchronized store
+the source of data changes might be local or remote as local Syncbase syncs with
+other peers.
+
+The Watch method is the recommended way of retrieving existing data and watching
+for changes. Both local and synced mutations are surfaced in the watch stream.
+This allows developers to stay agnostic to the source of data changes
+and use the same code to handle local and synced changes alike.
+
+Local mutations are surfaced in the watch stream within milliseconds, which
+allows apps to be built with unidirectional data flow. Instead of updating the
+UI optimistically, UI actions can simply mutate Syncbase data. The watch stream
+will quickly receive local changes and trigger the necessary UI updates.
+
+<img src="/images/syncbase-guide-data-flow.png" alt="Unidirectional Data Flow using the Watch method">
+
+# Reading and Watching Data
+`addWatchChangeHandler` on `Database` can be used to register a handler that will
+be called with both initial existing data and any changes to the data later.
+
+Let's consider a simple Todos application where each collection corresponds to
+a Todo list and rows in each collection are the tasks. We can use the Watch method
+to maintain an in-memory representation of our data model the UI renders
+from. UI actions such as adding new task or deleting one simply do a `put` or
+`delete` on the corresponding collection.
+
+```Java
+db.addWatchChangeHandler(new Database.WatchChangeHandler() {
+
+    @Override
+    public void onInitialState(Iterator<WatchChange> values) {
+
+        // onInitialState is called with all of existing data in Syncbase.
+        // Although the value type is WatchChange, since this is existing
+        // data, there will not be any values with ChangeType == DELETE_CHANGE
+        while(values.hasNext()) {
+            updateState(values.next());
+        }
+
+        // Trigger UI update
+    }
+
+    @Override
+    public void onChangeBatch(Iterator<WatchChange> changes) {
+
+        // onChangeBatch is called whenever changes are made to the data.
+        // Changes that are part of the same batch are presented together,
+        // otherwise changes iterator may only contain a single change.
+        while(changes.hasNext()) {
+            updateState(changes.next());
+        }
+
+        // Trigger UI update
+    }
+});
+
+
+// Modeling our in-memory state as a map of Todolist-Id to a map of (Task-Id, Task)
+HashMap<String, Map<String, Task>> state = new HashMap<String, Map<String, Task>>();
+
+// Update the state based on the changes.
+void updateState(WatchChange change) {
+
+    String collectionId = change.getCollectionId().encode();
+    String rowKey = change.getRowKey();
+
+    switch (change.getChangeType()) {
+        case ChangeType.PUT_CHANGE:
+            if(!state.containsKey(collectionId)) {
+                state.put(collectionId, new HashMap<String, Task>());
+            }
+            Task rowValue = change.getValue(Task.class);
+            state.get(collectionId).put(rowKey, rowValue);
+            break;
+
+        case ChangeType.DELETE_CHANGE:
+            state.get(collectionId).remove(rowKey);
+            break;
+    }
+}
+{{# helpers.info }}
+### Tip
+`db.removeAllWatchChangeHandlers()` can be used in activity's `onDestroy`
+to remove all registered watch handlers.
+{{/ helpers.info }}
+
+```
+
+In most cases, source of a change should be irrelevant to the application.
+However `watchChange.isFromSync()` can tell you if a change is due to a local
+mutation or is synced from a remote Syncbase.
+
+# Summary
+* Syncbase's Watch method is designed to help build reactive applications.
+* Watch surfaces both local and synced data changes.
+* We recommend using the Watch method to keep an up-to-date in-memory state that
+the UI renders from.
\ No newline at end of file
diff --git a/public/images/syncbase-guide-data-flow.png b/public/images/syncbase-guide-data-flow.png
new file mode 100644
index 0000000..8c83a77
--- /dev/null
+++ b/public/images/syncbase-guide-data-flow.png
Binary files differ