diff --git a/client/catalog-dev/js/catalog.js b/client/catalog-dev/js/catalog.js
new file mode 100644
index 0000000..d013fda
--- /dev/null
+++ b/client/catalog-dev/js/catalog.js
@@ -0,0 +1,714 @@
+//Run when the document loads AND we have the config loaded.
+(function(){
+  "use strict";
+  var config;
+  Promise.all([
+    new Promise(function(resolve, reject){
+      $.ajax('config.json').done(function(data){
+        config = data;
+        resolve();
+      }).fail(function(){
+        console.error("Failed to get config.");
+        ga('send', 'event', 'error', 'config');
+        reject();
+      });
+    }),
+    new Promise(function(resolve, reject){
+      var timeout = setTimeout(function(){
+        console.error("Document never loaded? Something bad has happened!");
+        reject();
+      }, 10000);
+      $(function () {
+        clearTimeout(timeout);
+        resolve();
+      });
+    })
+  ]).then(function(){
+    new Atmos(config);
+  }, function(){
+    console.error("Failed to initialize!");
+    ga('send', 'event', 'error', 'init');
+  });
+})();
+
+var Atmos = (function(){
+  "use strict";
+
+  var closeButton = '<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>';
+
+  var guid = function(){
+    var d = new Date().getTime();
+    var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+      var r = (d + Math.random()*16)%16 | 0;
+      d = Math.floor(d/16);
+      return (c=='x' ? r : (r&0x3|0x8)).toString(16);
+    });
+    return uuid;
+  }
+
+  /**
+   * Atmos
+   * @version 2.0
+   *
+   * Configures an Atmos object. This manages the atmos interface.
+   *
+   * @constructor
+   * @param {string} catalog - NDN path
+   * @param {Object} config - Object of configuration options for a Face.
+   */
+  var Atmos = function(config){
+
+    //Internal variables.
+    this.results = [];
+    this.resultCount = Infinity;
+    this.name = null;
+    this.page = 0;
+    this.resultsPerPage = 25;
+    this.retrievedSegments = 0;
+
+    //Config/init
+    this.config = config;
+
+    this.catalog = config['global']['catalogPrefix'];
+
+    this.face = new Face(config['global']['faceConfig']);
+
+    //Easy access dom variables
+    this.categories = $('#side-menu');
+    this.resultTable = $('#resultTable');
+    this.filters = $('#filters');
+    this.searchInput = $('#search');
+    this.searchBar = $('#searchBar');
+    this.searchButton = $('#searchButton');
+    this.resultMenu = $('.resultMenu');
+    this.alerts = $('#alerts');
+    this.requestForm = $('#requestForm');
+
+    var scope = this;
+
+    $('.requestSelectedButton').click(function(){
+      ga('send', 'event', 'button', 'click', 'request');
+      scope.request(scope.resultTable.find('.resultSelector:checked:not([disabled])').parent().parent());
+    });
+
+    this.filterSetup();
+
+    //Init autocomplete
+    this.searchInput.autoComplete(function(field, callback){
+      ga('send', 'event', 'search', 'autocomplete');
+      scope.autoComplete(field, function(list){
+        callback(list.map(function(element){
+          return field + element + "/";
+        }));
+      });
+    });
+
+    //Handle search
+    this.searchBar.submit(function(e){
+      ga('send', 'event', 'search', 'submit');
+      e.preventDefault();
+      if (scope.searchInput.val().length === 0){
+        if (!scope.searchBar.hasClass('has-error')){
+          scope.searchBar.addClass('has-error').append('<span class="help-block">Search path is required!</span>');
+        }
+        return;
+      } else {
+        scope.searchBar.removeClass('has-error').find('.help-block').fadeOut(function(){$(this).remove()});
+      }
+      scope.pathSearch();
+    });
+
+    this.searchButton.click(function(){
+      console.log("Search Button Pressed");
+      ga('send', 'event', 'button', 'click', 'search');
+      scope.search();
+    });
+
+    //Result navigation handlers
+    this.resultMenu.find('.next').click(function(){
+      ga('send', 'event', 'button', 'click', 'next');
+      if (!$(this).hasClass('disabled')){
+        scope.getResults(scope.page + 1);
+      }
+    });
+    this.resultMenu.find('.previous').click(function(){
+      ga('send', 'event', 'button', 'click', 'previous');
+      if (!$(this).hasClass('disabled')){
+        scope.getResults(scope.page - 1);
+      }
+    });
+
+    //Change the number of results per page handler
+    var rpps = $('.resultsPerPageSelector').click(function(){
+
+      var t = $(this);
+
+      if (t.hasClass('active')){
+        return;
+      }
+
+      rpps.find('.active').removeClass('active');
+      t.addClass('active');
+      scope.resultsPerPage = Number(t.text());
+      scope.getResults(0); //Force return to page 1;
+
+    });
+
+    //Init tree search
+    $('#treeSearch div').treeExplorer(function(path, callback){
+      console.log("Tree Explorer request", path);
+      ga('send', 'event', 'tree', 'request');
+      scope.autoComplete(path, function(list){
+        console.log("Autocomplete response", list);
+        callback(list.map(function(element){
+          return (path == "/"?"/":"") + element + "/";
+        }));
+      })
+    });
+
+    this.setupRequestForm();
+
+  }
+
+  Atmos.prototype.clearResults = function(){
+    this.results = []; //Drop any old results.
+    this.retrievedSegments = 0;
+    this.resultCount = Infinity;
+    this.page = 0;
+    this.resultTable.empty();
+  }
+
+  Atmos.prototype.pathSearch = function(){
+    var value = this.searchInput.val();
+
+    this.clearResults();
+
+    var scope = this;
+
+    this.query(this.catalog, {"??": value},
+    function(interest, data){
+      console.log("Query response:", interest, data);
+
+      scope.name = data.getContent().toString().replace(/[\n\0]/g,"");
+
+      scope.getResults(0);
+
+    },
+    function(interest){
+      console.warn("Request failed! Timeout", interest);
+      scope.createAlert("Request timed out. \"" + interest.getName().toUri() + "\" See console for details.");
+    });
+
+  }
+
+  Atmos.prototype.search = function(){
+
+    var filters = this.getFilters();
+
+    console.log("Search started!", this.searchInput.val(), filters);
+
+    console.log("Initiating query");
+
+    this.clearResults();
+
+    var scope = this;
+
+    this.query(this.catalog, filters,
+    function(interest, data){ //Response function
+      console.log("Query Response:", interest, data);
+
+      scope.name = data.getContent().toString().replace(/[\n\0]/g,"");
+
+      scope.getResults(0);
+
+    }, function(interest){ //Timeout function
+      console.warn("Request failed! Timeout");
+      scope.createAlert("Request timed out. \"" + interest.getName().toUri() + "\" See console for details.");
+    });
+
+  }
+
+  Atmos.prototype.autoComplete = function(field, callback){
+
+    var scope = this;
+
+    this.query(this.catalog, {"?": field},
+    function(interest, data){
+
+      var name = new Name(data.getContent().toString().replace(/[\n\0]/g,""));
+
+      var interest = new Interest(name);
+      interest.setInterestLifetimeMilliseconds(5000);
+      interest.setMustBeFresh(true);
+
+      scope.face.expressInterest(interest,
+      function(interest, data){
+
+        if (data.getContent().length !== 0){
+          callback(JSON.parse(data.getContent().toString().replace(/[\n\0]/g, "")).next);
+        } else {
+          callback([]);
+        }
+
+      }, function(interest){
+        console.warn("Interest timed out!", interest);
+        scope.createAlert("Request timed out. \"" + interest.getName().toUri() + "\" See console for details.");
+      });
+
+    }, function(interest){
+      console.error("Request failed! Timeout", interest);
+      scope.createAlert("Request timed out. \"" + interest.getName().toUri() + "\" See console for details.");
+    });
+
+  }
+
+  Atmos.prototype.showResults = function(resultIndex) {
+
+    var results = this.results.slice(this.resultsPerPage * resultIndex, this.resultsPerPage * (resultIndex + 1));
+
+    var resultDOM = $(
+      results.reduce(function(prev, current){
+        prev.push('<tr><td><input class="resultSelector" type="checkbox"></td><td>');
+        prev.push(current);
+        prev.push('</td></tr>');
+        return prev;
+      }, ['<tr><th><input id="resultSelectAll" type="checkbox" title="Select All"> Select</th><th>Name</th></tr>']).join('')
+    );
+
+    resultDOM.find('#resultSelectAll').click(function(){
+      if ($(this).is(':checked')){
+        resultDOM.find('.resultSelector:not([disabled])').prop('checked', true);
+      } else {
+        resultDOM.find('.resultSelector:not([disabled])').prop('checked', false);
+      }
+    });
+
+    this.resultTable.hide().empty().append(resultDOM).slideDown('slow');
+
+    this.resultMenu.find('.pageNumber').text(resultIndex + 1);
+    this.resultMenu.find('.pageLength').text(this.resultsPerPage * resultIndex + results.length);
+
+    if (this.resultsPerPage * (resultIndex + 1) >= this.resultCount) {
+      this.resultMenu.find('.next').addClass('disabled');
+    } else if (resultIndex === 0){
+      this.resultMenu.find('.next').removeClass('disabled');
+    }
+
+    if (resultIndex === 0){
+      this.resultMenu.find('.previous').addClass('disabled');
+    } else if (resultIndex === 1) {
+      this.resultMenu.find('.previous').removeClass('disabled');
+    }
+
+  }
+
+  Atmos.prototype.getResults = function(index){
+
+    if ($('#results').hasClass('hidden')){
+      $('#results').removeClass('hidden').slideDown();
+    }
+
+    if ((this.results.length === this.resultCount) || (this.resultsPerPage * (index + 1) < this.results.length)){
+      //console.log("We already have index", index);
+      this.page = index;
+      this.showResults(index);
+      return;
+    }
+
+    if (this.name === null) {
+      console.error("This shouldn't be reached! We are getting results before a search has occured!");
+      throw new Error("Illegal State");
+    }
+
+    var first = new Name(this.name).appendSegment(this.retrievedSegments++);
+
+    console.log("Requesting data index: (", this.retrievedSegments - 1, ") at ", first.toUri());
+
+    var scope = this;
+
+    var interest = new Interest(first)
+    interest.setInterestLifetimeMilliseconds(5000);
+    interest.setMustBeFresh(true);
+
+    this.face.expressInterest(interest,
+      function(interest, data){ //Response
+
+        if (data.getContent().length === 0){
+          scope.resultMenu.find('.totalResults').text(0);
+          scope.resultMenu.find('.pageNumber').text(0);
+          scope.resultMenu.find('.pageLength').text(0);
+          console.log("Empty response.");
+          return;
+        }
+
+        var content = JSON.parse(data.getContent().toString().replace(/[\n\0]/g,""));
+
+        if (!content.results){
+          scope.resultMenu.find('.totalResults').text(0);
+          scope.resultMenu.find('.pageNumber').text(0);
+          scope.resultMenu.find('.pageLength').text(0);
+          console.log("No results were found!");
+          return;
+        }
+
+        scope.results = scope.results.concat(content.results);
+
+        scope.resultCount = content.resultCount;
+
+        scope.resultMenu.find('.totalResults').text(scope.resultCount);
+
+        scope.page = index;
+
+        scope.getResults(index); //Keep calling this until we have enough data.
+
+      },
+      function(interest){ //Timeout
+        console.error("Failed to retrieve results: timeout", interest);
+        scope.createAlert("Request timed out. \"" + interest.getName().toUri() + "\" See console for details.");
+      }
+    );
+
+  }
+
+  Atmos.prototype.query = function(prefix, parameters, callback, timeout) {
+
+    var queryPrefix = new Name(prefix);
+    queryPrefix.append("query");
+
+    var jsonString = JSON.stringify(parameters);
+    queryPrefix.append(jsonString);
+
+    var queryInterest = new Interest(queryPrefix);
+    queryInterest.setInterestLifetimeMilliseconds(4000);
+    queryInterest.setMustBeFresh(true);
+
+    this.face.expressInterest(queryInterest, callback, timeout);
+
+  }
+
+  /**
+   * This function returns a map of all the categories active filters.
+   * @return {Object<string, string>}
+   */
+  Atmos.prototype.getFilters = function(){
+    var filters = this.filters.children().toArray().reduce(function(prev, current){
+      var data = $(current).text().split(/:/);
+      prev[data[0]] = data[1];
+      return prev;
+    }, {}); //Collect a map<category, filter>.
+    //TODO Make the return value map<category, Array<filter>>
+    return filters;
+  }
+
+  /**
+   * Creates a closable alert for the user.
+   *
+   * @param {string} message
+   * @param {string} type - Override the alert type.
+   */
+  Atmos.prototype.createAlert = function(message, type) {
+
+    var alert = $('<div class="alert"><div>');
+    alert.addClass(type?type:'alert-info');
+    alert.text(message);
+    alert.append(closeButton);
+
+    this.alerts.append(alert);
+  }
+
+  /**
+   * Requests all of the names represented by the buttons in the elements list.
+   *
+   * @param elements {Array<jQuery>} A list of the table row elements
+   */
+  Atmos.prototype.request = function(){
+
+    //Pseudo globals.
+    var keyChain;
+    var certificateName;
+    var keyAdded = false;
+
+    return function(elements){
+
+      var names = [];
+      var destination = $('#requestDest .active').text();
+      $(elements).find('>*:nth-child(2)').each(function(){
+        var name = $(this).text();
+        names.push(name);
+      });//.append('<span class="badge">Requested!</span>')
+      //Disabling the checkbox doesn't make sense anymore with the ability to request to multiple destinations.
+      //$(elements).find('.resultSelector').prop('disabled', true).prop('checked', false);
+
+      var scope = this;
+      this.requestForm.on('submit', function(e){ //This will be registered for the next submit from the form.
+        e.preventDefault();
+
+        //Form checking
+        var dest = scope.requestForm.find('#requestDest .active');
+        if (dest.length !== 1){
+          $('#requestForm').append($('<div class="alert alert-warning">A destination is required!' + closeButton + '<div>'));
+          return;
+        }
+
+        $('#request').modal('hide')//Initial params are ok. We can close the form.
+        .remove('.alert') //Remove any alerts
+        .find('.active').removeClass('active'); //Disable the active destination
+
+        $(this).off(e); //Don't fire this again, the request must be regenerated
+
+        //Key setup
+        if (!keyAdded){
+          if (!scope.config.retrieval.demoKey || !scope.config.retrieval.demoKey.pub || !scope.config.retrieval.demoKey.priv){
+            scope.createAlert("This host was not configured to handle retrieval! See console for details.", 'alert-danger');
+            console.error("Missing/invalid key! This must be configured in the config on the server.", scope.config.demoKey);
+            return;
+          }
+
+          //FIXME base64 may or may not exist in other browsers. Need a new polyfill.
+          var pub = new Buffer(base64.toByteArray(scope.config.retrieval.demoKey.pub)); //MUST be a Buffer (Buffer != Uint8Array)
+          var priv = new Buffer(base64.toByteArray(scope.config.retrieval.demoKey.priv));
+
+          var identityStorage = new MemoryIdentityStorage();
+          var privateKeyStorage = new MemoryPrivateKeyStorage();
+          keyChain = new KeyChain(new IdentityManager(identityStorage, privateKeyStorage),
+                        new SelfVerifyPolicyManager(identityStorage));
+
+          var keyName = new Name("/retrieve/DSK-123");
+          certificateName = keyName.getSubName(0, keyName.size() - 1)
+            .append("KEY").append(keyName.get(-1))
+            .append("ID-CERT").append("0");
+
+          identityStorage.addKey(keyName, KeyType.RSA, new Blob(pub, false));
+          privateKeyStorage.setKeyPairForKeyName(keyName, KeyType.RSA, pub, priv);
+
+          scope.face.setCommandSigningInfo(keyChain, certificateName);
+
+          keyAdded = true;
+
+        }
+
+        //Retrieval
+        var retrievePrefix = new Name("/catalog/ui/" + guid());
+
+        //Due to a lack of success callback in the register prefix function, we have to pretend we
+        //know it succeeded with an arbitrary timeout.
+        var sendTimer = setTimeout(function(){
+          var prefix = new Name(dest.text());
+          prefix.append(retrievePrefix);
+          var interest = new Interest(prefix);
+          interest.setInterestLifetimeMilliseconds(3000);
+          scope.face.expressInterest(interest,
+            function(interest, data){ //Success
+              console.log("Request for", prefix.toUri(), "succeeded.", interest, data);
+            }, function(interest){ //Failure
+              console.error("Failure to request", prefix.toUri(), interest);
+              scope.createAlert("Failed to request " + prefix.toUri() + ". This means that the retrieve failed! See console for more details.");
+            }
+          );
+        }, 10000); //Wait 10 seconds
+
+        scope.face.registerPrefix(retrievePrefix,
+          function(prefix, interest, face, interestFilterId, filter){ //On Interest
+            //This function will exist until the page exits but will likely only be used once.
+
+            var data = new Data(interest.getName());
+            var content = JSON.stringify(names);
+            data.setContent(content);
+            keyChain.sign(data, certificateName);
+
+            try {
+              face.putData(data);
+              console.log("Responded for", interest.getName().toUri(), data);
+              scope.createAlert("Data retrieval has initiated.", "alert-success");
+            } catch (e) {
+              console.error("Failed to respond to", interest.getName().toUri(), data);
+              scope.createAlert("Data retrieval failed.");
+            }
+
+          }, function(prefix){ //On fail
+            clearTimeout(sendTimer); //Cancel the earlier request timer
+            scope.createAlert("Failed to register the retrieval URI! See console for details.", "alert-danger");
+            console.error("Failed to register URI:", prefix.toUri(), prefix);
+
+          }
+        );
+
+      });
+      $('#request').modal(); //This forces the form to be the only option.
+
+    }
+  }();
+
+  Atmos.prototype.filterSetup = function() {
+    //Filter setup
+
+    var prefix = new Name(this.catalog).append("filters-initialization");
+
+    var scope = this;
+
+    this.getAll(prefix, function(data) { //Success
+      var raw = JSON.parse(data.replace(/[\n\0]/g, '')); //Remove null byte and parse
+
+      console.log("Filter categories:", raw);
+
+      $.each(raw, function(index, object){ //Unpack list of objects
+        $.each(object, function(category, searchOptions) { //Unpack category from object (We don't know what it is called)
+          //Create the category
+          var e = $('<li><a href="#">' + category.replace(/_/g, " ") + '</a><ul class="subnav nav nav-pills nav-stacked"></ul></li>');
+
+          var sub = e.find('ul.subnav');
+          $.each(searchOptions, function(index, name){
+            //Create the filter list inside the category
+            var item = $('<li><a href="#">' + name + '</a></li>');
+            sub.append(item);
+            item.click(function(){ //Click on the side menu filters
+              if (item.hasClass('active')){ //Does the filter already exist?
+                item.removeClass('active');
+                scope.filters.find(':contains(' + category + ':' + name + ')').remove();
+              } else { //Add a filter
+                item.addClass('active');
+                var filter = $('<span class="label label-default"></span>');
+                filter.text(category + ':' + name);
+
+                scope.filters.append(filter);
+
+                filter.click(function(){ //Click on a filter
+                  filter.remove();
+                  item.removeClass('active');
+                });
+              }
+
+            });
+          });
+
+          //Toggle the menus. (Only respond when the immediate tab is clicked.)
+          e.find('> a').click(function(){
+            scope.categories.find('.subnav').slideUp();
+            var t = $(this).siblings('.subnav');
+            if ( !t.is(':visible') ){ //If the sub menu is not visible
+              t.slideDown(function(){
+                t.triggerHandler('focus');
+              }); //Make it visible and look at it.
+            }
+          });
+
+          scope.categories.append(e);
+
+        });
+      });
+
+    }, function(interest){ //Timeout
+      scope.createAlert("Failed to initialize the filters!", "alert-danger");
+      console.error("Failed to initialize filters!", interest);
+      ga('send', 'event', 'error', 'filters');
+    });
+
+  }
+
+  /**
+   * This function retrieves all segments in order until it knows it has reached the last one.
+   * It then returns the final joined result.
+   */
+  Atmos.prototype.getAll = function(prefix, callback, timeout){
+
+    var scope = this;
+    var d = [];
+
+    var request = function(segment){
+
+      var name = new Name(prefix);
+      name.appendSegment(segment);
+
+      var interest = new Interest(name);
+      interest.setInterestLifetimeMilliseconds(1000);
+      interest.setMustBeFresh(true); //Is this needed?
+
+      scope.face.expressInterest(interest, handleData, timeout);
+
+    }
+
+
+    var handleData = function(interest, data){
+
+      d.push(data.getContent().toString());
+
+      if (interest.getName().get(-1).toSegment() == data.getMetaInfo().getFinalBlockId().toSegment()){
+        callback(d.join(""));
+      } else {
+        request(interest.getName().toSegment()++);
+      }
+
+    }
+
+    request(0);
+
+  }
+
+  Atmos.prototype.setupRequestForm = function(){
+    this.requestForm.find('#requestCancel').click(function(){
+      $('#request').unbind('submit') //Removes all event handlers.
+      .modal('hide'); //Hides the form.
+    });
+
+    var dests = $(this.config['retrieval']['destinations'].reduce(function(prev, current){
+      prev.push('<li><a href="#">');
+      prev.push(current);
+      prev.push("</a></li>");
+      return prev;
+    }, []).join(""));
+
+    this.requestForm.find('#requestDest').append(dests)
+    .on('click', 'a', function(e){
+      $('#requestDest .active').removeClass('active');
+      $(this).parent().addClass('active');
+    });
+
+    //This code will remain unused until users must use their own keys instead of the demo key.
+//    var scope = this;
+
+//    var warning = '<div class="alert alert-warning">' + closeButton + '<div>';
+
+//    var handleFile = function(e){
+//      var t = $(this);
+//      if (e.target.files.length > 1){
+//        var el = $(warning);
+//        t.append(el.append("We are looking for a single file, we will try the first only!"));
+//      } else if (e.target.files.length === 0) {
+//        var el = $(warning.replace("alert-warning", "alert-danger"));
+//        t.append(el.append("No file was supplied!"));
+//        return;
+//      }
+
+//      var reader = new FileReader();
+//      reader.onload = function(e){
+//        var key;
+//        try {
+//          key = JSON.parse(e.target.result);
+//        } catch (e) {
+//          console.error("Could not parse the key! (", key, ")");
+//          var el = $(warning.replace("alert-warning", "alert-danger"));
+//          t.append(el.append("Failed to parse the key file, is it a valid json key?"));
+//        }
+
+//        if (!key.DEFAULT_RSA_PUBLIC_KEY_DER || !key.DEFAULT_RSA_PRIVATE_KEY_DER) {
+//          console.warn("Invalid key", key);
+//          var el = $(warning.replace("alert-warning", "alert-danger"));
+//          t.append(el.append("Failed to parse the key file, it is missing required attributes."));
+//        }
+
+
+//      };
+
+//    }
+
+//    this.requestForm.find('#requestDrop').on('dragover', function(e){
+//      e.dataTransfer.dropEffect = 'copy';
+//    }).on('drop', handleFile);
+
+//    this.requestForm.find('input[type=file]').change(handleFile);
+
+  }
+
+  return Atmos;
+
+})();
