diff --git a/Gruntfile.js b/Gruntfile.js
index 61efa3517..7dd004dc4 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -7,7 +7,8 @@ module.exports = function(grunt) {
                     'lib/static/main.js': ['lib/GUI/js/main.js']
                 },
                 options: {
-                    debug:     true
+                    debug: true,
+                    transform: ['browserify-handlebars']
                 }
             }
         },
@@ -22,7 +23,7 @@ module.exports = function(grunt) {
             }
         },
         watch: {
-            files: [ "lib/GUI/js/**/*", "lib/GUI/css/**/*"],
+            files: [ "lib/GUI/**/*"],
             tasks: [ 'default' ]
         }
     });
diff --git a/lib/GUI/css/main.less b/lib/GUI/css/main.less
index a39a29544..9691fc688 100644
--- a/lib/GUI/css/main.less
+++ b/lib/GUI/css/main.less
@@ -1,3 +1,28 @@
-body {
-	
+@import "../../../node_modules/helpers.less/helpers.less";
+
+/*** Main Styles ***/
+h1 {
+	text-align: center;
+
+	a, a:visited {
+		color: black;
+		text-decoration: none;
+	}
+
+	a:hover {
+		text-decoration: underline;
+	}
+}
+
+/*** Setup ***/
+
+
+/*** Package Entries ***/
+.entry {
+	background: #EEE;
+}
+
+/*** Search Results ***/
+.state-search #standard-content {
+	display: none;
 }
\ No newline at end of file
diff --git a/lib/GUI/entry.handlebars b/lib/GUI/entry.handlebars
new file mode 100644
index 000000000..9ccb307dd
--- /dev/null
+++ b/lib/GUI/entry.handlebars
@@ -0,0 +1,5 @@
+<article class='entry'>
+	<h3>{{ name }} <small>v{{ version }}</small></h3>
+	<div>User: {{ _npmUser.name }}</div>
+	<p>{{ description }}</p>
+</article>
\ No newline at end of file
diff --git a/lib/GUI/index.handlebars b/lib/GUI/index.handlebars
index 0b1f058c6..1c1df7fd4 100644
--- a/lib/GUI/index.handlebars
+++ b/lib/GUI/index.handlebars
@@ -7,28 +7,33 @@
 		<link rel="stylesheet" type="text/css" href="/-/static/main.css">
 	</head>
 	<body>
-		<h1><a href='/'>{{ name }}</a></h1>
+		<div id='content'>
+			<h1><a href='/'>{{ name }}</a></h1>
 
-		<form>
-			<input type='search' name='q' />
-			<button>Search</button>
-		</form>
+			<form id='search-form'>
+				<input type='search' name='q' />
+				<button>Search</button>
+			</form>
 
-		<h2>Setup:</h2>
-		<code>
-			npm set registry {{ baseUrl }}<br>
-			npm adduser --registry {{ baseUrl }}
-		</code>
+			<div id='search-results'></div>
 
-		<h2>Packages:</h2>
-		{{#each packages}}
-			<article>
-				<h3>{{ name }} <small>v{{ version }}</small></h3>
-				<div>User: {{ _npmUser.name }}</div>
-				<p>{{ description }}</p>
-			</article>
-		{{/each}}
+			<div id='standard-content'>
+				<article id='setup'>
+					<h2>Setup:</h2>
+					<code>
+						npm set registry {{ baseUrl }}<br>
+						npm adduser --registry {{ baseUrl }}
+					</code>
+				</article>
 
-		<script type='text/javascript' src='/-/static/main.js'></script>
+				<h2>Available Packages:</h2>
+				{{#each packages}}
+					{{> entry}}
+				{{/each}}
+
+				<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
+				<script type='text/javascript' src='/-/static/main.js'></script>
+			</div>
+		</div>
 	</body>
 </html>
diff --git a/lib/GUI/js/main.js b/lib/GUI/js/main.js
index e69de29bb..632ae0a12 100644
--- a/lib/GUI/js/main.js
+++ b/lib/GUI/js/main.js
@@ -0,0 +1,43 @@
+var $ = require('unopinionate').selector,
+	template = require('../entry.handlebars');
+
+$(function() {
+	var $form = $('#search-form'),
+		$input = $form.find('[type="search"]'),
+		$searchResults = $("#search-results"),
+		$body = $('body'),
+		request;
+
+	$form.bind('submit keyup', function(e) {
+		e.preventDefault();
+
+		var q = $input.val();
+
+		$body.addClass('state-search');
+
+		if(q) {
+			if(request) {
+				request.abort();
+			}
+
+			request = $.getJSON('/-/search/' + q, function(results) {
+				if(results.length) {
+					var html = '';
+
+					$.each(results, function(i, package) {
+						html += template(package);
+					});
+
+					$searchResults.html(html);
+				}
+				else {
+					$searchResults.html("<div class='search-no-results'>No Results</div>");
+				}
+			});
+		}
+		else {
+			$searchResults.html('');
+			$body.removeClass('state-search');
+		}
+	});
+});
diff --git a/lib/index.js b/lib/index.js
index f392a753b..7bf9abda5 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -14,6 +14,7 @@ var express = require('express')
   , Handlebars = require('handlebars')
   , fs = require('fs')
   , localList = require('./local-list')
+  , Search = require('./search')
   , _ = require('underscore');
 
 function match(regexp) {
@@ -29,6 +30,7 @@ function match(regexp) {
 module.exports = function(config_hash) {
 	var config = new Config(config_hash)
 	  , storage = new Storage(config)
+	  , search = new Search(storage);
 
 	var can = function(action) {
 		return function(req, res, next) {
@@ -122,8 +124,10 @@ module.exports = function(config_hash) {
 			console.log(d)
 		})
 	})*/
-
+	
+	Handlebars.registerPartial('entry', fs.readFileSync(require.resolve('./GUI/entry.handlebars'), 'utf8'));
 	var template = Handlebars.compile(fs.readFileSync(require.resolve('./GUI/index.handlebars'), 'utf8'));
+
 	app.get('/', can('access'), function(req, res, next) {
 		res.setHeader('Content-Type', 'text/html');
 
@@ -236,6 +240,32 @@ module.exports = function(config_hash) {
 		});
 	});
 
+	// Search
+	app.get('/-/search/:query', function(req, res, next) {
+		var results = search.query(req.params.query),
+			packages = [];
+
+		var getData = function(i) {
+			storage.get_package(results[i].ref, function(err, package) {
+				packages.push(package.versions[package['dist-tags'].latest]);
+
+				if(i >= results.length - 1) {
+					res.send(packages);
+				}
+				else {
+					getData(i + 1);
+				}
+			});
+		};
+
+		if(results.length) {
+			getData(0);
+		}
+		else {
+			res.send([]);
+		}
+	});
+
 	// tagging a package
 	app.put('/:package/:tag', can('publish'), media('application/json'), function(req, res, next) {
 		if (typeof(req.body) !== 'string') return next('route')
diff --git a/lib/search.js b/lib/search.js
index 5c59b4d87..840fc8d3b 100644
--- a/lib/search.js
+++ b/lib/search.js
@@ -1,35 +1,40 @@
 var lunr = require('lunr')
   , localList = require('./local-list');
 
-var Search = function() {
+var Search = function(storage) {
+	this.storage = storage;
+
 	this.index = lunr(function () {
 		this.field('name', {boost: 10});
 		this.field('description');
 		this.field('author');
 	});
 
-	this.id = 0;
-
-	var packages = storage.get_local()
-	  , i = packages.length;
-
-	while(i--) {
-		this.index(packages[i]);
-	}
+	this.reindex();
 };
 
 Search.prototype = {
 	query: function(q) {
-		return index.search(q);
+		return this.index.search(q);
 	},
-	index: function(package) {
+	add: function(package) {
 		this.index.add({
-			id:           ++this.id,
-			title:        package.name,
+			id:           package.name,
+			name:         package.name,
 			description:  package.description,
 			author:       package._npmUser.name
 		});
+	},
+	reindex: function() {
+		var self = this;
+		this.storage.get_local(function(err, packages) {
+			var i = packages.length;
+
+			while(i--) {
+				self.add(packages[i]);
+			}
+		});
 	}
 };
 
-module.exports = new Search();
\ No newline at end of file
+module.exports = Search;
\ No newline at end of file
diff --git a/lib/static/main.css b/lib/static/main.css
index e69de29bb..a70e4dcd9 100644
--- a/lib/static/main.css
+++ b/lib/static/main.css
@@ -0,0 +1,22 @@
+/*** Main Styles ***/
+h1 {
+  text-align: center;
+}
+h1 a,
+h1 a:visited {
+  color: black;
+  text-decoration: none;
+}
+h1 a:hover {
+  text-decoration: underline;
+}
+/*** Setup ***/
+/*** Package Entries ***/
+.entry {
+  background: #EEE;
+}
+/*** Search Results ***/
+.state-search #standard-content {
+  display: none;
+}
+/*# sourceMappingURL=data:application/json,%7B%22version%22%3A3%2C%22sources%22%3A%5B%22lib%2FGUI%2Fcss%2Fmain.less%22%5D%2C%22names%22%3A%5B%5D%2C%22mappings%22%3A%22%3BAAGA%3BEACC%2CkBAAA%3B%3BAADD%2CEAGC%3BAAHD%2CEAGI%2CEAAC%3BEACH%2CYAAA%3BEACA%2CqBAAA%3B%3BAALF%2CEAQC%2CEAAC%3BEACA%2C0BAAA%3B%3B%3B%3BAAQF%3BEACC%2CgBAAA%3B%3B%3BAAID%2CaAAc%3BEACb%2CaAAA%22%7D */
\ No newline at end of file
diff --git a/lib/static/main.js b/lib/static/main.js
index 8a7bd83c5..ea6e5f435 100644
--- a/lib/static/main.js
+++ b/lib/static/main.js
@@ -1,3 +1,572 @@
 (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+var templater = require("handlebars/runtime").default.template;module.exports = templater(function (Handlebars,depth0,helpers,partials,data) {
+  this.compilerInfo = [4,'>= 1.0.0'];
+helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
+  var buffer = "", stack1, helper, functionType="function", escapeExpression=this.escapeExpression;
 
-},{}]},{},[1])
\ No newline at end of file
+
+  buffer += "<article class='entry'>\n	<h3>";
+  if (helper = helpers.name) { stack1 = helper.call(depth0, {hash:{},data:data}); }
+  else { helper = (depth0 && depth0.name); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
+  buffer += escapeExpression(stack1)
+    + " <small>v";
+  if (helper = helpers.version) { stack1 = helper.call(depth0, {hash:{},data:data}); }
+  else { helper = (depth0 && depth0.version); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
+  buffer += escapeExpression(stack1)
+    + "</small></h3>\n	<div>User: "
+    + escapeExpression(((stack1 = ((stack1 = (depth0 && depth0._npmUser)),stack1 == null || stack1 === false ? stack1 : stack1.name)),typeof stack1 === functionType ? stack1.apply(depth0) : stack1))
+    + "</div>\n	<p>";
+  if (helper = helpers.description) { stack1 = helper.call(depth0, {hash:{},data:data}); }
+  else { helper = (depth0 && depth0.description); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
+  buffer += escapeExpression(stack1)
+    + "</p>\n</article>";
+  return buffer;
+  });
+},{"handlebars/runtime":9}],2:[function(require,module,exports){
+var $ = require('unopinionate').selector,
+	template = require('../entry.handlebars');
+
+$(function() {
+	var $form = $('#search-form'),
+		$input = $form.find('[type="search"]'),
+		$searchResults = $("#search-results"),
+		$body = $('body'),
+		request;
+
+	$form.bind('submit keyup', function(e) {
+		e.preventDefault();
+
+		var q = $input.val();
+
+		$body.addClass('state-search');
+
+		if(q) {
+			if(request) {
+				request.abort();
+			}
+
+			request = $.getJSON('/-/search/' + q, function(results) {
+				if(results.length) {
+					var html = '';
+
+					$.each(results, function(i, package) {
+						html += template(package);
+					});
+
+					$searchResults.html(html);
+				}
+				else {
+					$searchResults.html("<div class='search-no-results'>No Results</div>");
+				}
+			});
+		}
+		else {
+			$searchResults.html('');
+			$body.removeClass('state-search');
+		}
+	});
+});
+
+},{"../entry.handlebars":1,"unopinionate":10}],3:[function(require,module,exports){
+"use strict";
+/*globals Handlebars: true */
+var base = require("./handlebars/base");
+
+// Each of these augment the Handlebars object. No need to setup here.
+// (This is done to easily share code between commonjs and browse envs)
+var SafeString = require("./handlebars/safe-string")["default"];
+var Exception = require("./handlebars/exception")["default"];
+var Utils = require("./handlebars/utils");
+var runtime = require("./handlebars/runtime");
+
+// For compatibility and usage outside of module systems, make the Handlebars object a namespace
+var create = function() {
+  var hb = new base.HandlebarsEnvironment();
+
+  Utils.extend(hb, base);
+  hb.SafeString = SafeString;
+  hb.Exception = Exception;
+  hb.Utils = Utils;
+
+  hb.VM = runtime;
+  hb.template = function(spec) {
+    return runtime.template(spec, hb);
+  };
+
+  return hb;
+};
+
+var Handlebars = create();
+Handlebars.create = create;
+
+exports["default"] = Handlebars;
+},{"./handlebars/base":4,"./handlebars/exception":5,"./handlebars/runtime":6,"./handlebars/safe-string":7,"./handlebars/utils":8}],4:[function(require,module,exports){
+"use strict";
+var Utils = require("./utils");
+var Exception = require("./exception")["default"];
+
+var VERSION = "1.3.0";
+exports.VERSION = VERSION;var COMPILER_REVISION = 4;
+exports.COMPILER_REVISION = COMPILER_REVISION;
+var REVISION_CHANGES = {
+  1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
+  2: '== 1.0.0-rc.3',
+  3: '== 1.0.0-rc.4',
+  4: '>= 1.0.0'
+};
+exports.REVISION_CHANGES = REVISION_CHANGES;
+var isArray = Utils.isArray,
+    isFunction = Utils.isFunction,
+    toString = Utils.toString,
+    objectType = '[object Object]';
+
+function HandlebarsEnvironment(helpers, partials) {
+  this.helpers = helpers || {};
+  this.partials = partials || {};
+
+  registerDefaultHelpers(this);
+}
+
+exports.HandlebarsEnvironment = HandlebarsEnvironment;HandlebarsEnvironment.prototype = {
+  constructor: HandlebarsEnvironment,
+
+  logger: logger,
+  log: log,
+
+  registerHelper: function(name, fn, inverse) {
+    if (toString.call(name) === objectType) {
+      if (inverse || fn) { throw new Exception('Arg not supported with multiple helpers'); }
+      Utils.extend(this.helpers, name);
+    } else {
+      if (inverse) { fn.not = inverse; }
+      this.helpers[name] = fn;
+    }
+  },
+
+  registerPartial: function(name, str) {
+    if (toString.call(name) === objectType) {
+      Utils.extend(this.partials,  name);
+    } else {
+      this.partials[name] = str;
+    }
+  }
+};
+
+function registerDefaultHelpers(instance) {
+  instance.registerHelper('helperMissing', function(arg) {
+    if(arguments.length === 2) {
+      return undefined;
+    } else {
+      throw new Exception("Missing helper: '" + arg + "'");
+    }
+  });
+
+  instance.registerHelper('blockHelperMissing', function(context, options) {
+    var inverse = options.inverse || function() {}, fn = options.fn;
+
+    if (isFunction(context)) { context = context.call(this); }
+
+    if(context === true) {
+      return fn(this);
+    } else if(context === false || context == null) {
+      return inverse(this);
+    } else if (isArray(context)) {
+      if(context.length > 0) {
+        return instance.helpers.each(context, options);
+      } else {
+        return inverse(this);
+      }
+    } else {
+      return fn(context);
+    }
+  });
+
+  instance.registerHelper('each', function(context, options) {
+    var fn = options.fn, inverse = options.inverse;
+    var i = 0, ret = "", data;
+
+    if (isFunction(context)) { context = context.call(this); }
+
+    if (options.data) {
+      data = createFrame(options.data);
+    }
+
+    if(context && typeof context === 'object') {
+      if (isArray(context)) {
+        for(var j = context.length; i<j; i++) {
+          if (data) {
+            data.index = i;
+            data.first = (i === 0);
+            data.last  = (i === (context.length-1));
+          }
+          ret = ret + fn(context[i], { data: data });
+        }
+      } else {
+        for(var key in context) {
+          if(context.hasOwnProperty(key)) {
+            if(data) { 
+              data.key = key; 
+              data.index = i;
+              data.first = (i === 0);
+            }
+            ret = ret + fn(context[key], {data: data});
+            i++;
+          }
+        }
+      }
+    }
+
+    if(i === 0){
+      ret = inverse(this);
+    }
+
+    return ret;
+  });
+
+  instance.registerHelper('if', function(conditional, options) {
+    if (isFunction(conditional)) { conditional = conditional.call(this); }
+
+    // Default behavior is to render the positive path if the value is truthy and not empty.
+    // The `includeZero` option may be set to treat the condtional as purely not empty based on the
+    // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
+    if ((!options.hash.includeZero && !conditional) || Utils.isEmpty(conditional)) {
+      return options.inverse(this);
+    } else {
+      return options.fn(this);
+    }
+  });
+
+  instance.registerHelper('unless', function(conditional, options) {
+    return instance.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn, hash: options.hash});
+  });
+
+  instance.registerHelper('with', function(context, options) {
+    if (isFunction(context)) { context = context.call(this); }
+
+    if (!Utils.isEmpty(context)) return options.fn(context);
+  });
+
+  instance.registerHelper('log', function(context, options) {
+    var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
+    instance.log(level, context);
+  });
+}
+
+var logger = {
+  methodMap: { 0: 'debug', 1: 'info', 2: 'warn', 3: 'error' },
+
+  // State enum
+  DEBUG: 0,
+  INFO: 1,
+  WARN: 2,
+  ERROR: 3,
+  level: 3,
+
+  // can be overridden in the host environment
+  log: function(level, obj) {
+    if (logger.level <= level) {
+      var method = logger.methodMap[level];
+      if (typeof console !== 'undefined' && console[method]) {
+        console[method].call(console, obj);
+      }
+    }
+  }
+};
+exports.logger = logger;
+function log(level, obj) { logger.log(level, obj); }
+
+exports.log = log;var createFrame = function(object) {
+  var obj = {};
+  Utils.extend(obj, object);
+  return obj;
+};
+exports.createFrame = createFrame;
+},{"./exception":5,"./utils":8}],5:[function(require,module,exports){
+"use strict";
+
+var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
+
+function Exception(message, node) {
+  var line;
+  if (node && node.firstLine) {
+    line = node.firstLine;
+
+    message += ' - ' + line + ':' + node.firstColumn;
+  }
+
+  var tmp = Error.prototype.constructor.call(this, message);
+
+  // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
+  for (var idx = 0; idx < errorProps.length; idx++) {
+    this[errorProps[idx]] = tmp[errorProps[idx]];
+  }
+
+  if (line) {
+    this.lineNumber = line;
+    this.column = node.firstColumn;
+  }
+}
+
+Exception.prototype = new Error();
+
+exports["default"] = Exception;
+},{}],6:[function(require,module,exports){
+"use strict";
+var Utils = require("./utils");
+var Exception = require("./exception")["default"];
+var COMPILER_REVISION = require("./base").COMPILER_REVISION;
+var REVISION_CHANGES = require("./base").REVISION_CHANGES;
+
+function checkRevision(compilerInfo) {
+  var compilerRevision = compilerInfo && compilerInfo[0] || 1,
+      currentRevision = COMPILER_REVISION;
+
+  if (compilerRevision !== currentRevision) {
+    if (compilerRevision < currentRevision) {
+      var runtimeVersions = REVISION_CHANGES[currentRevision],
+          compilerVersions = REVISION_CHANGES[compilerRevision];
+      throw new Exception("Template was precompiled with an older version of Handlebars than the current runtime. "+
+            "Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+").");
+    } else {
+      // Use the embedded version info since the runtime doesn't know about this revision yet
+      throw new Exception("Template was precompiled with a newer version of Handlebars than the current runtime. "+
+            "Please update your runtime to a newer version ("+compilerInfo[1]+").");
+    }
+  }
+}
+
+exports.checkRevision = checkRevision;// TODO: Remove this line and break up compilePartial
+
+function template(templateSpec, env) {
+  if (!env) {
+    throw new Exception("No environment passed to template");
+  }
+
+  // Note: Using env.VM references rather than local var references throughout this section to allow
+  // for external users to override these as psuedo-supported APIs.
+  var invokePartialWrapper = function(partial, name, context, helpers, partials, data) {
+    var result = env.VM.invokePartial.apply(this, arguments);
+    if (result != null) { return result; }
+
+    if (env.compile) {
+      var options = { helpers: helpers, partials: partials, data: data };
+      partials[name] = env.compile(partial, { data: data !== undefined }, env);
+      return partials[name](context, options);
+    } else {
+      throw new Exception("The partial " + name + " could not be compiled when running in runtime-only mode");
+    }
+  };
+
+  // Just add water
+  var container = {
+    escapeExpression: Utils.escapeExpression,
+    invokePartial: invokePartialWrapper,
+    programs: [],
+    program: function(i, fn, data) {
+      var programWrapper = this.programs[i];
+      if(data) {
+        programWrapper = program(i, fn, data);
+      } else if (!programWrapper) {
+        programWrapper = this.programs[i] = program(i, fn);
+      }
+      return programWrapper;
+    },
+    merge: function(param, common) {
+      var ret = param || common;
+
+      if (param && common && (param !== common)) {
+        ret = {};
+        Utils.extend(ret, common);
+        Utils.extend(ret, param);
+      }
+      return ret;
+    },
+    programWithDepth: env.VM.programWithDepth,
+    noop: env.VM.noop,
+    compilerInfo: null
+  };
+
+  return function(context, options) {
+    options = options || {};
+    var namespace = options.partial ? options : env,
+        helpers,
+        partials;
+
+    if (!options.partial) {
+      helpers = options.helpers;
+      partials = options.partials;
+    }
+    var result = templateSpec.call(
+          container,
+          namespace, context,
+          helpers,
+          partials,
+          options.data);
+
+    if (!options.partial) {
+      env.VM.checkRevision(container.compilerInfo);
+    }
+
+    return result;
+  };
+}
+
+exports.template = template;function programWithDepth(i, fn, data /*, $depth */) {
+  var args = Array.prototype.slice.call(arguments, 3);
+
+  var prog = function(context, options) {
+    options = options || {};
+
+    return fn.apply(this, [context, options.data || data].concat(args));
+  };
+  prog.program = i;
+  prog.depth = args.length;
+  return prog;
+}
+
+exports.programWithDepth = programWithDepth;function program(i, fn, data) {
+  var prog = function(context, options) {
+    options = options || {};
+
+    return fn(context, options.data || data);
+  };
+  prog.program = i;
+  prog.depth = 0;
+  return prog;
+}
+
+exports.program = program;function invokePartial(partial, name, context, helpers, partials, data) {
+  var options = { partial: true, helpers: helpers, partials: partials, data: data };
+
+  if(partial === undefined) {
+    throw new Exception("The partial " + name + " could not be found");
+  } else if(partial instanceof Function) {
+    return partial(context, options);
+  }
+}
+
+exports.invokePartial = invokePartial;function noop() { return ""; }
+
+exports.noop = noop;
+},{"./base":4,"./exception":5,"./utils":8}],7:[function(require,module,exports){
+"use strict";
+// Build out our basic SafeString type
+function SafeString(string) {
+  this.string = string;
+}
+
+SafeString.prototype.toString = function() {
+  return "" + this.string;
+};
+
+exports["default"] = SafeString;
+},{}],8:[function(require,module,exports){
+"use strict";
+/*jshint -W004 */
+var SafeString = require("./safe-string")["default"];
+
+var escape = {
+  "&": "&amp;",
+  "<": "&lt;",
+  ">": "&gt;",
+  '"': "&quot;",
+  "'": "&#x27;",
+  "`": "&#x60;"
+};
+
+var badChars = /[&<>"'`]/g;
+var possible = /[&<>"'`]/;
+
+function escapeChar(chr) {
+  return escape[chr] || "&amp;";
+}
+
+function extend(obj, value) {
+  for(var key in value) {
+    if(Object.prototype.hasOwnProperty.call(value, key)) {
+      obj[key] = value[key];
+    }
+  }
+}
+
+exports.extend = extend;var toString = Object.prototype.toString;
+exports.toString = toString;
+// Sourced from lodash
+// https://github.com/bestiejs/lodash/blob/master/LICENSE.txt
+var isFunction = function(value) {
+  return typeof value === 'function';
+};
+// fallback for older versions of Chrome and Safari
+if (isFunction(/x/)) {
+  isFunction = function(value) {
+    return typeof value === 'function' && toString.call(value) === '[object Function]';
+  };
+}
+var isFunction;
+exports.isFunction = isFunction;
+var isArray = Array.isArray || function(value) {
+  return (value && typeof value === 'object') ? toString.call(value) === '[object Array]' : false;
+};
+exports.isArray = isArray;
+
+function escapeExpression(string) {
+  // don't escape SafeStrings, since they're already safe
+  if (string instanceof SafeString) {
+    return string.toString();
+  } else if (!string && string !== 0) {
+    return "";
+  }
+
+  // Force a string conversion as this will be done by the append regardless and
+  // the regex test will do this transparently behind the scenes, causing issues if
+  // an object's to string has escaped characters in it.
+  string = "" + string;
+
+  if(!possible.test(string)) { return string; }
+  return string.replace(badChars, escapeChar);
+}
+
+exports.escapeExpression = escapeExpression;function isEmpty(value) {
+  if (!value && value !== 0) {
+    return true;
+  } else if (isArray(value) && value.length === 0) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+exports.isEmpty = isEmpty;
+},{"./safe-string":7}],9:[function(require,module,exports){
+// Create a simple path alias to allow browserify to resolve
+// the runtime on a supported path.
+module.exports = require('./dist/cjs/handlebars.runtime');
+
+},{"./dist/cjs/handlebars.runtime":3}],10:[function(require,module,exports){
+(function (global){
+(function(root) {
+    var unopinionate = {
+        selector: root.jQuery || root.Zepto || root.ender || root.$,
+        template: root.Handlebars || root.Mustache
+    };
+
+    /*** Export ***/
+
+    //AMD
+    if(typeof define === 'function' && define.amd) {
+        define([], function() {
+            return unopinionate;
+        });
+    }
+    //CommonJS
+    else if(typeof module.exports !== 'undefined') {
+        module.exports = unopinionate;
+    }
+    //Global
+    else {
+        root.unopinionate = unopinionate;
+    }
+})(typeof window != 'undefined' ? window : global);
+
+}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{}]},{},[2])
\ No newline at end of file
diff --git a/package.json b/package.json
index 74956581c..049fdde0f 100644
--- a/package.json
+++ b/package.json
@@ -20,25 +20,29 @@
     "commander": ">= 2.1.0",
     "cookies": ">= 0.3.8",
     "express": "3.4.x",
-    "handlebars": "^2.0.0-alpha.2",
+    "handlebars": "1.x.x",
+    "helpers.less": "git://github.com/bpeacock/helpers.less.git",
     "js-yaml": ">= 3.0.1",
     "lunr": "^0.5.2",
     "minimatch": ">= 0.2.14",
     "mkdirp": ">= 0.3.5",
     "request": ">= 2.31.0",
     "semver": ">= 2.2.1",
-    "underscore": "^1.6.0"
+    "underscore": "^1.6.0",
+    "unopinionate": "0.0.4"
   },
   "optionalDependencies": {
     "fs-ext": ">= 0.3.2"
   },
   "devDependencies": {
     "browserify": "^3.46.0",
+    "browserify-handlebars": "~0.2.0",
     "eslint": ">= 0.4.2",
     "grunt": "^0.4.4",
     "grunt-browserify": "^2.0.8",
     "grunt-contrib-less": "^0.11.0",
     "grunt-contrib-watch": "^0.6.1",
+    "handlebars": "^1.3.0",
     "mocha": ">= 1.17.0",
     "rimraf": ">= 2.2.5"
   },