diff --git a/config/locator/locate.twitterauth.inc.php b/config/locator/locate.twitterauth.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..f417c9ee3823fefa97cd381b4270e4ee9f6628f0
--- /dev/null
+++ b/config/locator/locate.twitterauth.inc.php
@@ -0,0 +1,13 @@
+<?php
+
+$recipe = [];
+
+$recipe['twitterauth'] = [];
+
+$recipe['twitterauth']['name'] = 'Lunr\Spark\Twitter\Authentication';
+
+$recipe['twitterauth']['params'] = [ 'cas', 'logger', 'curl' ];
+
+$recipe['twitterauth']['singleton'] = TRUE;
+
+?>
diff --git a/config/locator/locate.twittersearch.inc.php b/config/locator/locate.twittersearch.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..c9f369c42d10f9e3dcda6c7a19fba79ea47b0a03
--- /dev/null
+++ b/config/locator/locate.twittersearch.inc.php
@@ -0,0 +1,13 @@
+<?php
+
+$recipe = [];
+
+$recipe['twittersearch'] = [];
+
+$recipe['twittersearch']['name'] = 'Lunr\Spark\Twitter\Search';
+
+$recipe['twittersearch']['params'] = [ 'cas', 'logger', 'curl' ];
+
+$recipe['twittersearch']['singleton'] = TRUE;
+
+?>
diff --git a/src/Virus/Twitter/TwitterAuthenticationTrait.php b/src/Virus/Twitter/TwitterAuthenticationTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..43fcce9a201afdc1fe79d3d2169df06c196db7a3
--- /dev/null
+++ b/src/Virus/Twitter/TwitterAuthenticationTrait.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * This file contains a twitter controller trait.
+ *
+ * PHP Version 5.4
+ *
+ * @category   Controller
+ * @package    Virus
+ * @subpackage Twitter
+ * @author     Dinos Theodorou <dinos@m2mobi.com>
+ * @copyright  2013, M2Mobi BV, Amsterdam, The Netherlands
+ * @license    http://lunr.nl/LICENSE MIT License
+ */
+
+namespace Virus\Twitter;
+
+use Lunr\Corona\HttpCode;
+
+/**
+ * Twitter trait for authentication methods.
+ *
+ * @category   Controller
+ * @package    Virus
+ * @subpackage Twitter
+ * @author     Dinos Theodorou <dinos@m2mobi.com>
+ */
+trait TwitterAuthenticationTrait
+{
+
+    /**
+     * Store result of the call in the response object.
+     *
+     * @param Integer $code    Return Code
+     * @param String  $message Error Message
+     * @param mixed   $info    Additional error information
+     *
+     * @return void
+     */
+    abstract protected function set_result($code, $message = NULL, $info = NULL);
+
+    /**
+     * Get the access token used for twitter API requests app-auth-only.
+     *
+     * @return void
+     */
+    public function get_bearer_token()
+    {
+        $consumer_key    = $this->request->get_post_data('consumer_key');
+        $consumer_secret = $this->request->get_post_data('consumer_secret');
+        $user_agent      = $this->request->get_post_data('user_agent');
+
+        if ($consumer_key == '')
+        {
+            $this->set_result(HttpCode::BAD_REQUEST, 'Missing consumer_key', 'consumer_key');
+            return;
+        }
+
+        if ($consumer_secret == '')
+        {
+            $this->set_result(HttpCode::BAD_REQUEST, 'Missing consumer_secret', 'consumer_secret');
+            return;
+        }
+
+        if ($user_agent == '')
+        {
+            $this->set_result(HttpCode::BAD_REQUEST, 'Missing user_agent', 'user_agent');
+            return;
+        }
+
+        $twitter = $this->locator->twitterauth();
+
+        $twitter->consumer_key    = $consumer_key;
+        $twitter->consumer_secret = $consumer_secret;
+        $twitter->user_agent      = $user_agent;
+
+        $result = $twitter->get_bearer_token();
+
+        $this->response->add_response_data('access_token', $result);
+
+        $this->set_result(HttpCode::OK);
+        $this->response->view = 'jsonview';
+    }
+
+}
\ No newline at end of file
diff --git a/src/Virus/Twitter/TwitterController.php b/src/Virus/Twitter/TwitterController.php
new file mode 100644
index 0000000000000000000000000000000000000000..51ea2ab8c7c8620bfb039e804243eb0a68d7c51e
--- /dev/null
+++ b/src/Virus/Twitter/TwitterController.php
@@ -0,0 +1,97 @@
+<?php
+
+/**
+ * This file contains a twitter controller class.
+ *
+ * PHP Version 5.4
+ *
+ * @category   Controller
+ * @package    Virus
+ * @subpackage Twitter
+ * @author     Dinos Theodorou <dinos@m2mobi.com>
+ * @copyright  2013, M2Mobi BV, Amsterdam, The Netherlands
+ * @license    http://lunr.nl/LICENSE MIT License
+ */
+
+namespace Virus\Twitter;
+
+use Lunr\Corona\HttpCode;
+use Virus\Core\ApiController;
+
+/**
+ * Twitter controller class
+ *
+ * @category   Controller
+ * @package    Virus
+ * @subpackage Twitter
+ * @author     Dinos Theodorou <dinos@m2mobi.com>
+ */
+class TwitterController extends ApiController
+{
+
+    use TwitterAuthenticationTrait;
+    use TwitterSearchTrait;
+
+    /**
+     * Constructor.
+     *
+     * @param \Lunr\Core\ConfigServiceLocator $locator Shared instance of the Service Locator
+     */
+    public function __construct($locator)
+    {
+        parent::__construct($locator);
+    }
+
+    /**
+     * Destructor.
+     */
+    public function __destruct()
+    {
+        parent::__destruct();
+    }
+
+    /**
+     * Default method.
+     *
+     * @return void
+     */
+    public function index()
+    {
+        $this->set_result(HttpCode::OK);
+
+        $params = [];
+
+        $params['user_agent']['title']      = 'User Agent';
+        $params['consumer_key']['title']    = 'Consumer Key';
+        $params['consumer_secret']['title'] = 'Consumer Secret';
+        $params['bearer_token']['title']    = 'Bearer Token';
+        $params['params']['title']          = 'Pairs of parameters as param1=value1&param2=value2';
+
+        $params['user_agent']['methods']      = ['get_bearer_token'];
+        $params['consumer_key']['methods']    = ['get_bearer_token'];
+        $params['consumer_secret']['methods'] = ['get_bearer_token'];
+        $params['bearer_token']['methods']    = ['search_tweets'];
+        $params['params']['methods']          = ['search_tweets'];
+
+        $this->response->add_response_data('title', 'Twitter');
+        $this->response->add_response_data('platform', 'twitter');
+        $this->response->add_response_data('methods', $this->get_api_methods());
+        $this->response->add_response_data('parameters', $params);
+        $this->response->view = 'apiconsoleview';
+    }
+
+    /**
+     * Get API methods implemented by this controller.
+     *
+     * @return array $names Array of method names.
+     */
+    protected function get_api_methods()
+    {
+        $methods = parent::get_api_methods();
+
+        return $methods;
+    }
+
+}
+
+?>
diff --git a/src/Virus/Twitter/TwitterSearchTrait.php b/src/Virus/Twitter/TwitterSearchTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..b72c1a079ae9f6cda2f1c840232ae4564e5eabb1
--- /dev/null
+++ b/src/Virus/Twitter/TwitterSearchTrait.php
@@ -0,0 +1,96 @@
+<?php
+
+/**
+ * This file contains a twitter controller trait.
+ *
+ * PHP Version 5.4
+ *
+ * @category   Controller
+ * @package    Virus
+ * @subpackage Twitter
+ * @author     Dinos Theodorou <dinos@m2mobi.com>
+ * @copyright  2013, M2Mobi BV, Amsterdam, The Netherlands
+ * @license    http://lunr.nl/LICENSE MIT License
+ */
+
+namespace Virus\Twitter;
+
+use Lunr\Corona\HttpCode;
+
+/**
+ * Twitter trait for search methods.
+ *
+ * @category   Controller
+ * @package    Virus
+ * @subpackage Twitter
+ * @author     Dinos Theodorou <dinos@m2mobi.com>
+ */
+trait TwitterSearchTrait
+{
+
+    /**
+     * Store result of the call in the response object.
+     *
+     * @param Integer $code    Return Code
+     * @param String  $message Error Message
+     * @param mixed   $info    Additional error information
+     *
+     * @return void
+     */
+    abstract protected function set_result($code, $message = NULL, $info = NULL);
+
+    /**
+     * Get the access token used for twitter API requests app-auth-only.
+     *
+     * @return void
+     */
+    public function search_tweets()
+    {
+        $bearer_token = $this->request->get_post_data('bearer_token');
+        $params       = $this->request->get_post_data('params');
+
+        if ($bearer_token == '')
+        {
+            $this->set_result(HttpCode::BAD_REQUEST, 'Missing bearer token', 'bearer_token');
+            return;
+        }
+
+        if ($params == '')
+        {
+            $this->set_result(HttpCode::BAD_REQUEST, 'Missing parameters', 'params');
+            return;
+        }
+
+        $pairs = explode('&', $params);
+
+        $search_params = [];
+
+        foreach ($pairs as $pair)
+        {
+            if(stripos($pair, '=') === false)
+            {
+                $this->set_result(HttpCode::BAD_REQUEST, 'Wrong parameter syntax', 'param_syntax');
+                return;
+            }
+
+            list($key, $value) = explode('=', $pair);
+
+            $search_params[$key] = $value;
+        }
+
+        $twitter = $this->locator->twitterauth();
+        $search  = $this->locator->twittersearch();
+
+        $twitter->bearer_token = $bearer_token;
+
+        $tweets = $search->search_tweets($search_params);
+
+        $this->response->add_response_data('tweets', $tweets);
+
+        $this->set_result(HttpCode::OK);
+        $this->response->view = 'jsonview';
+    }
+
+}
+
+?>
diff --git a/statics/images/platforms/twitter_small.png b/statics/images/platforms/twitter_small.png
new file mode 100644
index 0000000000000000000000000000000000000000..48a407fef9c750c83e100a80b18ba8f8bde3d8eb
Binary files /dev/null and b/statics/images/platforms/twitter_small.png differ
diff --git a/statics/js/home.js b/statics/js/home.js
index ec90a67bf4a62e03622878f27d7f649bc5d8b094..94aa4457511584369bf120ed68008d74d494fa48 100644
--- a/statics/js/home.js
+++ b/statics/js/home.js
@@ -16,3 +16,7 @@ $(function(){
 $('#facebook').on('click', function(){
     window.location = 'facebook';
 });
+
+$('#twitter').on('click', function(){
+    window.location = 'twitter';
+});
\ No newline at end of file
diff --git a/tests/scripts/linkedin/001_base.js b/tests/scripts/linkedin/001_base.js
index be22fc4f552ee02e90934ee539d75070f748515e..471edf191e4f16d8a3888b6254a90576f6b8e13e 100644
--- a/tests/scripts/linkedin/001_base.js
+++ b/tests/scripts/linkedin/001_base.js
@@ -1,12 +1,12 @@
 // Test the Lunr Virus Homepage
-casper.test.begin("Lunr Spark Twitter Module Tests", function suite(test){
+casper.test.begin("Lunr Spark LinkedIn Module Tests", function suite(test){
 
-    casper.start("http://infest.lunr.nl", function(){
-        test.assertExists('div[id="twitter"]', "Twitter tile is present on Homepage");
+    casper.start("http://infest.lunr.nl/", function(){
+        test.assertExists('div[id="linkedin"]', "LinkedIn tile is present on Homepage");
     });
 
     casper.run(function(){
         test.done();
     });
 
-});
+});
\ No newline at end of file
diff --git a/tests/scripts/twitter/001_base.js b/tests/scripts/twitter/001_base.js
index 64f5df649fdf5026ac55c09fed5153cbfa4a6352..4bc1b9aea208f9f8be119e9585addbc77f47f12e 100644
--- a/tests/scripts/twitter/001_base.js
+++ b/tests/scripts/twitter/001_base.js
@@ -1,8 +1,15 @@
 // Test the Lunr Virus Homepage
-casper.test.begin("Lunr Spark LinkedIn Module Tests", function suite(test){
+casper.test.begin("Lunr Spark Twitter Module Tests", function suite(test){
 
-    casper.start("http://infest.lunr.nl/", function(){
-        test.assertExists('div[id="linkedin"]', "LinkedIn tile is present on Homepage");
+    casper.start("http://infest.lunr.nl/~dinos/virus", function(){
+        test.assertExists('div[id="twitter"]', "Twitter tile is present on Homepage");
+        this.click('div[id="twitter"]');
+    });
+
+    casper.then(function(){
+        test.assertTitle("Twitter | Lunr Spark", "Virus Twitter title is the one expected");
+        test.assertExists('div[class="methods"]', "Method list is present");
+        test.assertElementCount('div[class="methods"] div[class="method"]', 2, "Twitter has 2 api methods available");
     });
 
     casper.run(function(){
diff --git a/tests/scripts/twitter/002_get_bearer_token.js b/tests/scripts/twitter/002_get_bearer_token.js
new file mode 100644
index 0000000000000000000000000000000000000000..2e6cb930f911fdcadee05122c1b073d8670644c5
--- /dev/null
+++ b/tests/scripts/twitter/002_get_bearer_token.js
@@ -0,0 +1,31 @@
+// Test the Lunr Virus Homepage
+casper.test.begin("Lunr Spark Twitter - Get bearer access token of Twitter app", function suite(test){
+
+    casper.start("http://infest.lunr.nl/~dinos/virus/twitter", function(){
+        this.click('div[id="get_bearer_token"]');
+    });
+
+    casper.then(function(){
+        this.fill('form[id="api_request"]', {
+            user_agent: apikeys["twitter"]["user_agent"],
+            consumer_key: apikeys["twitter"]["consumer_key"],
+            consumer_secret: apikeys["twitter"]["consumer_secret"]
+        }, true);
+        this.waitForResource("twitter/get_bearer_token");
+    });
+
+    casper.then(function(){
+        test.assertEvalEquals(function(){
+            return __utils__.findOne('#json_display_result').innerText;
+        }, '200', "get_bearer_token request successful");
+
+        test.assertEvalEquals(function(){
+            return __utils__.findOne('#json_display_access_token').innerText;
+        }, apikeys["twitter"]["bearer_token"], "Bearer Access Token is correct");
+    });
+
+    casper.run(function(){
+        test.done();
+    });
+
+});
\ No newline at end of file
diff --git a/tests/scripts/twitter/003_search_tweets.js b/tests/scripts/twitter/003_search_tweets.js
new file mode 100644
index 0000000000000000000000000000000000000000..58dc2755fb5e2fe6290ce37071dac22d262b4b8c
--- /dev/null
+++ b/tests/scripts/twitter/003_search_tweets.js
@@ -0,0 +1,30 @@
+// Test the Lunr Virus Homepage
+casper.test.begin("Lunr Spark Twitter - Search for tweets", function suite(test){
+
+    casper.start("http://infest.lunr.nl/~dinos/virus/twitter", function(){
+        this.click('div[id="search_tweets"]');
+    });
+
+    casper.then(function(){
+        this.fill('form[id="api_request"]', {
+            bearer_token: apikeys["twitter"]["bearer_token"],
+            params: apikeys["twitter"]["params"]
+        }, true);
+        this.waitForResource("twitter/search_tweets");
+    });
+
+    casper.then(function(){
+        test.assertEvalEquals(function(){
+            return __utils__.findOne('#json_display_result').innerText;
+        }, '200', "get_bearer_token request successful");
+
+        test.assertEvalEquals(function(){
+            return __utils__.findOne('#json_display_tweets').innerText;
+        }, '[object Object],[object Object]', 'Search returns exactly 2 objects as it was set.');
+    });
+
+    casper.run(function(){
+        test.done();
+    });
+
+});
\ No newline at end of file
