diff --git a/ma-impl.sublime-workspace b/ma-impl.sublime-workspace
index 86496c05d7c5a35d39bd9dfa5634583ec6b2f83c..ab22af651f5f4fde3e73eedba2a754c90b49bbb6 100644
--- a/ma-impl.sublime-workspace
+++ b/ma-impl.sublime-workspace
@@ -279,14 +279,6 @@
 	},
 	"buffers":
 	[
-		{
-			"file": "vipra-ui/app/templates/index.hbs",
-			"settings":
-			{
-				"buffer_size": 1290,
-				"line_ending": "Unix"
-			}
-		}
 	],
 	"build_system": "",
 	"build_system_choices":
@@ -476,6 +468,8 @@
 	],
 	"file_history":
 	[
+		"/home/eike/repos/master/ma-impl/vipra-ui/app/templates/index.hbs",
+		"/home/eike/Downloads/files.txt",
 		"/home/eike/repos/master/ma-impl/vipra-ui/app/templates/application.hbs",
 		"/home/eike/repos/master/ma-impl/vipra-ui/app/components/pagination-bar.js",
 		"/home/eike/.cache/.fr-kZOCSD/META-INF/MANIFEST.MF",
@@ -492,7 +486,6 @@
 		"/home/eike/repos/master/ma-impl/vipra-ui/app/controllers/words/index.js",
 		"/home/eike/repos/master/ma-impl/vipra-ui/app/controllers/words.js",
 		"/home/eike/repos/master/ma-impl/vipra-ui/app/adapters/application.js",
-		"/home/eike/repos/master/ma-impl/vipra-ui/app/templates/index.hbs",
 		"/home/eike/repos/master/ma-impl/vipra-ui/app/styles/app.scss",
 		"/home/eike/repos/master/ma-impl/vipra-ui/app/helpers/is-empty.js",
 		"/home/eike/repos/master/ma-impl/vipra-ui/app/routes/index.js",
@@ -602,8 +595,7 @@
 		"/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/articles/show.hbs",
 		"/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/components/filter-text.js",
 		"/home/eike/Repositories/fu/ss15/ma/impl/vm/webapps/test/index.html",
-		"/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/controllers/articles/list.js",
-		"/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/router.js"
+		"/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/controllers/articles/list.js"
 	],
 	"find":
 	{
@@ -927,39 +919,8 @@
 	"groups":
 	[
 		{
-			"selected": 0,
 			"sheets":
 			[
-				{
-					"buffer": 0,
-					"file": "vipra-ui/app/templates/index.hbs",
-					"semi_transient": false,
-					"settings":
-					{
-						"buffer_size": 1290,
-						"regions":
-						{
-						},
-						"selection":
-						[
-							[
-								1271,
-								1271
-							]
-						],
-						"settings":
-						{
-							"syntax": "Packages/Handlebars/grammars/Handlebars.tmLanguage",
-							"tab_size": 2,
-							"translate_tabs_to_spaces": true
-						},
-						"translation.x": 0.0,
-						"translation.y": 0.0,
-						"zoom_level": 1.0
-					},
-					"stack_index": 0,
-					"type": "text"
-				}
 			]
 		}
 	],
diff --git a/vipra-cmd/pom.xml b/vipra-cmd/pom.xml
index 4fdc5febca5416991630f86d1235b5d1c6233022..64fc4cdfb9681c0914d1f6e12d67c6f4c751156d 100644
--- a/vipra-cmd/pom.xml
+++ b/vipra-cmd/pom.xml
@@ -31,13 +31,6 @@
 			<version>1.1.1</version>
 		</dependency>
 
-		<!-- ElasticSearch -->
-		<dependency>
-			<groupId>org.elasticsearch</groupId>
-			<artifactId>elasticsearch</artifactId>
-			<version>2.1.0</version>
-		</dependency>
-
 		<!-- Stanford CoreNLP -->
 		<dependency>
 			<groupId>edu.stanford.nlp</groupId>
diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/option/ClearCommand.java b/vipra-cmd/src/main/java/de/vipra/cmd/option/ClearCommand.java
index 6625adda49113871a785464f1a7fc741577c2549..1ee15d554eaab4b981a8cf346304913638d4fc08 100644
--- a/vipra-cmd/src/main/java/de/vipra/cmd/option/ClearCommand.java
+++ b/vipra-cmd/src/main/java/de/vipra/cmd/option/ClearCommand.java
@@ -9,10 +9,10 @@ import org.apache.logging.log4j.Logger;
 import org.bson.types.ObjectId;
 import org.elasticsearch.client.Client;
 
-import de.vipra.cmd.es.ESClient;
 import de.vipra.cmd.model.ProcessedArticle;
 import de.vipra.util.Config;
 import de.vipra.util.ConsoleUtils;
+import de.vipra.util.ESClient;
 import de.vipra.util.model.Import;
 import de.vipra.util.model.TopicFull;
 import de.vipra.util.model.Word;
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 07594ef85a15aceb4da5c516e2ce2dfff26f933b..f6e960bfbd9f48446e014b2ddfef83d0db530aa9 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
@@ -18,7 +18,6 @@ import org.json.simple.JSONArray;
 import org.json.simple.JSONObject;
 import org.json.simple.parser.JSONParser;
 
-import de.vipra.cmd.es.ESClient;
 import de.vipra.cmd.file.Filebase;
 import de.vipra.cmd.file.FilebaseIndex;
 import de.vipra.cmd.lda.LDAAnalyzer;
@@ -28,6 +27,7 @@ import de.vipra.cmd.text.Processor;
 import de.vipra.util.Config;
 import de.vipra.util.Constants;
 import de.vipra.util.ConvertStream;
+import de.vipra.util.ESClient;
 import de.vipra.util.ElasticSerializer;
 import de.vipra.util.MongoUtils;
 import de.vipra.util.StringUtils;
diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/option/TestCommand.java b/vipra-cmd/src/main/java/de/vipra/cmd/option/TestCommand.java
index 9441138e7777a02c4bb648180c10c570a0ce7ac9..164c8a5d5d80a39360629ce79eeba16348525c84 100644
--- a/vipra-cmd/src/main/java/de/vipra/cmd/option/TestCommand.java
+++ b/vipra-cmd/src/main/java/de/vipra/cmd/option/TestCommand.java
@@ -6,8 +6,8 @@ import org.bson.types.ObjectId;
 import org.elasticsearch.client.transport.NoNodeAvailableException;
 import org.elasticsearch.client.transport.TransportClient;
 
-import de.vipra.cmd.es.ESClient;
 import de.vipra.util.Config;
+import de.vipra.util.ESClient;
 import de.vipra.util.model.Article;
 import de.vipra.util.service.DatabaseService;
 
diff --git a/vipra-rest/src/main/java/de/vipra/rest/resource/SearchResource.java b/vipra-rest/src/main/java/de/vipra/rest/resource/SearchResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..3f7c24a61640c5de4ca98cf6057839560e7345e1
--- /dev/null
+++ b/vipra-rest/src/main/java/de/vipra/rest/resource/SearchResource.java
@@ -0,0 +1,86 @@
+package de.vipra.rest.resource;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.search.SearchType;
+import org.elasticsearch.client.transport.TransportClient;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.SearchHits;
+
+import de.vipra.rest.APIMediaType;
+import de.vipra.rest.model.APIError;
+import de.vipra.rest.model.Wrapper;
+import de.vipra.util.Config;
+import de.vipra.util.ESClient;
+import de.vipra.util.MongoUtils;
+import de.vipra.util.StringUtils;
+import de.vipra.util.ex.ConfigException;
+import de.vipra.util.model.ArticleFull;
+
+@Path("search")
+public class SearchResource {
+
+	@Context
+	UriInfo uri;
+
+	final TransportClient client;
+
+	public SearchResource(@Context ServletContext servletContext) throws IOException, ConfigException {
+		Config config = Config.getConfig();
+		client = ESClient.getClient(config);
+	}
+
+	@GET
+	@Produces(APIMediaType.APPLICATION_JSONAPI)
+	public Response search(@QueryParam("query") String query, @QueryParam("skip") Integer skip,
+			@QueryParam("limit") Integer limit, @QueryParam("excerpt") Integer excerpt) {
+		Wrapper<List<ArticleFull>> res = new Wrapper<>();
+
+		if (skip == null || skip < 0)
+			skip = 0;
+
+		if (limit == null || limit < 0)
+			limit = 20;
+
+		SearchResponse response = null;
+		try {
+			response = client.prepareSearch("articles").setSearchType(SearchType.QUERY_AND_FETCH)
+					.setQuery(QueryBuilders.multiMatchQuery(query, "_all")).setFrom(skip).setSize(limit).execute()
+					.actionGet();
+		} catch (Exception e) {
+			res.addError(new APIError(Response.Status.BAD_REQUEST, "Error", e.getMessage()));
+			return res.badRequest();
+		}
+
+		SearchHits hits = response.getHits();
+		List<ArticleFull> articles = new ArrayList<>(10);
+		for (SearchHit hit : hits) {
+			Map<String, Object> source = hit.getSource();
+			ArticleFull article = new ArticleFull();
+			article.setId(MongoUtils.objectId(hit.getId()));
+			article.setTitle(source.get("title").toString());
+			if (excerpt != null && excerpt > 0)
+				article.setText(StringUtils.ellipsize(source.get("text").toString(), excerpt));
+			articles.add(article);
+		}
+
+		res.addMeta("total", articles.size());
+
+		return res.ok(articles);
+	}
+
+}
diff --git a/vipra-util/pom.xml b/vipra-util/pom.xml
index d7682c6490149e5d84b0f4e16e9df186f78b21ed..5084145ae53e0c0e941984e53c59ce3e41268117 100644
--- a/vipra-util/pom.xml
+++ b/vipra-util/pom.xml
@@ -50,5 +50,12 @@
 			<artifactId>jackson-annotations</artifactId>
 			<version>2.7.0</version>
 		</dependency>
+
+		<!-- ElasticSearch -->
+		<dependency>
+			<groupId>org.elasticsearch</groupId>
+			<artifactId>elasticsearch</artifactId>
+			<version>2.1.0</version>
+		</dependency>
 	</dependencies>
 </project>
\ No newline at end of file
diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/es/ESClient.java b/vipra-util/src/main/java/de/vipra/util/ESClient.java
similarity index 54%
rename from vipra-cmd/src/main/java/de/vipra/cmd/es/ESClient.java
rename to vipra-util/src/main/java/de/vipra/util/ESClient.java
index a48a17c9d219cacfe4108dab1cc42f25eab10a1e..efae45afc1bd94b693e18ada8fde18c6242db124 100644
--- a/vipra-cmd/src/main/java/de/vipra/cmd/es/ESClient.java
+++ b/vipra-util/src/main/java/de/vipra/util/ESClient.java
@@ -1,4 +1,4 @@
-package de.vipra.cmd.es;
+package de.vipra.util;
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
@@ -6,14 +6,16 @@ import java.net.UnknownHostException;
 import org.elasticsearch.client.transport.TransportClient;
 import org.elasticsearch.common.transport.InetSocketTransportAddress;
 
-import de.vipra.util.Config;
-import de.vipra.util.Constants;
-
 public abstract class ESClient {
 
+	private static TransportClient client;
+
 	public static TransportClient getClient(Config config) throws UnknownHostException {
-		return TransportClient.builder().build().addTransportAddress(
-				new InetSocketTransportAddress(InetAddress.getByName(Constants.ES_HOST), Constants.ES_PORT));
+		if (client == null) {
+			client = TransportClient.builder().build().addTransportAddress(
+					new InetSocketTransportAddress(InetAddress.getByName(Constants.ES_HOST), Constants.ES_PORT));
+		}
+		return client;
 	}
 
 }