diff --git a/app/corpora/cqi_over_socketio/__init__.py b/app/corpora/cqi_over_socketio/__init__.py
index d914973c88b906c592fb9f140ed34c5620b69dfe..68f28d8f0bc14950dc5203d4e6a1838d18260a27 100644
--- a/app/corpora/cqi_over_socketio/__init__.py
+++ b/app/corpora/cqi_over_socketio/__init__.py
@@ -1,4 +1,4 @@
-from app import db, socketio
+from app import db, hashids, socketio
 from app.decorators import socketio_login_required
 from app.models import Corpus
 from flask import session
@@ -57,7 +57,7 @@ from .cqi import *  # noqa
 def connect(auth):
     # the auth variable is used in a hacky way. It contains the corpus id for
     # which a corpus analysis session should be started.
-    corpus_id = auth['corpus_id']
+    corpus_id = hashids.decode(auth['corpus_id'])[0]
     corpus = Corpus.query.get(corpus_id)
     if corpus is None:
         # return {'code': 404, 'msg': 'Not Found'}
diff --git a/app/events/sqlalchemy.py b/app/events/sqlalchemy.py
index 457a2bde8b245ead1b4c324e06359189025256a9..b3362ca00d3e271864fb23902c33f6e3dbc4e00a 100644
--- a/app/events/sqlalchemy.py
+++ b/app/events/sqlalchemy.py
@@ -28,6 +28,11 @@ def ressource_after_delete(mapper, connection, ressource):
 @db.event.listens_for(QueryResult, 'after_insert')
 def ressource_after_insert_handler(mapper, connection, ressource):
     value = ressource.to_dict(backrefs=False, relationships=False)
+    if isinstance(ressource, Job):
+        value['inputs'] = {}
+        value['results'] = {}
+    elif isinstance(ressource, Corpus):
+        value['files'] = {}
     jsonpatch = [
         {'op': 'add', 'path': ressource.jsonpatch_path, 'value': value}
     ]
diff --git a/app/models.py b/app/models.py
index 23b91cf31ab7620c503419734be89c61eeac05cc..1572a14486b55d4bbc6c51cf911ba56def9f2940 100644
--- a/app/models.py
+++ b/app/models.py
@@ -544,7 +544,7 @@ class CorpusFile(FileMixin, HashidMixin, db.Model):
 
     @property
     def jsonpatch_path(self):
-        return f'/{self.corpus.jsonpatch_path}/files/{self.hashid}'
+        return f'{self.corpus.jsonpatch_path}/files/{self.hashid}'
 
     @property
     def path(self):
@@ -601,6 +601,7 @@ class CorpusFile(FileMixin, HashidMixin, db.Model):
         if backrefs:
             dict_corpus_file['corpus'] = self.corpus.to_dict(
                 backrefs=True, relationships=False)
+        return dict_corpus_file
 
 
 class Corpus(HashidMixin, db.Model):
@@ -705,7 +706,7 @@ class Corpus(HashidMixin, db.Model):
                 backrefs=True, relationships=False)
         if relationships:
             dict_corpus['files'] = {
-                x.id: x.to_dict(backrefs=False, relationships=True)
+                x.hashid: x.to_dict(backrefs=False, relationships=True)
                 for x in self.files
             }
         return dict_corpus
diff --git a/app/static/js/nopaque/App.js b/app/static/js/nopaque/App.js
index 6bad75e8a00dee1bed76278da49f4ce8c7dfd9ff..aff90f3a5f25837a27d48c6044f47271a4f7767f 100644
--- a/app/static/js/nopaque/App.js
+++ b/app/static/js/nopaque/App.js
@@ -65,33 +65,9 @@ class App {
   }
 
   usersPatchHandler(patch) {
-    let jobId;
     let listener;
-    let match;
-    let operation;
-    let re;
-    let relationship;
-    let ressourceId;
-    let userId;
 
-    for (operation of patch.filter(operation => operation.op === 'add')) {
-      re = new RegExp(`^/users/([A-Za-z0-9]*)/corpora/([A-Za-z0-9]*)/(files)`);
-      if (re.test(operation.path)) {
-        [match, userId, ressourceId, relationship] = operation.path.match(re);
-        if (!(relationship in this.users[userId].corpora[ressourceId])) {
-          this.users[userId].corpora[ressourceId][relationship] = {};
-        }
-        continue;
-      }
-      re = new RegExp(`^/users/([A-Za-z0-9]*)/jobs/([A-Za-z0-9]*)/(inputs|results)`);
-      if (re.test(operation.path)) {
-        [match, userId, ressourceId, relationship] = operation.path.match(re);
-        if (!(relationship in this.users[userId].jobs[ressourceId])) {
-          this.users[userId].jobs[ressourceId][relationship] = {};
-        }
-        continue;
-      }
-    }
+    console.log(patch);
     this.data = jsonpatch.apply_patch(this.data, patch);
     for (listener of this.eventListeners['users.patch']) {listener(patch);}
   }
diff --git a/app/static/js/nopaque/CorpusAnalysis/CQiClient.js b/app/static/js/nopaque/CorpusAnalysis/CQiClient.js
index 42efef511f71a40d620be5463908c82227e56f4e..a605eb076d3ac0e3e6b6a430f60fb34ddb9cb52b 100644
--- a/app/static/js/nopaque/CorpusAnalysis/CQiClient.js
+++ b/app/static/js/nopaque/CorpusAnalysis/CQiClient.js
@@ -2,7 +2,11 @@ class CQiClient {
   constructor(corpusId) {
     this.socket = io(
       '/corpora/corpus/corpus_analysis',
-      {auth: {corpus_id: corpusId}, transports: ['websocket'], upgrade: false}
+      {
+        auth: {corpus_id: corpusId},
+        transports: ['websocket'],
+        upgrade: false
+      }
     );
     this.connected = false;
     this.corpora = new CQiCorpusCollection(this.socket);
@@ -55,7 +59,8 @@ class CQiCorpusCollection {
 
   get(corpusName) {
     return new Promise((resolve, reject) => {
-      let args = {corpus_name: corpusName};
+      const args = {corpus_name: corpusName};
+
       this.socket.emit('cqi.corpora.get', args, response => {
         if (response.code === 200) {
           resolve(new CQiCorpus(this.socket, response.payload));
@@ -95,7 +100,8 @@ class CQiCorpus {
 
   drop() {
     return new Promise((resolve, reject) => {
-      let args = {corpus_name: this.name};
+      const args = {corpus_name: this.name};
+
       this.socket.emit('cqi.corpora.corpus.drop', args, response => {
         if (response.code === 200) {
           resolve(response.payload);
@@ -108,11 +114,12 @@ class CQiCorpus {
 
   query(subcorpus_name, queryString) {
     return new Promise((resolve, reject) => {
-      let args = {
+      const args = {
         corpus_name: this.name,
         subcorpus_name: subcorpus_name,
         query: queryString
       };
+
       this.socket.emit('cqi.corpora.corpus.query', args, response => {
         if (response.code === 200) {
           resolve(response.payload);
@@ -126,7 +133,8 @@ class CQiCorpus {
   // nopaque specific CQi extension
   paginate(page=1, perPage=20) {
     return new Promise((resolve, reject) => {
-      let args = {corpus_name: this.name, page: page, per_page: perPage};
+      const args = {corpus_name: this.name, page: page, per_page: perPage};
+
       this.socket.emit('cqi.corpora.corpus.paginate', args, response => {
         if (response.code === 200) {
           resolve(response.payload);
@@ -138,7 +146,8 @@ class CQiCorpus {
   }
 
   updateDb() {
-    let args = {corpus_name: this.name};
+    const args = {corpus_name: this.name};
+
     this.socket.emit('cqi.corpora.corpus.update_db', args);
   }
 }
@@ -152,8 +161,11 @@ class CQiAlignmentAttributeCollection {
 
   get(alignmentAttributeName) {
     return new Promise((resolve, reject) => {
-      let args = {corpus_name: this.corpus.name,
-                  alignment_attribute_name: alignmentAttributeName};
+      const args = {
+        corpus_name: this.corpus.name,
+        alignment_attribute_name: alignmentAttributeName
+      };
+
       this.socket.emit('cqi.corpora.corpus.alignment_attributes.get', args, response => {
         if (response.code === 200) {
           resolve(new CQiAlignmentAttribute(this.socket, this.corpus, response.payload));
@@ -166,7 +178,8 @@ class CQiAlignmentAttributeCollection {
 
   list() {
     return new Promise((resolve, reject) => {
-      let args = {corpus_name: this.corpus.name};
+      const args = {corpus_name: this.corpus.name};
+
       this.socket.emit('cqi.corpus.alignment_attributes.list', args, response => {
         if (response.code === 200) {
           resolve(response.payload.map(x => {return new CQiAlignmentAttribute(this.socket, this.corpus, x);}));
@@ -197,10 +210,11 @@ class CQiPositionalAttributeCollection {
 
   get(positionalAttributeName) {
     return new Promise((resolve, reject) => {
-      let args = {
+      const args = {
         corpus_name: this.corpus.name,
         positional_attribute_name: positionalAttributeName
       };
+
       this.socket.emit('cqi.corpora.corpus.positional_attributes.get', args, response => {
         if (response.code === 200) {
           resolve(new CQiPositionalAttribute(this.socket, this.corpus, response.payload));
@@ -213,7 +227,8 @@ class CQiPositionalAttributeCollection {
 
   list() {
     return new Promise((resolve, reject) => {
-      let args = {corpus_name: this.corpus.name};
+      const args = {corpus_name: this.corpus.name};
+
       this.socket.emit('cqi.corpus.positional_attributes.list', args, response => {
         if (response.code === 200) {
           resolve(response.payload.map(x => {return new CQiPositionalAttribute(this.socket, this.corpus, x);}));
@@ -245,10 +260,11 @@ class CQiStructuralAttributeCollection {
 
   get(structuralAttributeName) {
     return new Promise((resolve, reject) => {
-      let args = {
+      const args = {
         corpus_name: this.corpus.name,
         structural_attribute_name: structuralAttributeName
       };
+
       this.socket.emit('cqi.corpora.corpus.structural_attributes.get', args, response => {
         if (response.code === 200) {
           resolve(new CQiStructuralAttribute(this.socket, this.corpus, response.payload));
@@ -261,7 +277,8 @@ class CQiStructuralAttributeCollection {
 
   list() {
     return new Promise((resolve, reject) => {
-      let args = {corpus_name: this.corpus.name};
+      const args = {corpus_name: this.corpus.name};
+
       this.socket.emit('cqi.corpus.structural_attributes.list', args, response => {
         if (response.code === 200) {
           resolve(response.payload.map(x => {return new CQiStructuralAttribute(this.socket, this.corpus, x);}));
@@ -293,7 +310,10 @@ class CQiSubcorpusCollection {
 
   get(subcorpusName) {
     return new Promise((resolve, reject) => {
-      let args = {corpus_name: this.corpus.name, subcorpus_name: subcorpusName};
+      const args = {
+        corpus_name: this.corpus.name,
+        subcorpus_name: subcorpusName
+      };
       this.socket.emit('cqi.corpora.corpus.subcorpora.get', args, response => {
         if (response.code === 200) {
           resolve(new CQiSubcorpus(this.socket, this.corpus, response.payload));
@@ -306,7 +326,8 @@ class CQiSubcorpusCollection {
 
   list() {
     return new Promise((resolve, reject) => {
-      let args = {corpus_name: this.corpus.name};
+      const args = {corpus_name: this.corpus.name};
+
       this.socket.emit('cqi.corpora.corpus.subcorpora.list', args, response => {
         if (response.code === 200) {
           resolve(response.payload.map(x => {return new CQiSubcorpus(this.socket, this.corpus, x);}));
@@ -330,7 +351,8 @@ class CQiSubcorpus {
 
   drop() {
     return new Promise((resolve, reject) => {
-      let args = {corpus_name: this.corpus.name, subcorpus_name: this.name};
+      const args = {corpus_name: this.corpus.name, subcorpus_name: this.name};
+
       this.socket.emit('cqi.corpora.corpus.subcorpora.subcorpus.drop', args, response => {
         if (response.code === 200) {
           resolve(response.payload);
@@ -343,13 +365,14 @@ class CQiSubcorpus {
 
   dump(field, first, last) {
     return new Promise((resolve, reject) => {
-      let args = {
+      const args = {
         corpus_name: this.corpus.name,
         subcorpus_name: this.name,
         field: field,
         first: first,
         last: last
       };
+
       this.socket.emit('cqi.corpora.corpus.subcorpora.subcorpus.dump', args, response => {
         if (response.code === 200) {
           resolve(response.payload);
@@ -362,11 +385,12 @@ class CQiSubcorpus {
 
   export(context=50) {
     return new Promise((resolve, reject) => {
-      let args = {
+      const args = {
         corpus_name: this.corpus.name,
         subcorpus_name: this.name,
         context: context
       };
+
       this.socket.emit('cqi.corpora.corpus.subcorpora.subcorpus.export', args, response => {
         if (response.code === 200) {
           resolve(response.payload);
@@ -379,13 +403,14 @@ class CQiSubcorpus {
 
   fdst_1(cutoff, field, attribute) {
     return new Promise((resolve, reject) => {
-      let args = {
+      const args = {
         corpus_name: this.corpus.name,
         subcorpus_name: this.name,
         cutoff: cutoff,
         field: field,
         attribute: attribute
       };
+
       this.socket.emit('cqi.corpora.corpus.subcorpora.subcorpus.fdist_1', args, response => {
         if (response.code === 200) {
           resolve(response.payload);
@@ -398,7 +423,7 @@ class CQiSubcorpus {
 
   fdst_2(cutoff, field1, attribute1, field2, attribute2) {
     return new Promise((resolve, reject) => {
-      let args = {
+      const args = {
         corpus_name: this.corpus.name,
         subcorpus_name: this.name,
         cutoff: cutoff,
@@ -407,6 +432,7 @@ class CQiSubcorpus {
         field2: field2,
         attribute2: attribute2
       };
+
       this.socket.emit('cqi.corpora.corpus.subcorpora.subcorpus.fdist_1', args, response => {
         if (response.code === 200) {
           resolve(response.payload);
@@ -420,13 +446,14 @@ class CQiSubcorpus {
   // nopaque specific CQi extension
   paginate(page=1, perPage=20, context=50) {
     return new Promise((resolve, reject) => {
-      let args = {
+      const args = {
         corpus_name: this.corpus.name,
         subcorpus_name: this.name,
         page: page,
         per_page: perPage,
         context: context
       };
+
       this.socket.emit('cqi.corpora.corpus.subcorpora.subcorpus.paginate', args, response => {
         if (response.code === 200) {
           resolve(response.payload);
diff --git a/app/static/js/nopaque/CorpusAnalysis/CorpusAnalysisApp.js b/app/static/js/nopaque/CorpusAnalysis/CorpusAnalysisApp.js
index 71a4780a62a828ffbdf5cf3e201aace82593ae97..ad324e34d2c8db2fbf59d7514b3672ba67cde5f6 100644
--- a/app/static/js/nopaque/CorpusAnalysis/CorpusAnalysisApp.js
+++ b/app/static/js/nopaque/CorpusAnalysis/CorpusAnalysisApp.js
@@ -69,7 +69,7 @@ class CorpusAnalysisApp {
           this.elements.initError.classList.remove('hide');
           this.elements.initProgress.classList.add('hide');
           if ('payload' in cQiError && 'code' in cQiError.payload && 'msg' in cQiError.payload) {
-            nopaque.appClient.flash(`${cQiError.payload.code}: ${cQiError.payload.msg}`, 'error');
+            app.flash(`${cQiError.payload.code}: ${cQiError.payload.msg}`, 'error');
           }
         }
       );
diff --git a/app/static/js/nopaque/CorpusAnalysis/CorpusAnalysisConcordance.js b/app/static/js/nopaque/CorpusAnalysis/CorpusAnalysisConcordance.js
index 24a9ab532a3bbfc11fc6a32a2d3198a839cd9abe..b6612e010c6b175a28fe53e8c1aa154e93d5be52 100644
--- a/app/static/js/nopaque/CorpusAnalysis/CorpusAnalysisConcordance.js
+++ b/app/static/js/nopaque/CorpusAnalysis/CorpusAnalysisConcordance.js
@@ -71,7 +71,7 @@ class CorpusAnalysisConcordance {
             this.elements.error.innerText = JSON.stringify(cQiError);
             this.elements.error.classList.remove('hide');
             if ('payload' in cQiError && 'code' in cQiError.payload && 'msg' in cQiError.payload) {
-              nopaque.appClient.flash(`${cQiError.payload.code}: ${cQiError.payload.msg}`, 'error');
+              app.flash(`${cQiError.payload.code}: ${cQiError.payload.msg}`, 'error');
             }
             this.elements.progress.classList.add('hide');
             this.app.enableActionElements();
@@ -166,7 +166,7 @@ class CorpusAnalysisConcordance {
       let subcorpus = this.data.subcorpora[this.settings.selectedSubcorpus];
       subcorpus.o.drop().then(
         cQiStatus => {
-          nopaque.appClient.flash(`${subcorpus.o.name} deleted`, 'corpus');
+          app.flash(`${subcorpus.o.name} deleted`, 'corpus');
           delete this.data.subcorpora[subcorpus.o.name];
           this.settings.selectedSubcorpus = undefined;
           for (let subcorpusName in this.data.subcorpora) {
@@ -187,7 +187,7 @@ class CorpusAnalysisConcordance {
           }
         },
         cQiError => {
-          nopaque.appClient.flash(`${cQiError.payload.code}: ${cQiError.payload.msg}`, 'error');
+          app.flash(`${cQiError.payload.code}: ${cQiError.payload.msg}`, 'error');
         }
       );
     });
diff --git a/app/static/js/nopaque/CorpusAnalysis/CorpusAnalysisReader.js b/app/static/js/nopaque/CorpusAnalysis/CorpusAnalysisReader.js
index 2b2a584337abde08accebcdb09d19ff715c3566b..649029883dbd48c16420d757688b2aab777a2358 100644
--- a/app/static/js/nopaque/CorpusAnalysis/CorpusAnalysisReader.js
+++ b/app/static/js/nopaque/CorpusAnalysis/CorpusAnalysisReader.js
@@ -49,7 +49,7 @@ class CorpusAnalysisReader {
             this.elements.error.innerText = JSON.stringify(error);
             this.elements.error.classList.remove('hide');
             if ('payload' in error && 'code' in error.payload && 'msg' in error.payload) {
-              nopaque.appClient.flash(`${error.payload.code}: ${error.payload.msg}`, 'error');
+              app.flash(`${error.payload.code}: ${error.payload.msg}`, 'error');
             }
             this.elements.progress.classList.add('hide');
             this.app.enableActionElements();
@@ -75,8 +75,12 @@ class CorpusAnalysisReader {
   }
 
   clearCorpus() {
+    let pAttrElement;
+    let pAttrElements;
+
     // Destroy with .p-attr elements associated Materialize tooltips
-    for (let pAttrElement of this.elements.corpus.querySelectorAll('.p-attr.tooltipped')) {
+    pAttrElements = this.elements.corpus.querySelectorAll('.p-attr.tooltipped');
+    for (pAttrElement of pAttrElements) {
       M.Tooltip.getInstance(pAttrElement)?.destroy();
     }
     this.elements.corpus.innerHTML = `
@@ -88,8 +92,10 @@ class CorpusAnalysisReader {
   }
 
   renderCorpus() {
+    let item;
+
     this.clearCorpus();
-    let item = this.data.corpus.p.items[0];
+    item = this.data.corpus.p.items[0];
     this.elements.corpus.innerHTML += `
         <p>${this.cposRange2HTML(item[0], item[item.length - 1])}</p>
     `.trim();
@@ -103,6 +109,10 @@ class CorpusAnalysisReader {
   }
 
   renderCorpusPagination() {
+    let i;
+    let page;
+    let paginateTriggerElement;
+
     this.clearCorpusPagination();
     if (this.data.corpus.p.pages === 0) {return;}
     this.elements.corpusPagination.innerHTML += `
@@ -119,7 +129,7 @@ class CorpusAnalysisReader {
         </a>
       </li>
     `.trim();
-    for (let i = 1; i <= this.data.corpus.p.pages; i++) {
+    for (i = 1; i <= this.data.corpus.p.pages; i++) {
       this.elements.corpusPagination.innerHTML += `
         <li class="${i === this.data.corpus.p.page ? 'active' : 'waves-effect'}">
           <a class="corpus-analysis-action pagination-trigger" ${i === this.data.corpus.p.page ? '' : 'data-target="' + i + '"'}>${i}</a>
@@ -140,10 +150,10 @@ class CorpusAnalysisReader {
         </a>
       </li>
     `.trim();
-    for (let paginateTriggerElement of this.elements.corpusPagination.querySelectorAll('.pagination-trigger[data-target]')) {
+    for (paginateTriggerElement of this.elements.corpusPagination.querySelectorAll('.pagination-trigger[data-target]')) {
       paginateTriggerElement.addEventListener('click', event => {
         event.preventDefault();
-        let page = parseInt(paginateTriggerElement.dataset.target);
+        page = parseInt(paginateTriggerElement.dataset.target);
         this.page(page);
       });
     }
@@ -151,10 +161,11 @@ class CorpusAnalysisReader {
   }
 
   cposRange2HTML(firstCpos, lastCpos) {
+    let cpos;
     let prevPAttr, pAttr, nextPAttr;
     let isEntityStart, isEntityEnd;
     let html = '';
-    for (let cpos = firstCpos; cpos <= lastCpos; cpos++) {
+    for (cpos = firstCpos; cpos <= lastCpos; cpos++) {
       prevPAttr = cpos > firstCpos ? this.data.corpus.p.lookups.cpos_lookup[cpos - 1] : null;
       pAttr = this.data.corpus.p.lookups.cpos_lookup[cpos];
       nextPAttr = cpos < lastCpos ? this.data.corpus.p.lookups.cpos_lookup[cpos + 1] : null;
diff --git a/app/static/js/nopaque/RessourceLists/CorpusFileList.js b/app/static/js/nopaque/RessourceLists/CorpusFileList.js
index e49ee8fa1bfc3cc3cf478a3081c9236569a11956..ed6a4b493bd3fd3e39ea146b7471bb1a1f9ba9d1 100644
--- a/app/static/js/nopaque/RessourceLists/CorpusFileList.js
+++ b/app/static/js/nopaque/RessourceLists/CorpusFileList.js
@@ -5,6 +5,7 @@ class CorpusFileList extends RessourceList {
   }
 
   init(user) {
+    console.log(user);
     this._init(user.corpora[this.corpusId].files);
   }
 
diff --git a/app/templates/corpora/analyse_corpus.html.j2 b/app/templates/corpora/analyse_corpus.html.j2
index ccf682e0da1ad566c2df1a11c3a2cfcad9a7d825..8e69ce74c5d2d4ea7ab0a01ba86d5708e708a97e 100644
--- a/app/templates/corpora/analyse_corpus.html.j2
+++ b/app/templates/corpora/analyse_corpus.html.j2
@@ -65,7 +65,7 @@
 <script src="{{ ASSET_URL }}"></script>
 {% endassets %}
 <script>
-let corpusAnalysisApp = new CorpusAnalysisApp({{ corpus.id }});
+let corpusAnalysisApp = new CorpusAnalysisApp('{{ corpus.hashid }}');
 let corpusAnalysisConcordance = new CorpusAnalysisConcordance(corpusAnalysisApp);
 let corpusAnalysisReader = new CorpusAnalysisReader(corpusAnalysisApp);
 corpusAnalysisApp.init();