This closes #142
diff --git a/ui-modules/app-inspector/app/components/entity-tree/entity-node.html b/ui-modules/app-inspector/app/components/entity-tree/entity-node.html
index 9159b45..dd5fd6d 100644
--- a/ui-modules/app-inspector/app/components/entity-tree/entity-node.html
+++ b/ui-modules/app-inspector/app/components/entity-tree/entity-node.html
@@ -22,9 +22,12 @@
             <brooklyn-status-icon value="{{entity.serviceState}}" ng-if="entity.serviceState || entity.applicationId"></brooklyn-status-icon>
             <i class="fa fa-2x fa-external-link" ng-if="!entity.serviceState && !entity.applicationId"></i>
             <span>{{entity.name}}</span>
+            <span class="node-icon"><img ng-src="{{ iconUrl }}"/></span>
         </a>
-        <div class="entity-node-toggle" ng-if="entity.children.length > 0 || entity.members.length > 0" ng-click="onToggle($event)" >
+        <div class="entity-node-toggle-wrapper">
+          <div class="entity-node-toggle" ng-if="entity.children.length > 0 || entity.members.length > 0" ng-click="onToggle($event)" >
             <span class="glyphicon" ng-class="isChildrenOpen ? 'glyphicon-chevron-up' : 'glyphicon-chevron-down'"></span>
+          </div>
         </div>
     </div>
     <div class="entity-node-children" ng-show="isChildrenOpen">
diff --git a/ui-modules/app-inspector/app/components/entity-tree/entity-node.less b/ui-modules/app-inspector/app/components/entity-tree/entity-node.less
index 619ee24..6b7e3c4 100644
--- a/ui-modules/app-inspector/app/components/entity-tree/entity-node.less
+++ b/ui-modules/app-inspector/app/components/entity-tree/entity-node.less
@@ -75,10 +75,27 @@
         margin-left: 10px;
       }
     }
+    .entity-node-toggle-wrapper {
+      width: 38px;      
+      flex-grow: 0;
+    }
     .entity-node-toggle {
-      flex-shrink: 1;
+      width: 38px;      
       padding: 12px;
       cursor: row-resize;
     }
   }
+  .node-icon {
+    flex-grow: 0 !important;
+    max-height: 20px; //let it extend above and below span's boundaries
+    overflow: visible !important;
+    margin-top: -8px;
+    margin-left: 0 !important;
+    img {
+      .make-icon(36px);
+    }
+    img[src] {
+      margin-left: 10px;
+    }
+  }
 }
diff --git a/ui-modules/app-inspector/app/components/entity-tree/entity-tree.directive.js b/ui-modules/app-inspector/app/components/entity-tree/entity-tree.directive.js
index b3f7c25..76183e7 100644
--- a/ui-modules/app-inspector/app/components/entity-tree/entity-tree.directive.js
+++ b/ui-modules/app-inspector/app/components/entity-tree/entity-tree.directive.js
@@ -78,11 +78,7 @@
                 vm.applications = response.data;
 
                 function spawnNotification(app, opts) {
-                    let baseType = app.type;
-                    if (baseType === 'org.apache.brooklyn.entity.stock.BasicApplication' && app.children.length === 1) {
-                        baseType = app.children[0].catalogItemId || app.children[0].type;
-                    }
-                    iconService.get(baseType).then((icon)=> {
+                    iconService.get(app).then((icon)=> {
                         let options = Object.assign({
                             icon: app.iconUrl || icon,
                         }, opts);
@@ -110,7 +106,7 @@
             applicationId: '<',
         },
         link: link,
-        controller: ['$scope', '$state', '$stateParams', controller]
+        controller: ['$scope', '$state', '$stateParams', 'iconService', controller]
     };
 
     function link($scope) {
@@ -130,9 +126,10 @@
         });
     }
 
-    function controller ($scope, $state, $stateParams) {
+    function controller ($scope, $state, $stateParams, iconService) {
         $scope.isOpen = true;
-
+        iconService.get($scope.entity, true).then(value => $scope.iconUrl = value);
+        
         if ($stateParams.entityId === $scope.entity.id) {
             $scope.$emit('notifyEntity', {
                 message: 'expandChildren',
diff --git a/ui-modules/app-inspector/app/views/main/inspect/summary/summary.controller.js b/ui-modules/app-inspector/app/views/main/inspect/summary/summary.controller.js
index 51b0af3..003613a 100644
--- a/ui-modules/app-inspector/app/views/main/inspect/summary/summary.controller.js
+++ b/ui-modules/app-inspector/app/views/main/inspect/summary/summary.controller.js
@@ -25,11 +25,11 @@
     name: 'main.inspect.summary',
     url: '/summary',
     template: template,
-    controller: ['$scope', '$state', '$stateParams', '$q', '$http', 'brSnackbar', 'entityApi', 'locationApi', summaryController],
+    controller: ['$scope', '$state', '$stateParams', '$q', '$http', 'brSnackbar', 'entityApi', 'locationApi', 'iconService', summaryController],
     controllerAs: 'vm'
 };
 
-export function summaryController($scope, $state, $stateParams, $q, $http, brSnackbar, entityApi, locationApi) {
+export function summaryController($scope, $state, $stateParams, $q, $http, brSnackbar, entityApi, locationApi, iconService) {
     $scope.$emit(HIDE_INTERSTITIAL_SPINNER_EVENT);
 
     const {
@@ -51,14 +51,14 @@
     let observers = [];
 
     entityApi.entity(applicationId, entityId).then((response)=> {
-        vm.entity = response.data;
-        vm.name = response.data.name;
-        vm.error.entity = undefined;
-        observers.push(response.subscribe((response)=> {
+        let set = (response) => {
             vm.entity = response.data;
             vm.name = response.data.name;
             vm.error.entity = undefined;
-        }));
+            iconService.get(response.data, true).then(value => vm.iconUrl = value);
+        };
+        set(response);
+        observers.push(response.subscribe(set));
     }).catch((error)=> {
         vm.error.entity = 'Cannot load entity with ID: ' + entityId;
     });
diff --git a/ui-modules/app-inspector/app/views/main/inspect/summary/summary.less b/ui-modules/app-inspector/app/views/main/inspect/summary/summary.less
index ccd0ee0..059df66 100644
--- a/ui-modules/app-inspector/app/views/main/inspect/summary/summary.less
+++ b/ui-modules/app-inspector/app/views/main/inspect/summary/summary.less
@@ -20,14 +20,38 @@
 
   .entity-header {
 
+    
     .entity-name {
+      display: flex;
       border: none;
       -webkit-font-smoothing: antialiased;
+      align-items: center;
+      
+      .node-icon {
+        flex: 0 1 0px;
+        margin-left: 3px;
+        img[src] {
+          .make-icon(80px);
+          margin-right: 18px;
+        }
+      }
+      
+      .node-name {
+        flex: 1 0 200px;
+        border: none;
+      }
+      .editable-wrap {
+        flex: 1 0 200px;
+        width: auto;
+      }
+      
+      &.loading {
+        margin-left: 5px;
+        margin-top: 16px;
+        margin-bottom: 16px;
+      }
     }
-    .editable-wrap {
-      width: 100%;
-    }
-
+    
     .editable {
       color: @primary-500;
       height: 34px;
diff --git a/ui-modules/app-inspector/app/views/main/inspect/summary/summary.template.html b/ui-modules/app-inspector/app/views/main/inspect/summary/summary.template.html
index 8f5bea0..3d8f34d 100644
--- a/ui-modules/app-inspector/app/views/main/inspect/summary/summary.template.html
+++ b/ui-modules/app-inspector/app/views/main/inspect/summary/summary.template.html
@@ -19,8 +19,11 @@
 <div class="entity-summary" ng-init="show = { status: true, mostRecentActivityInError: true, policies: true };">
     <div class="tab-header">
         <div class="entity-header">
-            <h2 ng-if="!vm.entity" class="entity-name"><loading-state error="vm.error.entity"></loading-state></h2>
-            <h2 ng-if="vm.entity" class="entity-name" editable-text="vm.name" blur="submit" buttons="no" blur="submit" onaftersave="vm.updateEntityName()">{{ vm.entity.name }}</h2>
+            <h2 ng-if="!vm.entity" class="entity-name loading"><loading-state error="vm.error.entity"></loading-state></h2>
+            <h2 ng-if="vm.entity" class="entity-name">
+              <span class="node-icon"><img ng-src="{{ vm.iconUrl }}"/></span>
+              <span class="node-name" editable-text="vm.name" blur="submit" buttons="no" blur="submit" onaftersave="vm.updateEntityName()">{{ vm.entity.name }}</span>
+            </h2>
         </div>
         <p ng-if="vm.sensors['main.uri']">
             <a ng-href="{{vm.sensors['main.uri']}}">{{vm.sensors['main.uri']}}</a>
diff --git a/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.directive.js b/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.directive.js
index 435d758..705e085 100644
--- a/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.directive.js
+++ b/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.directive.js
@@ -225,7 +225,6 @@
         link: function(scope, element, attr, ngModel) {
             ngModel.$validators.composerBlueprintNameValidator = function(modelValue, viewValue) {
                 scope.updateDefaults(modelValue);
-                console.log("valildating", scope.config.bundle, scope.config.symbolicName);
                 if (!ngModel.$isEmpty(modelValue)) {
                     // anything set is valid
                     return true;
diff --git a/ui-modules/blueprint-composer/app/index.less b/ui-modules/blueprint-composer/app/index.less
index e42474c..e91b16e 100644
--- a/ui-modules/blueprint-composer/app/index.less
+++ b/ui-modules/blueprint-composer/app/index.less
@@ -37,13 +37,6 @@
 @import "components/dsl-editor/dsl-editor";
 @import "components/dsl-viewer/dsl-viewer";
 
-.make-icon(@size) {
-  width: auto;
-  height: auto;
-  max-width: @size;
-  max-height: @size;
-}
-
 .navbar {
   margin-bottom: 0;
 }
diff --git a/ui-modules/blueprint-composer/app/views/main/main.controller.js b/ui-modules/blueprint-composer/app/views/main/main.controller.js
index 87bf803..886b4a1 100644
--- a/ui-modules/blueprint-composer/app/views/main/main.controller.js
+++ b/ui-modules/blueprint-composer/app/views/main/main.controller.js
@@ -105,7 +105,6 @@
 
     vm.saveToCatalogConfig = {};
     if (edit) {
-        console.log("edit", edit);
         vm.saveToCatalogConfig = Object.assign(vm.saveToCatalogConfig, {
             version: edit.type.version,
             template: edit.type.template || false,
diff --git a/ui-modules/catalog/app/index.less b/ui-modules/catalog/app/index.less
index cbd7eea..18760e1 100644
--- a/ui-modules/catalog/app/index.less
+++ b/ui-modules/catalog/app/index.less
@@ -29,18 +29,6 @@
 @import "views/bundle/type/type";
 @import "views/bundle/type/modal";
 
-.make-icon(@size) {
-  // this won't _increase_ size, that's more complicated.  but it will cap both sizes while
-  // keeping aspect ratio.  if width or height are set they can interfere with the maxes to screw up aspect ratio.
-  // https://stackoverflow.com/questions/12912048/how-to-maintain-aspect-ratio-using-html-img-tag
-  width: auto;
-  height: auto;
-  max-width: @size;
-  max-height: @size;
-  // and center
-  margin: auto;
-}
-
 .snackbar {
   z-index: 200;
 }
diff --git a/ui-modules/home/app/index.less b/ui-modules/home/app/index.less
index a00daad..53be790 100644
--- a/ui-modules/home/app/index.less
+++ b/ui-modules/home/app/index.less
@@ -26,12 +26,6 @@
 @import 'views/main/deploy/modal';
 @import 'components/onboarding/onboarding';
 
-.make-icon(@size) {
-  width: auto;
-  height: auto;
-  max-width: @size;
-  max-height: @size;
-}
 .hideMainContent {
   display: none;
 }
diff --git a/ui-modules/utils/br-core/style/mixins.less b/ui-modules/utils/br-core/style/mixins.less
index b4c8432..b33d574 100644
--- a/ui-modules/utils/br-core/style/mixins.less
+++ b/ui-modules/utils/br-core/style/mixins.less
@@ -55,3 +55,15 @@
     font-size: 95%;
 }
 
+.make-icon(@size) {
+  // this won't _increase_ size, that's more complicated.  but it will cap both sizes while
+  // keeping aspect ratio.  if width or height are set they can interfere with the maxes to screw up aspect ratio.
+  // https://stackoverflow.com/questions/12912048/how-to-maintain-aspect-ratio-using-html-img-tag
+  width: auto;
+  height: auto;
+  max-width: @size;
+  max-height: @size;
+  // and center
+  margin: auto;
+}
+
diff --git a/ui-modules/utils/icon-generator/icon-generator.js b/ui-modules/utils/icon-generator/icon-generator.js
index 682af6b..4839d88 100644
--- a/ui-modules/utils/icon-generator/icon-generator.js
+++ b/ui-modules/utils/icon-generator/icon-generator.js
@@ -63,17 +63,30 @@
 }
 
 export function iconGeneratorPipe(iconGenerator) {
-    return function (input, field) {
-        if (typeof(input) === 'object') {
+    return function (input, opts) {
+        let field, doNotAutogenerate=false;
+        if (opts) {
+            if (typeof opts === 'string') {
+                field = opts;
+            } else {
+                field = opts.field;
+                doNotAutogenerate = opts.doNotAutogenerate;
+            }
+        }
+        let generateFrom = input;
+        if (input && typeof(input) === 'object') {
             if (input.hasOwnProperty('iconUrl') && input.iconUrl) {
                 return input.iconUrl;
             } else if (input.hasOwnProperty('links') && input.links.hasOwnProperty('iconUrl') && input.links.iconUrl) {
                 return input.links.iconUrl;
             } else if (input.hasOwnProperty(field || 'id')) {
-                return iconGenerator(input[field || 'id'])
+                generateFrom = input[field || 'id'];
             }
         }
-        return iconGenerator(input);
+        if (doNotAutogenerate) {
+            return null;
+        }
+        return iconGenerator(generateFrom);
     }
 }
 
@@ -104,21 +117,49 @@
 
 export function iconServiceProvider() {
     return {
-        $get: ['$q', '$http', 'iconGenerator', function ($q, $http, iconGenerator) {
-            return new IconService($q, $http, iconGenerator, new SessionsStorageWrapper(CACHE_NAME));
+        $get: ['$q', '$http', 'iconGenerator', '$log', function ($q, $http, iconGenerator, $log) {
+            return new IconService($q, $http, iconGenerator, $log, new SessionsStorageWrapper(CACHE_NAME));
         }]
     }
 }
 
-function IconService($q, $http, iconGenerator, cache) {
+function IconService($q, $http, iconGenerator, $log, cache) {
     this.get = getIcon;
-    function getIcon(id) {
+    function getIcon(entityOrTypeId, doNotAutogenerate) {
         let deferred = $q.defer();
+
+        let id;
+        if (typeof entityOrTypeId === 'string') {
+            id = entityOrTypeId;
+        } else if (typeof entityOrTypeId === 'object') {
+            if (entityOrTypeId.iconUrl) {
+                deferred.resolve(entityOrTypeId.iconUrl);
+                return deferred.promise;
+            }
+            if (entityOrTypeId.links && entityOrTypeId.links.iconUrl) {
+                deferred.resolve(entityOrTypeId.links.iconUrl);
+                return deferred.promise;
+            }
+            if (entityOrTypeId.catalogItemId) {
+                id = entity.catalogItemId;
+            } else if (entityOrTypeId.symbolicName) {
+                id = entity.symbolicName;
+            } else if (entityOrTypeId.type) {
+                let entity = entityOrTypeId;
+                id = entity.type;
+                if (id === 'org.apache.brooklyn.entity.stock.BasicApplication' && entity.children && entity.children.length === 1) {
+                    id = entity.children[0].catalogItemId || entity.children[0].type;
+                }
+            }
+        }
+        
         let icon;
         if (angular.isDefined(id)) {
             icon = cache.get(id);
         } else {
-            deferred.reject('Icon ID no defined');
+            $log.warn('No ID found for item, cannot make icon - '+entityOrTypeId, entityOrTypeId);
+            deferred.reject('No ID found for item, cannot make icon - '+entityOrTypeId);
+            return deferred.promise;
         }
         if (angular.isUndefined(icon)) {
             let path = id.split(':');
@@ -130,6 +171,8 @@
                 if (response.data.hasOwnProperty('iconUrl')) {
                     icon = response.data.iconUrl;
                     cache.put(id, icon);
+                } else if (doNotAutogenerate) {
+                    icon = null;
                 } else {
                     icon = iconGenerator(id);
                 }