diff --git a/.project b/.project
deleted file mode 100644
index 4c665a9634680143a83ebefc8924cc653f32ec40..0000000000000000000000000000000000000000
--- a/.project
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>vipra-config</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-	</buildSpec>
-	<natures>
-	</natures>
-</projectDescription>
diff --git a/README.md b/README.md
index 32e3e6a7a128d86ee99cfe558b86c963f333a417..0c47941367e396fcdae2cba1019dfd7653552c92 100644
--- a/README.md
+++ b/README.md
@@ -13,6 +13,8 @@ This application was created by Eike Cochu for his master's degree thesis in com
 
 ## Installation
 
+### Manual
+
 1. Deploy vipra.war or exploded vipra directory to a Java application server. Deploy to ROOT (/) or a different context path (/vipra, ...)
 2. Edit WEB-INF/classes/config.json if MongoDB or ElasticSearch do not run with default configuration (host/port)
 3. Deploy vipra-ui to a static webserver 
@@ -22,6 +24,43 @@ This application was created by Eike Cochu for his master's degree thesis in com
 
 if everything is left default, application should be available under: http://someserver/ and backend: http://someserver:8080/rest/
 
+### Docker
+
+1. Load docker image: `docker pull eikecochu/vipra`
+2. Create and run docker container: `docker run -p 80:80 -p 6789:6789 -p 9300:9300 -p 27017:27017 eikecochu/vipra`
+3. Install vipra: ``
+
+### Nginx Proxy
+
+To proxy requests through nginx, use this server configuration (replace `#SERVER_NAME_HERE#`):
+
+```bash
+server {
+    listen 80;
+    server_name #SERVER_NAME_HERE#;
+
+    access_log off;
+    error_log /var/log/nginx/vipra.error.log warn;
+
+    include include.d/security;
+    include include.d/ssl;
+
+    location / {
+        proxy_buffering off;
+        proxy_set_header Host $host;
+        proxy_set_header X-Real-IP $remote_addr;
+        proxy_pass http://localhost:80/;
+    }
+
+location /ws {
+        proxy_pass http://localhost:80/ws;
+        proxy_http_version 1.1;
+        proxy_set_header Upgrade $http_upgrade;
+        proxy_set_header Connection "upgrade";
+    }
+}
+```
+
 ## Development
 
 The following steps were reproduced in that order on a fully updated Ubuntu 15.10 virtual system to create a fully operational development environment for the Vipra projects. These steps are only required for project development. If you want to create a virtual machine for development, create a hard drive with at least 10 GB in size. 
diff --git a/Vagrantfile b/Vagrantfile
deleted file mode 100644
index 28cab3ce15de4bc866fe79e2141d868d70a8b4fd..0000000000000000000000000000000000000000
--- a/Vagrantfile
+++ /dev/null
@@ -1,20 +0,0 @@
-Vagrant.configure(2) do |config|
-  config.vm.box = 'ubuntu/wily64'
-
-  ENV['LC_ALL']="en_US.UTF-8"
-
-  config.vm.provider "virtualbox" do |v|
-    v.memory = 8192
-    v.cpus = 2
-  end
-
-  config.vm.define "master" do |master|
-    master.vm.hostname = 'vipra-master'
-    master.vm.network :private_network, ip: '192.168.10.10'
-    master.vm.network :forwarded_port, guest: 27017, host: 27017 # MongoDB
-    master.vm.network :forwarded_port, guest: 8080,  host: 8000  # Tomcat
-    master.vm.network :forwarded_port, guest: 9200,  host: 9200  # ElasticSearch REST API
-    master.vm.network :forwarded_port, guest: 9300,  host: 9300  # ElasticSearch Native
-  end
-
-end
diff --git a/docker/.gitignore b/docker/.gitignore
index faf8905d2e986260ba67e95b737803c9d97c5524..3e782a5e3175b34c75abcf3e23230d9995c3fb8c 100644
--- a/docker/.gitignore
+++ b/docker/.gitignore
@@ -1,2 +1,3 @@
 webapps/*
-webroot/*
\ No newline at end of file
+webroot/*
+data/
\ No newline at end of file
diff --git a/vipra-cmd/pom.xml b/vipra-cmd/pom.xml
index efc95329132d8f80e04dd6672475f04f16ef507f..0569678ad3e9c17eb02a86b63202586c5ccd9f1e 100644
--- a/vipra-cmd/pom.xml
+++ b/vipra-cmd/pom.xml
@@ -64,6 +64,13 @@
 			<version>1.1.0</version>
 		</dependency>
 
+		<!-- ZIP -->
+		<dependency>
+			<groupId>org.zeroturnaround</groupId>
+			<artifactId>zt-zip</artifactId>
+			<version>1.9</version>
+		</dependency>
+
 		<!-- Workspace -->
 		<dependency>
 			<groupId>de.vipra</groupId>
diff --git a/vipra-cmd/runcfg/CMD.launch b/vipra-cmd/runcfg/CMD.launch
index 0e3fecb125ac97797b96daa17da6c22724631ed2..b81b445da587eb6d6ac2e4e840f52900fc0bd270 100644
--- a/vipra-cmd/runcfg/CMD.launch
+++ b/vipra-cmd/runcfg/CMD.launch
@@ -11,7 +11,7 @@
 </listAttribute>
 <stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.m2e.launchconfig.classpathProvider"/>
 <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="de.vipra.cmd.Main"/>
-<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-Ai"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-B /home/eike/Downloads"/>
 <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="vipra-cmd"/>
 <stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/>
 <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea"/>
diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/CommandLineOptions.java b/vipra-cmd/src/main/java/de/vipra/cmd/CommandLineOptions.java
index 45e3b4adc920a1cb54094c2f882fbe0ae19275ec..9df57f19dfb2b2c1f9ade54b9c187c622ece97b8 100644
--- a/vipra-cmd/src/main/java/de/vipra/cmd/CommandLineOptions.java
+++ b/vipra-cmd/src/main/java/de/vipra/cmd/CommandLineOptions.java
@@ -18,7 +18,7 @@ public class CommandLineOptions {
 	public static final Option LIST = Option.builder("l").longOpt("list").desc("list available models").build();
 	public static final Option SILENT = Option.builder("s").longOpt("silent").desc("suppress all output").build();
 	public static final Option TEST = Option.builder("t").longOpt("test").desc("test database connections").build();
-	public static final Option ALL = Option.builder("A").longOpt("all").desc("select all models (-S all)c").build();
+	public static final Option ALL = Option.builder("A").longOpt("all").desc("select all models (-S all)").build();
 
 	public static final Option INDEX = Option.builder("i").longOpt("index").desc("create index for models").hasArgs().argName("[models...]")
 			.optionalArg(true).build();
@@ -38,6 +38,8 @@ public class CommandLineOptions {
 			.optionalArg(true).build();
 	public static final Option SELECT = Option.builder("S").longOpt("select").desc("select models").hasArgs().argName("models...").build();
 	public static final Option MESSAGE = Option.builder("m").longOpt("message").desc("send a global message").hasArg().argName("message").build();
+	public static final Option BACKUP = Option.builder("B").longOpt("backup").desc("backup data/filebase").hasArg().argName("path").build();
+	public static final Option RESTORE = Option.builder("R").longOpt("restore").desc("restore data/filebase").hasArg().argName("path").build();
 
 	private final Options options;
 	private CommandLine cmd;
@@ -45,7 +47,7 @@ public class CommandLineOptions {
 
 	public CommandLineOptions() {
 		final Option[] optionsArray = { CLEAR, DEBUG, HELP, INDEX, LIST, REREAD, SILENT, TEST, ALL, CREATE, DELETE, EDIT, PRINT, IMPORT, MODEL,
-				SELECT, MESSAGE };
+				SELECT, MESSAGE, BACKUP, RESTORE };
 		options = new Options();
 		for (final Option option : optionsArray)
 			options.addOption(option);
@@ -226,4 +228,20 @@ public class CommandLineOptions {
 		return getOptionValue(MESSAGE);
 	}
 
+	public boolean isBackup() {
+		return hasOption(BACKUP);
+	}
+
+	public String backupPath() {
+		return getOptionValue(BACKUP);
+	}
+
+	public boolean isRestore() {
+		return hasOption(RESTORE);
+	}
+
+	public String restorePath() {
+		return getOptionValue(RESTORE);
+	}
+
 }
diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/Main.java b/vipra-cmd/src/main/java/de/vipra/cmd/Main.java
index 9502c5cddcfbd7e250e2618a3ed8e69cbac8ef09..565276c16a619aacbecc54f16a41ed3eee53b09e 100644
--- a/vipra-cmd/src/main/java/de/vipra/cmd/Main.java
+++ b/vipra-cmd/src/main/java/de/vipra/cmd/Main.java
@@ -7,6 +7,7 @@ import java.util.ListIterator;
 import org.mongodb.morphia.logging.MorphiaLoggerFactory;
 import org.mongodb.morphia.logging.slf4j.SLF4JLoggerImplFactory;
 
+import de.vipra.cmd.option.BackupCommand;
 import de.vipra.cmd.option.ClearCommand;
 import de.vipra.cmd.option.Command;
 import de.vipra.cmd.option.CreateModelCommand;
@@ -18,6 +19,7 @@ import de.vipra.cmd.option.ListModelsCommand;
 import de.vipra.cmd.option.MessageCommand;
 import de.vipra.cmd.option.ModelingCommand;
 import de.vipra.cmd.option.PrintModelCommand;
+import de.vipra.cmd.option.RestoreCommand;
 import de.vipra.cmd.option.TestCommand;
 import de.vipra.util.ConsoleUtils;
 import de.vipra.util.LockFile;
@@ -83,6 +85,12 @@ public class Main {
 		if (opts.isMessage())
 			commands.add(new MessageCommand(opts.messageToSend()));
 
+		if (opts.isBackup())
+			commands.add(new BackupCommand(opts.backupPath()));
+
+		if (opts.isRestore())
+			commands.add(new RestoreCommand(opts.restorePath()));
+
 		if (opts.isClear())
 			commands.add(new ClearCommand());
 
diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/option/BackupCommand.java b/vipra-cmd/src/main/java/de/vipra/cmd/option/BackupCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..5a9b5b2e7db9b53c72852dcbe07b24cad33d7528
--- /dev/null
+++ b/vipra-cmd/src/main/java/de/vipra/cmd/option/BackupCommand.java
@@ -0,0 +1,41 @@
+package de.vipra.cmd.option;
+
+import java.io.File;
+import java.util.Date;
+
+import org.zeroturnaround.zip.ZipUtil;
+
+import de.vipra.util.Config;
+import de.vipra.util.FileUtils;
+
+public class BackupCommand implements Command {
+
+	private final String path;
+
+	public BackupCommand(final String path) {
+		this.path = path;
+	}
+
+	@Override
+	public void run() throws Exception {
+		final Config config = Config.getConfig();
+		final File tmpTarget = FileUtils.getTempFile("vipra-dump");
+		FileUtils.deleteDirectory(tmpTarget);
+		final Process p = Runtime.getRuntime().exec("mongodump -d " + config.getDatabaseName() + " -h " + config.getDatabaseHost() + " --port "
+				+ config.getDatabasePort() + " -o " + new File(tmpTarget, "db"));
+		p.waitFor();
+		FileUtils.copyDirectory(config.getDataDirectory(), new File(tmpTarget, "fb"));
+		FileUtils.copyDirectory(Config.getGenericConfigDir(), new File(tmpTarget, "config"));
+		File target = new File(path);
+		if (target.exists() && target.isDirectory())
+			target = new File(target, "vipra-" + new Date().getTime() + ".zip");
+		ZipUtil.pack(tmpTarget, target);
+		FileUtils.deleteDirectory(tmpTarget);
+	}
+
+	@Override
+	public boolean requiresLock() {
+		return true;
+	}
+
+}
diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/option/ImportCommand.java b/vipra-cmd/src/main/java/de/vipra/cmd/option/ImportCommand.java
index 116b67c27116098da5620b893a71ff0b59fa005b..597f9d88d181befa011823dbb837e34be9947d64 100644
--- a/vipra-cmd/src/main/java/de/vipra/cmd/option/ImportCommand.java
+++ b/vipra-cmd/src/main/java/de/vipra/cmd/option/ImportCommand.java
@@ -349,9 +349,8 @@ public class ImportCommand implements Command {
 		processor = new Processor();
 		final IPCClient ipcClient = new IPCClient();
 		for (final TopicModelConfig modelConfig : config.getTopicModelConfigs(models)) {
-			ipcClient.send(new IPCMessage(IPCMessageCode.START_IMPORTING).message("Started importing for model '" + modelConfig.getName() + "'"));
+			ipcClient.send(new IPCMessage(IPCMessageCode.IMPORTING).message("Started importing for model '" + modelConfig.getName() + "'"));
 			importForModel(modelConfig);
-			ipcClient.send(new IPCMessage(IPCMessageCode.STOP_IMPORTING).message("Finished importing for model '" + modelConfig.getName() + "'"));
 		}
 		ipcClient.close();
 	}
diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/option/IndexingCommand.java b/vipra-cmd/src/main/java/de/vipra/cmd/option/IndexingCommand.java
index adb8e7c77b450e497c630c21e59a829931e19177..ffcf1d9cecfae2014e8f49ac4cb27be5ee774d00 100644
--- a/vipra-cmd/src/main/java/de/vipra/cmd/option/IndexingCommand.java
+++ b/vipra-cmd/src/main/java/de/vipra/cmd/option/IndexingCommand.java
@@ -96,9 +96,8 @@ public class IndexingCommand implements Command {
 		elasticSerializer = new ESSerializer<>(ArticleFull.class);
 		final IPCClient ipcClient = new IPCClient();
 		for (final TopicModelConfig modelConfig : config.getTopicModelConfigs(models)) {
-			ipcClient.send(new IPCMessage(IPCMessageCode.START_INDEXING).message("Started indexing model '" + modelConfig.getName() + "'"));
+			ipcClient.send(new IPCMessage(IPCMessageCode.INDEXING).message("Started indexing model '" + modelConfig.getName() + "'"));
 			indexForModel(modelConfig);
-			ipcClient.send(new IPCMessage(IPCMessageCode.STOP_INDEXING).message("Finished indexing model '" + modelConfig.getName() + "'"));
 		}
 		ipcClient.close();
 	}
diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/option/ModelingCommand.java b/vipra-cmd/src/main/java/de/vipra/cmd/option/ModelingCommand.java
index ca2627cf72af2fc0441832d693291c5a9261a1c0..5e1b095bd017b241a3265caad255b1c80c1cdb49 100644
--- a/vipra-cmd/src/main/java/de/vipra/cmd/option/ModelingCommand.java
+++ b/vipra-cmd/src/main/java/de/vipra/cmd/option/ModelingCommand.java
@@ -62,9 +62,8 @@ public class ModelingCommand implements Command {
 
 		final IPCClient ipcClient = new IPCClient();
 		for (final TopicModelConfig modelConfig : config.getTopicModelConfigs(models)) {
-			ipcClient.send(new IPCMessage(IPCMessageCode.START_MODELING).message("Started generating model '" + modelConfig.getName() + "'"));
+			ipcClient.send(new IPCMessage(IPCMessageCode.MODELING).message("Started generating model '" + modelConfig.getName() + "'"));
 			modelForModel(modelConfig);
-			ipcClient.send(new IPCMessage(IPCMessageCode.STOP_MODELING).message("Finished generating model '" + modelConfig.getName() + "'"));
 		}
 		ipcClient.close();
 	}
diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/option/RestoreCommand.java b/vipra-cmd/src/main/java/de/vipra/cmd/option/RestoreCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..f68f906d1c960c85d1722512155526fc72342f45
--- /dev/null
+++ b/vipra-cmd/src/main/java/de/vipra/cmd/option/RestoreCommand.java
@@ -0,0 +1,41 @@
+package de.vipra.cmd.option;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+import org.zeroturnaround.zip.ZipUtil;
+
+import de.vipra.util.Config;
+import de.vipra.util.FileUtils;
+
+public class RestoreCommand implements Command {
+
+	private final String path;
+
+	public RestoreCommand(final String path) {
+		this.path = path;
+	}
+
+	@Override
+	public void run() throws Exception {
+		final File zip = new File(path);
+		if (!zip.isFile())
+			throw new FileNotFoundException(path);
+		final File tmpTarget = FileUtils.getTempFile("vipra-dump");
+		FileUtils.deleteDirectory(tmpTarget);
+		ZipUtil.unpack(zip, tmpTarget);
+		final Config config = Config.getConfig();
+		final Process p = Runtime.getRuntime().exec("mongorestore --drop -d " + config.getDatabaseName() + " -h " + config.getDatabaseHost()
+				+ " --port " + config.getDatabasePort() + " " + new File(tmpTarget, "db"));
+		p.waitFor();
+		FileUtils.copyDirectory(new File(tmpTarget, "fb"), config.getDataDirectory());
+		FileUtils.copyDirectory(new File(tmpTarget, "config"), Config.getGenericConfigDir());
+		FileUtils.deleteDirectory(tmpTarget);
+	}
+
+	@Override
+	public boolean requiresLock() {
+		return true;
+	}
+
+}
diff --git a/vipra-ui/README.md b/vipra-ui/README.md
index 333bb4deb5ad6983ff75c476c58c9128e766552f..899023c75ab12d239c1ec4f54c6f1e3802a0ada1 100644
--- a/vipra-ui/README.md
+++ b/vipra-ui/README.md
@@ -16,14 +16,17 @@ The frontend UI project. Built with AngularJS and many other Javascript and CSS
 * [randomColor](https://github.com/davidmerfield/randomColor) by David Merfield (CC0 1.0)
 * [FontAwesome](https://github.com/FortAwesome/Font-Awesome) by Dave Gandy (SIL OFL 1.1/MIT)
 * [Bower](https://github.com/bower/bower) by Twitter and other contributors (MIT)
+* [Reconnecting Websocket](https://github.com/joewalnes/reconnecting-websocket) by Joe Walnes (MIT)
+* [Awesome Bootstrap Checkbox](https://github.com/flatlogic/awesome-bootstrap-checkbox) by flatlogic.com (MIT)
 * [Gulp](https://github.com/gulpjs/gulp) by Fractal (MIT)
 * [gulp-less](https://github.com/plus3network/gulp-less) by Plus 3 Network (MIT)
+* [gulp-gzip](https://github.com/jstuckey/gulp-gzip) by Jeremy Stuckey (MIT)
 * [gulp-concat](https://github.com/contra/gulp-concat) by Fractal (MIT)
 * [gulp-uglify](https://github.com/terinjokes/gulp-uglify) by Terin Stock (MIT)
 * [gulp-clean-css](https://github.com/scniro/gulp-clean-css) by scniro (MIT)
 * [gulp-webserver](https://github.com/schickling/gulp-webserver) by Johannes Schickling (MIT)
 * [gulp-ng-annotate](https://github.com/Kagami/gulp-ng-annotate) by Kagami Hiiragi and contributors (CC0 1.0)
-* [gulp-templatecache](https://github.com/miickel/gulp-angular-templatecache) by Mickel (MIT)
+* [gulp-angular-templatecache](https://github.com/miickel/gulp-angular-templatecache) by Mickel (MIT)
 
 ## Installation
 
diff --git a/vipra-ui/app/html/directives/article-popover.html b/vipra-ui/app/html/directives/article-popover.html
new file mode 100644
index 0000000000000000000000000000000000000000..c30e304cdc0e6aa28c7e2c67132abe0af90fc52e
--- /dev/null
+++ b/vipra-ui/app/html/directives/article-popover.html
@@ -0,0 +1,21 @@
+<a ui-sref="articles.show({id: currentArticle.id})" ng-bind="currentArticle.title"></a>
+
+<table class="table table-bordered table-condensed table-fixed nomargin">
+  <tbody>
+    <tr>
+      <th class="infocol">Date</th>
+      <td ng-bind="currentArticleDate"></td>
+    </tr>
+    <tr ng-if="currentArticle.url">
+      <th>URL</th>
+      <td class="break-words">
+        <a ng-href="{{currentArticle.url}}" target="_blank">
+          <i class="fa fa-link"></i>
+          <span ng-bind="currentArticle.url"></span>
+        </a>
+      </td>
+    </tr>
+  </tbody>
+</table>
+
+<div class="text-justify article-popover-text" ng-bind-html="currentArticle.text"></div>
\ No newline at end of file
diff --git a/vipra-ui/app/html/index.html b/vipra-ui/app/html/index.html
index 44abb260695dd1e89b51a223d35ace50359fd1ee..ed11e0072cb18f98100871dd2c31df228bfe2d3f 100644
--- a/vipra-ui/app/html/index.html
+++ b/vipra-ui/app/html/index.html
@@ -3,7 +3,7 @@
     <div class="container">
       <div class="row row-spaced" ng-hide="search">
         <div class="col-md-12 text-center text-logo">
-          \ˈvī-prə\
+          VIPRA
         </div>
       </div>
       <div class="row row-spaced">
@@ -61,6 +61,13 @@
       </div>
     </div>
   </div>
+  <div class="container" ng-show="!searching && !search">
+    <div class="row">
+      <div class="col-md-offset-1 col-md-10 col-sm-12">
+        <div class="embed-responsive embed-responsive-16by9 screencast"></div>
+      </div>
+    </div>
+  </div>
   <div class="container">
     <div class="row row-spaced">
       <div class="col-md-12 text-center" ng-show="searching" ng-cloak>
diff --git a/vipra-ui/app/html/network.html b/vipra-ui/app/html/network.html
index 83610c2ce3a9670015e3601530d84e385d2d07ba..fe9e9ab44144d6ca445051c75ee0f9623146a953 100644
--- a/vipra-ui/app/html/network.html
+++ b/vipra-ui/app/html/network.html
@@ -1,6 +1,6 @@
 <div ng-cloak ng-hide="!rootModels.topicModel || state.name !== 'network'">
   <div class="fullsize navpadding">
-    <div class="graph-legend overlay" ng-class="{collapsed:legendCollapsed}">
+    <div class="graph-item top-left small overlay" ng-class="{collapsed:legendCollapsed}">
       <i class="collapser fa pointer pull-right" ng-class="{'fa-chevron-up':!legendCollapsed,'fa-chevron-down':legendCollapsed}" ng-click="legendCollapsed=!legendCollapsed"></i>
       <div ng-hide="legendCollapsed">
         <div class="checkbox">
@@ -19,7 +19,7 @@
           <input type="checkbox" id="showWords" ng-model="shown.words">
           <label for="showWords">Words</label>
         </div>
-        <div>
+        <div ng-show="!type">
           Window
           <window-dropdown ng-model="selectedWindow" windows="windows" />
         </div>
@@ -45,8 +45,17 @@
             </tr>
           </table>
         </div>
+        <div>
+          <button class="btn btn-default btn-block" ng-click="completeNetwork()">
+            Load missing relations
+          </button>
+        </div>
       </div>
     </div>
+    <div class="graph-item bottom-left large overlay" ng-show="currentArticle" ng-class="{collapsed:articlePopoverCollapsed}">
+      <i class="collapser fa pointer pull-right" ng-class="{'fa-chevron-down':!articlePopoverCollapsed,'fa-chevron-up':articlePopoverCollapsed}" ng-click="articlePopoverCollapsed=!articlePopoverCollapsed"></i>
+      <article-popover article="currentArticle" ng-show="!articlePopoverCollapsed"/>
+    </div>
     <div class="fullsize" id="visgraph"></div>
   </div>
 </div>
diff --git a/vipra-ui/app/img/vipra.png b/vipra-ui/app/img/vipra.png
new file mode 100644
index 0000000000000000000000000000000000000000..fbaf9113edc1c7e4f56597a4c10095efcf6c380f
Binary files /dev/null and b/vipra-ui/app/img/vipra.png differ
diff --git a/vipra-ui/app/img/vipra.svg b/vipra-ui/app/img/vipra.svg
index 57735f3c0d2c0ef46971c491692beca224c3b5dc..33da83817060df35a0a7926006fcc221240ddaf5 100644
--- a/vipra-ui/app/img/vipra.svg
+++ b/vipra-ui/app/img/vipra.svg
@@ -9,15 +9,51 @@
    xmlns="http://www.w3.org/2000/svg"
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="43.380642mm"
-   height="10.914062mm"
-   viewBox="0 0 153.71094 38.671875"
-   id="svg2"
+   width="64.600754mm"
+   height="15.858673mm"
+   viewBox="0 0 228.90031 56.192148"
+   id="svg4341"
    version="1.1"
    inkscape:version="0.91 r13725"
+   inkscape:export-filename="/home/eike/repos/master/ma-impl/vipra-ui/app/img/vipra.png"
+   inkscape:export-xdpi="104.2"
+   inkscape:export-ydpi="104.2"
    sodipodi:docname="vipra.svg">
   <defs
-     id="defs4" />
+     id="defs4343">
+    <filter
+       style="color-interpolation-filters:sRGB"
+       inkscape:label="Drop Shadow"
+       id="filter4947">
+      <feFlood
+         flood-opacity="0.498039"
+         flood-color="rgb(0,0,0)"
+         result="flood"
+         id="feFlood4949" />
+      <feComposite
+         in="flood"
+         in2="SourceGraphic"
+         operator="in"
+         result="composite1"
+         id="feComposite4951" />
+      <feGaussianBlur
+         in="composite1"
+         stdDeviation="2"
+         result="blur"
+         id="feGaussianBlur4953" />
+      <feOffset
+         dx="2"
+         dy="2"
+         result="offset"
+         id="feOffset4955" />
+      <feComposite
+         in="SourceGraphic"
+         in2="offset"
+         operator="over"
+         result="composite2"
+         id="feComposite4957" />
+    </filter>
+  </defs>
   <sodipodi:namedview
      id="base"
      pagecolor="#ffffff"
@@ -25,11 +61,11 @@
      borderopacity="1.0"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="3.959798"
-     inkscape:cx="123.60597"
-     inkscape:cy="-39.672792"
+     inkscape:zoom="2.8"
+     inkscape:cx="62.626262"
+     inkscape:cy="-82.676013"
      inkscape:document-units="px"
-     inkscape:current-layer="layer1"
+     inkscape:current-layer="g4904"
      showgrid="false"
      fit-margin-top="0"
      fit-margin-left="0"
@@ -41,7 +77,7 @@
      inkscape:window-y="24"
      inkscape:window-maximized="1" />
   <metadata
-     id="metadata7">
+     id="metadata4346">
     <rdf:RDF>
       <cc:Work
          rdf:about="">
@@ -56,17 +92,42 @@
      inkscape:label="Ebene 1"
      inkscape:groupmode="layer"
      id="layer1"
-     transform="translate(0,-1013.6903)">
-    <text
-       xml:space="preserve"
-       style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#e6e6e6;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
-       x="0"
-       y="1044.0419"
-       id="text3336"
-       sodipodi:linespacing="125%"><tspan
-         sodipodi:role="line"
-         id="tspan3338"
-         x="0"
-         y="1044.0419">\ˈvī-prə\</tspan></text>
+     transform="translate(19.075026,-1000.8527)">
+    <g
+       style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       id="text4349">
+      <g
+         id="g4904"
+         transform="matrix(0.73612555,0,0,0.73612555,-30.10349,966.59467)"
+         style="fill:#eeeeee;fill-opacity:1;filter:url(#filter4947)"
+         inkscape:export-xdpi="104.2"
+         inkscape:export-ydpi="104.2">
+        <path
+           id="path4894"
+           style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:87.5px;font-family:'Hoefler Text';-inkscape-font-specification:'Hoefler Text Medium';fill:#eeeeee;fill-opacity:1"
+           d="m 108.2695,55.262097 c 0,-0.7 -0.2625,-1.05 -0.525,-1.05 -4.1125,0 -6.3,0.525 -10.237495,0.525 -4.725,0 -7.2625,-0.525 -11.4625,-0.525 -0.4375,0 -0.7875,0.6125 -0.7875,1.225 0,0.7 0.175,1.225 0.525,1.225 5.8625,0.35 7.6125,2.1 7.6125,4.725 0,1.1375 -0.35,2.3625 -0.7875,3.7625 l -15.75,38.762503 -15.225,-39.812503 c -0.525,-1.4875 -0.9625,-2.7125 -0.9625,-3.85 0,-2.1 1.6625,-3.325 7.2625,-3.5875 0.35,0 0.4375,-0.525 0.4375,-1.225 0,-0.6125 -0.35,-1.225 -0.7,-1.225 -5.775,0 -8.225,0.525 -13.65,0.525 -5.425,0 -6.7375,-0.525 -12.5125,-0.525 -0.35,0 -0.6125,0.6125 -0.6125,1.225 0,0.7 0.525,1.225 0.875,1.225 8.05,0.9625 8.8375,2.1 11.375,8.8375 l 19.5125,50.312503 c 0.175,0.35 0.6125,0.7 1.225,0.7 0.7,0 1.05,-0.2625 1.225,-0.7 l 21.9625,-50.312503 c 2.5375,-5.6875 3.849995,-8.225 10.237495,-8.8375 0.6125,0 0.9625,-0.7875 0.9625,-1.4 z"
+           inkscape:connector-curvature="0" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4896"
+           style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:87.5px;font-family:'Hoefler Text';-inkscape-font-specification:'Hoefler Text Medium';fill:#eeeeee;fill-opacity:1"
+           d="m 135.74099,113.8871 c 0,-0.7 -0.2625,-1.1375 -0.7,-1.225 -8.4875,-0.9625 -9.0125,-2.8875 -9.0125,-7.35 l 0,-41.212503 c 0,-4.55 0.525,-6.3875 9.0125,-7.4375 0.4375,0 0.7,-0.525 0.7,-1.225 0,-0.6125 -0.2625,-1.225 -0.7,-1.225 -5.775,0 -8.05,0.525 -13.475,0.525 -5.425,0 -7.7,-0.525 -13.5625,-0.525 -0.35,0 -0.7,0.6125 -0.7,1.225 0,0.7 0.35,1.225 0.7,1.225 8.4875,1.05 9.1,2.8875 9.1,7.4375 l 0,41.212503 c 0,4.4625 -0.6125,6.3875 -9.1,7.35 -0.35,0.0875 -0.7,0.525 -0.7,1.225 0,0.7 0.35,1.225 0.7,1.225 5.8625,0 8.1375,-0.525 13.5625,-0.525 5.425,0 7.7,0.525 13.475,0.525 0.4375,0 0.7,-0.525 0.7,-1.225 z" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4898"
+           style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:87.5px;font-family:'Hoefler Text';-inkscape-font-specification:'Hoefler Text Medium';fill:#eeeeee;fill-opacity:1"
+           d="m 183.00154,72.062097 c 0,-10.7625 -6.5625,-17.85 -21.9625,-17.85 -5.775,0 -8.05,0.525 -13.475,0.525 -5.425,0 -7.7875,-0.525 -13.5625,-0.525 -0.35,0 -0.7,0.6125 -0.7,1.225 0,0.7 0.35,1.225 0.7,1.225 8.4875,1.05 9.1,2.8875 9.1,7.4375 l 0,41.212503 c 0,4.4625 -0.6125,6.3875 -9.1,7.35 -0.35,0.0875 -0.7,0.525 -0.7,1.225 0,0.7 0.35,1.225 0.7,1.225 5.775,0 8.1375,-0.525 13.5625,-0.525 5.425,0 7.7,0.525 13.475,0.525 0.4375,0 0.7,-0.525 0.7,-1.225 0,-0.7 -0.2625,-1.1375 -0.7,-1.225 -8.4875,-0.9625 -9.0125,-2.8875 -9.0125,-7.35 l 0,-15.487503 c 3.0625,0.2625 5.8625,0.4375 10.325,0.4375 11.6375,0 20.65,-7.875 20.65,-18.2 z m -9.7125,0 c 0,8.3125 -4.2875,15.3125 -14.9625,15.3125 -4.725,0 -6.3,-0.4375 -6.3,-3.15 l 0,-20.125 c 0,-4.55 0.175,-6.9125 8.6625,-6.9125 6.3875,0 12.6,4.2875 12.6,14.875 z" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4900"
+           style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:87.5px;font-family:'Hoefler Text';-inkscape-font-specification:'Hoefler Text Medium';fill:#eeeeee;fill-opacity:1"
+           d="m 239.14743,113.8871 c 0,-0.7 -0.2625,-1.1375 -0.6125,-1.225 -7.875,-0.875 -10.15,-3.675 -11.6375,-6.125 l -14.175,-21.525003 c 7.9625,-2.8 13.7375,-8.4 13.7375,-15.05 0,-9.625 -7,-15.75 -20.475,-15.75 -5.775,0 -8.1375,0.525 -13.5625,0.525 -5.425,0 -7.7,-0.525 -13.475,-0.525 -0.4375,0 -0.7,0.6125 -0.7,1.225 0,0.7 0.2625,1.225 0.7,1.225 8.4875,1.05 9.0125,2.8875 9.0125,7.4375 l 0,41.212503 c 0,4.4625 -0.525,6.3875 -9.0125,7.35 -0.4375,0.0875 -0.7,0.525 -0.7,1.225 0,0.7 0.2625,1.225 0.7,1.225 5.775,0 8.05,-0.525 13.475,-0.525 5.425,0 7.7875,0.525 13.5625,0.525 0.35,0 0.7,-0.525 0.7,-1.225 0,-0.7 -0.35,-1.1375 -0.7,-1.225 -8.4875,-0.9625 -9.1,-2.8875 -9.1,-7.35 l 0,-18.812503 c 6.65,0 7.525,0.7 11.4625,7 l 13.3,21.612503 c 2.5375,0 5.425,-0.525 7.9625,-0.525 1.925,0 5.8625,0.525 8.8375,0.525 0.4375,0 0.7,-0.525 0.7,-1.225 z m -22.3125,-43.925003 c 0,9.1875 -3.5875,14 -13.5625,14 -2.5375,0 -4.4625,-0.0875 -6.3875,-0.35 l 0,-19.5125 c 0,-4.55 0.175,-6.9125 8.75,-6.9125 8.4875,0 11.2,5.425 11.2,12.775 z" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4902"
+           style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:87.5px;font-family:'Hoefler Text';-inkscape-font-specification:'Hoefler Text Medium';fill:#eeeeee;fill-opacity:1"
+           d="m 300.02185,113.8871 c 0,-0.7 -0.525,-1.1375 -0.875,-1.225 -7,-0.7875 -9.5375,-4.2875 -11.1125,-8.75 l -18.2,-50.312503 c -0.0875,-0.35 -0.525,-0.7 -1.225,-0.7 -0.6125,0 -1.05,0.2625 -1.225,0.7 l -20.475,50.312503 c -2.275,5.1625 -4.025,8.225 -10.15,8.75 -0.35,0.0875 -0.9625,0.525 -0.9625,1.225 -0.0875,0.7 0.175,1.225 0.6125,1.225 4.1125,0 5.95,-0.525 9.8,-0.525 4.8125,0 6.0375,0.525 11.2,0.525 0.35,0 0.7,-0.525 0.7,-1.225 0,-0.7 -0.175,-1.225 -0.525,-1.225 -5.5125,-0.2625 -7.0875,-1.8375 -7.0875,-4.2 0,-1.225 0.4375,-2.7125 0.9625,-4.2 l 4.9875,-13.562503 18.025,0 5.075,14.612503 c 0.4375,1.4 0.7875,2.625 0.7875,3.675 0,2.1875 -1.6625,3.4125 -7.35,3.675 -0.35,0 -0.525,0.525 -0.525,1.225 0,0.7 0.35,1.225 0.7,1.225 5.775,0 8.3125,-0.525 13.7375,-0.525 4.8125,0 6.65,0.525 12.425,0.525 0.35,0 0.7,-0.525 0.7,-1.225 z m -26.5125,-25.987503 -16.0125,0 8.3125,-22.4 7.7,22.4 z" />
+      </g>
+    </g>
   </g>
 </svg>
diff --git a/vipra-ui/app/index.html b/vipra-ui/app/index.html
index af9a4e37e24bd80853e73ca7a6e1ae7e042df3b2..8c976eac0623037b3603c0ed40b6ed56df400ff0 100644
--- a/vipra-ui/app/index.html
+++ b/vipra-ui/app/index.html
@@ -9,11 +9,6 @@
   <!-- stylesheets -->
   <link href="css/vendor.css" rel="stylesheet">
   <link href="css/app.css" rel="stylesheet">
-  <!-- javascript -->
-  <script src="js/vendor.js"></script>
-  <script src="js/config.js"></script>
-  <script src="js/app.js"></script>
-  <script src="js/templates.js"></script>
 </head>
 <body ng-attr-class="{{state?state.name:''}}">
   <nav class="navbar navbar-default navbar-fixed-top">
@@ -140,5 +135,10 @@
       <polyline style="animation-delay:1.5s" class="logo-shape" points="0,0 100,75 100,120 0,0" fill="#0079a2" />
     </svg>
   </div>
+  <!-- javascript -->
+  <script src="js/vendor.js"></script>
+  <script src="js/config.js"></script>
+  <script src="js/app.js"></script>
+  <script src="js/templates.js"></script>
 </body>
 </html>
\ No newline at end of file
diff --git a/vipra-ui/app/js/app.js b/vipra-ui/app/js/app.js
index 2985c762f6cb395190b4c125c76a5ea83ad2a131..6754e3f7ddf41904aff5718b64686304201b36ef 100644
--- a/vipra-ui/app/js/app.js
+++ b/vipra-ui/app/js/app.js
@@ -2,7 +2,7 @@
  * Vipra Application
  * Main application file
  ******************************************************************************/
-/* globals angular, $, Vipra */
+/* globals angular, $, Vipra, ReconnectingWebSocket */
 (function() {
 
   "use strict";
@@ -230,32 +230,23 @@
     $rootScope.showMessage = function(msg) {
       AlertFactory.showAlert(msg, {time:7000});
     };
+    
+    var socket = new ReconnectingWebSocket(Vipra.getWSURL(), null, {
+      reconnectInterval: 10000
+    });
 
-    window.vipraWS = function() {
-      var socket = new WebSocket(Vipra.config.websocketUrl);
-
-      socket.onmessage = function(event) {
-        try {
-          var data = JSON.parse(event.data);
-          $rootScope.$apply(function() {
-            $rootScope.handleWSMessage(data);
-          });
-        } catch(e) {
-          $rootScope.$apply(function() {
-            $rootScope.showMessage(event.data);
-          });
-        }
-      };
-
-      socket.onclose = function() {
-        setTimeout(function() {
-          window.vipraWS();
-        }, 5000);
-      };
+    socket.onmessage = function(event) {
+      try {
+        var data = JSON.parse(event.data);
+        $rootScope.$apply(function() {
+          $rootScope.handleWSMessage(data);
+        });
+      } catch(e) {
+        $rootScope.$apply(function() {
+          $rootScope.showMessage(event.data);
+        });
+      }
     };
-
-    window.vipraWS();
-
   }]);
 
   $(document).on('change', '.btn-file :file', function() {
diff --git a/vipra-ui/app/js/config.js b/vipra-ui/app/js/config.js
index 6a10054bf69fd58cbcb0b0a6eb2d8df80251ab43..09dd54209566eccf97d7edb11c00553e28be2e4f 100644
--- a/vipra-ui/app/js/config.js
+++ b/vipra-ui/app/js/config.js
@@ -20,11 +20,6 @@
      *                      this is the restUrl
      */
     restUrl: '/rest',
-
-    /*
-     * Point this URL to the backend websocket. The default is /ws.
-     */
-    websocketUrl: '/ws'
   };
 
 })();
\ No newline at end of file
diff --git a/vipra-ui/app/js/controllers.js b/vipra-ui/app/js/controllers.js
index 31325a87fe71ff73579aa01d9b3056c57aae6837..349a0dc01b3cb09398254231974b1bc239359b01 100644
--- a/vipra-ui/app/js/controllers.js
+++ b/vipra-ui/app/js/controllers.js
@@ -218,6 +218,8 @@
         }, function(data) {
           $scope.searching = false;
           $scope.searchResults = data;
+        }, function() {
+          $scope.searching = false;
         });
       };
 
@@ -292,9 +294,9 @@
 
       $scope.shown = {
         articles: true,
-        similararticles: true,
+        similararticles: false,
         topics: true,
-        words: true
+        words: false
       };
 
       var newNode = function(title, type, show, dbid, color, shape, loader) {
@@ -324,6 +326,9 @@
           },
           font: {
             color: '#000'
+          },
+          shadow: {
+            enabled: true
           }
         };
       };
@@ -350,7 +355,7 @@
       };
 
       var wordNode = function(word) {
-        return newNode(word.id, 'word', 'word.show', word.id, $scope.colors.words, 'box', $scope.loadWord);
+        return newNode(word.id, 'word', 'words.show', word.id, $scope.colors.words, 'box', $scope.loadWord);
       };
 
       var edgeExists = function(idA, idB) {
@@ -413,11 +418,18 @@
         }, 500);
       };
 
+      $scope.deselect = function() {
+        $scope.$apply(function() {
+          $scope.currentArticle = null;
+        });
+      };
+
       $scope.loadArticle = function(node) {
         ArticleFactory.get({
           id: node.dbid,
           fields: '_all'
         }, function(data) {
+          $scope.currentArticle = data;
           var i;
           if (data.topics) {
             for (i = 0; i < data.topics.length; i++)
@@ -436,7 +448,8 @@
       $scope.loadTopic = function(node) {
         if ($scope.shown.articles) {
           TopicFactory.articles({
-            id: node.dbid
+            id: node.dbid,
+            limit: 50
           }, function(data) {
             constructor(data, node, articleNode);
           });
@@ -494,6 +507,14 @@
         });
       };
 
+      $scope.completeNetwork = function() {
+        var nodes = $scope.nodes.get(),
+          updates = [];
+        for(var i = 0; i < nodes.length; i++)
+          nodes[i].loader(nodes[i]);
+        $scope.nodes.update(updates);
+      };
+
       $scope.$watch('rootModels.topicModel', function(newVal) {
         if ($scope.rootNode && $scope.rootNode.topicModel.id !== newVal.id)
           $state.transitionTo('index');
@@ -544,6 +565,7 @@
       var container = document.getElementById("visgraph");
       $scope.graph = new vis.Network(container, $scope.data, $scope.options);
       $scope.graph.on('selectNode', $scope.select);
+      $scope.graph.on('deselectNode', $scope.deselect);
       $scope.graph.on('doubleClick', $scope.open);
 
       if($stateParams.type) {
diff --git a/vipra-ui/app/js/directives.js b/vipra-ui/app/js/directives.js
index a2989a5ec29695d54d64464868817405150d69ac..ea7f9b94083fc789886efa435a6d59585f7276df 100644
--- a/vipra-ui/app/js/directives.js
+++ b/vipra-ui/app/js/directives.js
@@ -508,4 +508,34 @@
     };
   }]);
 
+  app.directive('articlePopover', ['ArticleFactory', function(ArticleFactory) {
+    return {
+      scope: {
+        id: '=',
+        article: '='
+      },
+      link: function($scope) {
+        $scope.$watch('id', function() {
+          if(!$scope.id) {
+            $scope.currentArticle = null;
+            return;
+          }
+
+          ArticleFactory.get({
+            id: $scope.id
+          }, function(data) {
+            $scope.currentArticle = data;
+            $scope.currentArticleDate = $scope.currentArticle ? Vipra.formatDate($scope.currentArticle.date) : null;
+          });
+        });
+
+        $scope.$watch('article', function() {
+          $scope.currentArticle = $scope.article;
+          $scope.currentArticleDate = $scope.article ? Vipra.formatDate($scope.currentArticle.date) : null;
+        });
+      },
+      templateUrl: 'html/directives/article-popover.html'
+    };
+  }]);
+
 })();
\ No newline at end of file
diff --git a/vipra-ui/app/js/helpers.js b/vipra-ui/app/js/helpers.js
index c3e02bbfa25b64f56da960c65f83525bd889c01c..c8eba43588d65ba0f5b47d82997893220372e945 100644
--- a/vipra-ui/app/js/helpers.js
+++ b/vipra-ui/app/js/helpers.js
@@ -168,6 +168,19 @@
     }
   };
 
+  Vipra.getWSURL = function() {
+    if(Vipra.config.websocketUrl) return Vipra.config.websocketUrl;
+    var protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
+    var path = Vipra.config.restUrl.replace(/rest$/, 'ws');
+    if(Vipra.config.restUrl.indexOf('//') !== -1) {
+      // contains protocol
+      return path.replace(/^[^/]+\/\//, protocol + '//');
+    } else {
+      // contains no protocol
+      return protocol + location.hostname + path;
+    }
+  };
+
   /**
    * Polyfills
    */
diff --git a/vipra-ui/app/less/app.less b/vipra-ui/app/less/app.less
index cb294ea3bac6b30d38f0a947bae457c4d40970c6..abb14385268ae0c83f99a9e3656d0fcced8874c9 100644
--- a/vipra-ui/app/less/app.less
+++ b/vipra-ui/app/less/app.less
@@ -3,6 +3,7 @@
 @sidebar-padding: 5px;
 @sidebar-width: 250px;
 @bar-color: #f8f8f8;
+@graph-spacing: 5px;
 
 html {
   position: relative;
@@ -85,32 +86,51 @@ a:hover {
   bottom: 50px;
 }
 
-.graph-legend {
-  @spacing: 5px;
+.graph-item {
   position: absolute;
-  top: 10px;
-  left: 10px;
-  padding: @spacing*2;
+  padding: @graph-spacing*2;
   background: rgba(128, 128, 128, 0.1);
   border-radius: 5px;
-  &:not(.collapsed) {
+  &:hover {
+    background: rgb(242, 242, 242);
+  }
+  &.top-left {
+    top: 10px;
+    left: 10px;
+  }
+  &.bottom-left {
+    bottom: 10px;
+    left: 10px;
+  }
+  &.top-right {
+    top: 10px;
+    right: 10px;
+  }
+  &.bottom-right {
+    bottom: 10px;
+    right: 10px;
+  }
+  &.small:not(.collapsed) {
     width: 220px;
   }
+  &.large:not(.collapsed) {
+    width: 400px;
+  }
   label + label {
-    padding-left: @spacing;
+    padding-left: @graph-spacing;
   }
   label,
   .checkbox {
     margin: 0;
   }
   div + div {
-    margin-top: @spacing;
+    margin-top: @graph-spacing;
   }
   table,
   table button {
     width: 100%;
     td + td {
-      padding-left: @spacing;
+      padding-left: @graph-spacing;
     }
   }
   .collapser {
@@ -120,6 +140,10 @@ a:hover {
   }
 }
 
+.graph-popover {
+
+}
+
 .initial {
   float: left;
   font-size: 70px;
@@ -741,8 +765,10 @@ entity-menu {
     padding: 80px 0 30px 0;
   }
   .text-logo {
-    font-size: 50px;
+    font-size: 60px;
+    letter-spacing: -8px;
     color: #fff;
+    text-shadow: 0 0 5px rgba(255,255,255,0.5);
   }
 }
 
@@ -755,10 +781,13 @@ entity-menu {
 
 .index {
   .navbar-default {
-    border: 0;
-    background: rgba(255,255,255,0.6);
+    border-color: rgba(255,255,255,.2);
+    background: 0;
     .navbar-nav>li>a {
       color: #555;
+      &:hover {
+        background-color: rgba(255,255,255,.2);
+      }
     }
   }
 }
@@ -808,16 +837,23 @@ entity-menu {
   outline: none;
 }
 
-@-moz-keyframes spin {
-  100% {
-    -moz-transform: rotateY(360deg);
-  }
+.break-words {
+  word-break: break-all;
 }
 
-@-webkit-keyframes spin {
-  100% {
-    -webkit-transform: rotateY(360deg);
-  }
+.article-popover-text {
+  max-height: 300px;
+  overflow-y: auto;
+  overflow-x: hidden;
+}
+
+.cfp-hotkeys-key {
+  width: 40px;
+}
+
+.screencast {
+  background: #eee;
+  margin: 10px auto;
 }
 
 @keyframes spin {
diff --git a/vipra-ui/bower.json b/vipra-ui/bower.json
index e29148b23a4626a8214c37e3867a3656ede6d8bb..8c9f679495ef4808a7334a6cdaabac02eddf1bbe 100644
--- a/vipra-ui/bower.json
+++ b/vipra-ui/bower.json
@@ -33,6 +33,7 @@
     "randomcolor": "randomColor#^0.x",
     "bootbox.js": "bootbox#^4.x",
     "angular-hotkeys": "chieffancypants/angular-hotkeys#^1.x",
-    "eonasdan-bootstrap-datetimepicker": "^4.x"
+    "eonasdan-bootstrap-datetimepicker": "^4.x",
+    "reconnectingWebsocket": "joewalnes/reconnecting-websocket#^1.0.0"
   }
 }
diff --git a/vipra-ui/gulpfile.js b/vipra-ui/gulpfile.js
index 900439345488c7b7d2d13e5623e2be43b8909ad1..01da53265233c67e0b2a18762ce9a7a3b110160a 100644
--- a/vipra-ui/gulpfile.js
+++ b/vipra-ui/gulpfile.js
@@ -27,7 +27,8 @@ var assets = {
     'bower_components/nya-bootstrap-select/dist/js/nya-bs-select.min.js',
     'bower_components/randomcolor/randomColor.js',
     'bower_components/bootbox.js/bootbox.js',
-    'bower_components/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js'
+    'bower_components/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js',
+    'bower_components/reconnectingWebsocket/reconnecting-websocket.min.js'
   ],
   css: [
     'bower_components/bootstrap/dist/css/bootstrap.min.css',
@@ -70,7 +71,7 @@ gulp.task('js', function() {
 });
 
 gulp.task('js-rel', function() {
-  gulp.src(['app/js/**/*.js', '!app/js/config.js'])
+  gulp.src(['app/js/**/*.js', '!app/js/config.js', '!app/js/dev.js'])
     .pipe(concat('app.js'))
     .pipe(ngannotate())
     .pipe(uglify())
diff --git a/vipra-ui/package.json b/vipra-ui/package.json
index 6a28e95a2321e383701656553b6cbd9dd633794f..7cccad3b4cae989111e9cd948ef869a6bc669a13 100644
--- a/vipra-ui/package.json
+++ b/vipra-ui/package.json
@@ -10,9 +10,7 @@
     "gulp-angular-templatecache": "^1.8.0",
     "gulp-clean-css": "^2.0.3",
     "gulp-concat": "^2.6.0",
-    "gulp-cssnano": "^2.1.0",
     "gulp-gzip": "^1.2.0",
-    "gulp-include": "^2.1.0",
     "gulp-less": "^3.0.5",
     "gulp-ng-annotate": "^2.0.0",
     "gulp-uglify": "^1.5.1",
diff --git a/vipra-util/src/main/java/de/vipra/util/FileUtils.java b/vipra-util/src/main/java/de/vipra/util/FileUtils.java
index 6a018fa4f9792b1dd9cdf5b2c0f8ef7f6f5e45f3..c3395210ba3434e03c79150a94b03c071fb2a41c 100644
--- a/vipra-util/src/main/java/de/vipra/util/FileUtils.java
+++ b/vipra-util/src/main/java/de/vipra/util/FileUtils.java
@@ -157,4 +157,14 @@ public class FileUtils extends org.apache.commons.io.FileUtils {
 		}).init(file);
 	}
 
+	public static File getTempFile(final String fileName) {
+		return new File(PathUtils.tempDir(), fileName);
+	}
+
+	public static File createTempFile(final String fileName) throws IOException {
+		final File file = getTempFile(fileName);
+		file.createNewFile();
+		return file;
+	}
+
 }
diff --git a/vipra-util/src/main/java/de/vipra/util/IPCMessageCode.java b/vipra-util/src/main/java/de/vipra/util/IPCMessageCode.java
index 59fb104e6de77561ba5839bc6265a3cdddae2bc0..811020be7997e6012609e0e8f8cf94723cc92979 100644
--- a/vipra-util/src/main/java/de/vipra/util/IPCMessageCode.java
+++ b/vipra-util/src/main/java/de/vipra/util/IPCMessageCode.java
@@ -3,10 +3,7 @@ package de.vipra.util;
 public enum IPCMessageCode {
 	TEST,
 	MESSAGE,
-	START_MODELING,
-	STOP_MODELING,
-	START_INDEXING,
-	STOP_INDEXING,
-	START_IMPORTING,
-	STOP_IMPORTING
+	MODELING,
+	INDEXING,
+	IMPORTING
 }
\ No newline at end of file
diff --git a/vipra-util/src/main/java/de/vipra/util/LockFile.java b/vipra-util/src/main/java/de/vipra/util/LockFile.java
index b68de7f6e18dc6f5fc7ed572dbf8eec5bd7fdc2a..68826b0f549a2f595fae71006ea3d8175730d6cd 100644
--- a/vipra-util/src/main/java/de/vipra/util/LockFile.java
+++ b/vipra-util/src/main/java/de/vipra/util/LockFile.java
@@ -7,7 +7,7 @@ import de.vipra.util.ex.LockFileException;
 
 public class LockFile {
 
-	private final File file = new File(PathUtils.tempDir(), "vipra.lock");
+	private final File file = FileUtils.getTempFile("vipra.lock");
 
 	public void lock() throws LockFileException {
 		if (isLocked())
diff --git a/vm/.gitignore b/vm/.gitignore
deleted file mode 100644
index dba9e7ff8f64e7235cb62cb93d3fdc9598dcf385..0000000000000000000000000000000000000000
--- a/vm/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-data/
-webapps/*
-webroot/*
\ No newline at end of file
diff --git a/vm/README.md b/vm/README.md
deleted file mode 100644
index 2a64d8d5b09a97e6b50592a5cfb06b01bc24027a..0000000000000000000000000000000000000000
--- a/vm/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# VM
-
-This is the development vagrant vm base. It contains the vm bootstrap file.
\ No newline at end of file
diff --git a/vm/bootstrap.sh b/vm/bootstrap.sh
deleted file mode 100644
index 3f16a108e4f441315b79eccee2ad437e293ef43d..0000000000000000000000000000000000000000
--- a/vm/bootstrap.sh
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/bin/sh
-
-# -----------------------------------------------------------------------------
-# upgrade system
-
-apt-get update
-apt-get upgrade -y
-
-# -----------------------------------------------------------------------------
-# install packages
-
-apt-get install git gdebi-core openjdk-8-jdk openjdk-8-jre mongodb tomcat8 -y
-
-# -----------------------------------------------------------------------------
-# setup tomcat
-
-# change user
-echo "TOMCAT8_USER=vagrant" >> /etc/default/tomcat8
-echo "TOMCAT8_GROUP=vagrant" >> /etc/default/tomcat8
-chown -R vagrant.vagrant /var/log/tomcat8 /var/cache/tomcat8 /var/lib/tomcat8/conf/*
-
-# webapp directory
-rm -rf /vagrant/vm/webapps
-mkdir /vagrant/vm/webapps
-ln -sf /vagrant/vm/webapps /var/lib/tomcat8/webapps
-
-systemctl enable tomcat8
-systemctl restart tomcat8
-
-# -----------------------------------------------------------------------------
-# install elasticsearch
-
-wget https://download.elasticsearch.org/elasticsearch/release/org/elasticsearch/distribution/deb/elasticsearch/2.1.1/elasticsearch-2.1.1.deb
-gdebi -n elasticsearch-2.1.1.deb
-rm elasticsearch-2.1.1.deb
-
-systemctl enable elasticsearch
-systemctl restart elasticsearch
-
-# -----------------------------------------------------------------------------
-# disable firewall
-
-ufw disable
-
-# -----------------------------------------------------------------------------
-# cleanup
-
-apt-get autoremove -y
-apt-get clean
-
-echo ""
-echo "--------------------------------------------------------------"
-echo "--- Provisioning complete."
-echo "--------------------------------------------------------------"
-echo ""
-
-exit 0
\ No newline at end of file
diff --git a/vm/webroot/.gitkeep b/vm/webroot/.gitkeep
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000