diff --git a/IPython/html/services/kernelspecs/handlers.py b/IPython/html/services/kernelspecs/handlers.py
index 2d1a75f..7239778 100644
--- a/IPython/html/services/kernelspecs/handlers.py
+++ b/IPython/html/services/kernelspecs/handlers.py
@@ -2,11 +2,43 @@
 
 # Copyright (c) IPython Development Team.
 # Distributed under the terms of the Modified BSD License.
+
+import glob
 import json
+import os
+pjoin = os.path.join
+
 from tornado import web
 
 from ...base.handlers import IPythonHandler, json_errors
+from ...utils import url_path_join
 
+def kernelspec_model(handler, name):
+    """Load a KernelSpec by name and return the REST API model"""
+    ksm = handler.kernel_spec_manager
+    spec = ksm.get_kernel_spec(name)
+    d = {'name': name}
+    d['spec'] = spec.to_dict()
+    d['resources'] = resources = {}
+    resource_dir = spec.resource_dir
+    for resource in ['kernel.js', 'kernel.css']:
+        if os.path.exists(pjoin(resource_dir, resource)):
+            resources[resource] = url_path_join(
+                handler.base_url,
+                'kernelspecs',
+                name,
+                resource
+            )
+    for logo_file in glob.glob(pjoin(resource_dir, 'logo-*')):
+        fname = os.path.basename(logo_file)
+        no_ext, _ = os.path.splitext(fname)
+        resources[no_ext] = url_path_join(
+            handler.base_url,
+            'kernelspecs',
+            name,
+            fname
+        )
+    return d
 
 class MainKernelSpecHandler(IPythonHandler):
     SUPPORTED_METHODS = ('GET',)
@@ -21,13 +53,11 @@ class MainKernelSpecHandler(IPythonHandler):
         model['kernelspecs'] = specs = {}
         for kernel_name in ksm.find_kernel_specs():
             try:
-                d = ksm.get_kernel_spec(kernel_name).to_dict()
+                d = kernelspec_model(self, kernel_name)
             except Exception:
                 self.log.error("Failed to load kernel spec: '%s'", kernel_name, exc_info=True)
                 continue
-            d['name'] = kernel_name
             specs[kernel_name] = d
-
         self.set_header("Content-Type", 'application/json')
         self.finish(json.dumps(model))
 
@@ -38,13 +68,12 @@ class KernelSpecHandler(IPythonHandler):
     @web.authenticated
     @json_errors
     def get(self, kernel_name):
-        ksm = self.kernel_spec_manager
         try:
-            kernelspec = ksm.get_kernel_spec(kernel_name)
+            model = kernelspec_model(self, kernel_name)
         except KeyError:
             raise web.HTTPError(404, u'Kernel spec %s not found' % kernel_name)
         self.set_header("Content-Type", 'application/json')
-        self.finish(kernelspec.to_json())
+        self.finish(json.dumps(model))
 
 
 # URL to handler mappings
diff --git a/IPython/html/static/notebook/js/kernelselector.js b/IPython/html/static/notebook/js/kernelselector.js
index a9165b8..3cd13d3 100644
--- a/IPython/html/static/notebook/js/kernelselector.js
+++ b/IPython/html/static/notebook/js/kernelselector.js
@@ -35,8 +35,8 @@ define([
         var change_kernel_submenu = $("#menu-change-kernel-submenu");
         var keys = Object.keys(data.kernelspecs).sort(function (a, b) {
             // sort by display_name
-            var da = data.kernelspecs[a].display_name;
-            var db = data.kernelspecs[b].display_name;
+            var da = data.kernelspecs[a].spec.display_name;
+            var db = data.kernelspecs[b].spec.display_name;
             if (da === db) {
                 return 0;
             } else if (da > db) {
@@ -50,7 +50,7 @@ define([
             var ks_submenu_entry = $("<li>").attr("id", "kernel-submenu-"+ks.name).append($('<a>')
                 .attr('href', '#')
                 .click($.proxy(this.change_kernel, this, ks.name))
-                .text(ks.display_name));
+                .text(ks.spec.display_name));
             change_kernel_submenu.append(ks_submenu_entry);
         }
     };
@@ -59,25 +59,17 @@ define([
         /**
          * TODO, have a methods to set kernel spec directly ?
          **/
-        var that = this;
         if (kernel_name === this.current_selection) {
             return;
         }
         var ks = this.kernelspecs[kernel_name];
-        var new_mode_url = 'kernelspecs/'+ks.name+'/kernel';
-
-        var css_url = this.notebook.base_url+new_mode_url+'.css';
-        $.ajax({
-            type: 'HEAD',
-            url: css_url,
-            success: function(){
-                $('#kernel-css')
-                .attr('href',css_url);
-            },
-            error:function(){
-                console.info("No custom kernel.css at URL:", css_url)
-            }
-        });
+        
+        var css_url = ks.resources['kernel.css'];
+        if (css_url) {
+            $('#kernel-css').attr('href', css_url);
+        } else {
+            $('#kernel-css').attr('href', '');
+        }
 
         try {
             this.notebook.start_session(kernel_name);
@@ -92,26 +84,23 @@ define([
             return;
         }
         this.events.trigger('spec_changed.Kernel', ks);
-
-
-        // load new mode kernel.js if exist
-        require([new_mode_url],
-            // if new mode has custom.js
-            function(new_mode){
-                that.lock_switch();
-                if(new_mode && new_mode.onload){
-                    new_mode.onload();
-                } else {
-                    console.warn("The current kernel defined a kernel.js file but does not contain "+
-                                 "any asynchronous module definition. This is undefined behavior "+
-                                 "which is not recommended");
+        
+        if (ks.resources['kernel.js']) {
+            require([ks.resources['kernel.js']],
+                function (kernel_mod) {
+                    if (kernel_mod && kernel_mod.onload) {
+                        kernel_mod.onload();
+                    } else {
+                        console.warn("Kernel " + ks.name + " has a kernel.js file that does not contain "+
+                                     "any asynchronous module definition. This is undefined behavior "+
+                                     "and not recommended.");
+                    }
+                }, function (err) {
+                    console.warn("Failed to load kernel.js from ", ks.resources['kernel.js'], err);
                 }
-            },
-            function(err){
-                // if new mode does not have custom.js
-                console.info("No custom kernel.css at URL:", new_mode_url)
-            }
-        );
+            );
+        }
+
     };
 
     KernelSelector.prototype.lock_switch = function() {
@@ -123,10 +112,16 @@ define([
 
     KernelSelector.prototype.bind_events = function() {
         var that = this;
+        var logo_img = this.element.find("img.current_kernel_logo");
         this.events.on('spec_changed.Kernel', function(event, data) {
             that.current_selection = data.name;
-            $("#kernel_indicator").find('.kernel_indicator_name').text(data.display_name);
-            that.element.find("img.current_kernel_logo").attr("src", that.notebook.base_url + "kernelspecs/" + data.name + "/logo-64x64.png");
+            $("#kernel_indicator").find('.kernel_indicator_name').text(data.spec.display_name);
+            if (data.resources['logo-64x64']) {
+                logo_img.attr("src", data.resources['logo-64x64']);
+                logo_img.show();
+            } else {
+                logo_img.hide();
+            }
         });
 
         this.events.on('kernel_created.Session', function(event, data) {
@@ -139,7 +134,6 @@ define([
             }
         });
         
-        var logo_img = this.element.find("img.current_kernel_logo");
         logo_img.on("load", function() {
             logo_img.show();
         });
diff --git a/IPython/html/static/notebook/js/notebook.js b/IPython/html/static/notebook/js/notebook.js
index 94be416..8e8fe59 100644
--- a/IPython/html/static/notebook/js/notebook.js
+++ b/IPython/html/static/notebook/js/notebook.js
@@ -247,7 +247,7 @@ define([
         
         this.events.on('spec_changed.Kernel', function(event, data) {
             that.metadata.kernelspec = 
-                {name: data.name, display_name: data.display_name};
+                {name: data.name, display_name: data.spec.display_name};
         });
 
         this.events.on('kernel_ready.Kernel', function(event, data) {