diff --git a/vipra-cmd/runcfg/CMD.launch b/vipra-cmd/runcfg/CMD.launch
index 2684d5379e17d2688b8b6be10bfd0a026892f0fa..bee7078bfab75ad04d237aa2164895de91ae036e 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="-S test -dcI /home/eike/repos/master/ma-impl/docker/data/test-1.json"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-S test2 -dcI /home/eike/repos/master/ma-impl/docker/data/test-1.json"/>
 <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/lda/Analyzer.java b/vipra-cmd/src/main/java/de/vipra/cmd/lda/Analyzer.java
index 2409ea023cf53bd54a56be0b2c9b7dab24f5fa69..92fb40b5a56db54f9b2e0cb05ecdf3c4dc4c9e6c 100644
--- a/vipra-cmd/src/main/java/de/vipra/cmd/lda/Analyzer.java
+++ b/vipra-cmd/src/main/java/de/vipra/cmd/lda/Analyzer.java
@@ -237,7 +237,7 @@ public class Analyzer {
 			final double[][] probabilities = new double[wordCount][windowCount];
 			for (int idxWord = 0; idxWord < wordCount; idxWord++) {
 				for (int idxSeq = 0; idxSeq < windowCount; idxSeq++) {
-					probabilities[idxWord][idxSeq] = Double.parseDouble(in.readLine());
+					probabilities[idxWord][idxSeq] = Math.exp(Double.parseDouble(in.readLine()));
 				}
 			}
 
diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/option/CreateModelCommand.java b/vipra-cmd/src/main/java/de/vipra/cmd/option/CreateModelCommand.java
index 14df7a19542cedd76f590774ee1757e7efd361db..bfa74d5867a211d1c9092e698bda8bae07511046 100644
--- a/vipra-cmd/src/main/java/de/vipra/cmd/option/CreateModelCommand.java
+++ b/vipra-cmd/src/main/java/de/vipra/cmd/option/CreateModelCommand.java
@@ -1,18 +1,13 @@
 package de.vipra.cmd.option;
 
 import java.io.File;
-import java.io.IOException;
 import java.util.Random;
 
 import org.bson.types.ObjectId;
 
-import com.fasterxml.jackson.core.JsonGenerationException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-
 import de.vipra.cmd.Main;
 import de.vipra.util.Config;
 import de.vipra.util.ConsoleUtils;
-import de.vipra.util.ex.DatabaseException;
 import de.vipra.util.model.TopicModelConfig;
 import de.vipra.util.model.TopicModelFull;
 import de.vipra.util.service.MongoService;
@@ -28,15 +23,21 @@ public class CreateModelCommand implements Command {
 		this.names = names;
 	}
 
-	private TopicModelFull createModel(final String name, final TopicModelConfig modelConfig, final File modelDir)
-			throws JsonGenerationException, JsonMappingException, IOException, DatabaseException {
+	private TopicModelFull createModel(final String name, final TopicModelConfig modelConfig) throws Exception {
 		final TopicModelFull topicModel = new TopicModelFull(name, modelConfig);
 		topicModel.setColorSeed(random.nextLong());
+		dbTopicModels.createSingle(topicModel);
+		config.getTopicModelConfigs().put(topicModel.getName(), modelConfig);
+
+		final File modelDir = new File(config.getDataDirectory(), topicModel.getName());
+
+		if (!modelDir.mkdirs())
+			throw new Exception("could not create model directory: " + modelDir.getAbsolutePath());
+
 		modelConfig.setName(topicModel.getName());
 		modelConfig.setGroup(topicModel.getGroup());
 		modelConfig.saveToFile(modelDir);
-		dbTopicModels.createSingle(topicModel);
-		config.getTopicModelConfigs().put(topicModel.getName(), modelConfig);
+
 		return topicModel;
 	}
 
@@ -63,12 +64,7 @@ public class CreateModelCommand implements Command {
 			if (msg != null)
 				throw new Exception(msg);
 
-			final File modelDir = new File(config.getDataDirectory(), name);
-
-			if (!modelDir.mkdirs())
-				throw new Exception("could not create model directory: " + modelDir.getAbsolutePath());
-
-			final TopicModelFull topicModel = createModel(name, modelConfig, modelDir);
+			final TopicModelFull topicModel = createModel(name, modelConfig);
 			ConsoleUtils
 					.info("model created: " + topicModel.getName() + (topicModel.getGroup() == null ? "" : " in group: " + topicModel.getGroup()));
 			Main.stats.stop("create." + name);
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 427a830610a7b097ffb4a9a539a5a2627426f3d3..dc6885da292f6f58e078cec4e4167aee31aa2808 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
@@ -6,6 +6,7 @@ import java.io.FileReader;
 import java.io.FilenameFilter;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -182,11 +183,12 @@ public class ImportCommand implements Command {
 				if (spotlightAnalyzer != null) {
 					final SpotlightResponse spotlightResponse = spotlightAnalyzer.analyze(article.getText());
 
-					final List<TextEntityCount> textEntitiesCounts = spotlightResponse.getEntities();
+					List<TextEntityCount> textEntitiesCounts = spotlightResponse.getEntities();
 					if (textEntitiesCounts != null) {
 						// replace entities with hypernyms
 						if (modelConfig.isProcessorUseHypernyms()) {
 							final HypernymAnalyzer hypernymAnalyzer = HypernymAnalyzer.getInstance();
+							final Map<String, TextEntityCount> replacedTextEntities = new HashMap<>(textEntitiesCounts.size());
 							for (final TextEntityCount textEntityCount : textEntitiesCounts) {
 								final TextEntity textEntity = textEntityCount.getEntity();
 								final String hypernym = hypernymAnalyzer.getHypernym(textEntity.realEntity());
@@ -194,7 +196,13 @@ public class ImportCommand implements Command {
 									textEntity.setUrl(hypernymAnalyzer.getURL(hypernym));
 									textEntity.setIsHypernym(true);
 								}
+								final TextEntityCount replacedTextEntity = replacedTextEntities.get(textEntity.getUrl());
+								if (replacedTextEntity != null)
+									replacedTextEntity.setCount(replacedTextEntity.getCount() + textEntityCount.getCount());
+								else
+									replacedTextEntities.put(textEntity.getUrl(), textEntityCount);
 							}
+							textEntitiesCounts = new ArrayList<>(replacedTextEntities.values());
 						}
 
 						blockedWords = new HashSet<>(textEntitiesCounts.size());
diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/option/ListModelsCommand.java b/vipra-cmd/src/main/java/de/vipra/cmd/option/ListModelsCommand.java
index c899a979326d816daff6b3eba6a76486cdabecdc..0959b78d4cd8840945ffdac9aec0a32c09e70908 100644
--- a/vipra-cmd/src/main/java/de/vipra/cmd/option/ListModelsCommand.java
+++ b/vipra-cmd/src/main/java/de/vipra/cmd/option/ListModelsCommand.java
@@ -20,7 +20,7 @@ public class ListModelsCommand implements Command {
 			longestModelName = Math.max(longestModelName, entry.getValue().getName().length());
 		for (final Entry<String, TopicModelConfig> entry : config.getTopicModelConfigs().entrySet())
 			ConsoleUtils.info(Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a(StringUtils.pad(entry.getValue().getName(), longestModelName)).reset()
-					+ " " + entry.getValue().toString());
+					+ " " + entry.getValue().toString() + " " + entry.getValue().getGroup());
 	}
 
 	@Override
diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/text/StopwordsAnnotator.java b/vipra-cmd/src/main/java/de/vipra/cmd/text/StopwordsAnnotator.java
index 2a4c19856e5bc291688548246e6bdd659753aa25..04aefe2ec642fb78db1f2dd2e60f3b976b1a6e7b 100644
--- a/vipra-cmd/src/main/java/de/vipra/cmd/text/StopwordsAnnotator.java
+++ b/vipra-cmd/src/main/java/de/vipra/cmd/text/StopwordsAnnotator.java
@@ -21,7 +21,7 @@ public class StopwordsAnnotator implements Annotator, CoreAnnotation<Boolean> {
 
 	public StopwordsAnnotator(final String input, final Properties props) {
 		stopWords = new HashSet<>(Arrays.asList(props.getProperty(NAME).split(" ")));
-		stopWords.addAll(Arrays.asList("-LRB-", "-RRB-", "-LSB-", "-RSB-", "-LCB-", "-RCB-"));
+		stopWords.addAll(Arrays.asList("-lrb-", "-rrb-", "-lsb-", "-rsb-", "-lcb-", "-rcb-"));
 	}
 
 	@Override
diff --git a/vipra-ui/app/html/articles/entities.html b/vipra-ui/app/html/articles/entities.html
index 493746dfc6bb01612d96b6c7dbc512d5869e2f3d..13de7b7631fd7705813f0196e5ab8e3f52428b54 100644
--- a/vipra-ui/app/html/articles/entities.html
+++ b/vipra-ui/app/html/articles/entities.html
@@ -41,7 +41,7 @@
                   </tr>
                 </thead>
                 <tbody>
-                  <tr ng-repeat="entity in entities | orderBy:articlesShowModels.entitiesSort">
+                  <tr ng-repeat="entity in entities | orderBy:articlesShowModels.entitiesSort track by entity.entity.entity">
                     <td>
                       <entity-link entity="::entity.entity" />
                     </td>
diff --git a/vipra-ui/app/html/articles/index.html b/vipra-ui/app/html/articles/index.html
index 24518891e9f283cbd192b3128038d2dee63f7286..fa42a19b59d91fbb8da3026f10b991c06b13f317 100644
--- a/vipra-ui/app/html/articles/index.html
+++ b/vipra-ui/app/html/articles/index.html
@@ -14,13 +14,10 @@
           <div class="panel-heading clearfix">
             Found
             <ng-pluralize count="articlesTotal||0" when="{0:'no articles',1:'1 article',other:'{} articles'}"></ng-pluralize> in the database.
-            <div class="pull-right">
-              Page <span ng-bind="wordsIndexModels.page||1"></span> of <span ng-bind="maxPage||1"></span>
-            </div>
           </div>
           <table class="table table-hover table-condensed table-fixed">
             <tbody>
-              <tr ng-repeat="article in articles">
+              <tr ng-repeat="article in articles track by article.id">
                 <td>
                   <article-link article="::article"/>
                 </td>
@@ -33,10 +30,8 @@
               </tr>
             </tbody>
           </table>
-          <div class="panel-footer clearfix">
-            <div class="pull-right">
-              Page <span ng-bind="wordsIndexModels.page||1"></span> of <span ng-bind="maxPage||1"></span>
-            </div>
+          <div class="panel-footer">
+            <sub-pagination total="articlesTotal" page="articlesIndexModels.page" limit="articlesIndexModels.limit" />
           </div>
         </div>
       </div>
diff --git a/vipra-ui/app/html/articles/show.html b/vipra-ui/app/html/articles/show.html
index 9fe9273f91f06152a84935dd5de7596af16927d8..b95e11333563c858cacb5d0facf3b9e9d0d44521 100644
--- a/vipra-ui/app/html/articles/show.html
+++ b/vipra-ui/app/html/articles/show.html
@@ -30,7 +30,7 @@
               <tbody>
                 <tr>
                   <th class="infocol">Date</th>
-                  <td ng-bind-template="{{$root.Vipra.formatDateTime(article.date)}}"></td>
+                  <td ng-bind-template="{{Vipra.formatDateTime(article.date)}}"></td>
                 </tr>
                 <tr ng-if="article.url">
                   <th>URL</th>
@@ -58,18 +58,14 @@
                 <tr>
                   <th class="infocol" ng-model="articlesShowModels.topicsSort" sort-by="share">Share</th>
                   <th ng-model="articlesShowModels.topicsSort" sort-by="topic.name">Name</th>
-                  <th class="colorcol"></th>
                 </tr>
               </thead>
               <tbody>
-                <tr ng-repeat="topic in article.topics | orderBy:articlesShowModels.topicsSort" ng-mouseenter="highlightSlice(topic.topic.id, true)" ng-mouseleave="highlightSlice(topic.topic.id, false)">
-                  <td class="text-right" ng-bind-template="{{(topic.share*100).toFixed(0)}}%"></td>
+                <tr ng-repeat="topic in article.topics | orderBy:articlesShowModels.topicsSort track by topic.topic.id" ng-mouseenter="highlightSlice(topic.topic.id, true)" ng-mouseleave="highlightSlice(topic.topic.id, false)">
+                  <td class="text-right" ng-bind-template="{{::(topic.share*100).toFixed(0)}}%"></td>
                   <td>
                     <topic-link topic="::topic.topic" />
                   </td>
-                  <td>
-                    <span class="colorbox shown plain" style="background:{{::topic.color}}"></span>
-                  </td>
                 </tr>
               </tbody>
             </table>
@@ -89,7 +85,7 @@
             </tr>
           </thead>
           <tbody>
-            <tr ng-repeat="simArticle in article.similarArticles | orderBy:articlesShowModels.similarSort">
+            <tr ng-repeat="simArticle in article.similarArticles | orderBy:articlesShowModels.similarSort track by simArticle.article.id">
               <td class="text-right" ng-bind-template="{{::simArticle.share}}%"></td>
               <td>
                 <article-link article="::simArticle.article" />
diff --git a/vipra-ui/app/html/articles/words.html b/vipra-ui/app/html/articles/words.html
index 7c9a87ba6b44d2822828dd5839efa5fb72c59fd9..ccdf7b9beade0a6250cc1df34e7ff3814bad7b9e 100644
--- a/vipra-ui/app/html/articles/words.html
+++ b/vipra-ui/app/html/articles/words.html
@@ -44,7 +44,7 @@
                   </tr>
                 </thead>
                 <tbody>
-                  <tr ng-repeat="word in words | orderBy:articlesShowModels.wordsSort">
+                  <tr ng-repeat="word in words | orderBy:articlesShowModels.wordsSort track by word.word">
                     <td>
                       <word-link word="::word" />
                     </td>
diff --git a/vipra-ui/app/html/directives/alert.html b/vipra-ui/app/html/directives/alert.html
index c703f74d9eb64413bc240f21ab2d2bb34ca6793d..c565a37e4d813a997e8cd9ad1017113ecd508a39 100644
--- a/vipra-ui/app/html/directives/alert.html
+++ b/vipra-ui/app/html/directives/alert.html
@@ -1,4 +1,4 @@
-<div ng-attr-class="{{classes}}" role="alert">
+<div ng-attr-class="{{::classes}}" role="alert">
   <button type="button" class="close" data-dismiss="alert" aria-label="Close" ng-if="dismissible"><span aria-hidden="true">&times;</span></button>
-  <strong ng-bind="ngModel.title"></strong> <span ng-bind="ngModel.detail"></span>
+  <strong ng-bind="::ngModel.title"></strong> <span ng-bind="::ngModel.detail"></span>
 </div>
\ No newline at end of file
diff --git a/vipra-ui/app/html/directives/article-link.html b/vipra-ui/app/html/directives/article-link.html
index 952d2991b5e61401bdb68726e4220a81956b1758..e4e93c8fd219761cf7fc2cd531e2a25e2a021b55 100644
--- a/vipra-ui/app/html/directives/article-link.html
+++ b/vipra-ui/app/html/directives/article-link.html
@@ -9,7 +9,7 @@
       <i class="fa text-muted pointer" ng-class="{'fa-chevron-down':!detailsShown,'fa-chevron-up':detailsShown}" ng-click="toggleDetails()" ng-if="::showDetails" analytics-on analytics-event="Article details" analytics-category="Article actions"></i>
     </div>
     <a class="article-link" ui-sref="articles.show({id:article.id})" ng-attr-title="{{::article.title}}">
-      <span class="title" ng-bind="article.title"></span>
+      <span class="title" ng-bind="::article.title"></span>
       <ng-transclude/>
     </a>
   </span>
@@ -17,7 +17,7 @@
   <div ng-if="detailsShown" class="details">
     <span ng-bind="::articleDetails.text"></span>
     <div>
-      <a class="badge topic-badge text-outline" ng-style="{'background':topic.topic.color}" ng-repeat="topic in articleDetails.topics">
+      <a class="badge topic-badge text-outline" ng-style="{'background':topic.topic.color}" ng-repeat="topic in articleDetails.topics track by topic.topic.id">
         <topic-link topic="::topic.topic" badge="false" />
       </a>
     </div>
diff --git a/vipra-ui/app/html/directives/article-menu.html b/vipra-ui/app/html/directives/article-menu.html
index 09815f09a46b98ed3d312bb0bf6001545029f853..4ae1d1143eba6caf251f6659f95ac3f00d25e246 100644
--- a/vipra-ui/app/html/directives/article-menu.html
+++ b/vipra-ui/app/html/directives/article-menu.html
@@ -4,7 +4,8 @@
   </a>
   <ul class="dropdown-menu" ng-class="{'dropdown-menu-right':dropdownRight}">
     <li><a ui-sref="articles.show({id:article.id})">Show</a></li>
-    <li role="separator" class="divider"></li>
+    <li><a ui-sref="articles.show.entities({id:article.id})">Entities</a></li>
+    <li><a ui-sref="articles.show.words({id:article.id})">Words</a></li>
     <li><a ui-sref="network({type:'articles',id:article.id})">Network</a></li>
   </ul>
 </div>
\ No newline at end of file
diff --git a/vipra-ui/app/html/directives/entity-link.html b/vipra-ui/app/html/directives/entity-link.html
index 5fb9e2fdbca25ea8b202ecd08de14f5d36cfa975..2abd24c2f03477e60c21625142fec7cd0cba9692 100644
--- a/vipra-ui/app/html/directives/entity-link.html
+++ b/vipra-ui/app/html/directives/entity-link.html
@@ -1,7 +1,7 @@
 <div class="link-wrapper">
   <span class="menu-padding ellipsis">
     <a class="entity-link" ui-sref="entities.show({id:entity.entity})" ng-attr-title="{{::entity.entity}}">
-      <span class="title" ng-bind="entity.entity"></span>
+      <span class="title" ng-bind="::entity.entity"></span>
       <ng-transclude/>
     </a>
   </span>
diff --git a/vipra-ui/app/html/directives/entity-menu.html b/vipra-ui/app/html/directives/entity-menu.html
index 1e1c965f9a5b4776ce98e182240d3c9f6e9b758c..1d205f726fd44be870cb1a86b550bc802450a95c 100644
--- a/vipra-ui/app/html/directives/entity-menu.html
+++ b/vipra-ui/app/html/directives/entity-menu.html
@@ -5,7 +5,6 @@
   <ul class="dropdown-menu" ng-class="{'dropdown-menu-right':dropdownRight}">
     <li><a ui-sref="entities.show({id:entity.entity})">Show</a></li>
     <li ng-if="entity.isWord"><a ui-sref="words.show({id:entity.entity})">Show word</a></li>
-    <li role="separator" class="divider"></li>
     <li><a ui-sref="entities.show.articles({id:entity.entity})">Articles</a></li>
     <li role="separator" class="divider"></li>
     <li><a ng-href="{{entity.url}}" target="_blank"><span class="dbpedia-logo"></span> DBPedia</a></li>
diff --git a/vipra-ui/app/html/directives/pagination-full.html b/vipra-ui/app/html/directives/pagination-full.html
index 7564a87c025a491eaf2e554a3a882ba83cd4b220..30e2564110e7da1b3f64aed57a87eecc89dc7aae 100644
--- a/vipra-ui/app/html/directives/pagination-full.html
+++ b/vipra-ui/app/html/directives/pagination-full.html
@@ -28,7 +28,7 @@
   </div>
 
   <div class="btn-group btn-group-justified button-pagination">
-    <div class="btn-group" ng-repeat="p in pages">
+    <div class="btn-group" ng-repeat="p in pages track by p">
       <button class="btn btn-default" ng-class="{current:page==p}" ng-attr-title="{{'Page ' + p}}" ng-click="changePage(p)" analytics-on analytics-event="Paginator (i)" analytics-category="Filter actions" ng-bind="p"></button>
     </div>
   </div>
diff --git a/vipra-ui/app/html/directives/pagination.html b/vipra-ui/app/html/directives/pagination.html
index 069d579dadc6fbd51f327639947d9b82b65fa83a..b5f42ab659c944eca192c8b2b81bd92e7de3813e 100644
--- a/vipra-ui/app/html/directives/pagination.html
+++ b/vipra-ui/app/html/directives/pagination.html
@@ -8,7 +8,7 @@
       <a ui-sref="{page:page==2?null:page-1}" ng-show="page>1" ng-click="changePage(page-1)" analytics-on analytics-event="Paginator (-1)" analytics-category="Filter actions" ng-cloak>&lsaquo;</a>
       <span ng-hide="page>1">&lsaquo;</span>
     </li>
-    <li ng-class="{active:p==page}" ng-repeat="p in pages">
+    <li ng-class="{active:p==page}" ng-repeat="p in pages track by p">
       <a ui-sref="{page:p===1?null:p}" ng-bind="p" ng-click="changePage(p)" analytics-on analytics-event="Paginator (i)" analytics-category="Filter actions"></a>
     </li>
     <li title="Next" ng-class="{disabled:page>=maxPage}">
diff --git a/vipra-ui/app/html/directives/sequence-dropdown.html b/vipra-ui/app/html/directives/sequence-dropdown.html
index cd86d8ffc3b24c4105460572d55a4a9ab62debd1..5c4bb1cc0122098b3ced7d4d14052b344c4d3a5d 100644
--- a/vipra-ui/app/html/directives/sequence-dropdown.html
+++ b/vipra-ui/app/html/directives/sequence-dropdown.html
@@ -1 +1,3 @@
-<select class="form-control inline" ng-model="ngModel" ng-disabled="!sequences" ng-options="sequence as sequence.label for sequence in sequences track by sequence.id"></select>
\ No newline at end of file
+<select class="form-control inline" ng-model="ngModel" ng-disabled="!sequences" ng-options="sequence as sequence.label for sequence in sequences track by sequence.id">
+  <option value="" style="display:none" disabled selected>None</option>
+</select>
\ No newline at end of file
diff --git a/vipra-ui/app/html/directives/sub-pagination.html b/vipra-ui/app/html/directives/sub-pagination.html
new file mode 100644
index 0000000000000000000000000000000000000000..0c3ccc0cb0df498d7c50e896ac6ec9040ee18764
--- /dev/null
+++ b/vipra-ui/app/html/directives/sub-pagination.html
@@ -0,0 +1,15 @@
+<ul class="pager">
+  <li class="previous" ng-class="{disabled:page===1}">
+    <a ng-click="changePage(page-1)" analytics-on analytics-event="Paginator (-1)" analytics-category="Filter actions">
+      <i class="fa fa-angle-left"></i> Prev
+    </a>
+  </li>
+  <li class="current">
+    Page <span ng-bind="page||1"></span> of <span ng-bind="maxPage||1"></span>
+  </li>
+  <li class="next" ng-class="{disabled:page>=maxPage}">
+    <a ng-click="changePage(page+1)" analytics-on analytics-event="Paginator (i+1)" analytics-category="Filter actions">
+      Next <i class="fa fa-angle-right"></i>
+    </a>
+  </li>
+</ul>
\ No newline at end of file
diff --git a/vipra-ui/app/html/directives/topic-link.html b/vipra-ui/app/html/directives/topic-link.html
index 0bb40417ab7f2f19a3dc0dc7eed0c8a1d18b8b5c..cee3218d639ca45574b38dc4b73a6cf616d62cb2 100644
--- a/vipra-ui/app/html/directives/topic-link.html
+++ b/vipra-ui/app/html/directives/topic-link.html
@@ -1,7 +1,10 @@
 <div class="link-wrapper">
   <span class="menu-padding ellipsis">
-    <a ui-sref="topics.show.articles({id:topic.id})" class="badge pull-right" ng-bind="::topic.articlesCount" ng-attr-title="{{::topic.articlesCount}} article(s)" ng-if="::showBadge"></a>
-	  <a class="topic-link" ui-sref="topics.show({id:topic.id})" ng-attr-title="{{::topic.name}}">
+    <div class="pull-right">
+      <a ui-sref="topics.show.articles({id:topic.id})" class="badge" ng-bind="::topic.articlesCount" ng-attr-title="{{::topic.articlesCount}} article(s)" ng-if="::showBadge"></a>
+      <span class="colorbox plain shown" style="background:{{::topic.color}}"></span>
+    </div>
+	  <a class="topic-link" ui-sref="topics.show({id:topic.id})" ng-attr-title="{{topic.name}}">
 	    <span class="title" ng-bind="topic.name"></span>
 	    <ng-transclude/>
 	  </a>
diff --git a/vipra-ui/app/html/directives/topic-menu.html b/vipra-ui/app/html/directives/topic-menu.html
index b533279a237575113b041630b9ea5d81bd363261..e6984e1fb0eadb9b993d4b0ce8ec059595383954 100644
--- a/vipra-ui/app/html/directives/topic-menu.html
+++ b/vipra-ui/app/html/directives/topic-menu.html
@@ -4,9 +4,10 @@
   </a>
   <ul class="dropdown-menu" ng-class="{'dropdown-menu-right':dropdownRight}">
     <li><a ui-sref="topics.show({id:topic.id})">Show</a></li>
-    <li><a ng-click="renameTopic()" analytics-on analytics-event="Rename topic" analytics-category="Topic actions">Rename...</a></li>
-    <li role="separator" class="divider"></li>
-    <li><a ui-sref="network({type:'topics',id:topic.id})">Network</a></li>
+    <li><a ui-sref="topics.show.sequences({id:topic.id})">Sequences</a></li>
     <li><a ui-sref="topics.show.articles({id:topic.id})">Articles</a></li>
+    <li><a ui-sref="network({type:'topics',id:topic.id})">Network</a></li>
+    <li role="separator" class="divider"></li>
+    <li><a ng-click="renameTopic()" analytics-on analytics-event="Rename topic" analytics-category="Topic actions">Rename...</a></li>
   </ul>
 </div>
diff --git a/vipra-ui/app/html/directives/topicmodel-button.html b/vipra-ui/app/html/directives/topicmodel-button.html
index 9e45cceb1cd49b22b12ebd0df7525dbfbda246f5..83c08462fb335df68ffd5ab834e649a1ee66a9a5 100644
--- a/vipra-ui/app/html/directives/topicmodel-button.html
+++ b/vipra-ui/app/html/directives/topicmodel-button.html
@@ -1,8 +1,8 @@
 <button type="button" class="list-group-item topic-model" ng-click="changeTopicModel(topicModel)" ng-class="{'active selected-model':rootModels.topicModel.id===topicModel.id}" analytics-on analytics-event="Topic model" analytics-category="Topic model actions">
   <span class="badge badge-group">
     <span class="badge-part" ng-if="!topicModel.lastGenerated" title="Model was never generated">Non-generated</span>
-    <span class="badge-part" ng-bind="::topicModel.articleCount" ng-show="topicModel.articleCount" ng-attr-title="{{::topicModel.articleCount + ' article(s)'}}" ng-cloak></span>
     <span class="badge-part" ng-bind="::topicModel.topicCount" ng-show="topicModel.topicCount" ng-attr-title="{{::topicModel.topicCount + ' topic(s)'}}" ng-cloak></span>
+    <span class="badge-part" ng-bind="::topicModel.articleCount" ng-show="topicModel.articleCount" ng-attr-title="{{::topicModel.articleCount + ' article(s)'}}" ng-cloak></span>
   </span>
   <span ng-bind="::topicModel.name"></span>
   <br ng-show="topicModel.modelConfig.description" ng-cloak>
diff --git a/vipra-ui/app/html/directives/word-evolution.html b/vipra-ui/app/html/directives/word-evolution.html
index 471079ba7fa6d7214d2a801b5195e1ce49f44815..3796949addaa92a94fa50de3cd48b7d0f8e76ce9 100644
--- a/vipra-ui/app/html/directives/word-evolution.html
+++ b/vipra-ui/app/html/directives/word-evolution.html
@@ -18,12 +18,12 @@
   <div class="panel-body">
     <div class="topic-list sidebar">
       <ul class="list-unstyled item-choice">
-        <li ng-repeat="word in topic.words" ng-mouseenter="highlightSeries(word.word, true)" ng-mouseleave="highlightSeries(word.word, false)">
+        <li ng-repeat="word in topic.words track by word.word" ng-mouseenter="highlightSeries(word.word, true)" ng-mouseleave="highlightSeries(word.word, false)">
           <div class="checkbox checkbox-condensed" ng-class="{selected:word.selected}">
             <input tabindex="0" type="checkbox" ng-model="word.selected" ng-attr-id="{{::word.word}}" ng-change="redrawWordEvolutionChart()">
             <label class="check" ng-attr-for="{{::word.word}}" analytics-on analytics-event="Word Evolution Word" analytics-category="Chart actions">
               <span class="ellipsis menu-padding" ng-attr-title="{{::word.word}}">
-                <span ng-bind="word.word"></span>
+                <span ng-bind="::word.word"></span>
               </span>
               <word-menu word="word" class="menu-button" />
             </label>
@@ -34,7 +34,7 @@
     </div>
     <div class="center message-container">
       <div class="wrapper">
-        <div class="chart area-chart" ng-attr-id="{{chartId}}" highcharts="wordEvolution"></div>
+        <div class="chart area-chart" ng-attr-id="{{::chartId}}" highcharts="wordEvolution"></div>
       </div>
     </div>
   </div>
diff --git a/vipra-ui/app/html/directives/word-menu.html b/vipra-ui/app/html/directives/word-menu.html
index 97c31b2712070037b30c2b0e95ffbf6d4174c507..d6f17117fae0b682dbaf8082228ee55225974b1e 100644
--- a/vipra-ui/app/html/directives/word-menu.html
+++ b/vipra-ui/app/html/directives/word-menu.html
@@ -4,7 +4,6 @@
   </a>
   <ul class="dropdown-menu" ng-class="{'dropdown-menu-right':dropdownRight}">
     <li><a ui-sref="words.show({id:id})">Show</a></li>
-    <li role="separator" class="divider"></li>
     <li><a ui-sref="words.show.topics({id:id})">Topics</a></li>
     <li><a ui-sref="words.show.articles({id:id})">Articles</a></li>
   </ul>
diff --git a/vipra-ui/app/html/entities/articles.html b/vipra-ui/app/html/entities/articles.html
index dec71c1de08231a21d032dae254d0a2d732999cb..65ae82528392b015dbd3acb3968d838a13bfaea1 100644
--- a/vipra-ui/app/html/entities/articles.html
+++ b/vipra-ui/app/html/entities/articles.html
@@ -41,7 +41,7 @@
               </div>
               <table class="table table-hover table-condensed table-fixed">
                 <tbody>
-                  <tr ng-repeat="article in articles">
+                  <tr ng-repeat="article in articles track by article.id">
                     <td>
                       <article-link article="::article"/>
                     </td>
diff --git a/vipra-ui/app/html/entities/index.html b/vipra-ui/app/html/entities/index.html
index 8cc34a7ffd31ab55fbf7986e95e4f301084b98d8..a8d5d2ab0f78670c896d200f884f9f0c076a5330 100644
--- a/vipra-ui/app/html/entities/index.html
+++ b/vipra-ui/app/html/entities/index.html
@@ -14,13 +14,10 @@
           <div class="panel-heading clearfix">
             Found
             <ng-pluralize count="entitiesTotal||0" when="{0:'no entities',1:'1 entity',other:'{} entities'}"></ng-pluralize> in the database.
-            <div class="pull-right">
-              Page <span ng-bind="wordsIndexModels.page||1"></span> of <span ng-bind="maxPage||1"></span>
-            </div>
           </div>
           <table class="table table-hover table-condensed table-fixed">
             <tbody>
-              <tr ng-repeat="entity in entities">
+              <tr ng-repeat="entity in entities track by entity.entity">
                 <td>
                 	<entity-link entity="::entity" />
                 </td>
@@ -33,10 +30,8 @@
               </tr>
             </tbody>
           </table>
-          <div class="panel-footer clearfix">
-            <div class="pull-right">
-              Page <span ng-bind="wordsIndexModels.page||1"></span> of <span ng-bind="maxPage||1"></span>
-            </div>
+          <div class="panel-footer">
+            <sub-pagination total="entitiesTotal" page="entitiesIndexModels.page" limit="entitiesIndexModels.limit" />
           </div>
         </div>
       </div>
diff --git a/vipra-ui/app/html/explorer.html b/vipra-ui/app/html/explorer.html
index b888481bdc234cdb167811e4d82e15c4d65a56ac..87657d31358c6443908702998f110b788b449388 100644
--- a/vipra-ui/app/html/explorer.html
+++ b/vipra-ui/app/html/explorer.html
@@ -22,12 +22,12 @@
         <span class="glyphicon glyphicon-remove-circle searchclear" ng-click="search=''" analytics-on analytics-event="Explorer Filter Topics (clear)" analytics-category="Filter actions"></span>
       </div>
       <ul class="list-unstyled item-choice topic-choice">
-        <li ng-repeat="topic in topics | orderBy:explorerModels.sorttopics:explorerModels.sortdir | filter:search" ng-mouseenter="highlightTopic(topic.id, true)" ng-mouseleave="highlightTopic(topic.id, false)" ng-class="{selected:topic.selected}" class="text-muted topic" ng-attr-data-id="{{::topic.id}}">
+        <li ng-repeat="topic in topics | orderBy:explorerModels.sorttopics:explorerModels.sortdir | filter:search track by topic.id" ng-mouseenter="highlightTopic(topic.id, true)" ng-mouseleave="highlightTopic(topic.id, false)" ng-class="{selected:topic.selected}" class="text-muted topic" ng-attr-data-id="{{::topic.id}}">
           <div class="checkbox checkbox-condensed">
             <span class="valuebar" ng-style="{width:topic.topicCurrValue}"></span>
             <input tabindex="0" type="checkbox" ng-model="topic.selected" ng-attr-id="relevance-{{::topic.id}}" ng-change="changeSelectedTopics()">
             <label class="check" ng-attr-for="relevance-{{::topic.id}}" analytics-on analytics-event="Explorer Topic Relevance Choice" analytics-category="Explorer actions">
-              <span class="ellipsis menu-padding" ng-attr-title="{{::topic.name}}">
+              <span class="ellipsis menu-padding" ng-attr-title="{{topic.name}}">
                 <span class="title" ng-bind="topic.name"></span>
               </span>
               <topic-menu topic="topic" class="menu-button" />
@@ -73,12 +73,12 @@
   <div class="ui-layout-south no-padding no-border" id="lower">
     <div class="ui-layout-west explorer-sidebar no-border">
       <ul class="list-unstyled item-choice no-offset">
-        <li ng-repeat="topic in selectedTopics = (topics | filter:{selected: true} | filter:search | orderBy:explorerModels.sorttopics:explorerModels.sortdir)" ng-mouseenter="highlightTopic(topic.id, true)" ng-mouseleave="highlightTopic(topic.id, false)" ng-class="{active:explorerModels.activeTopic.id===topic.id}" class="pointer text-muted topic" ng-attr-data-id="{{::topic.id}}">
+        <li ng-repeat="topic in selectedTopics = (topics | filter:{selected: true} | filter:search | orderBy:explorerModels.sorttopics:explorerModels.sortdir) track by topic.id" ng-mouseenter="highlightTopic(topic.id, true)" ng-mouseleave="highlightTopic(topic.id, false)" ng-class="{active:explorerModels.activeTopic.id===topic.id}" class="pointer text-muted topic" ng-attr-data-id="{{::topic.id}}">
           <div class="radio radio-condensed">
             <span class="valuebar" ng-style="{width:topic.topicCurrValue}"></span>
             <input tabindex="0" type="radio" ng-model="explorerModels.activeTopic" ng-attr-id="detail-{{::topic.id}}" name="topic-active" ng-value="topic">
             <label class="radio" ng-attr-for="detail-{{::topic.id}}" analytics-on analytics-event="Explorer Topic Detail Choice" analytics-category="Explorer actions">
-              <span class="ellipsis menu-padding" ng-attr-title="{{::topic.name}}">
+              <span class="ellipsis menu-padding" ng-attr-title="{{topic.name}}">
                 <span class="title" ng-bind="topic.name"></span>
               </span>
               <topic-menu topic="topic" class="menu-button" />
@@ -120,7 +120,7 @@
                 </tr>
               </thead>
               <tbody>
-                <tr ng-repeat="article in articles | orderBy:explorerModels.articlesSort">
+                <tr ng-repeat="article in articles | orderBy:explorerModels.articlesSort track by article.id">
                   <td>
                     <article-link article="::article" />
                   </td>
diff --git a/vipra-ui/app/html/index.html b/vipra-ui/app/html/index.html
index ba7ee29fbbd988fa468d7d1cea2ed405aabe1545..a9a87355a852b6a78acd20f20b4d0fc874a75b58 100644
--- a/vipra-ui/app/html/index.html
+++ b/vipra-ui/app/html/index.html
@@ -78,7 +78,7 @@
       <div class="col-md-12" ng-show="searchResults.length > 0" ng-cloak>
         <h4>Results</h4>
         <ul class="list-unstyled search-results">
-          <li class="search-result" ng-repeat="article in searchResults">
+          <li class="search-result" ng-repeat="article in searchResults track by article.id">
             <a ui-sref="articles.show({id:article.id})" ng-bind="article.title"></a>
             <p>
               <span class="text" ng-bind="article.text"></span>
diff --git a/vipra-ui/app/html/partials/topicmodel-popover.html b/vipra-ui/app/html/partials/topicmodel-popover.html
deleted file mode 100644
index eef9175423d8b39b3c974fef4c41ee4771f43241..0000000000000000000000000000000000000000
--- a/vipra-ui/app/html/partials/topicmodel-popover.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<table class="popover-table">
-  <tr>
-    <th>Article count</th>
-    <td ng-bind="rootModels.topicModel.articleCount || 0"></td>
-  </tr>
-  <tr>
-    <th>Topic count</th>
-    <td ng-bind="rootModels.topicModel.topicCount || 0"></td>
-  </tr>
-  <tr>
-    <th>Entity count</th>
-    <td ng-bind="rootModels.topicModel.entityCount || 0"></td>
-  </tr>
-  <tr>
-    <th>Word count</th>
-    <td ng-bind="rootModels.topicModel.wordCount || 0"></td>
-  </tr>
-  <tr>
-    <th>Window count</th>
-    <td ng-bind="rootModels.topicModel.windowCount || 0"></td>
-  </tr>
-  <tr>
-    <th>Last generated</th>
-    <td ng-bind-template="{{$root.Vipra.formatDateTime(rootModels.topicModel.lastGenerated) || 'never'}}"></td>
-  </tr>
-  <tr>
-    <th>Last indexed</th>
-    <td ng-bind-template="{{$root.Vipra.formatDateTime(rootModels.topicModel.lastIndexed) || 'never'}}"></td>
-  </tr>
-  <tr>
-    <th>Last modified</th>
-    <td ng-bind-template="{{$root.Vipra.formatDateTime(rootModels.topicModel.modified) || 'never'}}"></td>
-  </tr>
-</table>
\ No newline at end of file
diff --git a/vipra-ui/app/html/topics/articles.html b/vipra-ui/app/html/topics/articles.html
index d0232f29adf269e8f1df97f5dc64e687271f4235..a5d41b22e23d327d7abf1df984760f38343423aa 100644
--- a/vipra-ui/app/html/topics/articles.html
+++ b/vipra-ui/app/html/topics/articles.html
@@ -2,7 +2,7 @@
 <div class="container" ng-cloak ng-hide="!rootModels.topicModel || state.name !== 'topics.show.articles'">
   <div class="page-header no-border">
     <span class="label label-default">Topic</span>
-    <h1 ng-bind="::topic.name"></h1>
+    <h1 ng-bind="topic.name"></h1>
   </div>
   <div>
     <ul class="nav nav-tabs" role="tablist">
@@ -37,6 +37,7 @@
                     <option value="title">Title</option>
                     <option value="date">Date</option>
                     <option value="created">Added</option>
+                    <option value="topicsCount"># of topics</option>
                   </select>
                   <span class="input-group-btn">
                     <sort-dir ng-model="topicsArticlesModels.sortdir" />
@@ -46,7 +47,7 @@
               </div>
               <table class="table table-hover table-condensed table-fixed">
                 <tbody>
-                  <tr ng-repeat="article in articles">
+                  <tr ng-repeat="article in articles track by article.id">
                     <td>
                       <article-link article="::article"/>
                     </td>
diff --git a/vipra-ui/app/html/topics/index.html b/vipra-ui/app/html/topics/index.html
index aa50877e2ea3eca00c4110fde8fc9442aec49d48..10412713aa45ba1f7b1a8d6c4717964c9c9171c3 100644
--- a/vipra-ui/app/html/topics/index.html
+++ b/vipra-ui/app/html/topics/index.html
@@ -14,13 +14,10 @@
           <div class="panel-heading clearfix">
             Found
             <ng-pluralize count="topicsTotal||0" when="{0:'no topics',1:'1 topic',other:'{} topics'}"></ng-pluralize> in the database.
-            <div class="pull-right">
-              Page <span ng-bind="wordsIndexModels.page||1"></span> of <span ng-bind="maxPage||1"></span>
-            </div>
           </div>
           <table class="table table-hover table-condensed table-fixed">
             <tbody>
-              <tr ng-repeat="topic in topics">
+              <tr ng-repeat="topic in topics track by topic.id">
                 <td>
                   <topic-link topic="::topic" />
                 </td>
@@ -33,10 +30,8 @@
               </tr>
             </tbody>
           </table>
-          <div class="panel-footer clearfix">
-            <div class="pull-right">
-              Page <span ng-bind="wordsIndexModels.page||1"></span> of <span ng-bind="maxPage||1"></span>
-            </div>
+          <div class="panel-footer">
+            <sub-pagination total="topicsTotal" page="topicsIndexModels.page" limit="topicsIndexModels.limit" />
           </div>
         </div>
       </div>
diff --git a/vipra-ui/app/html/topics/sequences.html b/vipra-ui/app/html/topics/sequences.html
index 78ec3f0f2f542947979c8c958d2cea147934e987..38c772fbe728a0a9b3bbecff9bfc65df10d01ac8 100644
--- a/vipra-ui/app/html/topics/sequences.html
+++ b/vipra-ui/app/html/topics/sequences.html
@@ -2,7 +2,7 @@
 <div class="container" ng-cloak ng-hide="!rootModels.topicModel || state.name !== 'topics.show.sequences'">
   <div class="page-header no-border">
     <span class="label label-default">Topic</span>
-    <h1 ng-bind="::topic.name"></h1>
+    <h1 ng-bind="topic.name"></h1>
   </div>
   <div>
     <ul class="nav nav-tabs" role="tablist">
@@ -43,7 +43,7 @@
                   </tr>
                 </thead>
                 <tbody>
-                  <tr class="compare-row" ng-repeat="word in sequence.words | orderBy:topicsShowModels.seqSortWords" ng-attr-word="{{::word.word}}">
+                  <tr class="compare-row" ng-repeat="word in sequence.words | orderBy:topicsShowModels.seqSortWords track by word.word" ng-attr-word="{{::word.word}}">
                     <td>
                       <word-link word="::word" />
                     </td>
@@ -66,7 +66,7 @@
                   </tr>
                 </thead>
                 <tbody>
-                  <tr class="compare-row" ng-repeat="word in sequence.words | orderBy:topicsShowModels.seqSortWords" ng-attr-word="{{::word.word}}">
+                  <tr class="compare-row" ng-repeat="word in sequence.words | orderBy:topicsShowModels.seqSortWords track by word.word" ng-attr-word="{{::word.word}}">
                     <td class="text-center">
                       <change-pos change="word.change"/>
                     </td>
@@ -91,7 +91,7 @@
                   </tr>
                 </thead>
                 <tbody>
-                  <tr class="compare-row" ng-repeat="word in sequenceCompare.words | orderBy:topicsShowModels.seqSortWords" ng-attr-word="{{::word.word}}">
+                  <tr class="compare-row" ng-repeat="word in sequenceCompare.words | orderBy:topicsShowModels.seqSortWords track by word.word" ng-attr-word="{{::word.word}}">
                     <td>
                       <word-link word="::word" />
                     </td>
diff --git a/vipra-ui/app/html/words/articles.html b/vipra-ui/app/html/words/articles.html
index 23f7abef39013694282d3103970148c55966e0c0..17b8e78a7c895d4ee329366d122a4ab2a218f3bc 100644
--- a/vipra-ui/app/html/words/articles.html
+++ b/vipra-ui/app/html/words/articles.html
@@ -45,7 +45,7 @@
               </div>
               <table class="table table-hover table-condensed table-fixed">
                 <tbody>
-                  <tr ng-repeat="article in articles">
+                  <tr ng-repeat="article in articles track by article.id">
                     <td>
                       <article-link article="::article"/>
                     </td>
diff --git a/vipra-ui/app/html/words/index.html b/vipra-ui/app/html/words/index.html
index 8f3cb8d7aa08698f3119b22e7fb24be4b83376c4..13f25ab27306d835f5c979e8661ad116ff488ae0 100644
--- a/vipra-ui/app/html/words/index.html
+++ b/vipra-ui/app/html/words/index.html
@@ -14,13 +14,10 @@
           <div class="panel-heading clearfix">
             Found
             <ng-pluralize count="wordsTotal||0" when="{0:'no words',1:'1 word',other:'{} words'}"></ng-pluralize> in the database.
-            <div class="pull-right">
-              Page <span ng-bind="wordsIndexModels.page||1"></span> of <span ng-bind="maxPage||1"></span>
-            </div>
           </div>
           <table class="table table-hover table-condensed table-fixed">
             <tbody>
-              <tr ng-repeat="word in words">
+              <tr ng-repeat="word in words track by word.word">
                 <td>
                 	<word-link word="::word" />
                 </td>
@@ -34,9 +31,7 @@
             </tbody>
           </table>
           <div class="panel-footer clearfix">
-            <div class="pull-right">
-              Page <span ng-bind="wordsIndexModels.page||1"></span> of <span ng-bind="maxPage||1"></span>
-            </div>
+            <sub-pagination total="wordsTotal" page="wordsIndexModels.page" limit="wordsIndexModels.limit" />
           </div>
         </div>
       </div>
diff --git a/vipra-ui/app/html/words/topics.html b/vipra-ui/app/html/words/topics.html
index 26b6adf16a568076259edc0cd1c254b1bb011f57..96c0fa297a47c8ac4ad01349681881345b5fb694 100644
--- a/vipra-ui/app/html/words/topics.html
+++ b/vipra-ui/app/html/words/topics.html
@@ -44,7 +44,7 @@
               </div>
               <table class="table table-hover table-condensed table-fixed">
                 <tbody>
-                  <tr ng-repeat="topic in topics">
+                  <tr ng-repeat="topic in topics track by topic.id">
                     <td>
                       <topic-link topic="::topic" />
                     </td>
diff --git a/vipra-ui/app/index.html b/vipra-ui/app/index.html
index a303f682e29b099d25c2f3b398d221d3c5b15c14..443134fe416756d8d92e8aece2692982f708c07a 100644
--- a/vipra-ui/app/index.html
+++ b/vipra-ui/app/index.html
@@ -48,30 +48,30 @@
         </ul>
         <form class="navbar-form navbar-left search-form" role="search" ng-hide="state.name === 'index'" ng-cloak>
           <div class="form-group has-feedback">
-            <input tabindex="0" type="text" class="form-control" placeholder="Search..." ng-model="rootModels.search" ng-enter="menubarSearch(rootModels.search)" id="menuSearchBox">
+            <input tabindex="0" type="text" class="form-control search-collapsed" placeholder="Search..." ng-model="rootModels.search" ng-enter="menubarSearch(rootModels.search)" id="quicksearch">
             <i class="form-control-feedback glyphicon glyphicon-search text-muted"></i>
           </div>
         </form>
         <ul class="nav navbar-nav navbar-right">
-          <li ng-class="{'text-italic active':rootModels.topicModel}" bs-popover popover-template="partials/topicmodel-popover.html" popover-delay="500" popover-placement="bottom">
+          <li ng-class="{'text-italic active':rootModels.topicModel}">
             <a class="active-topicmodel" tabindex="0" ng-click="chooseTopicModel()" ng-bind-template="{{rootModels.topicModel ? rootModels.topicModel.name : 'Models'}}" analytics-on analytics-event="Menu Item (Topic Models)" analytics-category="Menu actions"></a>
           </li>
-          <li ng-class="{disabled:!rootModels.helpEnabled}" ng-attr-title="{{ rootModels.helpEnabled ? 'Help' : 'No help available' }}">
+          <li class="menu-icon" ng-class="{disabled:!rootModels.helpEnabled}" ng-attr-title="{{ rootModels.helpEnabled ? 'Help' : 'No help available' }}">
             <a ng-click="showHelp()">
               <i class="fa fa-question-circle"></i>
             </a>
           </li>
-          <li title="Keyboard cheatsheet">
+          <li class="menu-icon" title="Keyboard cheatsheet">
             <a tabindex="0" ng-click="showCheatSheet()" analytics-on analytics-event="Menu Item (Cheatsheet)" analytics-category="Menu actions">
               <i class="fa fa-keyboard-o"></i>
             </a>
           </li>
-          <li ui-sref-active="active" title="About">
+          <li class="menu-icon" ui-sref-active="active" title="About">
             <a tabindex="0" ui-sref="about">
               <i class="fa fa-info-circle"></i>
             </a>
           </li>
-          <li title="Feedback">
+          <li class="menu-icon" title="Feedback">
             <a tabindex="0" ng-click="showFeedbackModal()" analytics-on analytics-event="Menu Item (Feedback)" analytics-category="Menu actions">
               <i class="fa fa-comment-o"></i>
             </a>
@@ -81,7 +81,7 @@
     </div>
   </nav>
   <div class="main" ui-view ng-cloak></div>
-  <div id="topicModelModal" class="modal" tabindex="-1" role="dialog" data-backdrop="static" data-keyboard="false" ng-show="!fatal">
+  <div id="topicModelModal" class="modal fade" tabindex="-1" role="dialog" data-backdrop="static" data-keyboard="false" ng-if="!fatal">
     <div class="modal-dialog modal-lg">
       <div class="modal-content">
         <div class="modal-header">
@@ -93,7 +93,7 @@
             <input tabindex="0" type="text" class="form-control" placeholder="Filter..." ng-model="rootModels.topicModelFilter">
             <i class="form-control-feedback glyphicon glyphicon-search text-muted"></i>
           </div>
-          <div class="panel panel-default" ng-repeat="(groupName, group) in groups" ng-show="filtered.length">
+          <div class="panel panel-default topic-group" ng-repeat="(groupName, group) in groups track by groupName" ng-show="filtered.length">
             <div class="panel-heading pointer" ng-click="group.collapsed=!group.collapsed">
               <i class="fa folder-icon" ng-class="{'fa-folder-open-o':!group.collapsed,'fa-folder-o':group.collapsed}"></i>
               <span ng-bind="::groupName"></span>
@@ -103,11 +103,11 @@
               </div>
             </div>
             <div ng-attr-id="{{::groupName}}" class="list-group nomargin collapse in" ng-show="topicModelsCount && !group.collapsed" ng-cloak>
-              <topicmodel-button ng-repeat="topicModel in filtered = (group | filter:{name:rootModels.topicModelFilter})"></topicmodel-button>
+              <topicmodel-button ng-repeat="topicModel in filtered = (group | filter:{name:rootModels.topicModelFilter}) track by topicModel.id"></topicmodel-button>
             </div>
           </div>
           <div class="list-group nomargin" ng-show="topicModelsCount" ng-cloak>
-            <topicmodel-button ng-repeat="topicModel in topicModels | filter:{name:rootModels.topicModelFilter}"></topicmodel-button>
+            <topicmodel-button ng-repeat="topicModel in topicModels | filter:{name:rootModels.topicModelFilter} track by topicModel.id"></topicmodel-button>
           </div>
           <p class="text-center" ng-show="loading.any" ng-cloak>
             Loading...
@@ -136,7 +136,7 @@
       </div>
     </div>
   </div>
-  <div id="feedbackModal" class="modal" tabindex="-1" role="dialog" data-backdrop="static">
+  <div id="feedbackModal" class="modal fade" tabindex="-1" role="dialog" data-backdrop="static">
     <div class="modal-dialog modal-lg">
       <div class="modal-content">
         <div class="modal-header">
@@ -149,7 +149,7 @@
       </div>
     </div>
   </div>
-  <div id="helpModal" class="modal" tabindex="-1" role="dialog" data-backdrop="static">
+  <div id="helpModal" class="modal fade" tabindex="-1" role="dialog" data-backdrop="static">
     <div class="modal-dialog modal-lg">
       <div class="modal-content">
         <div class="modal-header">
diff --git a/vipra-ui/app/js/app.js b/vipra-ui/app/js/app.js
index 4cc3fa117564f91bfc8f3797ef4a20ff22fe07b3..cadb228563fc63c3a7854eb35f6be0c3c484b5e5 100644
--- a/vipra-ui/app/js/app.js
+++ b/vipra-ui/app/js/app.js
@@ -234,7 +234,7 @@
     }
   ]);
 
-  app.run(['$rootScope', '$state', function($rootScope, $state) {
+  app.run(['$rootScope', '$state', '$interval', function($rootScope, $state, $interval) {
 
     $rootScope.loading = {};
 
@@ -262,6 +262,15 @@
     $rootScope.$on('$stateChangeStart', function() {
       $rootScope.alerts = [];
     });
+
+    // http://www.mograblog.com/2015/10/angular-improve-website-performance.html
+    // this cancels intervals on scope destroy
+    var ScopeProt = Object.getPrototypeOf($rootScope);  
+    ScopeProt.$interval = function(func, time){  
+      var timer = $interval(func,time);  
+      this.on('$destroy', function(){ $timeout.cancel(timer); });  
+      return timer;  
+    };  
   }]);
 
   $(document).on('change', '.btn-file :file', function() {
@@ -277,6 +286,17 @@
     }
   });
 
+  $(document).on('click', '#quicksearch', function() {
+    if($(this).hasClass('search-collapsed'))
+      $(this).removeClass('search-collapsed');
+  });
+
+  $(document).on('blur', '#quicksearch', function(e) {
+    if(!this.value) {
+      $(this).addClass('search-collapsed');
+    }
+  });
+
   // hold onto the drop down menu                                             
   var dropdownMenu;
 
diff --git a/vipra-ui/app/js/controllers.js b/vipra-ui/app/js/controllers.js
index 372fae3248284d971ea90f42fc991e9f9bc098c6..9877f182d8ccce527c1d8a0d72372a6a1b350702 100644
--- a/vipra-ui/app/js/controllers.js
+++ b/vipra-ui/app/js/controllers.js
@@ -19,25 +19,21 @@
         helpEnabled: false
       };
 
-      var prevTopicModelLoading = false;
       var prevTopicModelDefer = $q.defer();
 
       $scope.rootModels.tmLoading = prevTopicModelDefer.promise;
 
       if (localStorage.tm) {
-        prevTopicModelLoading = true;
         $rootScope.loadingScreen = true;
 
         TopicModelFactory.get({
           id: localStorage.tm
         }, function(data) {
           $scope.rootModels.topicModel = data;
-          prevTopicModelLoading = false;
           $scope.loadingScreen = false;
           prevTopicModelDefer.resolve();
         }, function() {
           delete localStorage.tm;
-          prevTopicModelLoading = false;
           $scope.loadingScreen = false;
           $scope.chooseTopicModel();
           prevTopicModelDefer.reject();
@@ -71,15 +67,15 @@
       };
 
       $scope.chooseTopicModel = function() {
-        if (prevTopicModelLoading)
-          return;
-        $scope.queryTopicModels();
-        $scope.rootModels.topicModelModalOpen = true;
-        $('#topicModelModal').modal();
-        if ($scope.rootModels.topicModel)
-          $('.selected-model').focus();
-        else
-          $('.topic-model').first().focus();
+        $scope.rootModels.tmLoading.finally(function() {
+          $scope.queryTopicModels();
+          $scope.rootModels.topicModelModalOpen = true;
+          $('#topicModelModal').modal();
+          if ($scope.rootModels.topicModel)
+            $('.selected-model').focus();
+          else
+            $('.topic-model').first().focus();
+        });
       };
 
       $scope.changeTopicModel = function(topicModel) {
@@ -212,6 +208,10 @@
           $('#helpModal').modal();
         }
       };
+
+      $scope.showSearch = function() {
+        $scope.searchExpanded = true;
+      };
     }
   ]);
 
@@ -1721,7 +1721,7 @@
 
       $scope.checkTopicModel('entities.show.articles', function() {
         $scope.id = $stateParams.id;
-        $scope.rootModels.title = $scope.entity;
+        $scope.rootModels.title = $scope.id;
 
         $scope.entitiesArticlesModels = {
           sortkey: 'date',
@@ -1950,8 +1950,8 @@
         var pages = [],
           max = Math.ceil($scope.total / $scope.limit * 1.0),
           pad = 2,
-          start = Math.max($scope.page - pad, 1),
-          end = Math.min(Math.max($scope.page + pad, start + pad * 2), max);
+          end = Math.min(Math.max($scope.page + pad, Math.max($scope.page - pad, 1) + pad * 2), max),
+          start = Math.max(Math.min($scope.page - pad, end - pad * 2), 1);
         for (var i = start; i <= end; i++) {
           pages.push(i);
         }
@@ -1968,7 +1968,8 @@
       $scope.calculatePages();
 
       $scope.changePage = function(page) {
-        $scope.page = parseInt(page, 10);
+        if(page < 1 || page > $scope.maxPage) return;
+        $scope.page = page;
         window.scrollTo(0,0);
       };
 
diff --git a/vipra-ui/app/js/directives.js b/vipra-ui/app/js/directives.js
index 9370e889bfc8a14f891c9991d7759a46a2f14ba4..e70ab740e5f7b1aec9d7a48e584591fece871722 100644
--- a/vipra-ui/app/js/directives.js
+++ b/vipra-ui/app/js/directives.js
@@ -130,6 +130,21 @@
     };
   }]);
 
+  app.directive('subPagination', [function() {
+    return {
+      restrict: 'E',
+      replace: true,
+      scope: {
+        total: '=',
+        page: '=',
+        limit: '=',
+        change: '&'
+      },
+      controller: 'PaginationController',
+      templateUrl: 'html/directives/sub-pagination.html'
+    }
+  }]);
+
   app.directive('highcharts', [function() {
     return {
       scope: {
diff --git a/vipra-ui/app/less/app.less b/vipra-ui/app/less/app.less
index f0a7e501664adede8e92f5d80f3188d65b689e0c..069ef4c4ad3f690a49ab952c69fab4583fd87930 100644
--- a/vipra-ui/app/less/app.less
+++ b/vipra-ui/app/less/app.less
@@ -12,7 +12,7 @@ html {
 
 body {
   padding-top: @topbarSpace;
-  padding-bottom: 20px;
+  padding-bottom: @topbarSpace;
 }
 
 html, body {
@@ -252,6 +252,7 @@ td {
   }
 }
 
+.navbar a,
 .vis-network {
   outline: none;
 }
@@ -564,10 +565,6 @@ entity-menu {
   width: 100px;
 }
 
-.colorcol {
-  width: 21px;
-}
-
 .page-header.no-border {
   border-color: transparent;
 }
@@ -976,11 +973,21 @@ entity-menu {
   position: fixed;
 }
 
-.active-topicmodel {
-  max-width: 120px;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
+.navbar-collapse {
+  &:not(.in) {
+    .active-topicmodel {
+      max-width: 120px;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+    }
+  }
+
+  &.in {
+    .menu-icon {
+      float: left;
+    }
+  }
 }
 
 .stats-badges {
@@ -1006,6 +1013,10 @@ entity-menu {
     color: #fff;
     cursor: default;
   }
+  .btn {
+    padding-left: 0;
+    padding-right: 0;
+  }
 }
 
 .date-compact {
@@ -1088,8 +1099,31 @@ entity-menu {
   }
 }
 
-.article-text {
-  padding-bottom: 40px;
+.topic-group {
+  margin-bottom: 8px;
+}
+
+.badge + .colorbox {
+  margin-left: 5px;
+}
+
+.search-collapsed {
+  width: 1px !important;
+  padding-right: 20px !important;
+  background: transparent;
+  border: none !important;
+  -webkit-box-shadow: none !important;
+  -moz-box-shadow: none !important;
+  box-shadow: none !important;
+  cursor: pointer;
+}
+
+#quicksearch {
+  transition: all .5s;
+}
+
+.pager {
+  margin: 0;
 }
 
 [ng\:cloak], [ng-cloak], .ng-cloak {
@@ -1186,9 +1220,7 @@ entity-menu {
     overflow: hidden!important;
   }
   .date-compact {
-    small {
-      display: block;
-    }
+    display: none;
   }
 }