diff --git a/src/main/images/Floodlight Icons.sketch/Data b/src/main/images/Floodlight Icons.sketch/Data
new file mode 100644
index 0000000000000000000000000000000000000000..bb5c893b9e5d4172708bd150a5c1137548333db9
Binary files /dev/null and b/src/main/images/Floodlight Icons.sketch/Data differ
diff --git a/src/main/images/Floodlight Icons.sketch/QuickLook/Preview.png b/src/main/images/Floodlight Icons.sketch/QuickLook/Preview.png
new file mode 100644
index 0000000000000000000000000000000000000000..77fc493ec2b292f44d48e5a360f0459b45dab267
Binary files /dev/null and b/src/main/images/Floodlight Icons.sketch/QuickLook/Preview.png differ
diff --git a/src/main/images/Floodlight Icons.sketch/QuickLook/Thumbnail.png b/src/main/images/Floodlight Icons.sketch/QuickLook/Thumbnail.png
new file mode 100644
index 0000000000000000000000000000000000000000..942c917bac3f2f0d351c47e4ad18001e31c4132d
Binary files /dev/null and b/src/main/images/Floodlight Icons.sketch/QuickLook/Thumbnail.png differ
diff --git a/src/main/images/README b/src/main/images/README
new file mode 100644
index 0000000000000000000000000000000000000000..46da010ef7e73c2732a4d86d65089c11f4df2f61
--- /dev/null
+++ b/src/main/images/README
@@ -0,0 +1 @@
+These icons were created with Sketch, available at http://www.bohemiancoding.com/sketch/
diff --git a/src/main/resources/web/img/server.png b/src/main/resources/web/img/server.png
new file mode 100644
index 0000000000000000000000000000000000000000..341c73d1712d246b14dd84c5234f8b344e346238
Binary files /dev/null and b/src/main/resources/web/img/server.png differ
diff --git a/src/main/resources/web/img/switch.png b/src/main/resources/web/img/switch.png
new file mode 100644
index 0000000000000000000000000000000000000000..d241d92d74d012aa886823a597936b7dcab759c3
Binary files /dev/null and b/src/main/resources/web/img/switch.png differ
diff --git a/src/main/resources/web/js/views/topology.js b/src/main/resources/web/js/views/topology.js
index a5988b4fce4df9a1d1586052a3f22a2b62051dbc..77129aa3fb1e19c773a5bb61cc44be0e15f377ce 100644
--- a/src/main/resources/web/js/views/topology.js
+++ b/src/main/resources/web/js/views/topology.js
@@ -19,84 +19,92 @@ window.TopologyView = Backbone.View.extend({
         this.template = _.template(tpl.get('topology'));
         this.model.bind("change", this.render, this);
         this.hosts = this.options.hosts.models;
-        this.host_links = new Array();
+        this.host_links = [];
     },
 
     render:function (eventName) {
         $(this.el).html(this.template());
-        // code from D3 force-directed graph example since there's no other docs
         var width = 900,
-          height = 600; // might as well make it square
+            height = 600;
         var color = d3.scale.category20();
         var force = d3.layout.force()
-            .charge(-240)
-            .linkDistance(100)
-            .size([width, height]);
+                             .charge(-500)
+                             .linkDistance(200)
+                             .size([width, height]);
         var svg = d3.select("#topology-graph").append("svg")
-            .attr("width", width)
-            .attr("height", height);
+                    .attr("width", width)
+                    .attr("height", height);
         if(this.model.nodes) {
-          for (var i = 0; i < this.model.nodes.length; i++) {
-            this.model.nodes[i].group = 1;
-            this.model.nodes[i].id = this.model.nodes[i].name;
-          }
-
-          for (var i = 0; i < this.hosts.length; i++) {
-            host = this.hosts[i];
-            if (host.attributes['ipv4'].length > 0) {
-                host.name = host.attributes['ipv4'][0] + "\n" + host.id;
-            } else {
-                host.name = host.id;
+            for (var i = 0; i < this.model.nodes.length; i++) {
+                this.model.nodes[i].group = 1;
+                this.model.nodes[i].id = this.model.nodes[i].name;
             }
-            host.group = 2;
-            //console.log(host);
-          }
-
-          var all_nodes = this.model.nodes.concat(this.hosts);
-
-          var all_nodes_map = new Array();
-
-          _.each(all_nodes, function(n) {
-            all_nodes_map[n.id] = n;
-          });
-
-          for (var i = 0; i < this.hosts.length; i++) {
-            host = this.hosts[i];
-            for (var j = 0; j < host.attributes['attachmentPoint'].length; j++) {
-              var link = {source:all_nodes_map[host.id],
-                      target:all_nodes_map[host.attributes['attachmentPoint'][j]['switchDPID']],
-                      value:10};
-              //console.log(link);
-              if ( link.source && link.target) {
-                  this.host_links.push(link);
-              } else {
-                  console.log("Error: skipping link with undefined stuff!")
-              }
+            
+            for (var i = 0; i < this.hosts.length; i++) {
+                host = this.hosts[i];
+                if (host.attributes['ipv4'].length > 0) {
+                    host.name = host.attributes['ipv4'][0] + "\n" + host.id;
+                } else {
+                    host.name = host.id;
+                }
+                host.group = 2;
+                //console.log(host);
             }
-          }
-
-          var all_links = this.model.links.concat(this.host_links);
-
-          force.nodes(all_nodes).links(all_links).start();
-          var link = svg.selectAll("line.link").data(all_links).enter()
-                    .append("line").attr("class", "link")
-                    .style("stroke", function (d) { return "black"; });
-          var node = svg.selectAll("circle.node").data(all_nodes)
-                        .enter().append("circle")
-                        .attr("class", "node")
-                        .attr("r", 20)
-                        .style("fill", function(d) { return color(d.group); })
-                        .call(force.drag);
-          node.append("title").text(function(d) { return d.name; });
-          force.on("tick", function() {
-            link.attr("x1", function(d) { return d.source.x; })
-                .attr("y1", function(d) { return d.source.y; })
-                .attr("x2", function(d) { return d.target.x; })
-                .attr("y2", function(d) { return d.target.y; });
-
-            node.attr("cx", function(d) { return d.x; })
-                .attr("cy", function(d) { return d.y; });
-          });
+            
+            var all_nodes = this.model.nodes.concat(this.hosts);
+            
+            var all_nodes_map = [];
+            
+            _.each(all_nodes, function(n) {
+                all_nodes_map[n.id] = n;
+            });
+            
+            for (var i = 0; i < this.hosts.length; i++) {
+                host = this.hosts[i];
+                //for (var j = 0; j < host.attributes['attachmentPoint'].length; j++) {
+                for (var j = 0; j < 1; j++) { // FIXME hack to ignore multiple APs
+                    var link = {source:all_nodes_map[host.id],
+                                target:all_nodes_map[host.attributes['attachmentPoint'][j]['switchDPID']],
+                                value:10};
+                    //console.log(link);
+                    if ( link.source && link.target) {
+                        this.host_links.push(link);
+                    } else {
+                        console.log("Error: skipping link with undefined stuff!")
+                    }
+                }
+            }
+            
+            var all_links = this.model.links.concat(this.host_links);
+            
+            force.nodes(all_nodes).links(all_links).start();
+            var link = svg.selectAll("line.link").data(all_links).enter()
+                          .append("line").attr("class", "link")
+                          .style("stroke", function (d) { return "black"; });
+            var node = svg.selectAll(".node").data(all_nodes)
+                          .enter().append("g")
+                          .attr("class", "node")
+                          .call(force.drag);
+                          
+            node.append("image")
+                .attr("xlink:href", function (d) {return d.group==1 ? "/ui/img/switch.png" : "/ui/img/server.png"})
+                .attr("x", -16).attr("y", -16)
+                .attr("width", 32).attr("height", 32);
+            node.append("text").attr("dx", 20).attr("dy", ".35em")
+                .text(function(d) { return d.name });
+            node.on("click", function (d) {
+                // TODO we could add some functionality here
+                console.log('clicked '+d.name);
+            });
+            node.append("title").text(function(d) { return d.name; });
+            force.on("tick", function() {
+                link.attr("x1", function(d) { return d.source.x; })
+                    .attr("y1", function(d) { return d.source.y; })
+                    .attr("x2", function(d) { return d.target.x; })
+                    .attr("y2", function(d) { return d.target.y; });
+                node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
+                
+            });
         }
         return this;
     }