diff --git a/app/models.py b/app/models.py
index c3a096683e4ce874547f240efc5dafcba39c903f..d5284554b0a9aa1b1c59a5419650a4571b63f732 100644
--- a/app/models.py
+++ b/app/models.py
@@ -247,6 +247,21 @@ class Job(db.Model):
         """
         return '<Job %r>' % self.title
 
+    def to_jsonifyable(self):
+        return {'id': self.id,
+                'creation_date': self.creation_date.timestamp(),
+                'description': self.description,
+                'end_date': (self.end_date.timestamp() if self.end_date else
+                             None),
+                'mem_mb': self.mem_mb,
+                'n_cores': self.n_cores,
+                'service': self.service,
+                'service_args': self.service_args,
+                'service_version': self.service_version,
+                'status': self.status,
+                'title': self.title,
+                'user_id': self.user_id}
+
 
 class Corpus(db.Model):
     """
@@ -269,6 +284,12 @@ class Corpus(db.Model):
         """
         return '<Corpus %r>' % self.title
 
+    def to_jsonifyable(self):
+        return {'id': self.id,
+                'creation_date': self.creation_date,
+                'description': self.description,
+                'title': self.title,
+                'user_id': self.user_id}
 
 '''
 ' Flask-Login is told to use the application’s custom anonymous user by setting
diff --git a/app/templates/main/dashboard.html.j2 b/app/templates/main/dashboard.html.j2
index c8a02c0785344dd7bbe852aac6b5469bef38ee8e..ac063daeae60fb37dd18f42c31c0d8b01880205f 100644
--- a/app/templates/main/dashboard.html.j2
+++ b/app/templates/main/dashboard.html.j2
@@ -76,45 +76,114 @@
         </div>
       </div>
     </div>
-    <div class="collection list">
-      {% for job in current_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>
+    <div class="collection list"></div>
   </div>
 </div>
 <script>
   var jobList = new List("job-list", {valueNames: ["title"],
                                       page: 4,
-                                      pagination: true});
+                                      pagination: false});
   jobList.on("filterComplete", updatePagination);
   jobList.on("searchComplete", updatePagination);
 </script>
 
+<script>
+  const SERVICE_COLORS = {"nlp": "blue",
+                          "ocr": "green"}
+  const SERVICE_ICONS = {"nlp": "format_textdirection_l_to_r",
+                         "ocr": "find_in_page"}
+  const STATUS_COLORS = {"pending": "amber",
+                         "running": "indigo",
+                         "complete": "teal"}
+
+  var getJobsCallbackFunctions = [];
+
+  function getJobs() {
+    fetch("/api/v1.0/jobs")
+    .then(function(response) {
+      if (response.status >= 200 && response.status < 300) {
+        return Promise.resolve(response)
+      } else {
+        return Promise.reject(new Error(response.statusText))
+      }
+    })
+    .then(function(response) {
+        return response.json()
+    })
+    .then(function(jobs) {
+      for (callbackFunction of getJobsCallbackFunctions) {
+        callbackFunction(jobs);
+      }
+    })
+    .catch(function(error) {
+      console.log('Request failed', error);
+    });
+  }
+
+  setInterval(getJobs, 1000);
+
+  function createJobElement(job) {
+    jobElement = document.createElement("a");
+    jobElement.classList.add("avatar", "collection-item");
+    jobElement.dataset.key = "id";
+    jobElement.dataset.value = job.id;
+    jobElement.href = `/jobs/${job.id}`;
+    jobDescriptionElement = document.createElement("p");
+    jobDescriptionElement.dataset.key = "description";
+    jobDescriptionElement.innerText = job.description;
+    jobServiceElement = document.createElement("i");
+    jobServiceElement.classList.add("circle", "material-icons", SERVICE_COLORS[job.service]);
+    jobServiceElement.dataset.key = "service";
+    jobServiceElement.innerText = SERVICE_ICONS[job.service];
+    jobStatusElement = document.createElement("span");
+    jobStatusElement.classList.add("badge", "new", "status", STATUS_COLORS[job.status]);
+    jobStatusElement.dataset.badgeCaption = "";
+    jobStatusElement.dataset.key = "status";
+    jobStatusElement.innerText = job.status;
+    jobTitleElement = document.createElement("span");
+    jobTitleElement.classList.add("title");
+    jobTitleElement.dataset.key = "title";
+    jobTitleElement.innerText = job.title;
+
+    jobElement.appendChild(jobServiceElement);
+    jobElement.appendChild(jobStatusElement);
+    jobElement.appendChild(jobTitleElement);
+    jobElement.appendChild(jobDescriptionElement);
+
+    return jobElement;
+  }
+
+
+  function updateJobElement(job, jobElement) {
+    /*
+    if (jobElement.dataset.value != job.id) {
+      jobElement.dataset.value = job.id;
+      jobElement.href = `/jobs/${job.id}`;
+    }
+    */
+
+
+  }
+
+  function processJobs(jobs) {
+    for (job of jobs) {
+      jobElement = jobList.list.querySelectorAll('[data-key="id"]')
+                               .querySelector(`[data-value="${job.id}"]`);
+      console.log(jobElement);
+      if (jobElement) {
+        statusElement = jobElement.querySelector(".status");
+        currentStatus = statusElement.text
+        continue;
+      }
+      jobList.list.appendChild(createJobElement(job));
+    }
+    jobList.reIndex();
+    jobList.update();
+  }
+
+  getJobsCallbackFunctions.push(processJobs)
+</script>
+
 <div id="new-corpus-modal" class="modal">
   <div class="modal-content">
     <h4>New corpus</h4>