diff --git a/index.html b/index.html
index eb212449b415080476f1311fa2c0fbf3eaa35626..38d864b6800244266e390d3e4ab06af82f92dfba 100644
--- a/index.html
+++ b/index.html
@@ -39,6 +39,13 @@
           <label>endpoint</label>
           <input type="text" class="form-control" id="endpoint" />
         </div>
+
+        <div class="form-group">
+          <label>layers</label>
+          <select class="form-control" id="layersList" size="10"></select>
+          <button id="getLayers" class="btn btn-primary btn-block" type="button">Get Layers</button>
+        </div>
+
         <div class="form-group">
           <label>bounding box</label>
           <input id="boundingBoxInput" type="text" class="form-control mb-2" />
diff --git a/lib/helpers/Layers.js b/lib/helpers/Layers.js
new file mode 100644
index 0000000000000000000000000000000000000000..d2cf4ec8528a873bd43ea8238d56d9882e05f9d4
--- /dev/null
+++ b/lib/helpers/Layers.js
@@ -0,0 +1,57 @@
+define([
+  "dojo/_base/declare",
+  "dojox/xml/DomParser",
+], function (declare, DomParser) {
+
+  return declare(null, {
+
+    constructor: function (document) {
+
+      let parsed = DomParser.parse(document);
+      let parsedLayers = parsed.getElementsByTagName("Layer");
+      let layers = parsedLayers.map(layer => {
+        let name = layer.getElementsByTagName("Title")[0].childNodes[0].nodeValue;
+        let id = layer.getElementsByTagName("Identifier")[0].childNodes[0].nodeValue;
+        let lowerCorner = layer.getElementsByTagName("ows:LowerCorner")[0].childNodes[0].nodeValue;
+        let upperCorner = layer.getElementsByTagName("ows:UpperCorner")[0].childNodes[0].nodeValue;
+        let boundingbox = [...lowerCorner.split(" "), ...upperCorner.split(" ")];
+        boundingbox = boundingbox.map(value => parseFloat(value));
+
+        return {
+          name: name,
+          id: id,
+          boundingbox: boundingbox
+        }
+
+      });
+
+      this._layers = layers;
+
+      this.getLayers = function() {
+        return this._layers;
+      }
+
+      this.getLayerById = function (id) {
+
+      };
+
+      this.getLayerCenter = function (id) {
+        let layer = this._layers.find(l => {
+          if (id == l.id) {
+            return l;
+          }
+        });
+
+        return {
+          lon: (layer.boundingbox[0] + layer.boundingbox[2]) / 2,
+          lat: (layer.boundingbox[1] + layer.boundingbox[3]) / 2
+        };
+
+      };
+
+
+    }
+
+  });
+
+});
\ No newline at end of file
diff --git a/lib/main.js b/lib/main.js
index 00dc0bdd910ba2e653e3cfd4efdbaa7a11e32b15..4475ef82058d70e86753751674ec57591b3f6560 100644
--- a/lib/main.js
+++ b/lib/main.js
@@ -1,22 +1,23 @@
 require([
-  'dojo/topic',
-  'CesiumAdaptor/CesiumViewer',
-  'helpers/NodeCache',
-  'style/NodeStyler',
-  'style/DefaultStyle',
-  'style/NodeLevelStyle',
-  'gui/Legend',
-  'helpers/Timeout',
-  'state/State',
-  'dojo/domReady!'
-], function (topic, CesiumViewer, NodeCache, NodeStyler, DefaultStyle, NodeLevelStyle, Legend, Timeout, State) {
+  "dojo/topic",
+  "CesiumAdaptor/CesiumViewer",
+  "helpers/NodeCache",
+  "style/NodeStyler",
+  "style/DefaultStyle",
+  "style/NodeLevelStyle",
+  "gui/Legend",
+  "helpers/Timeout",
+  "state/State",
+  "state/Operations",
+  "dojo/domReady!"
+], function (topic, CesiumViewer, NodeCache, NodeStyler, DefaultStyle, NodeLevelStyle, Legend, Timeout, State, Operations) {
 
   Cesium.BingMapsApi.defaultKey = "AmdoJEIiP8BcA__QO9SjBAgv4h73-uiH4lGinmzwyfjK-Fjs8t7GbmfpFjmyj1cl";
   let osm = Cesium.createOpenStreetMapImageryProvider({
-    url: 'https://a.tile.openstreetmap.org/'
+    url: "https://a.tile.openstreetmap.org/"
   });
 
-  CesiumViewer.createViewer('cesiumContainer', {
+  CesiumViewer.createViewer("cesiumContainer", {
     baseLayerPicker: false,
     imageryProvider: osm,
     fullscreenButton: false,
@@ -41,10 +42,11 @@ require([
   legend.setVisible(false);
   legend.render();
 
-  let state = new State();
+  let operations = new Operations();
+  let state = new State(operations);
 
   $("#host").val("81.169.187.7");
-  $("#port").val("9000");
+  $("#port").val("9001");
   $("#endpoint").val("service/v1");
 
   $("#request").click(function (event) {
@@ -53,6 +55,10 @@ require([
 
   });
 
+  $("#layersList").change(function (event) {
+    state.selectLayer(this.value);
+  });
+
   $("#stylesList").change(function () {
 
     let selection = this.value;
@@ -91,9 +97,8 @@ require([
     timeout.trigger();
   });
 
-  $("#setPlace").click(function (event) {
-    state.changeState("ManualRequest");
-    state.makeRequest();
+  $("#getLayers").click(function (event) {
+    state.getLayers();
   });
 
 });
\ No newline at end of file
diff --git a/lib/state/BoundingBoxDefined.js b/lib/state/BoundingBoxDefined.js
index ffbe7ea8a3065fd41cfd964c9a2503fb1bec7e68..44290d9a8f6798fbca4358f62ba507bd2311a33b 100644
--- a/lib/state/BoundingBoxDefined.js
+++ b/lib/state/BoundingBoxDefined.js
@@ -11,7 +11,7 @@ define([
     init(target, bb) {
       bb.unregister();
       $("#boundingBoxInput").val(bb.toString());
-      $('#toggleFreezeScene').prop('disabled', false);
+      $("#toggleFreezeScene").prop("disabled", false);
       target.makeRequest();
     },
 
@@ -34,6 +34,16 @@ define([
 
     toggleFreezingScene: function (target) {
       target.changeState("FreezeScene");
+    },
+
+    selectingLayer: function (target, layer) {
+      target.operations.selectLayer(layer);
+      target.changeState("BoundingBoxUndefined");
+    },
+
+    gettingLayers: function (target) {
+      target.operations.getLayers();
+      target.changeState("NoLayerSelected");
     }
 
   });
diff --git a/lib/state/BoundingBoxDefining.js b/lib/state/BoundingBoxDefining.js
index a6a346fad611e755c66c78db20c9e72fa4fdedb6..906b83d5dafef9adb99db9b3b1af66f118e1493a 100644
--- a/lib/state/BoundingBoxDefining.js
+++ b/lib/state/BoundingBoxDefining.js
@@ -25,6 +25,14 @@ define([
 
     toggleFreezingScene: function (target) {
       // no-op
+    },
+
+    selectingLayer: function (target, layer) {
+      // no-op
+    },
+
+    gettingLayers: function (target) {
+      // no-op
     }
 
   });
diff --git a/lib/state/BoundingBoxUndefined.js b/lib/state/BoundingBoxUndefined.js
index b3098cea6add04f678d3ed907f5551642ef7852a..1ce987d3cee23006da0b69539ef8c2d5689faff4 100644
--- a/lib/state/BoundingBoxUndefined.js
+++ b/lib/state/BoundingBoxUndefined.js
@@ -1,6 +1,7 @@
 define([
   "dojo/_base/declare",
-], function (declare) {
+  "helpers/NodeCache"
+], function (declare, NodeCache) {
 
   return declare(null, {
 
@@ -10,6 +11,7 @@ define([
 
     init(target, bb) {
       bb.clear();
+      NodeCache.clearAll();
       $("#boundingBoxInput").val("");
       $('#toggleFreezeScene').prop('disabled', true);
     },
@@ -24,6 +26,15 @@ define([
 
     toggleFreezingScene: function (target) {
       // no-op
+    },
+
+    selectingLayer: function (target, layer) {
+      target.operations.selectLayer(layer);
+    },
+
+    gettingLayers: function (target) {
+      target.operations.getLayers();
+      target.changeState("NoLayerSelected");
     }
 
   });
diff --git a/lib/state/FreezeScene.js b/lib/state/FreezeScene.js
index f93f99af910a638aad382d89039355d1d5ef33ea..f0ae118e3514d9e5e29269fa438965534fa4fbb8 100644
--- a/lib/state/FreezeScene.js
+++ b/lib/state/FreezeScene.js
@@ -25,6 +25,16 @@ define([
 
     toggleFreezingScene: function (target) {
       target.changeState("BoundingBoxDefined");
+    },
+
+    selectingLayer: function (target, layer) {
+      target.operations.selectLayer(layer);
+      target.changeState("BoundingBoxUndefined");
+    },
+
+    gettingLayers: function (target) {
+      target.operations.getLayers();
+      target.changeState("NoLayerSelected");
     }
 
   });
diff --git a/lib/state/NoLayerSelected.js b/lib/state/NoLayerSelected.js
new file mode 100644
index 0000000000000000000000000000000000000000..1e6b996fb1e7bbdb3cc7f315ae8c08846ec9957d
--- /dev/null
+++ b/lib/state/NoLayerSelected.js
@@ -0,0 +1,43 @@
+define([
+  "dojo/_base/declare",
+  "helpers/NodeCache"
+], function (declare, NodeCache) {
+
+  return declare(null, {
+
+    constructor: function () {
+
+    },
+
+    init(target, bb) {
+      bb.clear();
+      NodeCache.clearAll();
+      $("#boundingBoxInput").val("");
+      $('#toggleFreezeScene').prop('disabled', true);
+    },
+
+    settingBoundingBox: function (target, bb) {
+      // no-op
+    },
+
+    makingRequest: function (target) {
+      // no-op
+    },
+
+    toggleFreezingScene: function (target) {
+      // no-op
+    },
+
+    selectingLayer: function (target, layer) {
+      target.operations.selectLayer(layer);
+      target.changeState("BoundingBoxUndefined");
+    },
+
+    gettingLayers: function (target) {
+      target.operations.getLayers();
+      target.changeState("NoLayerSelected");
+    }
+
+  });
+
+});
\ No newline at end of file
diff --git a/lib/state/Operations.js b/lib/state/Operations.js
new file mode 100644
index 0000000000000000000000000000000000000000..46181fecc7883bd16250e6eae7b92e87c77746c9
--- /dev/null
+++ b/lib/state/Operations.js
@@ -0,0 +1,56 @@
+define([
+  "dojo/_base/declare",
+  "dojo/request",
+  "helpers/UrlBuilder",
+  "CesiumAdaptor/CesiumViewer",
+  "helpers/Layers"
+], function (declare, request, UrlBuilder, CesiumViewer, Layers) {
+
+  return declare(null, {
+
+    constructor: function () {
+      this._layers = null;
+
+    },
+
+    getLayers: function () {
+
+      let url = new UrlBuilder(location.protocol.slice(0, -1), $("#host").val())
+        .port($("#port").val())
+        .path($("#endpoint").val())
+        .param("service", "3DPS")
+        .param("acceptversions", "1.0")
+        .param("request", "GetCapabilities")
+        .build();
+
+      request(url, { handleAs: "text" }).then(document => {
+
+        this._layers = new Layers(document);
+
+        $("#layersList").empty();
+
+        $.each(this._layers.getLayers(), function (i, layer) {
+          $("#layersList").append($("<option>", {
+            value: layer.id,
+            text: layer.name
+          }));
+        });
+
+      });
+
+
+    },
+
+    selectLayer: function (layer) {
+      // let selection = listElement.value;
+      let layerCenter = this._layers.getLayerCenter(layer);
+      let viewer = CesiumViewer.getViewer();
+      let center = Cesium.Cartesian3.fromDegrees(layerCenter.lon, layerCenter.lat, 20000.0);
+      viewer.camera.setView({
+        destination: center
+      });
+    }
+
+  });
+
+});
\ No newline at end of file
diff --git a/lib/state/SceneRendered.js b/lib/state/SceneRendered.js
index 00fcdd1d66c9922eabeabe9d9b552ee9df53fb0b..b4fe9519c867584bed6987bf6a6b36b8c9a502d9 100644
--- a/lib/state/SceneRendered.js
+++ b/lib/state/SceneRendered.js
@@ -31,6 +31,16 @@ define([
 
     toggleFreezingScene: function (target) {
       target.changeState("FreezeScene");
+    },
+
+    selectingLayer: function (target, layer) {
+      target.operations.selectLayer(layer);
+      target.changeState("BoundingBoxUndefined");
+    },
+
+    gettingLayers: function (target) {
+      target.operations.getLayers();
+      target.changeState("NoLayerSelected");
     }
 
   });
diff --git a/lib/state/State.js b/lib/state/State.js
index 577d5bdb015a6a1d7323a78585dc71952c27730f..81b4ae0b77715fcd78f895369e26303ac92c1404 100644
--- a/lib/state/State.js
+++ b/lib/state/State.js
@@ -7,9 +7,10 @@ define([
 
   return declare(null, {
 
-    constructor: function () {
+    constructor: function (operations) {
+      this.operations = operations;
       this._stateFactory = new StateFactory();
-      this._current = this._stateFactory.createState("BoundingBoxUndefined");
+      this._current = this._stateFactory.createState("NoLayerSelected");
       this._boundingBox = new BoundingBox();
       topic.subscribe("BoundingBoxCreated", this.changeState.bind(this));
       topic.subscribe("PortrayalResponseHandled", this.changeState.bind(this));
@@ -34,7 +35,15 @@ define([
 
     getBB: function () {
       return this._boundingBox;
-    }
+    },
+
+    selectLayer: function (layer) {
+      this._current.selectingLayer(this, layer);
+    },
+
+    getLayers: function () {
+      this._current.gettingLayers(this);
+    },
 
   });
 
diff --git a/lib/state/StateFactory.js b/lib/state/StateFactory.js
index f453d224d2b863f757a631ab2b0f5d83ca10b161..672b76ad718ceaa1e3bf4803b04aee8000d93256 100644
--- a/lib/state/StateFactory.js
+++ b/lib/state/StateFactory.js
@@ -1,12 +1,13 @@
 define([
   "dojo/_base/declare",
+  "state/NoLayerSelected",
   "state/BoundingBoxUndefined",
   "state/BoundingBoxDefining",
   "state/BoundingBoxDefined",
   "state/WaitingForPortrayal",
   "state/FreezeScene",
   "state/SceneRendered"
-], function (declare, BoundingBoxUndefined, BoundingBoxDefining, BoundingBoxDefined, WaitingForPortrayal, FreezeScene, SceneRendered) {
+], function (declare, NoLayerSelected, BoundingBoxUndefined, BoundingBoxDefining, BoundingBoxDefined, WaitingForPortrayal, FreezeScene, SceneRendered) {
 
   return declare(null, {
 
@@ -16,26 +17,22 @@ define([
 
     createState: function (stateName) {
       switch (stateName) {
+        case "NoLayerSelected":
+          return new NoLayerSelected();
         case "BoundingBoxUndefined":
           return new BoundingBoxUndefined();
-          break;
         case "BoundingBoxDefining":
           return new BoundingBoxDefining();
-          break;
         case "BoundingBoxDefined":
           return new BoundingBoxDefined();
-          break;
         case "WaitingForPortrayal":
           return new WaitingForPortrayal();
-          break;
         case "FreezeScene":
           return new FreezeScene();
-          break;
         case "SceneRendered":
           return new SceneRendered();
-          break;
         default:
-          return new BoundingBoxUndefined();
+          return new NoLayerSelected();
       }
     }
 
diff --git a/lib/state/WaitingForPortrayal.js b/lib/state/WaitingForPortrayal.js
index 7349b108252f1a15f65c5e97fd81ee78c6fb8762..ac1dceb3560557492eb8fc32f5c40404e36a8dc1 100644
--- a/lib/state/WaitingForPortrayal.js
+++ b/lib/state/WaitingForPortrayal.js
@@ -27,6 +27,14 @@ define([
 
     toggleFreezingScene: function (target) {
       // no-op
+    },
+
+    selectingLayer: function (target, layer) {
+      // no-op
+    },
+
+    gettingLayers: function (target) {
+      // no-op
     }
 
   });