diff --git a/app/static/js/corpora.js b/app/static/js/corpora.js
new file mode 100644
index 0000000000000000000000000000000000000000..6922adec6c6dcdb4df927283701854f38ba84ea9
--- /dev/null
+++ b/app/static/js/corpora.js
@@ -0,0 +1,33 @@
+function createCorpusElement(corpus) {
+  corpusElement = document.createElement("a");
+  corpusElement.classList.add("avatar", "collection-item");
+  corpusElement.dataset.key = "id";
+  corpusElement.dataset.value = corpus.id;
+  corpusElement.href = `/corpora/${corpus.id}`;
+  corpusDescriptionElement = document.createElement("p");
+  corpusDescriptionElement.dataset.key = "description";
+  corpusDescriptionElement.innerText = corpus.description;
+  corpusIconElement = document.createElement("i");
+  corpusIconElement.classList.add("circle", "material-icons");
+  corpusIconElement.innerText = "book";
+  corpusTitleElement = document.createElement("span");
+  corpusTitleElement.classList.add("title");
+  corpusTitleElement.dataset.key = "title";
+  corpusTitleElement.innerText = corpus.title;
+
+  corpusElement.appendChild(corpusIconElement);
+  corpusElement.appendChild(corpusTitleElement);
+  corpusElement.appendChild(corpusDescriptionElement);
+
+  return corpusElement;
+}
+
+
+function createCorpusElements(corpusList) {
+  for (corpus of corpora) {
+    corpusList.list.appendChild(createCorpusElement(corpus));
+  }
+  corpusList.reIndex();
+  corpusList.update();
+  updatePagination(corpusList);
+}
diff --git a/app/static/js/jobs.js b/app/static/js/jobs.js
new file mode 100644
index 0000000000000000000000000000000000000000..97fd1afa3723b11ff3877e7e0730523a3251cb2b
--- /dev/null
+++ b/app/static/js/jobs.js
@@ -0,0 +1,53 @@
+// Job list code
+const SERVICE_COLORS = {"nlp": "blue",
+                        "ocr": "green",
+                        "default": "red"};
+const SERVICE_ICONS = {"nlp": "format_textdirection_l_to_r",
+                       "ocr": "find_in_page",
+                       "default": "help"};
+const STATUS_COLORS = {"pending": "amber",
+                       "running": "indigo",
+                       "complete": "teal",
+                       "default": "red"};
+
+
+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 createJobElements(jobList) {
+  for (job of jobs) {
+    jobList.list.appendChild(createJobElement(job));
+  }
+  jobList.reIndex();
+  jobList.update();
+  updatePagination(jobList);
+}
diff --git a/app/static/js/polls.js b/app/static/js/polls.js
new file mode 100644
index 0000000000000000000000000000000000000000..c8e8ce34c273823b0803b56c805f6f2753f54853
--- /dev/null
+++ b/app/static/js/polls.js
@@ -0,0 +1,57 @@
+var subscribers = {"corpora": [], "jobs": []};
+
+
+function getCorpora() {
+  fetch("/api/v1.0/corpora")
+  .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(data) {
+    if (JSON.stringify(corpora) != JSON.stringify(data)) {
+      corpora = data;
+      for (subscriber of subscribers.corpora) {
+        subscriber();
+      }
+    }
+  })
+  .catch(function(error) {
+    console.log('Request failed', error);
+  });
+}
+
+
+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(data) {
+    if (JSON.stringify(jobs) != JSON.stringify(data)) {
+      jobs = data;
+      for (subscriber of subscribers.jobs) {
+        subscriber();
+      }
+    }
+  })
+  .catch(function(error) {
+    console.log('Request failed', error);
+  });
+}
+
+
+setInterval(getCorpora, 5000);
+setInterval(getJobs, 5000);
diff --git a/app/static/js/utils.js b/app/static/js/utils.js
new file mode 100644
index 0000000000000000000000000000000000000000..91e3a66c3ef78c0e7f3c0d3048f05f12d41bf09f
--- /dev/null
+++ b/app/static/js/utils.js
@@ -0,0 +1,9 @@
+// List.js utils
+var updatePagination = function(list) {
+  pagination = list.listContainer.querySelector(".pagination");
+  if (pagination.childElementCount <= 1) {
+    pagination.classList.add("hide");
+  } else {
+    pagination.classList.remove("hide");
+  }
+}
diff --git a/app/templates/base.html.j2 b/app/templates/base.html.j2
index 94ca3988e167f53ed97a71a2f1361f0ccaca00ce..d5b361b773aa4a033588dbfc9fdc8851a0fefdd6 100644
--- a/app/templates/base.html.j2
+++ b/app/templates/base.html.j2
@@ -11,18 +11,25 @@
     <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='fonts/material-icons/material-icons.css') }}">
     <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/materialize.min.css') }}" media="screen,projection"/>
     <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/opaque.css') }}" media="screen,projection"/>
-    <script src="{{ url_for('static', filename='js/list.js') }}"></script>
+    {% if current_user.is_authenticated %}
     <script>
-      // Utils
-      var updatePagination = function(list) {
-        pagination = list.listContainer.querySelector(".pagination");
-        if (pagination.childElementCount <= 1) {
-          pagination.classList.add("hide");
-        } else {
-          pagination.classList.remove("hide");
-        }
-      }
+      var corpora = [
+        {% for corpus in current_user.corpora.all() %}
+        {{ corpus.to_dict()|tojson }},
+        {% endfor %}
+      ];
+      var jobs = [
+        {% for job in current_user.jobs.all() %}
+        {{ job.to_dict()|tojson }},
+        {% endfor %}
+      ];
     </script>
+    <script src="{{ url_for('static', filename='js/polls.js') }}"></script>
+    {% endif %}
+    <script src="{{ url_for('static', filename='js/list.js') }}"></script>
+    <script src="{{ url_for('static', filename='js/utils.js') }}"></script>
+    <script src="{{ url_for('static', filename='js/corpora.js') }}"></script>
+    <script src="{{ url_for('static', filename='js/jobs.js') }}"></script>
     <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
   </head>
   <body>
diff --git a/app/templates/main/dashboard.html.j2 b/app/templates/main/dashboard.html.j2
index ac063daeae60fb37dd18f42c31c0d8b01880205f..94c9766252eef7de49b8abb75fe2aff85b87f5c0 100644
--- a/app/templates/main/dashboard.html.j2
+++ b/app/templates/main/dashboard.html.j2
@@ -27,15 +27,7 @@
         </div>
       </div>
     </div>
-    <div class="collection list">
-      {% for corpus in current_user.corpora.all() %}
-        <a href="#!" class="collection-item avatar">
-            <i class="material-icons circle">book</i>
-            <span class="title">{{ corpus.title }}</span>
-            <p>{{ corpus.description }}</p>
-        </a>
-      {% endfor %}
-    </div>
+    <div class="collection list"></div>
   </div>
 </div>
 <script>
@@ -44,6 +36,10 @@
                                         pagination: true});
   corpusList.on("filterComplete", updatePagination);
   corpusList.on("searchComplete", updatePagination);
+  createCorpusElements(corpusList);
+  subscribers.corpora.push(function() {
+    console.log('[Corpora]: Something changed.');
+  });
 </script>
 
 <div class="col s12">
@@ -85,103 +81,10 @@
                                       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)
+  createJobElements(jobList);
+  subscribers.jobs.push(function() {
+    console.log('[Jobs]: Something changed.');
+  });
 </script>
 
 <div id="new-corpus-modal" class="modal">