diff --git a/docs/framework/backbone.md b/docs/framework/backbone.md
index f60bbd58e4dc269c4ea6ec95ee0c33bd81ea0c71..0a9dfe9a3e291267562ea6918a25e5a3efaf56cd 100644
--- a/docs/framework/backbone.md
+++ b/docs/framework/backbone.md
@@ -1,53 +1,7 @@
 # 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>
+!!! failure "Deprecated"
+    CiviCRM no longer recommends using Backbone. This page is here primarily for archival purposes.
 
 ## Background
 
@@ -71,149 +25,71 @@ Backbone is currently used in the following parts of CiviCRM:
 
 ## External Packages
 
+* [Underscore](http://documentcloud.github.io/underscore/)
+    * General utilities for working with objects, arrays, and client-side HTML templates
+    * Scope of usage:
+        * Profile Designer
+        * CiviVolunteer
+        * CiviHR
+
+* [Backbone](http://documentcloud.github.io/backbone/)
+    * MV* framework. Defines three key base-classes:
+        * `Backbone.Model` - (for representing individual data records)
+        * `Backbone.Collection` - (for representing a collection of data records)
+        * `Backbone.View` - (for rendering markup and responding to events)
+    * Scope of usage:
+        * Profile Designer
+        * CiviVolunteer
+        * CiviHR
+
+* [Backbone.Marionette](http://marionettejs.com/)
+    * An "opinionated" Backbone framework. It adds more base-classes which significantly reduce the boiler-plate and clutter required for defining & combining normal `Backbone.View` classes.
+    * See also:
+        * [A simple Backbone.Marionette tutorial](http://davidsulc.com/blog/2012/04/15/a-simple-backbone-marionette-tutorial/) (Blog, Apr 2012)
+        * [Tutorial: A full Backbone.Marionette application](http://davidsulc.com/blog/2012/05/06/tutorial-a-full-backbone-marionette-application-part-1/) (Blog, May 2012)
+        * [Backbone.Marionette.js: A Simple Introduction](https://leanpub.com/marionette-gentle-introduction) (eBook, July 2013)
+    * Scope of usage:
+        * Profile Designer
+        * CiviVolunteer
+        * CiviHR
+
+* [Backbone.ModelBinder](https://github.com/theironcook/Backbone.ModelBinder)
+    * A two-way link between Backbone "models" and HTML "forms" – form fields can be initialized using data from models, and models can be updated using form fields.
+    * Scope of usage:
+        * CiviHR
+
+* [Backbone.Forms](https://github.com/powmedia/backbone-forms)
+    * Like `Backbone.ModelBinder`, this can define a 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".
+    * Scope of usage:
+        * Profile Designer
 
 
-<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">
-
+### `CRM.Backbone.trackSaved`
+
+Tracking saved/unsaved status
+
+```javascript
+// 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)
+```
+
+!!! 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) before checking `isSaved()`. For example:
+
+    ```javascript
     var model = new MyModel({
       property1: value1,
       property2: value2,
@@ -233,55 +109,37 @@ before checking isSaved():
         });
       }
     });
+    ```
 
-</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)
+### `CRM.Backbone.trackSoftDelete`
 
+Using soft deletion
 
-    // Remove a deletion flag
-    model.setSoftDeleted(false);
-    // assert: model.isSoftDeleted() === false
-    // event: softDeleted(model, is_soft_deleted)
+```javascript
+var MyModel = Backbone.Model.extend({...});
+CRM.Backbone.trackSoftDelete(MyModel);
 
+// Create an example model
+var model = new MyModel({id: 123});
+// assert: model.isSoftDeleted() === false
 
-    // Perform save or deletion (depending on whether isSoftDeleted())
-    model.save();
-    // If isSoftDeleted()==false, call normal save()
-    // If isSoftDeleted()==true, call destroy() instead
+// Flag a model for deletion
+model.setSoftDeleted(true);
+// assert: model.isSoftDeleted() === true
+// event: softDeleted(model, is_soft_deleted)
 
-</div>
+// Remove a deletion flag
+model.setSoftDeleted(false);
+// assert: model.isSoftDeleted() === false
+// event: softDeleted(model, is_soft_deleted)
 
-</div>
+// Perform save or deletion (depending on whether isSoftDeleted())
+model.save();
+// If isSoftDeleted()==false, call normal save()
+// If isSoftDeleted()==true, call destroy() instead
+```
 
-
-
-#### CRM.Backbone.sync
+### `CRM.Backbone.sync`
 
 The Backbone.sync framework is generally used for loading and saving
 data through web-services. The default implementation of Backbone.sync
@@ -300,125 +158,76 @@ them directly. Instead, use the CRM.Backbone.extendModel and
 CRM.Backbone.extendCollection helpers to mix-in the necessary
 properties.
 
-#### CRM.Backbone.extend(Model,Collection)
+### `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">
-
+`extendModel()` and `extendCollection()` helpers.
+
+```javascript
+var ContactModel = Backbone.Model.extend({
+  ...
+});
+CRM.Backbone.extendModel(ContactModel, "Contact");
+
+var ContactCollection = Backbone.Collection.extend({
+  model: ContactModel
+});
+CRM.Backbone.extendCollection(ContactCollection);
+```
+
+Create a new contact record
+
+```javascript
+var contact = new ContactModel({
+  contact_type: 'Individual',
+  first_name: 'Bat',
+  last_name: 'Man'
+});
+contact.save({}, {
+  success: function() { ... }
+  error: function()  { ... }
+});
+```
+
+Load a specific contact record
+
+```javascript
+var contact = new ContactModel({
+  id: 123
+});
+contact.fetch({
+  success: function() { ... }
+  error: function()  { ... }
+});
+```
+
+Load all organizations
+
+```javascript
+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");
+  }
+});
+```
+
+Update list of emails for contact #123 (immediately)
+
+```javascript
     // 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({
@@ -426,87 +235,72 @@ extendModel() and extendCollection() helpers.
       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>
+```
+
+Update list of emails for contact #123 (delayed-save)
+
+```javascript
+// 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.
+```
 
 ## 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**"
+(`http://local.example.com`) and request the following:
+
+`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>).
+The source for the unit-tests are stored in ["tests/qunit/crm-backbone"](https://github.com/civicrm/civicrm-core/tree/master/tests/qunit/crm-backbone).