diff --git a/app/main/events.py b/app/main/events.py
index e516a00e7c0b7315b594e9e565d534b014a6b82d..c734799e05a70276559a9cf02ad428952c161a69 100644
--- a/app/main/events.py
+++ b/app/main/events.py
@@ -1,9 +1,11 @@
 from flask import current_app, request
 from flask_login import current_user, login_required
+from ..decorators import admin_required
 from .. import db, socketio
 from ..models import User
 import json
 import jsonpatch
+import logging
 
 
 '''
@@ -28,6 +30,26 @@ def connect():
                                    request.sid)
 
 
+@socketio.on('connect_admin')
+@login_required
+@admin_required
+def connect_admin(selected_user_id):
+    '''
+    ' The Socket.IO module creates a session id (sid) on each request. The
+    ' initiating admin is automatically placed in a room with that sid, which
+    ' will be used for further information exchange generated by a background
+    ' task associated with the sid. Admin will be placed in that room on emiting
+    ' "conncect_admin".
+    '''
+    logger = logging.getLogger(__name__)
+    logger.warning('Admin emitted "connect_admin".')
+    logger.warning('Selected user id is: {}'.format(selected_user_id))
+    socketio.start_background_task(background_task_foreign,
+                                   current_app._get_current_object(),
+                                   selected_user_id,
+                                   request.sid)
+
+
 @socketio.on('disconnect')
 @login_required
 def disconnect():
@@ -51,9 +73,13 @@ def background_task(app, user_id, session_id):
     '''
     with app.app_context():
         user = db.session.query(User).filter_by(id=user_id).first()
+        logging.getLogger(__name__)
+        logging.warning('User object is: {}'.format(user))
         ''' Get current values from the database. '''
         corpora = user.corpora_as_dict()
+        logging.warning('Corpora are: {}'.format(corpora))
         jobs = user.jobs_as_dict()
+        logging.warning('Jobs are: {}'.format(jobs))
         ''' Send initial values. '''
         socketio.emit('init-corpora',
                       json.dumps(corpora),
@@ -83,3 +109,54 @@ def background_task(app, user_id, session_id):
             jobs = new_jobs
             socketio.sleep(3)
     disconnected.remove(session_id)
+
+
+def background_task_foreign(app, user_id, session_id):
+    '''
+    ' Sends initial corpus and job lists to the client. Afterwards it checks
+    ' every 3 seconds if changes to the initial values appeared. If changes are
+    ' detected, a RFC 6902 compliant JSON patch gets send.
+    '
+    ' NOTE: The initial values are send as a init-* events.
+    '       The JSON patches are send as update-* events.
+    '
+    '       > where '*' is either 'corpora' or 'jobs'
+    '''
+    with app.app_context():
+        user = db.session.query(User).filter_by(id=user_id).first()
+        logging.getLogger(__name__)
+        logging.warning('User object is: {}'.format(user))
+        ''' Get current values from the database. '''
+        corpora = user.corpora_as_dict()
+        logging.warning('Corpora are: {}'.format(corpora))
+        jobs = user.jobs_as_dict()
+        logging.warning('Jobs are: {}'.format(jobs))
+        ''' Send initial values. '''
+        socketio.emit('init-foreign-corpora',
+                      json.dumps(corpora),
+                      room=session_id)
+        socketio.emit('init-foreign-jobs',
+                      json.dumps(jobs),
+                      room=session_id)
+        ''' TODO: Implement maximum runtime for this loop. '''
+        while session_id not in disconnected:
+            ''' Get current values from the database '''
+            new_corpora = user.corpora_as_dict()
+            new_jobs = user.jobs_as_dict()
+            ''' Compute JSON patches. '''
+            corpus_patch = jsonpatch.JsonPatch.from_diff(corpora, new_corpora)
+            jobs_patch = jsonpatch.JsonPatch.from_diff(jobs, new_jobs)
+            ''' In case there are patches, send them to the user. '''
+            if corpus_patch:
+                socketio.emit('update-foreign-corpora',
+                              corpus_patch.to_string(),
+                              room=session_id)
+            if jobs_patch:
+                socketio.emit('update-foreign-jobs',
+                              jobs_patch.to_string(),
+                              room=session_id)
+            ''' Set new values as references for the next iteration. '''
+            corpora = new_corpora
+            jobs = new_jobs
+            socketio.sleep(3)
+    disconnected.remove(session_id)
diff --git a/app/templates/admin/admin_user_page.html.j2 b/app/templates/admin/admin_user_page.html.j2
index 8a2204f7e881089581e6c2802899bba33fbf5fa0..8b13a6d4d5da2442f6a359d04cc03820cd7a8c77 100644
--- a/app/templates/admin/admin_user_page.html.j2
+++ b/app/templates/admin/admin_user_page.html.j2
@@ -21,50 +21,41 @@
     </div>
   </div>
 </div>
+<script type="text/javascript">
+  var selected_user_id = {{selected_user.id|tojson|safe}}
+  socket.emit('connect_admin', selected_user_id);
+</script>
 <div class="col s12 m6">
-  <div class="card large">
-    <div class="card-content">
-      <span class="card-title">User Jobs</span>
-      <div id="users">
-        <div class="input-field">
-          <i class="material-icons prefix">search</i>
-          <input id="search-corpus" class="search" type="text"></input>
-          <label for="search-corpus">Search jobs</label>
-        </div>
-        <div class="collection list">
-          {% for job in selected_user.jobs.all() %}
-            {% if job.service == 'nlp' %}
-              {% set service_color = 'blue' %}
-              {% set service_icon = 'format_textdirection_l_to_r' %}
-            {% elif job.service =='ocr' %}
-              {% set service_color = 'green' %}
-              {% set service_icon = 'find_in_page' %}
-            {% else %}
-              {% set service_color = 'red' %}
-              {% set service_icon = 'help' %}
-            {% endif %}
-            {% if job.status == 'pending' %}
-              {% set badge_color = 'amber' %}
-            {% elif job.status =='running' %}
-              {% set badge_color = 'indigo' %}
-            {% elif job.status =='complete' %}
-              {% set badge_color = 'teal' %}
-            {% else %}
-              {% set badge_color = 'red' %}
-            {% endif %}
-            <a href="{{ url_for('main.job', job_id=job.id) }}" class="collection-item avatar">
-                <i class="material-icons circle {{ service_color }}">{{ service_icon }}</i>
-                <span class="new badge {{ badge_color }}" data-badge-caption="">{{ job.status }}</span>
-                <span class="title">{{ job.title }}</span>
-                <p>{{ job.description }}</p>
-            </a>
-          {% endfor %}
+  <div id="job-list">
+    <div class="card">
+      <div class="card-content">
+        <div class="row">
+          <div class="col s12">
+            <div class="input-field">
+              <i class="material-icons prefix">search</i>
+              <input id="search-job" class="search" type="text"></input>
+              <label for="search-job">Search job</label>
+            </div>
+          </div>
+          <div class="col s12">
+            <ul class="pagination"></ul>
+          </div>
         </div>
-        <ul class="pagination"></ul>
       </div>
     </div>
+    <div class="collection list"></div>
   </div>
 </div>
+<script>
+  var jobList = new JobList("job-list", {
+    item: '<div><span class="title"></span><span class="description"></span></div>',
+    page: 4,
+    pagination: true,
+    valueNames: ["description", "title", {data: ["id"]}]
+  });
+  jobList.on("filterComplete", List.updatePagination);
+  jobList.on("searchComplete", List.updatePagination);
+</script>
 <div class="col s12">
   <div class="card large">
     <div class="card-content">
diff --git a/app/templates/base.html.j2 b/app/templates/base.html.j2
index c6bac81a217fd99fec758413e1fb1554fa1b1e4e..8488c8dfcf03a70abfbf18d472bffcca2cd6741b 100644
--- a/app/templates/base.html.j2
+++ b/app/templates/base.html.j2
@@ -26,6 +26,7 @@
       var jobsSubscribers = [];
       var socket = io();
 
+
       socket.on('init-corpora', function(msg) {
         var subscriber;
 
@@ -64,6 +65,46 @@
         console.log(msg);
       });
     </script>
+    <script>
+      var foreignCorpora;
+      var foreignCorporaSubscribers = [];
+      var foreignJobs;
+      var foreignJobsSubscribers = [];
+
+
+      socket.on('init-foreign-corpora', function(msg) {
+        var subscriber;
+
+        foreignCorpora = JSON.parse(msg);
+        for (subscriber of foreignCorporaSubscribers) {subscriber._init();}
+      });
+
+
+      socket.on('init-foreign-jobs', function(msg) {
+        var subscriber;
+
+        foreignJobs = JSON.parse(msg);
+        for (subscriber of foreignJobsSubscribers) {subscriber._init();}
+      });
+
+
+      socket.on('update-foreign-corpora', function(msg) {
+        var patch, patchedCorpora, subscriber;
+
+        patch = JSON.parse(msg);
+        foreignCorpora = jsonpatch.apply_patch(foreignCorpora, patch);
+        for (subscriber of foreignCorporaSubscribers) {subscriber._update(patch);}
+      });
+
+
+      socket.on('update-foreign-jobs', function(msg) {
+        var patch, patchedJobs, subscriber;
+
+        patch = JSON.parse(msg);
+        foreignJobs = jsonpatch.apply_patch(foreignJobs, patch);
+        for (subscriber of foreignJobsSubscribers) {subscriber._update(patch);}
+      });
+    </script>
     <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
   </head>
   <body>