diff --git a/vospace-ui-frontend/src/App.vue b/vospace-ui-frontend/src/App.vue
index 1aced9b4e5ba226a94d09686a6d0efa0fa6069cc..4081bffc5ea36748f96ac05a207bd3af1a5d8d33 100644
--- a/vospace-ui-frontend/src/App.vue
+++ b/vospace-ui-frontend/src/App.vue
@@ -28,6 +28,9 @@ export default {
   }),
   components: {
     TopMenu
+  },
+  mounted() {
+    this.$store.dispatch('loadJobs');
   }
 }
 </script>
diff --git a/vospace-ui-frontend/src/api/mock/data/job.json b/vospace-ui-frontend/src/api/mock/data/job.json
index 633abc9aaca6432168df723153c54d934763c4f3..946c27000747cf259c034d13481a1227c2399cff 100644
--- a/vospace-ui-frontend/src/api/mock/data/job.json
+++ b/vospace-ui-frontend/src/api/mock/data/job.json
@@ -1,4 +1,5 @@
 {
   "id": "1234",
-  "status": "EXECUTING"
+  "status": "EXECUTING",
+  "read": true
 }
diff --git a/vospace-ui-frontend/src/api/mock/data/jobs.json b/vospace-ui-frontend/src/api/mock/data/jobs.json
new file mode 100644
index 0000000000000000000000000000000000000000..1c4c53bde5822d8555dd0b4c2602f76273534f97
--- /dev/null
+++ b/vospace-ui-frontend/src/api/mock/data/jobs.json
@@ -0,0 +1,11 @@
+[{
+    "id": "1",
+    "status": "COMPLETED",
+    "read": true
+  },
+  {
+    "id": "2",
+    "status": "COMPLETED",
+    "read": true
+  }
+]
diff --git a/vospace-ui-frontend/src/api/mock/index.js b/vospace-ui-frontend/src/api/mock/index.js
index 45c0226b944d9a2062a5c3c22511da896bbb4992..ed27af48f484a5dccd3357f8d1f9a127dd4d81d9 100644
--- a/vospace-ui-frontend/src/api/mock/index.js
+++ b/vospace-ui-frontend/src/api/mock/index.js
@@ -2,6 +2,7 @@ import root from 'raw-loader!./data/nodes/root.html';
 import folder1 from 'raw-loader!./data/nodes/folder1.html';
 import folder2 from 'raw-loader!./data/nodes/folder2.html';
 import job from './data/job';
+import jobs from './data/jobs';
 import store from '../../store';
 
 const fetch = (mockData, showLoading = true, time = 500) => {
@@ -36,5 +37,8 @@ export default {
   },
   startRecallFromTapeJob() {
     return fetch(job);
+  },
+  loadJobs() {
+    return fetch(jobs, false);
   }
 }
diff --git a/vospace-ui-frontend/src/components/Jobs.vue b/vospace-ui-frontend/src/components/Jobs.vue
new file mode 100644
index 0000000000000000000000000000000000000000..b0abb7e7cd7863a3156e8fd2aa09ee5197c48b92
--- /dev/null
+++ b/vospace-ui-frontend/src/components/Jobs.vue
@@ -0,0 +1,24 @@
+<template>
+<table class="table b-table table-striped table-hover">
+  <thead>
+    <tr>
+      <th>Id</th>
+      <th>Status</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr v-for="job in jobs" :key="job.id">
+      <td>{{job.id}}</td>
+      <td>{{job.status}}</td>
+    </tr>
+  </tbody>
+</table>
+</template>
+
+<script>
+export default {
+  computed: {
+    jobs() { return this.$store.state.jobs }
+  }
+}
+</script>
diff --git a/vospace-ui-frontend/src/components/JobsMenuItem.vue b/vospace-ui-frontend/src/components/JobsMenuItem.vue
new file mode 100644
index 0000000000000000000000000000000000000000..688688f81a3e295a3ebe93c6ccc54fa25090445b
--- /dev/null
+++ b/vospace-ui-frontend/src/components/JobsMenuItem.vue
@@ -0,0 +1,16 @@
+<template>
+<b-navbar-nav>
+  <b-nav-item href="#/jobs">
+    <strong>Jobs</strong>&nbsp;
+    <b-badge variant="light">{{jobs.length}} <span class="sr-only">unread messages</span></b-badge>
+  </b-nav-item>
+</b-navbar-nav>
+</template>
+
+<script>
+export default {
+  computed: {
+    jobs() { return this.$store.state.jobs }
+  }
+}
+</script>
diff --git a/vospace-ui-frontend/src/components/TopMenu.vue b/vospace-ui-frontend/src/components/TopMenu.vue
index 1115343a9e7ffbd5b1defe3993f5c3dcbd617efc..813bddffec7eaebde20c57045b895b76be7a9672 100644
--- a/vospace-ui-frontend/src/components/TopMenu.vue
+++ b/vospace-ui-frontend/src/components/TopMenu.vue
@@ -1,11 +1,22 @@
 <template>
 <div>
   <b-navbar toggleable="lg" type="dark" id="top-menu">
-    <b-navbar-brand href="#" class="d-none d-md-block">VOSpace</b-navbar-brand>
+    <b-navbar-brand href="#/" class="d-none d-md-block">VOSpace</b-navbar-brand>
+    <JobsMenuItem />
   </b-navbar>
 </div>
 </template>
 
+<script>
+import JobsMenuItem from './JobsMenuItem.vue';
+
+export default {
+  components: {
+    JobsMenuItem
+  }
+}
+</script>
+
 <style>
 #top-menu {
   background-color: #093784;
diff --git a/vospace-ui-frontend/src/router.js b/vospace-ui-frontend/src/router.js
index 2bb82a7ef9c3788e0128010afd775fa2746be2ce..6b8ab996559d50d1122319548cca7498bd7c68f8 100644
--- a/vospace-ui-frontend/src/router.js
+++ b/vospace-ui-frontend/src/router.js
@@ -1,6 +1,7 @@
 import VueRouter from 'vue-router';
 
 import Main from './components/Main.vue';
+import Jobs from './components/Jobs.vue';
 
 export default new VueRouter({
   routes: [{
@@ -10,5 +11,8 @@ export default new VueRouter({
     name: 'nodes',
     path: '/nodes/:path(.*)',
     component: Main
+  }, {
+    path: '/jobs',
+    component: Jobs
   }]
 })
diff --git a/vospace-ui-frontend/src/store.js b/vospace-ui-frontend/src/store.js
index f4b4a331d95c9bd753e5b293507ca1538090ccda..14255d7346a2fa59409141033bc77ac1b4e9601f 100644
--- a/vospace-ui-frontend/src/store.js
+++ b/vospace-ui-frontend/src/store.js
@@ -11,7 +11,8 @@ export default new Vuex.Store({
   state: {
     path: '',
     loading: true,
-    tapeButtonEnabled: false
+    tapeButtonEnabled: false,
+    jobs: []
   },
   mutations: {
     setLoading(state, loading) {
@@ -25,6 +26,17 @@ export default new Vuex.Store({
     },
     setTapeButtonEnabled(state, value) {
       state.tapeButtonEnabled = value;
+    },
+    setJobs(state, jobs) {
+      // empty the array
+      state.jobs.splice(0, jobs.length);
+      // fill again
+      for (let i = 0; i < jobs.length; i++) {
+        state.jobs.push(jobs[i]);
+      }
+    },
+    addJob(state, job) {
+      state.jobs.push(job);
     }
   },
   actions: {
@@ -45,16 +57,21 @@ export default new Vuex.Store({
     computeButtonVisibility({ commit }) {
       commit('setTapeButtonEnabled', document.querySelectorAll('#nodes input.tape:checked').length > 0);
     },
-    startRecallFromTapeJob() {
+    startRecallFromTapeJob({ commit }) {
       let tapeCheckboxes = document.querySelectorAll('#nodes input.tape:checked');
       let paths = [];
       for (let i = 0; i < tapeCheckboxes.length; i++) {
         paths.push(tapeCheckboxes[i].getAttribute('data-node'));
       }
       client.startRecallFromTapeJob(paths)
-        .then(() => {
+        .then(job => {
           main.showInfo('Job started');
+          commit('addJob', job);
         });
+    },
+    loadJobs({ commit }) {
+      client.loadJobs()
+        .then(jobs => commit('setJobs', jobs));
     }
   }
 });