diff --git a/docs/framework/backbone.md b/docs/framework/backbone.md
new file mode 100644
index 0000000000000000000000000000000000000000..f60bbd58e4dc269c4ea6ec95ee0c33bd81ea0c71
--- /dev/null
+++ b/docs/framework/backbone.md
@@ -0,0 +1,512 @@
+# Backbone Reference
+
+<div class="panelMacro">
+
++--+
+|  |
++--+
+
+</div>
+
+
+
+<span id="BackboneReference-status"
+class="confluence-anchor-link"></span>
+
+<div class="panel"
+style="background-color: #FFFFCE;border-color: #000;border-style: solid;border-width: 1px;">
+
+<div class="panelHeader"
+style="border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #000;background-color: #F7D6C1;">
+
+**Table of Contents**
+
+</div>
+
+<div class="panelContent" style="background-color: #FFFFCE;">
+
+<div>
+
+-   [Background](#BackboneReference-Background)
+-   [Examples](#BackboneReference-Examples)
+-   [External Packages](#BackboneReference-ExternalPackages)
+-   [CiviCRM Additions](#BackboneReference-CiviCRMAdditions)
+
+<!-- -->
+
+-   [CRM.Backbone.trackSaved](#BackboneReference-CRM.Backbone.trackSaved)
+-   [CRM.Backbone.trackSoftDelete](#BackboneReference-CRM.Backbone.trackSoftDelete)
+-   [CRM.Backbone.sync](#BackboneReference-CRM.Backbone.sync)
+-   [CRM.Backbone.extend(Model,Collection)](#BackboneReference-CRM.Backbone.extend(Model,Collection))
+
+<!-- -->
+
+-   [Unit Tests](#BackboneReference-UnitTests)
+
+</div>
+
+</div>
+
+</div>
+
+## Background
+
+Backbone is a model-view (MV) framework for Javascript which follows a
+minimalist, plugin-oriented architecture: at its core, Backbone defines
+a minimal set of classes and utilities for building user-interfaces with
+object-oriented Javascript. Like the Drupal and jQuery communities, the
+Backbone community has a wide range of plugins to address missing
+functionality.
+
+## Examples
+
+Backbone is currently used in the following parts of CiviCRM:
+
+-   Profile Designer (v4.3+): Drag/drop interface for creating
+    profile forms. (At time of writing, usable with CiviSurvey)
+-   CiviVolunteer Extension (v4.4+): Drag/drop interface for managing
+    volunteer assignments
+-   CiviHR Extension (v4.4+): Split-pane interface for editing "Jobs"
+    and related records
+
+## External Packages
+
+
+
+<div class="table-wrap">
+
++--------------------------+--------------------------+--------------------------+
+| Package                  | Description              | Scope of Usage           |
++==========================+==========================+==========================+
+| [Underscore](http://docu | General utilities for    | Profile Designer         |
+| mentcloud.github.io/unde | working with objects,    |                          |
+| rscore/){.external-link} | arrays, and client-side  | CiviVolunteer            |
+|                          | HTML templates           |                          |
+|                          |                          | CiviHR                   |
++--------------------------+--------------------------+--------------------------+
+| [Backbone](http://docume | MV* framework. Defines  | Profile Designer         |
+| ntcloud.github.io/backbo | three key base-classes:  |                          |
+| ne/){.external-link}     |                          | CiviVolunteer            |
+|                          | -   Backbone.Model (for  |                          |
+|                          |     representing         | CiviHR                   |
+|                          |     individual           |                          |
+|                          |     data records)        |                          |
+|                          | -   Backbone.Collection  |                          |
+|                          |     (for representing a  |                          |
+|                          |     collection of        |                          |
+|                          |     data records)        |                          |
+|                          | -   Backbone.View (for   |                          |
+|                          |     rendering markup and |                          |
+|                          |     responding           |                          |
+|                          |     to events)           |                          |
++--------------------------+--------------------------+--------------------------+
+| [Backbone.Marionette](ht | An "opinionated"         | Profile Designer         |
+| tp://marionettejs.com/){ | Backbone framework. It   |                          |
+| .external-link}          | adds more base-classes   | CiviVolunteer            |
+|                          | which significantly      |                          |
+|                          | reduce the boiler-plate  | CiviHR                   |
+|                          | and clutter required for |                          |
+|                          | defining & combining     |                          |
+|                          | normal Backbone.View     |                          |
+|                          | classes.                 |                          |
+|                          |                          |                          |
+|                          | See also:                |                          |
+|                          |                          |                          |
+|                          | -   [A simple            |                          |
+|                          |     Backbone.Marionette  |                          |
+|                          |     tutorial (Blog,      |                          |
+|                          |     Apr 2012)](http://da |                          |
+|                          | vidsulc.com/blog/2012/04 |                          |
+|                          | /15/a-simple-backbone-ma |                          |
+|                          | rionette-tutorial/){.ext |                          |
+|                          | ernal-link}              |                          |
+|                          | -   [Tutorial: A full    |                          |
+|                          |     Backbone.Marionette  |                          |
+|                          |     application (Blog,   |                          |
+|                          |     May 2012)](http://da |                          |
+|                          | vidsulc.com/blog/2012/05 |                          |
+|                          | /06/tutorial-a-full-back |                          |
+|                          | bone-marionette-applicat |                          |
+|                          | ion-part-1/){.external-l |                          |
+|                          | ink}                     |                          |
+|                          | -   [Backbone.Marionette |                          |
+|                          | .js:                     |                          |
+|                          |     A Simple             |                          |
+|                          |     Introduction (eBook, |                          |
+|                          |     July 2013)](https:// |                          |
+|                          | leanpub.com/marionette-g |                          |
+|                          | entle-introduction){.ext |                          |
+|                          | ernal-link}              |                          |
++--------------------------+--------------------------+--------------------------+
+| [Backbone.ModelBinder](h | A two-way link between   | CiviHR                   |
+| ttps://github.com/theiro | Backbone "models" and    |                          |
+| ncook/Backbone.ModelBind | HTML "forms" – form      |                          |
+| er){.external-link}      | fields can be            |                          |
+|                          | initialized using data   |                          |
+|                          | from models, and models  |                          |
+|                          | can be updated using     |                          |
+|                          | form fields.             |                          |
++--------------------------+--------------------------+--------------------------+
+| [Backbone.Forms](https:/ | Like                     | Profile Designer         |
+| /github.com/powmedia/bac | Backbone.ModelBinder,    |                          |
+| kbone-forms){.external-l | this can define a        |                          |
+| ink}                     | two-way link between     |                          |
+|                          | Backbone "models" and    |                          |
+|                          | HTML "forms" – however,  |                          |
+|                          | it goes a step further   |                          |
+|                          | by auto-generating the   |                          |
+|                          | HTML form based on the   |                          |
+|                          | "model schema".          |                          |
++--------------------------+--------------------------+--------------------------+
+
+</div>
+
+## CiviCRM Additions
+
+#### CRM.Backbone.trackSaved
+
+<div class="code panel" style="border-width: 1px;">
+
+<div class="codeHeader panelHeader" style="border-bottom-width: 1px;">
+
+**Tracking saved/unsaved status**
+
+</div>
+
+<div class="codeContent panelContent">
+
+    // Setup model class
+    var MyModel = Backbone.Model.extend({...});
+    CRM.Backbone.trackSaved(MyModel);
+
+
+    // Use the class
+    var model = new MyModel({id: 123});
+    model.fetch();
+    // assert: model.isSaved() === true -- because our client matches server
+    model.set('property', 'value'):
+    // assert: model.isSaved() === false -- because our client deviates from server
+    // event: saved(model,is_saved)
+    model.save();
+    // assert: model.isSaved() === true -- because our client matches server
+    // event: saved(model,is_saved)
+
+</div>
+
+</div>
+
+Note: The fetch() and save() methods each trigger an AJAX call –
+***after completing*** the AJAX call, the save-status will be updated.
+If you want to update a view based on the save-status, it's best to
+define a callback for the model's "saved" event. However, you *can*
+update the view using "success", "error", or "sync" callbacks – but you
+***must*** use
+[_.defer()](http://documentcloud.github.io/underscore/#defer){.external-link}
+before checking isSaved():
+
+<div class="code panel" style="border-width: 1px;">
+
+<div class="codeHeader panelHeader" style="border-bottom-width: 1px;">
+
+**Using isSaved() with success & error**
+
+</div>
+
+<div class="codeContent panelContent">
+
+    var model = new MyModel({
+      property1: value1,
+      property2: value2,
+      ...
+    });
+    model.save({}, {
+      success: function(model) {
+        // model.isSaved() may return weird results, so defer a moment...
+        _.defer(function(){
+          console.log('Success! isSaved()=' + model.isSaved()); // displays "true"
+        });
+      },
+      error: function(model) {
+        // model.isSaved() may return weird results, so defer a moment...
+        _.defer(function(){
+          console.log('Disaster! isSaved()=' + model.isSaved()); // displays "false"
+        });
+      }
+    });
+
+</div>
+
+</div>
+
+#### CRM.Backbone.trackSoftDelete
+
+<div class="code panel" style="border-width: 1px;">
+
+<div class="codeHeader panelHeader" style="border-bottom-width: 1px;">
+
+**Using soft deletion**
+
+</div>
+
+<div class="codeContent panelContent">
+
+    var MyModel = Backbone.Model.extend({...});
+    CRM.Backbone.trackSoftDelete(MyModel);
+
+    // Create an example model
+    var model = new MyModel({id: 123});
+    // assert: model.isSoftDeleted() === false
+
+
+    // Flag a model for deletion
+    model.setSoftDeleted(true);
+    // assert: model.isSoftDeleted() === true
+    // event: softDeleted(model, is_soft_deleted)
+
+
+    // Remove a deletion flag
+    model.setSoftDeleted(false);
+    // assert: model.isSoftDeleted() === false
+    // event: softDeleted(model, is_soft_deleted)
+
+
+    // Perform save or deletion (depending on whether isSoftDeleted())
+    model.save();
+    // If isSoftDeleted()==false, call normal save()
+    // If isSoftDeleted()==true, call destroy() instead
+
+</div>
+
+</div>
+
+
+
+#### CRM.Backbone.sync
+
+The Backbone.sync framework is generally used for loading and saving
+data through web-services. The default implementation of Backbone.sync
+is heavily driven by URLs – to indicate that a client-side Model (or
+Collection) is tied to a server resource, one sets the "url" property on
+the Model (or Collection) and pays careful attention to the path and
+parameters in the URL. In APIv3, we focus less on URLs and more on the
+triplet of "*entity,action,params*". To use CRM.Backbone.sync, one omits
+the "url" and instead adds the properties "crmEntityName" (which
+corresponds to APIv3's *entity*) and "toCrmCriteria()" (which
+corresponds to APIv3's *params*).
+
+Using CRM.Backbone.sync requires setting multiple properties on each
+class. To ensure that these are handled correctly, one shouldn't call
+them directly. Instead, use the CRM.Backbone.extendModel and
+CRM.Backbone.extendCollection helpers to mix-in the necessary
+properties.
+
+#### CRM.Backbone.extend(Model,Collection)
+
+To define models & collections which APIv3 for persistence, use the
+extendModel() and extendCollection() helpers.
+
+<div class="code panel" style="border-width: 1px;">
+
+<div class="codeHeader panelHeader" style="border-bottom-width: 1px;">
+
+**Define model & collection classes**
+
+</div>
+
+<div class="codeContent panelContent">
+
+    var ContactModel = Backbone.Model.extend({
+      ...
+    });
+    CRM.Backbone.extendModel(ContactModel, "Contact");
+
+    var ContactCollection = Backbone.Collection.extend({
+      model: ContactModel
+    });
+    CRM.Backbone.extendCollection(ContactCollection);
+
+</div>
+
+</div>
+
+<div class="code panel" style="border-width: 1px;">
+
+<div class="codeHeader panelHeader" style="border-bottom-width: 1px;">
+
+**Create a new contact record**
+
+</div>
+
+<div class="codeContent panelContent">
+
+    var contact = new ContactModel({
+      contact_type: 'Individual',
+      first_name: 'Bat',
+      last_name: 'Man'
+    });
+    contact.save({}, {
+      success: function() { ... }
+      error: function()  { ... }
+    });
+
+</div>
+
+</div>
+
+<div class="code panel" style="border-width: 1px;">
+
+<div class="codeHeader panelHeader" style="border-bottom-width: 1px;">
+
+**Load a specific contact record**
+
+</div>
+
+<div class="codeContent panelContent">
+
+    var contact = new ContactModel({
+      id: 123
+    });
+    contact.fetch({
+      success: function() { ... }
+      error: function()  { ... }
+    });
+
+</div>
+
+</div>
+
+<div class="code panel" style="border-width: 1px;">
+
+<div class="codeHeader panelHeader" style="border-bottom-width: 1px;">
+
+**Load all organizations**
+
+</div>
+
+<div class="codeContent panelContent">
+
+    var contacts = new ContactCollection([], {
+      // crmCriteria defines query parameters per APIv3
+      crmCriteria: {contact_type: 'Organization'}
+    });
+    contacts.fetch({
+      success: function() {
+        console.log("Loaded " + contacts.length + " contact(s)");
+      },
+      error: function() {
+        console.log("Failed to load contacts");
+      }
+    });
+
+</div>
+
+</div>
+
+<div class="code panel" style="border-width: 1px;">
+
+<div class="codeHeader panelHeader" style="border-bottom-width: 1px;">
+
+**Update list of emails for contact #123 (immediately)**
+
+</div>
+
+<div class="codeContent panelContent">
+
+    // Update the list of email addresses for contact 123
+    var emails = new EmailCollection([], {
+      crmCriteria: {contact_id: 123}
+    });
+    emails.fetch(...);
+
+    ...
+
+    // Add an email on client and server (with an immediate AJAX request)
+    var email = emails.create({
+      contact_id: 123,
+      email: 'new-email@example.com'
+    }, ...);
+
+
+    ...
+
+    // Modify an email on client and server (with an immediate AJAX request)
+    emails.get(456).set('on_hold', 1);
+    emails.get(456).save(...);
+
+    ...
+
+    // Remove an email on client and server (with an immediate AJAX request)
+    emails.get(789).destroy(...);
+
+</div>
+
+</div>
+
+<div class="code panel" style="border-width: 1px;">
+
+<div class="codeHeader panelHeader" style="border-bottom-width: 1px;">
+
+**Update list of emails for contact #123 (delayed-save)**
+
+</div>
+
+<div class="codeContent panelContent">
+
+    // Update the list of email addresses for contact 123
+    var emails = new EmailCollection([], {
+      crmCriteria: {contact_id: 123}
+    });
+    emails.fetch(...);
+
+    ...
+
+    // Add a new email on client (but don't send to server yet)
+    var email = new EmailModel({
+      contact_id: 123,
+      email: 'another-email@example.com'
+    });
+    emails.add(model);
+
+    // Update an email on client (but don't send to server yet)
+    emails.get(456).set('on_hold', 1);
+
+    // Remove an email on client (but don't send to server yet)
+    emails.get(789).setSoftDeleted(true);
+
+    ...
+
+    // Send all changes to all emails to server (with one AJAX call)
+    emails.save(...);
+
+    // NOTE: Use this carefully. This will perform INSERTs, UPDATEs, and/or DELETEs
+    // to make the email list match on the client and server. The server will use
+    // an algorithm like this:
+    //
+    // 1. Accept list of records from client.
+    // 2. Query list of pre-existing emails on server (matching crmCriteria).
+    // 3. Identify records in BOTH client and server. UPDATE them.
+    // 4. Identify records in CLIENT but not server. INSERT them.
+    // 5. Identify records in SERVER but not client. DELETE them.
+    //
+    // This is generally appropriate when you know the client has the full,
+    // proper collection -- e.g. it's appropriate with the collection of "Email",
+    // "Phone", or "Address" records of one contact. However, it's not appropriate
+    // for a collection of "Activities" (because concurrent processes may add new
+    // activities that are unknown the client -- and those records shouldn't be
+    // deleted). If you have a use-case that needs a different / more nuanced
+    // reconciliation strategy, post to the forum to discuss.
+
+</div>
+
+</div>
+
+## Unit Tests
+
+The CiviCRM Backbone plugins are tested with qUnit. To run the
+unit-tests, use a web-browser to connect to a CiviCRM installation
+("http://local.example.com") and request
+"*http://local.example.com*/**civicrm/tests/qunit/crm-backbone**"
+
+The source for the unit-tests are stored in "tests/qunit/crm-backbone"
+(e.g.
+<https://github.com/civicrm/civicrm-core/tree/master/tests/qunit/crm-backbone>).
diff --git a/mkdocs.yml b/mkdocs.yml
index 2019e48457e0e81bff4b8b38334f21a4f3a59537..fb01c555abec88c6d56c1f882bb336c8cba2ec09 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -68,6 +68,7 @@ pages:
   - "API architecture": framework/api-architecture.md
   - Asset Builder: framework/asset-builder.md
   - Bootstrap Process: framework/bootstrap.md
+  - Backbone Reference: framework/backbone.md
   - Cache Reference: framework/cache.md
   - AJAX Pages and Forms Refernce: framework/ajax.md
   # Components: /framework/components.md
diff --git a/redirects/wiki-crmdoc.txt b/redirects/wiki-crmdoc.txt
index 7d612e80d72f5988ada697f43e84b04847f97458..3874e62e335ef8ae3b242a8e57e45407f2ab0264 100644
--- a/redirects/wiki-crmdoc.txt
+++ b/redirects/wiki-crmdoc.txt
@@ -175,3 +175,4 @@ Tarball+installation+testing testing/manual/#tarball
 Contributing+to+CiviCRM+using+GitHub tools/git/#github
 Git+Commit+Messages+for+CiviCRM tools/git/#committing
 Transaction+Reference framework/database/transactions.md
+Backbone+Reference framework/backbone