diff --git a/assets/config/.eslintrc b/assets/config/.eslintrc
--- a/assets/config/.eslintrc
+++ b/assets/config/.eslintrc
@@ -247,6 +247,10 @@
             "classes": "never"
         }],
         "prefer-promise-reject-errors": "error",
+        "prefer-const": ["error", {
+            "destructuring": "any",
+            "ignoreReadBeforeAssign": false
+        }],
         "quotes": ["error", "single", {
             "avoidEscape": true,
             "allowTemplateLiterals": true
diff --git a/assets/config/webpack-plugins/dump-highlightjs-languages-data-plugin.js b/assets/config/webpack-plugins/dump-highlightjs-languages-data-plugin.js
--- a/assets/config/webpack-plugins/dump-highlightjs-languages-data-plugin.js
+++ b/assets/config/webpack-plugins/dump-highlightjs-languages-data-plugin.js
@@ -26,12 +26,12 @@
       const languages = hljs.listLanguages();
       const hljsLanguagesData = {'languages': languages};
       const languageAliases = {};
-      for (let language of languages) {
+      for (const language of languages) {
         const languageData = hljs.getLanguage(language);
         if (!languageData.hasOwnProperty('aliases')) {
           continue;
         }
-        for (let alias of languageData.aliases) {
+        for (const alias of languageData.aliases) {
           languageAliases[alias] = language;
           languageAliases[alias.toLowerCase()] = language;
         }
diff --git a/assets/config/webpack-plugins/fix-swh-source-maps-webpack-plugin.js b/assets/config/webpack-plugins/fix-swh-source-maps-webpack-plugin.js
--- a/assets/config/webpack-plugins/fix-swh-source-maps-webpack-plugin.js
+++ b/assets/config/webpack-plugins/fix-swh-source-maps-webpack-plugin.js
@@ -32,10 +32,10 @@
           }).forEach(key => {
             let bundleName = key.replace(/^js\//, '');
             bundleName = bundleName.replace(/^css\//, '');
-            let pos = bundleName.indexOf('.');
+            const pos = bundleName.indexOf('.');
             bundleName = bundleName.slice(0, pos);
-            let asset = compilation.assets[key];
-            let source = asset.source().replace(/swh.\[name\]/g, 'swh.' + bundleName);
+            const asset = compilation.assets[key];
+            const source = asset.source().replace(/swh.\[name\]/g, 'swh.' + bundleName);
             compilation.updateAsset(key, new sources.RawSource(source));
           });
         }
diff --git a/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/index.js b/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/index.js
--- a/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/index.js
+++ b/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/index.js
@@ -56,7 +56,7 @@
     compiler.hooks.done.tap(pluginName, statsObj => {
 
       // get the stats object in JSON format
-      let stats = statsObj.toJson();
+      const stats = statsObj.toJson();
       this.stats = stats;
 
       // set output folder
@@ -72,7 +72,7 @@
       // map each generated webpack chunk to its js asset
       Object.keys(stats.assetsByChunkName).forEach((chunkName, i) => {
         if (Array.isArray(stats.assetsByChunkName[chunkName])) {
-          for (let asset of stats.assetsByChunkName[chunkName]) {
+          for (const asset of stats.assetsByChunkName[chunkName]) {
             if (asset.endsWith('.js')) {
               this.chunkNameToJsAsset[chunkName] = asset;
               this.chunkNameToJsAsset[i] = asset;
@@ -101,22 +101,22 @@
         }
 
         // do not process modules in the exclusion list
-        for (let toExclude of this.exclude) {
+        for (const toExclude of this.exclude) {
           if (srcFilePath.startsWith(toExclude)) {
             return;
           }
         }
 
         // remove webpack loader call if any
-        let loaderEndPos = srcFilePath.indexOf('!');
+        const loaderEndPos = srcFilePath.indexOf('!');
         if (loaderEndPos !== -1) {
           srcFilePath = srcFilePath.slice(loaderEndPos + 1);
         }
 
         // iterate on all chunks containing the module
         mod.chunks.forEach(chunk => {
-          let chunkName = this.chunkIdToName[chunk];
-          let chunkJsAsset = stats.publicPath + this.chunkNameToJsAsset[chunkName];
+          const chunkName = this.chunkIdToName[chunk];
+          const chunkJsAsset = stats.publicPath + this.chunkNameToJsAsset[chunkName];
 
           // init the chunk to source files mapping if needed
           if (!this.chunkJsAssetToSrcFiles.hasOwnProperty(chunkJsAsset)) {
@@ -129,31 +129,31 @@
           }
 
           // init source file metadata
-          let srcFileData = {'id': this.cleanupPath(srcFilePath)};
+          const srcFileData = {'id': this.cleanupPath(srcFilePath)};
 
           // find and parse the corresponding package.json file
           let packageJsonPath;
-          let nodeModule = srcFilePath.startsWith('./node_modules/');
+          const nodeModule = srcFilePath.startsWith('./node_modules/');
           if (nodeModule) {
             packageJsonPath = this.findPackageJsonPath(srcFilePath);
           } else {
             packageJsonPath = './package.json';
           }
-          let packageJson = this.parsePackageJson(packageJsonPath);
+          const packageJson = this.parsePackageJson(packageJsonPath);
 
           // extract license information, overriding it if needed
           let licenseOverridden = false;
           let licenseFilePath;
           if (this.options['licenseOverride']) {
-            for (let srcFilePrefixKey of Object.keys(this.options['licenseOverride'])) {
+            for (const srcFilePrefixKey of Object.keys(this.options['licenseOverride'])) {
               let srcFilePrefix = srcFilePrefixKey;
               if (!srcFilePrefixKey.startsWith('.')) {
                 srcFilePrefix = './' + path.join('node_modules', srcFilePrefixKey);
               }
               if (srcFilePath.startsWith(srcFilePrefix)) {
-                let spdxLicenseExpression = this.options['licenseOverride'][srcFilePrefixKey]['spdxLicenseExpression'];
+                const spdxLicenseExpression = this.options['licenseOverride'][srcFilePrefixKey]['spdxLicenseExpression'];
                 licenseFilePath = this.options['licenseOverride'][srcFilePrefixKey]['licenseFilePath'];
-                let parsedSpdxLicenses = this.parseSpdxLicenseExpression(spdxLicenseExpression, `file ${srcFilePath}`);
+                const parsedSpdxLicenses = this.parseSpdxLicenseExpression(spdxLicenseExpression, `file ${srcFilePath}`);
                 srcFileData['licenses'] = this.spdxToWebLabelsLicenses(parsedSpdxLicenses);
                 licenseOverridden = true;
                 break;
@@ -163,12 +163,12 @@
 
           if (!licenseOverridden) {
             srcFileData['licenses'] = this.extractLicenseInformation(packageJson);
-            let licenseDir = path.join(...packageJsonPath.split('/').slice(0, -1));
+            const licenseDir = path.join(...packageJsonPath.split('/').slice(0, -1));
             licenseFilePath = this.findLicenseFile(licenseDir);
           }
 
           // copy original license file and get its url
-          let licenseCopyUrl = this.copyLicenseFile(licenseFilePath);
+          const licenseCopyUrl = this.copyLicenseFile(licenseFilePath);
           srcFileData['licenses'].forEach(license => {
             license['copy_url'] = licenseCopyUrl;
           });
@@ -186,20 +186,20 @@
       // process additional scripts if needed
       if (this.options['additionalScripts']) {
         for (let script of Object.keys(this.options['additionalScripts'])) {
-          let scriptFilesData = this.options['additionalScripts'][script];
+          const scriptFilesData = this.options['additionalScripts'][script];
           if (script.indexOf('://') === -1 && !script.startsWith('/')) {
             script = stats.publicPath + script;
           }
           this.chunkJsAssetToSrcFiles[script] = [];
           this.srcIdsInChunkJsAsset[script] = new Set();
-          for (let scriptSrc of scriptFilesData) {
-            let scriptSrcData = {'id': scriptSrc['id']};
-            let licenceFilePath = scriptSrc['licenseFilePath'];
-            let parsedSpdxLicenses = this.parseSpdxLicenseExpression(scriptSrc['spdxLicenseExpression'],
-                                                                     `file ${scriptSrc['path']}`);
+          for (const scriptSrc of scriptFilesData) {
+            const scriptSrcData = {'id': scriptSrc['id']};
+            const licenceFilePath = scriptSrc['licenseFilePath'];
+            const parsedSpdxLicenses = this.parseSpdxLicenseExpression(scriptSrc['spdxLicenseExpression'],
+                                                                       `file ${scriptSrc['path']}`);
             scriptSrcData['licenses'] = this.spdxToWebLabelsLicenses(parsedSpdxLicenses);
             if (licenceFilePath.indexOf('://') === -1 && !licenceFilePath.startsWith('/')) {
-              let licenseCopyUrl = this.copyLicenseFile(licenceFilePath);
+              const licenseCopyUrl = this.copyLicenseFile(licenceFilePath);
               scriptSrcData['licenses'].forEach(license => {
                 license['copy_url'] = licenseCopyUrl;
               });
@@ -219,18 +219,18 @@
         }
       }
 
-      for (let srcFiles of Object.values(this.chunkJsAssetToSrcFiles)) {
+      for (const srcFiles of Object.values(this.chunkJsAssetToSrcFiles)) {
         srcFiles.sort((a, b) => a.id.localeCompare(b.id));
       }
 
       if (this.outputType === 'json') {
         // generate the jslicenses.json file
-        let weblabelsData = JSON.stringify(this.chunkJsAssetToSrcFiles);
-        let weblabelsJsonFile = path.join(this.weblabelsOutputDir, 'jslicenses.json');
+        const weblabelsData = JSON.stringify(this.chunkJsAssetToSrcFiles);
+        const weblabelsJsonFile = path.join(this.weblabelsOutputDir, 'jslicenses.json');
         fs.writeFileSync(weblabelsJsonFile, weblabelsData);
       } else {
         // generate the jslicenses.html file
-        let weblabelsPageFile = path.join(this.weblabelsOutputDir, 'jslicenses.html');
+        const weblabelsPageFile = path.join(this.weblabelsOutputDir, 'jslicenses.html');
         ejs.renderFile(path.join(__dirname, 'jslicenses.ejs'),
                        {'jslicenses_data': this.chunkJsAssetToSrcFiles},
                        {'rmWhitespace': true},
@@ -253,7 +253,7 @@
   }
 
   findPackageJsonPath(srcFilePath) {
-    let pathSplit = srcFilePath.split('/');
+    const pathSplit = srcFilePath.split('/');
     let packageJsonPath;
     for (let i = 3; i < pathSplit.length; ++i) {
       packageJsonPath = path.join(...pathSplit.slice(0, i), 'package.json');
@@ -298,7 +298,7 @@
 
   parsePackageJson(packageJsonPath) {
     if (!this.packageJsonCache.hasOwnProperty(packageJsonPath)) {
-      let packageJsonStr = fs.readFileSync(packageJsonPath).toString('utf8');
+      const packageJsonStr = fs.readFileSync(packageJsonPath).toString('utf8');
       this.packageJsonCache[packageJsonPath] = JSON.parse(packageJsonStr);
     }
     return this.packageJsonCache[packageJsonPath];
@@ -324,7 +324,7 @@
   spdxToWebLabelsLicense(spdxLicenceId) {
     for (let i = 0; i < spdxLicensesMapping.length; ++i) {
       if (spdxLicensesMapping[i]['spdx_ids'].indexOf(spdxLicenceId) !== -1) {
-        let licenseData = Object.assign({}, spdxLicensesMapping[i]);
+        const licenseData = Object.assign({}, spdxLicensesMapping[i]);
         delete licenseData['spdx_ids'];
         delete licenseData['magnet_link'];
         licenseData['copy_url'] = '';
@@ -349,7 +349,7 @@
       ret.push(this.spdxToWebLabelsLicense(spdxLicenses['license']));
     } else if (spdxLicenses.hasOwnProperty('left')) {
       if (spdxLicenses['left'].hasOwnProperty('license')) {
-        let licenseData = this.spdxToWebLabelsLicense(spdxLicenses['left']['license']);
+        const licenseData = this.spdxToWebLabelsLicense(spdxLicenses['left']['license']);
         ret.push(licenseData);
       } else {
         ret = ret.concat(this.spdxToWebLabelsLicenses(spdxLicenses['left']));
@@ -365,9 +365,9 @@
       spdxLicenseExpression = packageJson['license'];
     } else if (packageJson.hasOwnProperty('licenses')) {
       // for node packages using deprecated licenses property
-      let licenses = packageJson['licenses'];
+      const licenses = packageJson['licenses'];
       if (Array.isArray(licenses)) {
-        let l = [];
+        const l = [];
         licenses.forEach(license => {
           l.push(license['type']);
         });
@@ -376,8 +376,8 @@
         spdxLicenseExpression = licenses['type'];
       }
     }
-    let parsedSpdxLicenses = this.parseSpdxLicenseExpression(spdxLicenseExpression,
-                                                             `module ${packageJson['name']}`);
+    const parsedSpdxLicenses = this.parseSpdxLicenseExpression(spdxLicenseExpression,
+                                                               `module ${packageJson['name']}`);
     return this.spdxToWebLabelsLicenses(parsedSpdxLicenses);
   }
 
@@ -387,7 +387,7 @@
       return;
     }
     let destPath = this.cleanupPath(srcFilePath);
-    let destDir = path.join(this.weblabelsOutputDir, ...destPath.split('/').slice(0, -1));
+    const destDir = path.join(this.weblabelsOutputDir, ...destPath.split('/').slice(0, -1));
     this.recursiveMkdir(destDir);
     destPath = path.join(this.weblabelsOutputDir, destPath + ext);
     fs.copyFileSync(srcFilePath, destPath);
@@ -395,9 +395,9 @@
   }
 
   recursiveMkdir(destPath) {
-    let destPathSplit = destPath.split('/');
+    const destPathSplit = destPath.split('/');
     for (let i = 1; i < destPathSplit.length; ++i) {
-      let currentPath = path.join('/', ...destPathSplit.slice(0, i + 1));
+      const currentPath = path.join('/', ...destPathSplit.slice(0, i + 1));
       if (!fs.existsSync(currentPath)) {
         fs.mkdirSync(currentPath);
       }
diff --git a/assets/config/webpack.config.development.js b/assets/config/webpack.config.development.js
--- a/assets/config/webpack.config.development.js
+++ b/assets/config/webpack.config.development.js
@@ -45,7 +45,7 @@
 });
 
 // common loaders for css related assets (css, sass)
-let cssLoaders = [
+const cssLoaders = [
   MiniCssExtractPlugin.loader,
   {
     loader: 'cache-loader'
diff --git a/assets/src/bundles/admin/deposit.js b/assets/src/bundles/admin/deposit.js
--- a/assets/src/bundles/admin/deposit.js
+++ b/assets/src/bundles/admin/deposit.js
@@ -56,12 +56,12 @@
             name: 'swhid_context',
             render: (data, type, row) => {
               if (data && type === 'display') {
-                let originPattern = ';origin=';
-                let originPatternIdx = data.indexOf(originPattern);
+                const originPattern = ';origin=';
+                const originPatternIdx = data.indexOf(originPattern);
                 if (originPatternIdx !== -1) {
                   let originUrl = data.slice(originPatternIdx + originPattern.length);
-                  let nextSepPattern = ';';
-                  let nextSepPatternIdx = originUrl.indexOf(nextSepPattern);
+                  const nextSepPattern = ';';
+                  const nextSepPatternIdx = originUrl.indexOf(nextSepPattern);
                   if (nextSepPatternIdx !== -1) { /* Remove extra context */
                     originUrl = originUrl.slice(0, nextSepPatternIdx);
                   }
@@ -76,7 +76,7 @@
             name: 'reception_date',
             render: (data, type, row) => {
               if (type === 'display') {
-                let date = new Date(data);
+                const date = new Date(data);
                 return date.toLocaleString();
               }
               return data;
diff --git a/assets/src/bundles/admin/origin-save.js b/assets/src/bundles/admin/origin-save.js
--- a/assets/src/bundles/admin/origin-save.js
+++ b/assets/src/bundles/admin/origin-save.js
@@ -54,7 +54,7 @@
     enableRowSelection('#swh-unauthorized-origin-urls');
     swh.webapp.addJumpToPagePopoverToDataTable(unauthorizedOriginTable);
 
-    let columnsData = [
+    const columnsData = [
       {
         data: 'id',
         name: 'id',
@@ -66,7 +66,7 @@
         name: 'request_date',
         render: (data, type, row) => {
           if (type === 'display') {
-            let date = new Date(data);
+            const date = new Date(data);
             return date.toLocaleString();
           }
           return data;
@@ -309,7 +309,7 @@
 export function rejectOriginSaveRequest() {
   const selectedRow = pendingSaveRequestsTable.row('.selected');
   if (selectedRow.length) {
-    let rejectOriginSaveRequestCallback = async() => {
+    const rejectOriginSaveRequestCallback = async() => {
       const rowData = selectedRow.data();
       const rejectSaveRequestUrl = Urls.admin_origin_save_request_reject(rowData['visit_type'], rowData['origin_url']);
       await csrfPost(rejectSaveRequestUrl);
@@ -324,10 +324,10 @@
 }
 
 function removeOriginSaveRequest(requestTable) {
-  let selectedRow = requestTable.row('.selected');
+  const selectedRow = requestTable.row('.selected');
   if (selectedRow.length) {
-    let requestId = selectedRow.data()['id'];
-    let removeOriginSaveRequestCallback = async() => {
+    const requestId = selectedRow.data()['id'];
+    const removeOriginSaveRequestCallback = async() => {
       const removeSaveRequestUrl = Urls.admin_origin_save_request_remove(requestId);
       await csrfPost(removeSaveRequestUrl);
       requestTable.ajax.reload(null, false);
diff --git a/assets/src/bundles/auth/index.js b/assets/src/bundles/auth/index.js
--- a/assets/src/bundles/auth/index.js
+++ b/assets/src/bundles/auth/index.js
@@ -150,7 +150,7 @@
             name: 'creation_date',
             render: (data, type, row) => {
               if (type === 'display') {
-                let date = new Date(data);
+                const date = new Date(data);
                 return date.toLocaleString();
               }
               return data;
diff --git a/assets/src/bundles/browse/origin-search.js b/assets/src/bundles/browse/origin-search.js
--- a/assets/src/bundles/browse/origin-search.js
+++ b/assets/src/bundles/browse/origin-search.js
@@ -8,13 +8,13 @@
 import {handleFetchError, isArchivedOrigin} from 'utils/functions';
 
 const limit = 100;
-let linksPrev = [];
+const linksPrev = [];
 let linkNext = null;
 let linkCurrent = null;
 let inSearch = false;
 
 function parseLinkHeader(s) {
-  let re = /<(.+)>; rel="next"/;
+  const re = /<(.+)>; rel="next"/;
   return s.match(re)[1];
 }
 
@@ -33,10 +33,10 @@
     $('#swh-origin-search-results').show();
     $('#swh-no-result').hide();
     clearOriginSearchResultsTable();
-    let table = $('#origin-search-results tbody');
-    let promises = [];
-    for (let [i, origin] of origins.entries()) {
-      let browseUrl = `${Urls.browse_origin()}?origin_url=${encodeURIComponent(origin.url)}`;
+    const table = $('#origin-search-results tbody');
+    const promises = [];
+    for (const [i, origin] of origins.entries()) {
+      const browseUrl = `${Urls.browse_origin()}?origin_url=${encodeURIComponent(origin.url)}`;
       let tableRow =
         `<tr id="origin-${i}" class="swh-search-result-entry swh-tr-hover-highlight">`;
       tableRow +=
@@ -104,7 +104,7 @@
 
 function searchOriginsFirst(searchQueryText, limit) {
   let baseSearchUrl;
-  let searchMetadata = $('#swh-search-origin-metadata').prop('checked');
+  const searchMetadata = $('#swh-search-origin-metadata').prop('checked');
   if (searchMetadata) {
     baseSearchUrl = new URL(Urls.api_1_origin_metadata_search(), window.location);
     baseSearchUrl.searchParams.append('fulltext', searchQueryText);
@@ -112,14 +112,14 @@
     baseSearchUrl = new URL(Urls.api_1_origin_search(searchQueryText), window.location);
   }
 
-  let withVisit = $('#swh-search-origins-with-visit').prop('checked');
+  const withVisit = $('#swh-search-origins-with-visit').prop('checked');
   baseSearchUrl.searchParams.append('limit', limit);
   baseSearchUrl.searchParams.append('with_visit', withVisit);
   const visitType = $('#swh-search-visit-type').val();
   if (visitType !== 'any') {
     baseSearchUrl.searchParams.append('visit_type', visitType);
   }
-  let searchUrl = baseSearchUrl.toString();
+  const searchUrl = baseSearchUrl.toString();
   searchOrigins(searchUrl);
 }
 
@@ -135,7 +135,7 @@
     // Save link to the next results page.
     linkNext = null;
     if (response.headers.has('Link')) {
-      let parsedLink = parseLinkHeader(response.headers.get('Link'));
+      const parsedLink = parseLinkHeader(response.headers.get('Link'));
       if (parsedLink !== undefined) {
         linkNext = parsedLink;
       }
@@ -195,12 +195,12 @@
       event.preventDefault();
       if (event.target.checkValidity()) {
         $(event.target).removeClass('was-validated');
-        let searchQueryText = $('#swh-origins-url-patterns').val().trim();
-        let withVisit = $('#swh-search-origins-with-visit').prop('checked');
-        let withContent = $('#swh-filter-empty-visits').prop('checked');
-        let searchMetadata = $('#swh-search-origin-metadata').prop('checked');
+        const searchQueryText = $('#swh-origins-url-patterns').val().trim();
+        const withVisit = $('#swh-search-origins-with-visit').prop('checked');
+        const withContent = $('#swh-filter-empty-visits').prop('checked');
+        const searchMetadata = $('#swh-search-origin-metadata').prop('checked');
         const visitType = $('#swh-search-visit-type').val();
-        let queryParameters = new URLSearchParams();
+        const queryParameters = new URLSearchParams();
         queryParameters.append('q', searchQueryText);
         if (withVisit) {
           queryParameters.append('with_visit', withVisit);
@@ -240,12 +240,12 @@
       event.preventDefault();
     });
 
-    let urlParams = new URLSearchParams(window.location.search);
-    let query = urlParams.get('q');
-    let withVisit = urlParams.has('with_visit');
-    let withContent = urlParams.has('with_content');
-    let searchMetadata = urlParams.has('search_metadata');
-    let visitType = urlParams.get('visit_type');
+    const urlParams = new URLSearchParams(window.location.search);
+    const query = urlParams.get('q');
+    const withVisit = urlParams.has('with_visit');
+    const withContent = urlParams.has('with_content');
+    const searchMetadata = urlParams.has('search_metadata');
+    const visitType = urlParams.get('visit_type');
     if (query) {
       $('#swh-origins-url-patterns').val(query);
       $('#swh-search-origins-with-visit').prop('checked', withVisit);
diff --git a/assets/src/bundles/browse/snapshot-navigation.js b/assets/src/bundles/browse/snapshot-navigation.js
--- a/assets/src/bundles/browse/snapshot-navigation.js
+++ b/assets/src/bundles/browse/snapshot-navigation.js
@@ -38,7 +38,7 @@
     // taking icons into account, in order to make the whole names readable
     $('#swh-branches-releases-dd').on('show.bs.dropdown', () => {
       if (dropdownResized) return;
-      let dropdownWidth = $('.swh-branches-releases').width();
+      const dropdownWidth = $('.swh-branches-releases').width();
       $('.swh-branches-releases').width(dropdownWidth + 25);
       dropdownResized = true;
     });
diff --git a/assets/src/bundles/browse/swhid-utils.js b/assets/src/bundles/browse/swhid-utils.js
--- a/assets/src/bundles/browse/swhid-utils.js
+++ b/assets/src/bundles/browse/swhid-utils.js
@@ -18,9 +18,9 @@
 
 export function swhIdContextOptionToggled(event) {
   event.stopPropagation();
-  let swhIdElt = $(event.target).closest('.swhid-ui').find('.swhid');
-  let swhIdWithContext = $(event.target).data('swhid-with-context');
-  let swhIdWithContextUrl = $(event.target).data('swhid-with-context-url');
+  const swhIdElt = $(event.target).closest('.swhid-ui').find('.swhid');
+  const swhIdWithContext = $(event.target).data('swhid-with-context');
+  const swhIdWithContextUrl = $(event.target).data('swhid-with-context-url');
   let currentSwhId = swhIdElt.text();
   if ($(event.target).prop('checked')) {
     swhIdElt.attr('href', swhIdWithContextUrl);
@@ -38,11 +38,11 @@
 }
 
 function addLinesInfo() {
-  let swhIdElt = $('#swhid-tab-content').find('.swhid');
+  const swhIdElt = $('#swhid-tab-content').find('.swhid');
   let currentSwhId = swhIdElt.text().replace(/;\n/g, ';');
-  let lines = [];
+  const lines = [];
   let linesPart = ';lines=';
-  let linesRegexp = new RegExp(/L(\d+)/g);
+  const linesRegexp = new RegExp(/L(\d+)/g);
   let line = linesRegexp.exec(window.location.hash);
   while (line) {
     lines.push(parseInt(line[1]));
@@ -69,14 +69,14 @@
 $(document).ready(() => {
   new ClipboardJS('.btn-swhid-copy', {
     text: trigger => {
-      let swhId = $(trigger).closest('.swhid-ui').find('.swhid').text();
+      const swhId = $(trigger).closest('.swhid-ui').find('.swhid').text();
       return swhId.replace(/;\n/g, ';');
     }
   });
 
   new ClipboardJS('.btn-swhid-url-copy', {
     text: trigger => {
-      let swhIdUrl = $(trigger).closest('.swhid-ui').find('.swhid').attr('href');
+      const swhIdUrl = $(trigger).closest('.swhid-ui').find('.swhid').attr('href');
       return window.location.origin + swhIdUrl;
     }
   });
@@ -85,7 +85,7 @@
     $('#swh-identifiers').css('width', '1000px');
   }
 
-  let tabSlideOptions = {
+  const tabSlideOptions = {
     tabLocation: 'right',
     clickScreenToCloseFilters: ['.ui-slideouttab-panel', '.modal'],
     offset: function() {
diff --git a/assets/src/bundles/origin/visits-calendar.js b/assets/src/bundles/origin/visits-calendar.js
--- a/assets/src/bundles/origin/visits-calendar.js
+++ b/assets/src/bundles/origin/visits-calendar.js
@@ -8,8 +8,8 @@
 import Calendar from 'js-year-calendar';
 import 'js-year-calendar/dist/js-year-calendar.css';
 
-let minSize = 15;
-let maxSize = 28;
+const minSize = 15;
+const maxSize = 28;
 let currentPopover = null;
 let visitsByDate = {};
 
@@ -28,9 +28,9 @@
   for (let i = 0; i < filteredVisits.length; ++i) {
     filteredVisits[i]['startDate'] = filteredVisits[i]['date'];
     filteredVisits[i]['endDate'] = filteredVisits[i]['startDate'];
-    let date = new Date(filteredVisits[i]['date']);
+    const date = new Date(filteredVisits[i]['date']);
     date.setHours(0, 0, 0, 0);
-    let dateStr = date.toDateString();
+    const dateStr = date.toDateString();
     if (!visitsByDate.hasOwnProperty(dateStr)) {
       visitsByDate[dateStr] = [filteredVisits[i]];
     } else {
@@ -59,24 +59,24 @@
     startYear: year,
     renderEnd: e => yearClickedCallback(e.currentYear),
     customDataSourceRenderer: (element, date, events) => {
-      let dateStr = date.toDateString();
-      let nbVisits = visitsByDate[dateStr].length;
+      const dateStr = date.toDateString();
+      const nbVisits = visitsByDate[dateStr].length;
       let t = nbVisits / maxNbVisitsByDate;
       if (maxNbVisitsByDate === 1) {
         t = 0;
       }
-      let size = minSize + t * (maxSize - minSize);
-      let offsetX = (maxSize - size) / 2 - parseInt($(element).css('padding-left'));
-      let offsetY = (maxSize - size) / 2 - parseInt($(element).css('padding-top')) + 1;
-      let cellWrapper = $('<div></div>');
+      const size = minSize + t * (maxSize - minSize);
+      const offsetX = (maxSize - size) / 2 - parseInt($(element).css('padding-left'));
+      const offsetY = (maxSize - size) / 2 - parseInt($(element).css('padding-top')) + 1;
+      const cellWrapper = $('<div></div>');
       cellWrapper.css('position', 'relative');
-      let dayNumber = $('<div></div>');
+      const dayNumber = $('<div></div>');
       dayNumber.text($(element).text());
-      let circle = $('<div></div>');
+      const circle = $('<div></div>');
       let r = 0;
       let g = 0;
       for (let i = 0; i < nbVisits; ++i) {
-        let visit = visitsByDate[dateStr][i];
+        const visit = visitsByDate[dateStr][i];
         if (visit.status === 'full') {
           g += 255;
         } else if (visit.status === 'partial') {
@@ -103,14 +103,14 @@
       if (currentPopover !== e.element) {
         closePopover();
       }
-      let dateStr = e.date.toDateString();
+      const dateStr = e.date.toDateString();
       if (visitsByDate.hasOwnProperty(dateStr)) {
 
-        let visits = visitsByDate[dateStr];
+        const visits = visitsByDate[dateStr];
         let content = '<div><h6>' + e.date.toDateString() + '</h6></div>';
         content += '<ul class="swh-list-unstyled">';
         for (let i = 0; i < visits.length; ++i) {
-          let visitTime = visits[i].formatted_date.substr(visits[i].formatted_date.indexOf(',') + 2);
+          const visitTime = visits[i].formatted_date.substr(visits[i].formatted_date.indexOf(',') + 2);
           content += '<li><a class="swh-visit-icon swh-visit-' + visits[i].status + '" title="' + visits[i].status +
                      ' visit" href="' + visits[i].url + '">' + visitTime + '</a></li>';
         }
diff --git a/assets/src/bundles/origin/visits-histogram.js b/assets/src/bundles/origin/visits-histogram.js
--- a/assets/src/bundles/origin/visits-histogram.js
+++ b/assets/src/bundles/origin/visits-histogram.js
@@ -23,17 +23,17 @@
   // histogram size and margins
   let width = 1000;
   let height = 200;
-  let margin = {top: 20, right: 80, bottom: 30, left: 50};
+  const margin = {top: 20, right: 80, bottom: 30, left: 50};
 
   // create responsive svg
-  let svg = d3.select(container)
+  const svg = d3.select(container)
     .attr('style',
           'padding-bottom: ' + Math.ceil(height * 100 / width) + '%')
     .append('svg')
     .attr('viewBox', '0 0 ' + width + ' ' + height);
 
   // create tooltip div
-  let tooltip = d3.select('body')
+  const tooltip = d3.select('body')
     .append('div')
     .attr('class', 'd3-tooltip')
     .style('opacity', 0);
@@ -43,53 +43,53 @@
   height = height - margin.top - margin.bottom;
 
   // create main svg group element
-  let g = svg.append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
+  const g = svg.append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
 
   // create x scale
-  let x = d3.scaleTime().rangeRound([0, width]);
+  const x = d3.scaleTime().rangeRound([0, width]);
 
   // create y scale
-  let y = d3.scaleLinear().range([height, 0]);
+  const y = d3.scaleLinear().range([height, 0]);
 
   // create ordinal colorscale mapping visit status
-  let colors = d3.scaleOrdinal()
+  const colors = d3.scaleOrdinal()
     .domain(['full', 'partial', 'failed', 'ongoing'])
     .range(['#008000', '#edc344', '#ff0000', '#0000ff']);
 
   // first swh crawls were made in 2015
-  let startYear = 2015;
+  const startYear = 2015;
   // set latest display year as the current one
-  let now = new Date();
-  let endYear = now.getUTCFullYear() + 1;
-  let monthExtent = [new Date(Date.UTC(startYear, 0, 1)), new Date(Date.UTC(endYear, 0, 1))];
+  const now = new Date();
+  const endYear = now.getUTCFullYear() + 1;
+  const monthExtent = [new Date(Date.UTC(startYear, 0, 1)), new Date(Date.UTC(endYear, 0, 1))];
 
   // create months bins based on setup extent
-  let monthBins = d3.timeMonths(d3.timeMonth.offset(monthExtent[0], -1), monthExtent[1]);
+  const monthBins = d3.timeMonths(d3.timeMonth.offset(monthExtent[0], -1), monthExtent[1]);
   // create years bins based on setup extent
-  let yearBins = d3.timeYears(monthExtent[0], monthExtent[1]);
+  const yearBins = d3.timeYears(monthExtent[0], monthExtent[1]);
 
   // set x scale domain
   x.domain(d3.extent(monthBins));
 
   // use D3 histogram layout to create a function that will bin the visits by month
-  let binByMonth = d3.histogram()
+  const binByMonth = d3.histogram()
     .value(d => d.date)
     .domain(x.domain())
     .thresholds(monthBins);
 
   // use D3 nest function to group the visits by status
-  let visitsByStatus = d3.groups(visitsData, d => d['status'])
+  const visitsByStatus = d3.groups(visitsData, d => d['status'])
     .sort((a, b) => d3.ascending(a[0], b[0]));
 
   // prepare data in order to be able to stack visit statuses by month
-  let statuses = [];
-  let histData = [];
+  const statuses = [];
+  const histData = [];
   for (let i = 0; i < monthBins.length; ++i) {
     histData[i] = {};
   }
   visitsByStatus.forEach(entry => {
     statuses.push(entry[0]);
-    let monthsData = binByMonth(entry[1]);
+    const monthsData = binByMonth(entry[1]);
     for (let i = 0; i < monthsData.length; ++i) {
       histData[i]['x0'] = monthsData[i]['x0'];
       histData[i]['x1'] = monthsData[i]['x1'];
@@ -98,12 +98,12 @@
   });
 
   // create function to stack visits statuses by month
-  let stacked = d3.stack()
+  const stacked = d3.stack()
     .keys(statuses)
     .value((d, key) => d[key].length);
 
   // compute the maximum amount of visits by month
-  let yMax = d3.max(histData, d => {
+  const yMax = d3.max(histData, d => {
     let total = 0;
     for (let i = 0; i < statuses.length; ++i) {
       total += d[statuses[i]].length;
@@ -115,8 +115,8 @@
   y.domain([0, yMax]);
 
   // compute ticks values for the y axis
-  let step = 5;
-  let yTickValues = [];
+  const step = 5;
+  const yTickValues = [];
   for (let i = 0; i <= yMax / step; ++i) {
     yTickValues.push(i * step);
   }
@@ -149,14 +149,14 @@
     .attr('fill-opacity', d => d.getUTCFullYear() === currentYear ? 0.3 : 0)
     .attr('stroke', 'none')
     .attr('x', d => {
-      let date = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
+      const date = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
       return x(date);
     })
     .attr('y', 0)
     .attr('height', height)
     .attr('width', d => {
-      let date = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
-      let yearWidth = x(d3.timeYear.offset(date, 1)) - x(date);
+      const date = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
+      const yearWidth = x(d3.timeYear.offset(date, 1)) - x(date);
       return yearWidth;
     })
     // mouse event callbacks used to show rectangle years
@@ -209,11 +209,11 @@
       tooltip.transition()
         .duration(200)
         .style('opacity', 1);
-      let ds = d.data.x1.toISOString().substr(0, 7).split('-');
+      const ds = d.data.x1.toISOString().substr(0, 7).split('-');
       let tooltipText = '<b>' + ds[1] + ' / ' + ds[0] + ':</b><br/>';
       for (let i = 0; i < statuses.length; ++i) {
-        let visitStatus = statuses[i];
-        let nbVisits = d.data[visitStatus].length;
+        const visitStatus = statuses[i];
+        const nbVisits = d.data[visitStatus].length;
         if (nbVisits === 0) continue;
         tooltipText += nbVisits + ' ' + visitStatus + ' visits';
         if (i !== statuses.length - 1) tooltipText += '<br/>';
@@ -260,19 +260,19 @@
     .attr('fill', 'none')
     .attr('stroke', d => d.getUTCFullYear() === currentYear ? 'black' : 'none')
     .attr('x', d => {
-      let date = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
+      const date = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
       return x(date);
     })
     .attr('y', 0)
     .attr('height', height)
     .attr('width', d => {
-      let date = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
-      let yearWidth = x(d3.timeYear.offset(date, 1)) - x(date);
+      const date = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
+      const yearWidth = x(d3.timeYear.offset(date, 1)) - x(date);
       return yearWidth;
     });
 
   // add x axis with a tick for every 1st day of each year
-  let xAxis = g.append('g')
+  const xAxis = g.append('g')
     .attr('class', 'axis')
     .attr('transform', 'translate(0,' + height + ')')
     .call(
@@ -285,9 +285,9 @@
   // of each year range
   xAxis.selectAll('text')
     .attr('transform', d => {
-      let year = d.getUTCFullYear();
-      let date = new Date(Date.UTC(year, 0, 1));
-      let yearWidth = x(d3.timeYear.offset(date, 1)) - x(date);
+      const year = d.getUTCFullYear();
+      const date = new Date(Date.UTC(year, 0, 1));
+      const yearWidth = x(d3.timeYear.offset(date, 1)) - x(date);
       return 'translate(' + -yearWidth / 2 + ', 0)';
     });
 
@@ -297,7 +297,7 @@
     .call(d3.axisLeft(y).tickValues(yTickValues));
 
   // add legend for visit statuses
-  let legendGroup = g.append('g')
+  const legendGroup = g.append('g')
     .attr('font-family', 'sans-serif')
     .attr('font-size', 10)
     .attr('text-anchor', 'end');
@@ -308,7 +308,7 @@
     .attr('dy', '0.32em')
     .text('visit status:');
 
-  let legend = legendGroup.selectAll('g')
+  const legend = legendGroup.selectAll('g')
     .data(statuses.slice().reverse())
     .enter().append('g')
     .attr('transform', (d, i) => 'translate(0,' + (i + 1) * 20 + ')');
diff --git a/assets/src/bundles/origin/visits-reporting.js b/assets/src/bundles/origin/visits-reporting.js
--- a/assets/src/bundles/origin/visits-reporting.js
+++ b/assets/src/bundles/origin/visits-reporting.js
@@ -18,7 +18,7 @@
 
 // function to gather full visits
 function filterFullVisits(differentSnapshots) {
-  let filteredVisits = [];
+  const filteredVisits = [];
   for (let i = 0; i < allVisits.length; ++i) {
     if (allVisits[i].status !== 'full') continue;
     if (!differentSnapshots) {
@@ -26,7 +26,7 @@
     } else if (filteredVisits.length === 0) {
       filteredVisits.push(allVisits[i]);
     } else {
-      let lastVisit = filteredVisits[filteredVisits.length - 1];
+      const lastVisit = filteredVisits[filteredVisits.length - 1];
       if (allVisits[i].snapshot !== lastVisit.snapshot) {
         filteredVisits.push(allVisits[i]);
       }
@@ -38,14 +38,14 @@
 // function to update the visits list view based on the selected year
 function updateVisitsList(year) {
   $('#swh-visits-list').children().remove();
-  let visitsByYear = [];
+  const visitsByYear = [];
   for (let i = 0; i < filteredVisits.length; ++i) {
     if (filteredVisits[i].date.getUTCFullYear() === year) {
       visitsByYear.push(filteredVisits[i]);
     }
   }
   let visitsCpt = 0;
-  let nbVisitsByRow = 4;
+  const nbVisitsByRow = 4;
   let visitsListHtml = '<div class="swh-visits-list-row">';
   for (let i = 0; i < visitsByYear.length; ++i) {
     if (visitsCpt > 0 && visitsCpt % nbVisitsByRow === 0) {
@@ -114,7 +114,7 @@
     allVisits.forEach((v, i) => {
       // Turn Unix epoch into Javascript Date object
       v.date = new Date(Math.floor(v.date * 1000));
-      let visitLink = '<a class="swh-visit-icon swh-visit-' + v.status + '" href="' + v.url + '">' + v.formatted_date + '</a>';
+      const visitLink = '<a class="swh-visit-icon swh-visit-' + v.status + '" href="' + v.url + '">' + v.formatted_date + '</a>';
       if (v.status === 'full') {
         if (!firstFullVisit) {
           firstFullVisit = v;
diff --git a/assets/src/bundles/revision/diff-utils.js b/assets/src/bundles/revision/diff-utils.js
--- a/assets/src/bundles/revision/diff-utils.js
+++ b/assets/src/bundles/revision/diff-utils.js
@@ -19,7 +19,7 @@
 let nbDiffsComputed = 0;
 
 // the no newline at end of file marker from Github
-let noNewLineMarker = '<span class="no-nl-marker" title="No newline at end of file">' +
+const noNewLineMarker = '<span class="no-nl-marker" title="No newline at end of file">' +
                         '<svg aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16">' +
                           '<path fill-rule="evenodd" d="M16 5v3c0 .55-.45 1-1 1h-3v2L9 8l3-3v2h2V5h2zM8 8c0 2.2-1.8 4-4 4s-4-1.8-4-4 1.8-4 4-4 4 1.8 4 4zM1.5 9.66L5.66 5.5C5.18 5.19 4.61 5 4 5 2.34 5 1 6.34 1 8c0 .61.19 1.17.5 1.66zM7 8c0-.61-.19-1.17-.5-1.66L2.34 10.5c.48.31 1.05.5 1.66.5 1.66 0 3-1.34 3-3z"></path>' +
                         '</svg>' +
@@ -30,9 +30,9 @@
 // to track the total number of deleted lines in files diffs
 let nbDeletions = 0;
 // to track the already computed diffs by id
-let computedDiffs = {};
+const computedDiffs = {};
 // map a diff id to its computation url
-let diffsUrls = {};
+const diffsUrls = {};
 // to keep track of diff lines to highlight
 let startLines = null;
 let endLines = null;
@@ -51,11 +51,11 @@
 
 // to check if a DOM element is in the viewport
 function isInViewport(elt) {
-  let elementTop = $(elt).offset().top;
-  let elementBottom = elementTop + $(elt).outerHeight();
+  const elementTop = $(elt).offset().top;
+  const elementBottom = elementTop + $(elt).outerHeight();
 
-  let viewportTop = $(window).scrollTop();
-  let viewportBottom = viewportTop + $(window).height();
+  const viewportTop = $(window).scrollTop();
+  const viewportBottom = viewportTop + $(window).height();
 
   return elementBottom > viewportTop && elementTop < viewportBottom;
 }
@@ -81,14 +81,14 @@
 function parseDiffHunkRangeIfAny(lineText) {
   let baseFromLine, baseToLine;
   if (lineText.startsWith('@@')) {
-    let linesInfoRegExp = new RegExp(/^@@ -(\d+),(\d+) \+(\d+),(\d+) @@$/gm);
-    let linesInfoRegExp2 = new RegExp(/^@@ -(\d+) \+(\d+),(\d+) @@$/gm);
-    let linesInfoRegExp3 = new RegExp(/^@@ -(\d+),(\d+) \+(\d+) @@$/gm);
-    let linesInfoRegExp4 = new RegExp(/^@@ -(\d+) \+(\d+) @@$/gm);
-    let linesInfo = linesInfoRegExp.exec(lineText);
-    let linesInfo2 = linesInfoRegExp2.exec(lineText);
-    let linesInfo3 = linesInfoRegExp3.exec(lineText);
-    let linesInfo4 = linesInfoRegExp4.exec(lineText);
+    const linesInfoRegExp = new RegExp(/^@@ -(\d+),(\d+) \+(\d+),(\d+) @@$/gm);
+    const linesInfoRegExp2 = new RegExp(/^@@ -(\d+) \+(\d+),(\d+) @@$/gm);
+    const linesInfoRegExp3 = new RegExp(/^@@ -(\d+),(\d+) \+(\d+) @@$/gm);
+    const linesInfoRegExp4 = new RegExp(/^@@ -(\d+) \+(\d+) @@$/gm);
+    const linesInfo = linesInfoRegExp.exec(lineText);
+    const linesInfo2 = linesInfoRegExp2.exec(lineText);
+    const linesInfo3 = linesInfoRegExp3.exec(lineText);
+    const linesInfo4 = linesInfoRegExp4.exec(lineText);
     if (linesInfo) {
       baseFromLine = parseInt(linesInfo[1]) - 1;
       baseToLine = parseInt(linesInfo[3]) - 1;
@@ -128,7 +128,7 @@
     }
     lines = lines.map(x => toLnInt(x));
   } else {
-    let lineNumber = toLnInt(lineNumbersStr.trim());
+    const lineNumber = toLnInt(lineNumbersStr.trim());
     if (from) {
       lines = [lineNumber, 0];
     } else if (to) {
@@ -170,8 +170,8 @@
 
 // function to highlight a single diff line
 function highlightDiffLine(diffId, i) {
-  let line = $(`#${diffId} .hljs-ln-line[data-line-number="${i}"]`);
-  let lineNumbers = $(`#${diffId} .hljs-ln-numbers[data-line-number="${i}"]`);
+  const line = $(`#${diffId} .hljs-ln-line[data-line-number="${i}"]`);
+  const lineNumbers = $(`#${diffId} .hljs-ln-numbers[data-line-number="${i}"]`);
   lineNumbers.css('color', 'black');
   lineNumbers.css('font-weight', 'bold');
   line.css('background-color', lineHighlightColor);
@@ -297,7 +297,7 @@
     }
   }
 
-  let selectedLinesFragment = selectedDiffLinesToFragment(startLines, endLines, unified);
+  const selectedLinesFragment = selectedDiffLinesToFragment(startLines, endLines, unified);
   window.location.hash = `diff_${diffId}+${selectedLinesFragment}`;
   return firstHighlightedLine;
 }
@@ -318,7 +318,7 @@
 export async function computeDiff(diffUrl, diffId) {
 
   // force diff computation ?
-  let force = diffUrl.indexOf('force=true') !== -1;
+  const force = diffUrl.indexOf('force=true') !== -1;
 
   // it no forced computation and diff already computed, do nothing
   if (!force && computedDiffs.hasOwnProperty(diffId)) {
@@ -381,17 +381,17 @@
     // but also compute line numbers for unified and side-by-side diffs
     let baseFromLine = '';
     let baseToLine = '';
-    let fromToLines = [];
-    let fromLines = [];
-    let toLines = [];
+    const fromToLines = [];
+    const fromLines = [];
+    const toLines = [];
     let maxNumberChars = 0;
     let diffFromStr = '';
     let diffToStr = '';
     let linesOffset = 0;
 
     $(`#${diffId} .hljs-ln-numbers`).each((i, lnElt) => {
-      let lnText = lnElt.nextSibling.innerText;
-      let linesInfo = parseDiffHunkRangeIfAny(lnText);
+      const lnText = lnElt.nextSibling.innerText;
+      const linesInfo = parseDiffHunkRangeIfAny(lnText);
       let fromLine = '';
       let toLine = '';
       // parsed lines info from the diff output
@@ -465,10 +465,10 @@
 
     // diff highlighting for added/removed lines on top of code highlighting
     $(`.${diffId} .hljs-ln-numbers`).each((i, lnElt) => {
-      let lnText = lnElt.nextSibling.innerText;
+      const lnText = lnElt.nextSibling.innerText;
       if (lnText.startsWith('@@')) {
         $(lnElt).parent().addClass('swh-diff-lines-info');
-        let linesInfoText = $(lnElt).parent().find('.hljs-ln-code .hljs-ln-line').text();
+        const linesInfoText = $(lnElt).parent().find('.hljs-ln-code .hljs-ln-line').text();
         $(lnElt).parent().find('.hljs-ln-code .hljs-ln-line').children().remove();
         $(lnElt).parent().find('.hljs-ln-code .hljs-ln-line').text('');
         $(lnElt).parent().find('.hljs-ln-code .hljs-ln-line').append(`<span class="hljs-meta">${linesInfoText}</span>`);
@@ -502,17 +502,17 @@
     $(`.${diffId} .hljs-ln-code`).each((i, lnElt) => {
       if (lnElt.firstChild) {
         if (lnElt.firstChild.nodeName !== '#text') {
-          let lineText = lnElt.firstChild.innerHTML;
+          const lineText = lnElt.firstChild.innerHTML;
           if (lineText[0] === '-' || lineText[0] === '+') {
             lnElt.firstChild.innerHTML = lineText.substr(1);
-            let newTextNode = document.createTextNode(lineText[0]);
+            const newTextNode = document.createTextNode(lineText[0]);
             $(lnElt).prepend(newTextNode);
           }
         }
         $(lnElt).contents().filter((i, elt) => {
           return elt.nodeType === 3; // Node.TEXT_NODE
         }).each((i, textNode) => {
-          let swhNoNewLineMarker = '[swh-no-nl-marker]';
+          const swhNoNewLineMarker = '[swh-no-nl-marker]';
           if (textNode.textContent.indexOf(swhNoNewLineMarker) !== -1) {
             textNode.textContent = textNode.textContent.replace(swhNoNewLineMarker, '');
             $(lnElt).append($(noNewLineMarker));
@@ -570,7 +570,7 @@
 function computeVisibleDiffs() {
   $('.swh-file-diff-panel').each((i, elt) => {
     if (isInViewport(elt)) {
-      let diffId = elt.id.replace('diff_', '');
+      const diffId = elt.id.replace('diff_', '');
       computeDiff(diffsUrls[diffId], diffId);
     }
   });
@@ -591,14 +591,14 @@
 // setup waypoints to request diffs computation on the fly while scrolling
 function setupWaypoints() {
   for (let i = 0; i < changes.length; ++i) {
-    let diffData = changes[i];
+    const diffData = changes[i];
 
     // create a waypoint that will trigger diff computation when
     // the top of the diff panel hits the bottom of the viewport
     $(`#diff_${diffData.id}`).waypoint({
       handler: function() {
         if (isInViewport(this.element)) {
-          let diffId = this.element.id.replace('diff_', '');
+          const diffId = this.element.id.replace('diff_', '');
           computeDiff(diffsUrls[diffId], diffId);
           this.destroy();
         }
@@ -611,7 +611,7 @@
     $(`#diff_${diffData.id}`).waypoint({
       handler: function() {
         if (isInViewport(this.element)) {
-          let diffId = this.element.id.replace('diff_', '');
+          const diffId = this.element.id.replace('diff_', '');
           computeDiff(diffsUrls[diffId], diffId);
           this.destroy();
         }
@@ -651,7 +651,7 @@
 // callback when the user clicks on the 'Compute all diffs' button
 export function computeAllDiffs(event) {
   $(event.currentTarget).addClass('active');
-  for (let diffId in diffsUrls) {
+  for (const diffId in diffsUrls) {
     if (diffsUrls.hasOwnProperty(diffId)) {
       computeDiff(diffsUrls[diffId], diffId);
     }
@@ -701,7 +701,7 @@
       }
 
       for (let i = 0; i < changes.length; ++i) {
-        let diffData = changes[i];
+        const diffData = changes[i];
         diffsUrls[diffData.id] = diffData.diff_url;
         $('#swh-revision-diffs').append(genDiffPanel(diffData));
       }
@@ -729,7 +729,7 @@
 
     // callback when the user requests to scroll on a specific diff or back to top
     $('#swh-revision-changes-list a[href^="#"], #back-to-top a[href^="#"]').click(e => {
-      let href = $.attr(e.currentTarget, 'href');
+      const href = $.attr(e.currentTarget, 'href');
       scrollToDiffPanel(href);
       return false;
     });
diff --git a/assets/src/bundles/revision/log-utils.js b/assets/src/bundles/revision/log-utils.js
--- a/assets/src/bundles/revision/log-utils.js
+++ b/assets/src/bundles/revision/log-utils.js
@@ -6,8 +6,8 @@
  */
 
 export function revsOrderingTypeClicked(event) {
-  let urlParams = new URLSearchParams(window.location.search);
-  let orderingType = $(event.target).val();
+  const urlParams = new URLSearchParams(window.location.search);
+  const orderingType = $(event.target).val();
   if (orderingType) {
     urlParams.set('revs_ordering', $(event.target).val());
   } else if (urlParams.has('revs_ordering')) {
@@ -18,8 +18,8 @@
 
 export function initRevisionsLog() {
   $(document).ready(() => {
-    let urlParams = new URLSearchParams(window.location.search);
-    let revsOrderingType = urlParams.get('revs_ordering');
+    const urlParams = new URLSearchParams(window.location.search);
+    const revsOrderingType = urlParams.get('revs_ordering');
     if (revsOrderingType) {
       $(`:input[value="${revsOrderingType}"]`).prop('checked', true);
     }
diff --git a/assets/src/bundles/save/index.js b/assets/src/bundles/save/index.js
--- a/assets/src/bundles/save/index.js
+++ b/assets/src/bundles/save/index.js
@@ -17,7 +17,7 @@
   acceptedCallback, pendingCallback, errorCallback
 ) {
   // Actually trigger the origin save request
-  let addSaveOriginRequestUrl = Urls.api_1_save_origin(originType, originUrl);
+  const addSaveOriginRequestUrl = Urls.api_1_save_origin(originType, originUrl);
   $('.swh-processing-save-request').css('display', 'block');
   let headers = {};
   let body = null;
@@ -122,7 +122,7 @@
     const response = await fetch(Urls.origin_save_types_list());
     const data = await response.json();
 
-    for (let originType of data) {
+    for (const originType of data) {
       $('#swh-input-visit-type').append(`<option value="${originType}">${originType}</option>`);
     }
     // set git as the default value as before
@@ -168,7 +168,7 @@
             name: 'request_date',
             render: (data, type, row) => {
               if (type === 'display') {
-                let date = new Date(data);
+                const date = new Date(data);
                 return date.toLocaleString();
               }
               return data;
@@ -258,25 +258,25 @@
       $('.swh-save-request-info').popover('dispose');
     });
 
-    let saveRequestAcceptedAlert = htmlAlert(
+    const saveRequestAcceptedAlert = htmlAlert(
       'success',
       'The "save code now" request has been accepted and will be processed as soon as possible.',
       true
     );
 
-    let saveRequestPendingAlert = htmlAlert(
+    const saveRequestPendingAlert = htmlAlert(
       'warning',
       'The "save code now" request has been put in pending state and may be accepted for processing after manual review.',
       true
     );
 
-    let saveRequestRateLimitedAlert = htmlAlert(
+    const saveRequestRateLimitedAlert = htmlAlert(
       'danger',
       'The rate limit for "save code now" requests has been reached. Please try again later.',
       true
     );
 
-    let saveRequestUnknownErrorAlert = htmlAlert(
+    const saveRequestUnknownErrorAlert = htmlAlert(
       'danger',
       'An unexpected error happened when submitting the "save code now request".',
       true
@@ -288,13 +288,13 @@
       $('.alert').alert('close');
       if (event.target.checkValidity()) {
         $(event.target).removeClass('was-validated');
-        let originType = $('#swh-input-visit-type').val();
+        const originType = $('#swh-input-visit-type').val();
         let originUrl = $('#swh-input-origin-url').val();
 
         originUrl = await getCanonicalOriginURL(originUrl);
 
         // read the extra inputs for the 'archives' type
-        let extraData = {};
+        const extraData = {};
         if (originType === 'archives') {
           extraData['archives_data'] = [];
           for (let i = 0; i < $('.swh-save-origin-artifact-form').length; ++i) {
@@ -333,10 +333,10 @@
     });
 
     $('#swh-input-origin-url').on('input', function(event) {
-      let originUrl = $(this).val().trim();
+      const originUrl = $(this).val().trim();
       $(this).val(originUrl);
       $('#swh-input-visit-type option').each(function() {
-        let val = $(this).val();
+        const val = $(this).val();
         if (val && originUrl.includes(val)) {
           $(this).prop('selected', true);
         }
@@ -352,7 +352,7 @@
 }
 
 export function validateSaveOriginUrl(input) {
-  let originType = $('#swh-input-visit-type').val();
+  const originType = $('#swh-input-visit-type').val();
   let originUrl = null;
   let validUrl = true;
 
@@ -363,7 +363,7 @@
   }
 
   if (validUrl) {
-    let allowedProtocols = ['http:', 'https:', 'svn:', 'git:'];
+    const allowedProtocols = ['http:', 'https:', 'svn:', 'git:'];
     validUrl = (
       allowedProtocols.find(protocol => protocol === originUrl.protocol) !== undefined
     );
@@ -401,25 +401,25 @@
 
 export function initTakeNewSnapshot() {
 
-  let newSnapshotRequestAcceptedAlert = htmlAlert(
+  const newSnapshotRequestAcceptedAlert = htmlAlert(
     'success',
     'The "take new snapshot" request has been accepted and will be processed as soon as possible.',
     true
   );
 
-  let newSnapshotRequestPendingAlert = htmlAlert(
+  const newSnapshotRequestPendingAlert = htmlAlert(
     'warning',
     'The "take new snapshot" request has been put in pending state and may be accepted for processing after manual review.',
     true
   );
 
-  let newSnapshotRequestRateLimitAlert = htmlAlert(
+  const newSnapshotRequestRateLimitAlert = htmlAlert(
     'danger',
     'The rate limit for "take new snapshot" requests has been reached. Please try again later.',
     true
   );
 
-  let newSnapshotRequestUnknownErrorAlert = htmlAlert(
+  const newSnapshotRequestUnknownErrorAlert = htmlAlert(
     'danger',
     'An unexpected error happened when submitting the "save code now request".',
     true
@@ -430,9 +430,9 @@
       event.preventDefault();
       event.stopPropagation();
 
-      let originType = $('#swh-input-visit-type').val();
-      let originUrl = $('#swh-input-origin-url').val();
-      let extraData = {};
+      const originType = $('#swh-input-visit-type').val();
+      const originUrl = $('#swh-input-origin-url').val();
+      const extraData = {};
 
       originSaveRequest(originType, originUrl, extraData,
                         () => $('#swh-take-new-snapshot-request-status').html(newSnapshotRequestAcceptedAlert),
@@ -506,7 +506,7 @@
   if ($.isEmptyObject(saveRequestTaskInfo)) {
     content = 'Not available';
   } else {
-    let saveRequestInfo = [];
+    const saveRequestInfo = [];
     const taskData = {
       'Type': ['raw', 'type'],
       'Visit status': ['raw', 'visit_status'],
@@ -529,7 +529,7 @@
       }
     }
     content = '<table class="table"><tbody>';
-    for (let info of saveRequestInfo) {
+    for (const info of saveRequestInfo) {
       content +=
             `<tr>
               <th class="swh-metadata-table-row swh-metadata-table-key">${info.key}</th>
@@ -548,7 +548,7 @@
   $('#swh-input-origin-url').val(originUrl);
   let originTypeFound = false;
   $('#swh-input-visit-type option').each(function() {
-    let val = $(this).val();
+    const val = $(this).val();
     if (val && originUrl.includes(val)) {
       $(this).prop('selected', true);
       originTypeFound = true;
@@ -556,7 +556,7 @@
   });
   if (!originTypeFound) {
     $('#swh-input-visit-type option').each(function() {
-      let val = $(this).val();
+      const val = $(this).val();
       if (val === visitType) {
         $(this).prop('selected', true);
       }
diff --git a/assets/src/bundles/vault/vault-create-tasks.js b/assets/src/bundles/vault/vault-create-tasks.js
--- a/assets/src/bundles/vault/vault-create-tasks.js
+++ b/assets/src/bundles/vault/vault-create-tasks.js
@@ -103,14 +103,14 @@
 }
 
 function validateEmail(email) {
-  let re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
+  const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
   return re.test(String(email).toLowerCase());
 }
 
 export function cookDirectoryArchive(directoryId) {
-  let email = $('#swh-vault-directory-email').val().trim();
+  const email = $('#swh-vault-directory-email').val().trim();
   if (!email || validateEmail(email)) {
-    let cookingTask = {
+    const cookingTask = {
       'object_type': 'directory',
       'object_id': directoryId,
       'email': email,
@@ -132,9 +132,9 @@
 }
 
 export function cookRevisionArchive(revisionId) {
-  let email = $('#swh-vault-revision-email').val().trim();
+  const email = $('#swh-vault-revision-email').val().trim();
   if (!email || validateEmail(email)) {
-    let cookingTask = {
+    const cookingTask = {
       'object_type': 'revision',
       'object_id': revisionId,
       'email': email,
diff --git a/assets/src/bundles/vault/vault-ui.js b/assets/src/bundles/vault/vault-ui.js
--- a/assets/src/bundles/vault/vault-ui.js
+++ b/assets/src/bundles/vault/vault-ui.js
@@ -8,7 +8,7 @@
 import {handleFetchError, handleFetchErrors, csrfPost} from 'utils/functions';
 import vaultTableRowTemplate from './vault-table-row.ejs';
 
-let progress =
+const progress =
   `<div class="progress">
     <div class="progress-bar progress-bar-success progress-bar-striped"
           role="progressbar" aria-valuenow="100" aria-valuemin="0"
@@ -16,7 +16,7 @@
     </div>
   </div>;`;
 
-let pollingInterval = 5000;
+const pollingInterval = 5000;
 let checkVaultId;
 
 function updateProgressBar(progressBar, cookingTask) {
@@ -52,7 +52,7 @@
     // link is dead
   } else {
     // get the associated cooking task
-    let vaultCookingTasks = JSON.parse(localStorage.getItem('swh-vault-cooking-tasks'));
+    const vaultCookingTasks = JSON.parse(localStorage.getItem('swh-vault-cooking-tasks'));
     for (let i = 0; i < vaultCookingTasks.length; ++i) {
       if (vaultCookingTasks[i].fetch_url === fetchUrl) {
         recookTask = vaultCookingTasks[i];
@@ -87,7 +87,7 @@
 
       // update task status
       recookTask.status = 'new';
-      let vaultCookingTasks = JSON.parse(localStorage.getItem('swh-vault-cooking-tasks'));
+      const vaultCookingTasks = JSON.parse(localStorage.getItem('swh-vault-cooking-tasks'));
       for (let i = 0; i < vaultCookingTasks.length; ++i) {
         if (vaultCookingTasks[i].object_id === recookTask.object_id) {
           vaultCookingTasks[i] = recookTask;
@@ -109,18 +109,18 @@
 }
 
 async function checkVaultCookingTasks() {
-  let vaultCookingTasks = JSON.parse(localStorage.getItem('swh-vault-cooking-tasks'));
+  const vaultCookingTasks = JSON.parse(localStorage.getItem('swh-vault-cooking-tasks'));
   if (!vaultCookingTasks || vaultCookingTasks.length === 0) {
     $('.swh-vault-table tbody tr').remove();
     checkVaultId = setTimeout(checkVaultCookingTasks, pollingInterval);
     return;
   }
-  let cookingTaskRequests = [];
-  let tasks = {};
-  let currentObjectIds = [];
+  const cookingTaskRequests = [];
+  const tasks = {};
+  const currentObjectIds = [];
 
   for (let i = 0; i < vaultCookingTasks.length; ++i) {
-    let cookingTask = vaultCookingTasks[i];
+    const cookingTask = vaultCookingTasks[i];
     currentObjectIds.push(cookingTask.object_id);
     tasks[cookingTask.object_id] = cookingTask;
     let cookingUrl;
@@ -134,7 +134,7 @@
     }
   }
   $('.swh-vault-table tbody tr').each((i, row) => {
-    let objectId = $(row).find('.vault-object-info').data('object-id');
+    const objectId = $(row).find('.vault-object-info').data('object-id');
     if ($.inArray(objectId, currentObjectIds) === -1) {
       $(row).remove();
     }
@@ -144,16 +144,16 @@
     handleFetchErrors(responses);
     const cookingTasks = await Promise.all(responses.map(r => r.json()));
 
-    let table = $('#vault-cooking-tasks tbody');
+    const table = $('#vault-cooking-tasks tbody');
     for (let i = 0; i < cookingTasks.length; ++i) {
-      let cookingTask = tasks[cookingTasks[i].obj_id];
+      const cookingTask = tasks[cookingTasks[i].obj_id];
       cookingTask.status = cookingTasks[i].status;
       cookingTask.fetch_url = cookingTasks[i].fetch_url;
       cookingTask.progress_message = cookingTasks[i].progress_message;
     }
     for (let i = 0; i < vaultCookingTasks.length; ++i) {
-      let cookingTask = vaultCookingTasks[i];
-      let rowTask = $(`#vault-task-${cookingTask.object_id}`);
+      const cookingTask = vaultCookingTasks[i];
+      const rowTask = $(`#vault-task-${cookingTask.object_id}`);
 
       if (!rowTask.length) {
 
@@ -166,8 +166,8 @@
           }
         }
 
-        let progressBar = $.parseHTML(progress)[0];
-        let progressBarContent = $(progressBar).find('.progress-bar');
+        const progressBar = $.parseHTML(progress)[0];
+        const progressBarContent = $(progressBar).find('.progress-bar');
         updateProgressBar(progressBarContent, cookingTask);
         table.prepend(vaultTableRowTemplate({
           browseUrl: browseUrl,
@@ -177,9 +177,9 @@
           swh: swh
         }));
       } else {
-        let progressBar = rowTask.find('.progress-bar');
+        const progressBar = rowTask.find('.progress-bar');
         updateProgressBar(progressBar, cookingTask);
-        let downloadLink = rowTask.find('.vault-dl-link');
+        const downloadLink = rowTask.find('.vault-dl-link');
         if (cookingTask.status === 'done') {
           downloadLink[0].innerHTML =
               '<button class="btn btn-default btn-sm" ' +
@@ -217,11 +217,11 @@
 
   $('#vault-remove-tasks').click(() => {
     clearTimeout(checkVaultId);
-    let tasksToRemove = [];
+    const tasksToRemove = [];
     $('.swh-vault-table tbody tr').each((i, row) => {
-      let taskSelected = $(row).find('.vault-task-toggle-selection').prop('checked');
+      const taskSelected = $(row).find('.vault-task-toggle-selection').prop('checked');
       if (taskSelected) {
-        let objectId = $(row).find('.vault-object-info').data('object-id');
+        const objectId = $(row).find('.vault-object-info').data('object-id');
         tasksToRemove.push(objectId);
         $(row).remove();
       }
diff --git a/assets/src/bundles/webapp/code-highlighting.js b/assets/src/bundles/webapp/code-highlighting.js
--- a/assets/src/bundles/webapp/code-highlighting.js
+++ b/assets/src/bundles/webapp/code-highlighting.js
@@ -14,11 +14,11 @@
   // keep track of the first highlighted line
   let firstHighlightedLine = null;
   // highlighting color
-  let lineHighlightColor = 'rgb(193, 255, 193)';
+  const lineHighlightColor = 'rgb(193, 255, 193)';
 
   // function to highlight a line
   function highlightLine(i) {
-    let lineTd = $(`.hljs-ln-line[data-line-number="${i}"]`);
+    const lineTd = $(`.hljs-ln-line[data-line-number="${i}"]`);
     lineTd.css('background-color', lineHighlightColor);
     return lineTd;
   }
@@ -40,8 +40,8 @@
   // function to highlight lines based on a url fragment
   // in the form '#Lx' or '#Lx-Ly'
   function parseUrlFragmentForLinesToHighlight() {
-    let lines = [];
-    let linesRegexp = new RegExp(/L(\d+)/g);
+    const lines = [];
+    const linesRegexp = new RegExp(/L(\d+)/g);
     let line = linesRegexp.exec(window.location.hash);
     if (line === null) {
       return;
@@ -81,9 +81,9 @@
     // can also be highlighted while holding the shift key)
     $('.swh-content').click(evt => {
       if (evt.target.classList.contains('hljs-ln-n')) {
-        let line = parseInt($(evt.target).data('line-number'));
+        const line = parseInt($(evt.target).data('line-number'));
         if (evt.shiftKey && firstHighlightedLine && line > firstHighlightedLine) {
-          let firstLine = firstHighlightedLine;
+          const firstLine = firstHighlightedLine;
           resetHighlightedLines();
           for (let i = firstLine; i <= line; ++i) {
             highlightLine(i);
diff --git a/assets/src/bundles/webapp/notebook-rendering.js b/assets/src/bundles/webapp/notebook-rendering.js
--- a/assets/src/bundles/webapp/notebook-rendering.js
+++ b/assets/src/bundles/webapp/notebook-rendering.js
@@ -26,11 +26,11 @@
 
 function escapeLaTeX(text) {
 
-  let blockMath = /\$\$(.+?)\$\$|\\\\\[(.+?)\\\\\]/msg;
-  let inlineMath = /\$(.+?)\$|\\\\\((.+?)\\\\\)/g;
-  let latexEnvironment = /\\begin\{([a-z]*\*?)\}(.+?)\\end\{\1\}/msg;
+  const blockMath = /\$\$(.+?)\$\$|\\\\\[(.+?)\\\\\]/msg;
+  const inlineMath = /\$(.+?)\$|\\\\\((.+?)\\\\\)/g;
+  const latexEnvironment = /\\begin\{([a-z]*\*?)\}(.+?)\\end\{\1\}/msg;
 
-  let mathTextFound = [];
+  const mathTextFound = [];
   let bm;
   while ((bm = blockMath.exec(text)) !== null) {
     mathTextFound.push(bm[1]);
@@ -46,13 +46,13 @@
     mathTextFound.push(le[1]);
   }
 
-  for (let mathText of mathTextFound) {
+  for (const mathText of mathTextFound) {
     // showdown will remove line breaks in LaTex array and
     // some escaping sequences when converting md to html.
     // So we use the following escaping hacks to keep them in the html
     // output and avoid MathJax typesetting errors.
     let escapedText = mathText.replace('\\\\', '\\\\\\\\');
-    for (let specialLaTexChar of ['{', '}', '#', '%', '&', '_']) {
+    for (const specialLaTexChar of ['{', '}', '#', '%', '&', '_']) {
       escapedText = escapedText.replace(new RegExp(`\\\\${specialLaTexChar}`, 'g'),
                                         `\\\\${specialLaTexChar}`);
     }
@@ -76,12 +76,12 @@
 
 export async function renderNotebook(nbJsonUrl, domElt) {
 
-  let showdown = await import(/* webpackChunkName: "showdown" */ 'utils/showdown');
+  const showdown = await import(/* webpackChunkName: "showdown" */ 'utils/showdown');
 
   await import(/* webpackChunkName: "highlightjs" */ 'utils/highlightjs');
 
   function renderMarkdown(text) {
-    let converter = new showdown.Converter({
+    const converter = new showdown.Converter({
       tables: true,
       simplifiedAutoLink: true,
       rawHeaderId: true,
@@ -124,9 +124,9 @@
   const nbJson = await response.json();
 
   // parse the notebook
-  let notebook = nb.parse(nbJson);
+  const notebook = nb.parse(nbJson);
   // render it to HTML and apply XSS filtering
-  let rendered = swh.webapp.filterXSS(notebook.render());
+  const rendered = swh.webapp.filterXSS(notebook.render());
   // insert rendered notebook in the DOM
   $(domElt).append(rendered);
   // set light red background color for stderr output cells
diff --git a/assets/src/bundles/webapp/pdf-rendering.js b/assets/src/bundles/webapp/pdf-rendering.js
--- a/assets/src/bundles/webapp/pdf-rendering.js
+++ b/assets/src/bundles/webapp/pdf-rendering.js
@@ -15,9 +15,9 @@
   let pageNum = 1;
   let pageRendering = false;
   let pageNumPending = null;
-  let defaultScale = 1.5;
-  let canvas = $('#pdf-canvas')[0];
-  let ctx = canvas.getContext('2d');
+  const defaultScale = 1.5;
+  const canvas = $('#pdf-canvas')[0];
+  const ctx = canvas.getContext('2d');
 
   // Get page info from document, resize canvas accordingly, and render page.
   async function renderPage(num) {
@@ -25,10 +25,10 @@
     // Using promise to fetch the page
     const page = await pdfDoc.getPage(num);
 
-    let divWidth = $('.swh-content').width();
-    let scale = Math.min(defaultScale, divWidth / page.getViewport({scale: 1.0}).width);
+    const divWidth = $('.swh-content').width();
+    const scale = Math.min(defaultScale, divWidth / page.getViewport({scale: 1.0}).width);
 
-    let viewport = page.getViewport({scale: scale});
+    const viewport = page.getViewport({scale: scale});
     canvas.width = viewport.width;
     canvas.height = viewport.height;
 
@@ -80,7 +80,7 @@
     queueRenderPage(pageNum);
   }
 
-  let pdfjs = await import(/* webpackChunkName: "pdfjs" */ 'pdfjs-dist');
+  const pdfjs = await import(/* webpackChunkName: "pdfjs" */ 'pdfjs-dist');
 
   pdfjs.GlobalWorkerOptions.workerSrc = staticAsset('js/pdf.worker.min.js');
 
diff --git a/assets/src/bundles/webapp/readme-rendering.js b/assets/src/bundles/webapp/readme-rendering.js
--- a/assets/src/bundles/webapp/readme-rendering.js
+++ b/assets/src/bundles/webapp/readme-rendering.js
@@ -11,7 +11,7 @@
 
 export async function renderMarkdown(domElt, markdownDocUrl) {
 
-  let showdown = await import(/* webpackChunkName: "showdown" */ 'utils/showdown');
+  const showdown = await import(/* webpackChunkName: "showdown" */ 'utils/showdown');
   await import(/* webpackChunkName: "highlightjs" */ 'utils/highlightjs');
 
   // Adapted from https://github.com/Bloggify/showdown-highlight
@@ -20,16 +20,16 @@
     return [{
       type: 'output',
       filter: function(text, converter, options) {
-        let left = '<pre><code\\b[^>]*>';
-        let right = '</code></pre>';
-        let flags = 'g';
-        let classAttr = 'class="';
-        let replacement = (wholeMatch, match, left, right) => {
+        const left = '<pre><code\\b[^>]*>';
+        const right = '</code></pre>';
+        const flags = 'g';
+        const classAttr = 'class="';
+        const replacement = (wholeMatch, match, left, right) => {
           match = decode(match);
-          let lang = (left.match(/class="([^ "]+)/) || [])[1];
+          const lang = (left.match(/class="([^ "]+)/) || [])[1];
 
           if (left.includes(classAttr)) {
-            let attrIndex = left.indexOf(classAttr) + classAttr.length;
+            const attrIndex = left.indexOf(classAttr) + classAttr.length;
             left = left.slice(0, attrIndex) + 'hljs ' + left.slice(attrIndex);
           } else {
             left = left.slice(0, -1) + ' class="hljs">';
@@ -48,7 +48,7 @@
   }
 
   $(document).ready(async() => {
-    let converter = new showdown.Converter({
+    const converter = new showdown.Converter({
       tables: true,
       extensions: [showdownHighlight]
     });
@@ -68,11 +68,11 @@
 
 export async function renderOrgData(domElt, orgDocData) {
 
-  let org = await import(/* webpackChunkName: "org" */ 'utils/org');
+  const org = await import(/* webpackChunkName: "org" */ 'utils/org');
 
-  let parser = new org.Parser();
-  let orgDocument = parser.parse(orgDocData, {toc: false});
-  let orgHTMLDocument = orgDocument.convert(org.ConverterHTML, {});
+  const parser = new org.Parser();
+  const orgDocument = parser.parse(orgDocData, {toc: false});
+  const orgHTMLDocument = orgDocument.convert(org.ConverterHTML, {});
   $(domElt).addClass('swh-org');
   $(domElt).html(swh.webapp.filterXSS(orgHTMLDocument.toString()));
   // remove toc and section numbers to get consistent
@@ -102,7 +102,7 @@
       handleFetchError(response);
       const data = await response.text();
 
-      let orgMode = '-*- mode: org -*-';
+      const orgMode = '-*- mode: org -*-';
       if (data.indexOf(orgMode) !== -1) {
         renderOrgData(domElt, data.replace(orgMode, ''));
       } else {
diff --git a/assets/src/bundles/webapp/status-widget.js b/assets/src/bundles/webapp/status-widget.js
--- a/assets/src/bundles/webapp/status-widget.js
+++ b/assets/src/bundles/webapp/status-widget.js
@@ -26,7 +26,7 @@
       const response = await fetch(statusDataURL);
       const data = await response.json();
 
-      for (let s of data.result.status) {
+      for (const s of data.result.status) {
         sc = s.status_code;
         sd = s.status;
         if (maxStatusCode < sc) {
diff --git a/assets/src/bundles/webapp/webapp-utils.js b/assets/src/bundles/webapp/webapp-utils.js
--- a/assets/src/bundles/webapp/webapp-utils.js
+++ b/assets/src/bundles/webapp/webapp-utils.js
@@ -10,7 +10,7 @@
 import {BREAKPOINT_MD} from 'utils/constants';
 
 let collapseSidebar = false;
-let previousSidebarState = localStorage.getItem('remember.lte.pushmenu');
+const previousSidebarState = localStorage.getItem('remember.lte.pushmenu');
 if (previousSidebarState !== undefined) {
   collapseSidebar = previousSidebarState === 'sidebar-collapse';
 }
@@ -25,8 +25,8 @@
   if (collapseSidebar) {
     // hack to avoid animated transition for collapsing sidebar
     // when loading a page
-    let sidebarTransition = $('.main-sidebar, .main-sidebar:before').css('transition');
-    let sidebarEltsTransition = $('.sidebar .nav-link p, .main-sidebar .brand-text, .sidebar .user-panel .info').css('transition');
+    const sidebarTransition = $('.main-sidebar, .main-sidebar:before').css('transition');
+    const sidebarEltsTransition = $('.sidebar .nav-link p, .main-sidebar .brand-text, .sidebar .user-panel .info').css('transition');
     $('.main-sidebar, .main-sidebar:before').css('transition', 'none');
     $('.sidebar .nav-link p, .main-sidebar .brand-text, .sidebar .user-panel .info').css('transition', 'none');
     $('body').addClass('sidebar-collapse');
@@ -57,7 +57,7 @@
   // redirect to last browse page if any when clicking on the 'Browse' entry
   // in the sidebar
   $(`.swh-browse-link`).click(event => {
-    let lastBrowsePage = sessionStorage.getItem('last-browse-page');
+    const lastBrowsePage = sessionStorage.getItem('last-browse-page');
     if (lastBrowsePage) {
       event.preventDefault();
       window.location = lastBrowsePage;
@@ -113,8 +113,8 @@
   let selectedCode = null;
 
   function getCodeOrPreEltUnderPointer(e) {
-    let elts = document.elementsFromPoint(e.clientX, e.clientY);
-    for (let elt of elts) {
+    const elts = document.elementsFromPoint(e.clientX, e.clientY);
+    for (const elt of elts) {
       if (elt.nodeName === 'CODE' || elt.nodeName === 'PRE') {
         return elt;
       }
@@ -129,7 +129,7 @@
 
   function selectCode(event, selectedCode) {
     if (selectedCode) {
-      let hljsLnCodeElts = $(selectedCode).find('.hljs-ln-code');
+      const hljsLnCodeElts = $(selectedCode).find('.hljs-ln-code');
       if (hljsLnCodeElts.length) {
         selectText(hljsLnCodeElts[0], hljsLnCodeElts[hljsLnCodeElts.length - 1]);
       } else {
@@ -170,8 +170,8 @@
     event.preventDefault();
     if (event.target.checkValidity()) {
       $(event.target).removeClass('was-validated');
-      let searchQueryText = $('#swh-origins-search-top-input').val().trim();
-      let queryParameters = new URLSearchParams();
+      const searchQueryText = $('#swh-origins-search-top-input').val().trim();
+      const queryParameters = new URLSearchParams();
       queryParameters.append('q', searchQueryText);
       queryParameters.append('with_visit', true);
       queryParameters.append('with_content', true);
@@ -206,7 +206,7 @@
     const data = await response.json();
 
     if (data.stat_counters && !$.isEmptyObject(data.stat_counters)) {
-      for (let objectType of ['content', 'revision', 'origin', 'directory', 'person', 'release']) {
+      for (const objectType of ['content', 'revision', 'origin', 'directory', 'person', 'release']) {
         const count = data.stat_counters[objectType];
         if (count !== undefined) {
           $(`#swh-${objectType}-count`).html(count.toLocaleString());
@@ -218,7 +218,7 @@
       $('.swh-counter').html('0');
     }
     if (data.stat_counters_history && !$.isEmptyObject(data.stat_counters_history)) {
-      for (let objectType of ['content', 'revision', 'origin']) {
+      for (const objectType of ['content', 'revision', 'origin']) {
         const history = data.stat_counters_history[objectType];
         if (history) {
           swh.webapp.drawHistoryCounterGraph(`#swh-${objectType}-count-history`, history);
@@ -327,7 +327,7 @@
 
 export function setSwhIdsContext(swhidsContext) {
   swhidsContext_ = {};
-  for (let swhidContext of swhidsContext) {
+  for (const swhidContext of swhidsContext) {
     swhidsContext_[swhidContext.object_type] = swhidContext;
   }
 }
@@ -353,7 +353,7 @@
 }
 
 export function setContainerFullWidth() {
-  let previousFullWidthState = JSON.parse(localStorage.getItem('swh-web-full-width'));
+  const previousFullWidthState = JSON.parse(localStorage.getItem('swh-web-full-width'));
   if (previousFullWidthState !== null) {
     setFullWidth(previousFullWidthState);
   }
diff --git a/assets/src/bundles/webapp/xss-filtering.js b/assets/src/bundles/webapp/xss-filtering.js
--- a/assets/src/bundles/webapp/xss-filtering.js
+++ b/assets/src/bundles/webapp/xss-filtering.js
@@ -21,7 +21,7 @@
     }
 
     // get currently browsed swh object metadata
-    let swhObjectMetadata = swh.webapp.getBrowsedSwhObjectMetadata();
+    const swhObjectMetadata = swh.webapp.getBrowsedSwhObjectMetadata();
 
     // the swh object is provided without any useful context
     // to get the image checksums from the web api
diff --git a/assets/src/utils/functions.js b/assets/src/utils/functions.js
--- a/assets/src/utils/functions.js
+++ b/assets/src/utils/functions.js
@@ -38,14 +38,14 @@
 }
 
 export function isGitRepoUrl(url, pathPrefix = '/') {
-  let allowedProtocols = ['http:', 'https:', 'git:'];
+  const allowedProtocols = ['http:', 'https:', 'git:'];
   if (allowedProtocols.find(protocol => protocol === url.protocol) === undefined) {
     return false;
   }
   if (!url.pathname.startsWith(pathPrefix)) {
     return false;
   }
-  let re = new RegExp('[\\w\\.-]+\\/?(?!=.git)(?:\\.git\\/?)?$');
+  const re = new RegExp('[\\w\\.-]+\\/?(?!=.git)(?:\\.git\\/?)?$');
   return re.test(url.pathname.slice(pathPrefix.length));
 };
 
@@ -54,9 +54,9 @@
 }
 
 export function selectText(startNode, endNode) {
-  let selection = window.getSelection();
+  const selection = window.getSelection();
   selection.removeAllRanges();
-  let range = document.createRange();
+  const range = document.createRange();
   range.setStart(startNode, 0);
   if (endNode.nodeName !== '#text') {
     range.setEnd(endNode, endNode.childNodes.length);
diff --git a/cypress/integration/code-highlighting.spec.js b/cypress/integration/code-highlighting.spec.js
--- a/cypress/integration/code-highlighting.spec.js
+++ b/cypress/integration/code-highlighting.spec.js
@@ -32,7 +32,7 @@
   it('should emphasize source code lines based on url fragment', function() {
     cy.visit(`${url}/#L${lineStart}-L${lineEnd}`);
     cy.get('.hljs-ln-line').then(lines => {
-      for (let line of lines) {
+      for (const line of lines) {
         const lineElt = $(line);
         const lineNumber = parseInt(lineElt.data('line-number'));
         if (lineNumber >= lineStart && lineNumber <= lineEnd) {
@@ -68,7 +68,7 @@
       .click({shiftKey: true})
       .get('.hljs-ln-line')
       .then(lines => {
-        for (let line of lines) {
+        for (const line of lines) {
           const lineElt = $(line);
           const lineNumber = parseInt(lineElt.data('line-number'));
           if (lineNumber >= lineStart && lineNumber <= lineEnd) {
diff --git a/cypress/integration/content-rendering.spec.js b/cypress/integration/content-rendering.spec.js
--- a/cypress/integration/content-rendering.spec.js
+++ b/cypress/integration/content-rendering.spec.js
@@ -64,10 +64,10 @@
       cy.get('.swh-content canvas')
         .wait(2000)
         .then(canvas => {
-          let width = canvas[0].width;
-          let height = canvas[0].height;
-          let context = canvas[0].getContext('2d');
-          let imgData = context.getImageData(0, 0, width, height);
+          const width = canvas[0].width;
+          const height = canvas[0].height;
+          const context = canvas[0].getContext('2d');
+          const imgData = context.getImageData(0, 0, width, height);
           assert.notEqual(imgData.data.reduce(sum), 0);
         });
     });
diff --git a/cypress/integration/deposit-admin.spec.js b/cypress/integration/deposit-admin.spec.js
--- a/cypress/integration/deposit-admin.spec.js
+++ b/cypress/integration/deposit-admin.spec.js
@@ -53,7 +53,7 @@
     cy.adminLogin();
     cy.visit(this.Urls.admin_deposit());
 
-    let testDeposits = responseDeposits;
+    const testDeposits = responseDeposits;
 
     cy.intercept(`${this.Urls.admin_deposit_list()}**`, {
       body: {
@@ -74,7 +74,7 @@
     cy.wait('@listDeposits').then((xhr) => {
       cy.log('response:', xhr.response);
       cy.log(xhr.response.body);
-      let deposits = xhr.response.body.data;
+      const deposits = xhr.response.body.data;
       cy.log('Deposits: ', deposits);
       expect(deposits.length).to.equal(testDeposits.length);
 
@@ -82,8 +82,8 @@
 
       // only 2 entries
       cy.get('@rows').each((row, idx, collection) => {
-        let deposit = deposits[idx];
-        let responseDeposit = testDeposits[idx];
+        const deposit = deposits[idx];
+        const responseDeposit = testDeposits[idx];
         assert.isNotNull(deposit);
         assert.isNotNull(responseDeposit);
         expect(deposit.id).to.be.equal(responseDeposit['id']);
@@ -93,7 +93,7 @@
         expect(deposit.swhid).to.be.equal(responseDeposit['swhid']);
         expect(deposit.swhid_context).to.be.equal(responseDeposit['swhid_context']);
 
-        let expectedOrigin = expectedOrigins[deposit.id];
+        const expectedOrigin = expectedOrigins[deposit.id];
         // ensure it's in the dom
         cy.contains(deposit.id).should('be.visible');
         if (deposit.status !== 'rejected') {
@@ -119,8 +119,8 @@
         cy.get('#swh-admin-deposit-list').find('tbody > tr').as('rows');
 
         cy.get('@rows').each((row, idx, collection) => {
-          let deposit = deposits[idx];
-          let expectedOrigin = expectedOrigins[deposit.id];
+          const deposit = deposits[idx];
+          const expectedOrigin = expectedOrigins[deposit.id];
 
           // ensure it's in the dom
           cy.contains(deposit.id).should('not.exist');
diff --git a/cypress/integration/directory.spec.js b/cypress/integration/directory.spec.js
--- a/cypress/integration/directory.spec.js
+++ b/cypress/integration/directory.spec.js
@@ -10,8 +10,8 @@
 let origin;
 
 let url;
-let dirs = [];
-let files = [];
+const dirs = [];
+const files = [];
 
 describe('Directory Tests', function() {
   before(function() {
@@ -19,7 +19,7 @@
 
     url = `${this.Urls.browse_origin_directory()}?origin_url=${origin.url}`;
 
-    for (let entry of origin.dirContent) {
+    for (const entry of origin.dirContent) {
       if (entry.type === 'file') {
         files.push(entry);
       } else {
@@ -45,8 +45,8 @@
     cy.get('.swh-content')
       .parent('tr')
       .then((rows) => {
-        for (let row of rows) {
-          let text = $(row).children('td').eq(2).text();
+        for (const row of rows) {
+          const text = $(row).children('td').eq(2).text();
           expect(text.trim()).to.not.be.empty;
         }
       });
diff --git a/cypress/integration/errors.spec.js b/cypress/integration/errors.spec.js
--- a/cypress/integration/errors.spec.js
+++ b/cypress/integration/errors.spec.js
@@ -126,7 +126,7 @@
     it(`should display 400 for invalid checksum for
         directory, snapshot, revision, content`, function() {
       const types = ['directory', 'snapshot', 'revision', 'content'];
-      for (let type of types) {
+      for (const type of types) {
         const url = this.Urls[`browse_${type}`](invalidChecksum);
         urlShouldShowError(url, {
           code: '400',
diff --git a/cypress/integration/home.spec.js b/cypress/integration/home.spec.js
--- a/cypress/integration/home.spec.js
+++ b/cypress/integration/home.spec.js
@@ -31,8 +31,8 @@
       .wait(500)
       .get('.swh-counter:visible')
       .then((counters) => {
-        for (let counter of counters) {
-          let innerText = $(counter).text();
+        for (const counter of counters) {
+          const innerText = $(counter).text();
           const value = parseInt(innerText.replace(/,/g, ''));
           assert.isAbove(value, 0);
         }
@@ -53,7 +53,7 @@
       .wait(500)
       .get('.swh-counter:visible')
       .then((counters) => {
-        for (let counter of counters) {
+        for (const counter of counters) {
           const value = parseInt($(counter).text());
           assert.equal(value, 0);
         }
diff --git a/cypress/integration/layout.spec.js b/cypress/integration/layout.spec.js
--- a/cypress/integration/layout.spec.js
+++ b/cypress/integration/layout.spec.js
@@ -163,12 +163,12 @@
     ];
 
     const responses = [];
-    for (let std of statusTestData) {
+    for (const std of statusTestData) {
       responses.push(genStatusResponse(std.status, std.statusCode));
     }
 
     let i = 0;
-    for (let std of statusTestData) {
+    for (const std of statusTestData) {
       cy.visit(url);
       // trick to override the response of an intercepted request
       // https://github.com/cypress-io/cypress/issues/9302
diff --git a/cypress/integration/origin-save.spec.js b/cypress/integration/origin-save.spec.js
--- a/cypress/integration/origin-save.spec.js
+++ b/cypress/integration/origin-save.spec.js
@@ -109,7 +109,7 @@
   });
 
   it('should format appropriately values depending on their type', function() {
-    let inputValues = [ // null values stay null
+    const inputValues = [ // null values stay null
       {type: 'json', value: null, expectedValue: null},
       {type: 'date', value: null, expectedValue: null},
       {type: 'raw', value: null, expectedValue: null},
@@ -123,7 +123,7 @@
     ];
     cy.window().then(win => {
       inputValues.forEach(function(input, index, array) {
-        let actualValue = win.swh.save.formatValuePerType(input.type, input.value);
+        const actualValue = win.swh.save.formatValuePerType(input.type, input.value);
         assert.equal(actualValue, input.expectedValue);
       });
     });
@@ -263,7 +263,7 @@
     cy.get('#swh-origin-save-requests-list-tab').click();
     cy.get('tbody tr').then(rows => {
       let i = 0;
-      for (let row of rows) {
+      for (const row of rows) {
         const cells = row.cells;
         const requestDateStr = new Date(this.originSaveJSON.data[i].save_request_date).toLocaleString();
         const saveStatus = this.originSaveJSON.data[i].save_task_status;
@@ -505,7 +505,7 @@
     cy.ambassadorLogin();
     cy.visit(url);
 
-    for (let visitType of anonymousVisitTypes) {
+    for (const visitType of anonymousVisitTypes) {
       cy.get('#swh-input-visit-type').select(visitType);
       cy.get('.swh-save-origin-archives-form').should('not.be.visible');
     }
@@ -517,9 +517,9 @@
   });
 
   it('should be allowed to submit \'archives\' save request when connected as ambassador', function() {
-    let originUrl = 'https://ftp.gnu.org/pub/pub/gnu/3dldf';
-    let artifactUrl = 'https://ftp.gnu.org/pub/pub/gnu/3dldf/3DLDF-1.1.4.tar.gz';
-    let artifactVersion = '1.1.4';
+    const originUrl = 'https://ftp.gnu.org/pub/pub/gnu/3dldf';
+    const artifactUrl = 'https://ftp.gnu.org/pub/pub/gnu/3dldf/3DLDF-1.1.4.tar.gz';
+    const artifactVersion = '1.1.4';
     stubSaveRequest({
       requestUrl: this.Urls.api_1_save_origin('archives', originUrl),
       saveRequestStatus: 'accepted',
@@ -550,11 +550,11 @@
   });
 
   it('should submit multiple artifacts for the archives visit type', function() {
-    let originUrl = 'https://ftp.gnu.org/pub/pub/gnu/3dldf';
-    let artifactUrl = 'https://ftp.gnu.org/pub/pub/gnu/3dldf/3DLDF-1.1.4.tar.gz';
-    let artifactVersion = '1.1.4';
-    let artifact2Url = 'https://ftp.gnu.org/pub/pub/gnu/3dldf/3DLDF-1.1.5.tar.gz';
-    let artifact2Version = '1.1.5';
+    const originUrl = 'https://ftp.gnu.org/pub/pub/gnu/3dldf';
+    const artifactUrl = 'https://ftp.gnu.org/pub/pub/gnu/3dldf/3DLDF-1.1.4.tar.gz';
+    const artifactVersion = '1.1.4';
+    const artifact2Url = 'https://ftp.gnu.org/pub/pub/gnu/3dldf/3DLDF-1.1.5.tar.gz';
+    const artifact2Version = '1.1.5';
 
     cy.ambassadorLogin();
     cy.visit(url);
@@ -629,11 +629,11 @@
   });
 
   it('should autofill artifact version when pasting artifact url', function() {
-    let originUrl = 'https://ftp.gnu.org/pub/pub/gnu/3dldf';
-    let artifactUrl = 'https://ftp.gnu.org/pub/pub/gnu/3dldf/3DLDF-1.1.4.tar.gz';
-    let artifactVersion = '3DLDF-1.1.4';
-    let artifact2Url = 'https://example.org/artifact/test/1.3.0.zip';
-    let artifact2Version = '1.3.0';
+    const originUrl = 'https://ftp.gnu.org/pub/pub/gnu/3dldf';
+    const artifactUrl = 'https://ftp.gnu.org/pub/pub/gnu/3dldf/3DLDF-1.1.4.tar.gz';
+    const artifactVersion = '3DLDF-1.1.4';
+    const artifact2Url = 'https://example.org/artifact/test/1.3.0.zip';
+    const artifact2Version = '1.3.0';
 
     cy.ambassadorLogin();
     cy.visit(url);
@@ -686,9 +686,9 @@
       }));
     }).as('saveRequest');
 
-    for (let originUrl of ['https://github.com/BiC-MnI/MnI_AuToReG',
-                           'https://github.com/BiC-MnI/MnI_AuToReG.git',
-                           'https://github.com/BiC-MnI/MnI_AuToReG/']) {
+    for (const originUrl of ['https://github.com/BiC-MnI/MnI_AuToReG',
+                             'https://github.com/BiC-MnI/MnI_AuToReG.git',
+                             'https://github.com/BiC-MnI/MnI_AuToReG/']) {
 
       // enter non canonical URL of github repo
       cy.get('#swh-input-origin-url')
diff --git a/cypress/integration/origin-search.spec.js b/cypress/integration/origin-search.spec.js
--- a/cypress/integration/origin-search.spec.js
+++ b/cypress/integration/origin-search.spec.js
@@ -133,7 +133,7 @@
     cy.get('#swh-origins-url-patterns')
       .type('http');
 
-    for (let visitType of ['git', 'tar']) {
+    for (const visitType of ['git', 'tar']) {
       cy.get('#swh-search-visit-type')
         .select(visitType);
 
@@ -146,7 +146,7 @@
         .should('be.visible');
 
       cy.get('tbody tr td.swh-origin-visit-type').then(elts => {
-        for (let elt of elts) {
+        for (const elt of elts) {
           cy.get(elt).should('have.text', visitType);
         }
       });
diff --git a/cypress/integration/persistent-identifiers.spec.js b/cypress/integration/persistent-identifiers.spec.js
--- a/cypress/integration/persistent-identifiers.spec.js
+++ b/cypress/integration/persistent-identifiers.spec.js
@@ -109,7 +109,7 @@
     cy.get('.ui-slideouttab-handle')
       .click();
 
-    for (let td of testsData) {
+    for (const td of testsData) {
       cy.get(`a[href="#swhid-tab-${td.objectType}"]`)
         .click();
 
@@ -128,7 +128,7 @@
     cy.get('.ui-slideouttab-handle')
       .click();
 
-    for (let td of testsData) {
+    for (const td of testsData) {
 
       cy.get(`a[href="#swhid-tab-${td.objectType}"]`)
         .click();
@@ -160,7 +160,7 @@
 
     const originBadgeUrl = this.Urls.swh_badge('origin', origin.url);
 
-    for (let td of testsData) {
+    for (const td of testsData) {
       cy.get(`a[href="#swhid-tab-${td.objectType}"]`)
         .click();
 
@@ -179,7 +179,7 @@
     cy.get('.ui-slideouttab-handle')
       .click();
 
-    for (let td of testsData) {
+    for (const td of testsData) {
       cy.get(`a[href="#swhid-tab-${td.objectType}"]`)
         .click();
 
@@ -187,7 +187,7 @@
         .click()
         .wait(500);
 
-      for (let badgeType of ['html', 'md', 'rst']) {
+      for (const badgeType of ['html', 'md', 'rst']) {
         cy.get(`.modal .swh-badge-${badgeType}`)
           .contains(`${urlPrefix}${originBrowseUrl}`)
           .contains(`${urlPrefix}${originBadgeUrl}`);
@@ -201,7 +201,7 @@
         .click()
         .wait(500);
 
-      for (let badgeType of ['html', 'md', 'rst']) {
+      for (const badgeType of ['html', 'md', 'rst']) {
         cy.get(`.modal .swh-badge-${badgeType}`)
           .contains(`${urlPrefix}${td.browseUrl}`)
           .contains(`${urlPrefix}${td.badgeSWHIDUrl}`);
@@ -217,7 +217,7 @@
   it('should be possible to retrieve SWHIDs context from JavaScript', function() {
     cy.window().then(win => {
       const swhIdsContext = win.swh.webapp.getSwhIdsContext();
-      for (let testData of testsData) {
+      for (const testData of testsData) {
         assert.isTrue(swhIdsContext.hasOwnProperty(testData.objectType));
         assert.equal(swhIdsContext[testData.objectType].swhid,
                      testData.objectSWHIDs.slice(-1)[0]);
diff --git a/cypress/integration/revision-diff.spec.js b/cypress/integration/revision-diff.spec.js
--- a/cypress/integration/revision-diff.spec.js
+++ b/cypress/integration/revision-diff.spec.js
@@ -81,12 +81,12 @@
   });
 
   it('should list all files with changes', function() {
-    let files = new Set([]);
-    for (let change of diffData.changes) {
+    const files = new Set([]);
+    for (const change of diffData.changes) {
       files.add(change.from_path);
       files.add(change.to_path);
     }
-    for (let file of files) {
+    for (const file of files) {
       cy.get('#swh-revision-changes-list a')
         .contains(file)
         .should('be.visible');
@@ -115,7 +115,7 @@
   });
 
   it('should have correct links in diff file names', function() {
-    for (let change of diffData.changes) {
+    for (const change of diffData.changes) {
       cy.get(`#swh-revision-changes-list a[href="#diff_${change.id}"`)
         .should('be.visible');
     }
@@ -124,7 +124,7 @@
   it('should load unified diff by default', function() {
     cy.get('#swh-compute-all-diffs')
       .click();
-    for (let change of diffData.changes) {
+    for (const change of diffData.changes) {
       cy.get(`#${change.id}-unified-diff`)
         .should('be.visible');
       cy.get(`#${change.id}-split-diff`)
@@ -148,7 +148,7 @@
     cy.get(`#${diffId} .hljs-ln-line`)
       .then(lines => {
         let inHighlightedRange = false;
-        for (let line of lines) {
+        for (const line of lines) {
           const lnNumber = $(line).data('line-number');
           if (lnNumber === start || lnNumber === end) {
             inHighlightedRange = true;
@@ -183,8 +183,8 @@
         let endLinesStr = swh.revision.formatDiffLineNumbers(diffId, endLines[0], endLines[1]);
 
         // highlight a range of lines
-        let startElt = `#${diffId}-unified-diff .hljs-ln-numbers[data-line-number="${startLinesStr}"]`;
-        let endElt = `#${diffId}-unified-diff .hljs-ln-numbers[data-line-number="${endLinesStr}"]`;
+        const startElt = `#${diffId}-unified-diff .hljs-ln-numbers[data-line-number="${startLinesStr}"]`;
+        const endElt = `#${diffId}-unified-diff .hljs-ln-numbers[data-line-number="${endLinesStr}"]`;
         cy.get(startElt).click();
         cy.get(endElt).click({shiftKey: true});
 
@@ -215,8 +215,8 @@
 
     const diffHighlightingData = diffsHighlightingData['unified'];
     const diffId = diffHighlightingData.diffId;
-    let startLines = diffHighlightingData.startLines;
-    let endLines = diffHighlightingData.endLines;
+    const startLines = diffHighlightingData.startLines;
+    const endLines = diffHighlightingData.endLines;
 
     unifiedDiffHighlightingTest(diffId, startLines, endLines);
 
@@ -226,8 +226,8 @@
 
     const diffHighlightingData = diffsHighlightingData['unified'];
     const diffId = diffHighlightingData.diffId;
-    let startLines = diffHighlightingData.startLines;
-    let endLines = diffHighlightingData.endLines;
+    const startLines = diffHighlightingData.startLines;
+    const endLines = diffHighlightingData.endLines;
 
     unifiedDiffHighlightingTest(diffId, endLines, startLines);
 
@@ -256,8 +256,8 @@
       // before testing diff highlighting
       .then(() => {
         // highlight a range of lines
-        let startElt = `#${singleDiffId} .hljs-ln-numbers[data-line-number="${startLine}"]`;
-        let endElt = `#${singleDiffId} .hljs-ln-numbers[data-line-number="${endLine}"]`;
+        const startElt = `#${singleDiffId} .hljs-ln-numbers[data-line-number="${startLine}"]`;
+        const endElt = `#${singleDiffId} .hljs-ln-numbers[data-line-number="${endLine}"]`;
         cy.get(startElt).click();
         cy.get(endElt).click({shiftKey: true});
 
@@ -288,8 +288,8 @@
   it('should highlight split diff from lines when selecting them from top to bottom', function() {
     const diffHighlightingData = diffsHighlightingData['split-from'];
     const diffId = diffHighlightingData.diffId;
-    let startLines = diffHighlightingData.startLines;
-    let endLines = diffHighlightingData.endLines;
+    const startLines = diffHighlightingData.startLines;
+    const endLines = diffHighlightingData.endLines;
 
     singleSpitDiffHighlightingTest(diffId, startLines, endLines, false);
   });
@@ -297,8 +297,8 @@
   it('should highlight split diff from lines when selecting them from bottom to top', function() {
     const diffHighlightingData = diffsHighlightingData['split-from'];
     const diffId = diffHighlightingData.diffId;
-    let startLines = diffHighlightingData.startLines;
-    let endLines = diffHighlightingData.endLines;
+    const startLines = diffHighlightingData.startLines;
+    const endLines = diffHighlightingData.endLines;
 
     singleSpitDiffHighlightingTest(diffId, endLines, startLines, false);
   });
@@ -306,8 +306,8 @@
   it('should highlight split diff to lines when selecting them from top to bottom', function() {
     const diffHighlightingData = diffsHighlightingData['split-to'];
     const diffId = diffHighlightingData.diffId;
-    let startLines = diffHighlightingData.startLines;
-    let endLines = diffHighlightingData.endLines;
+    const startLines = diffHighlightingData.startLines;
+    const endLines = diffHighlightingData.endLines;
 
     singleSpitDiffHighlightingTest(diffId, startLines, endLines, true);
   });
@@ -316,8 +316,8 @@
 
     const diffHighlightingData = diffsHighlightingData['split-to'];
     const diffId = diffHighlightingData.diffId;
-    let startLines = diffHighlightingData.startLines;
-    let endLines = diffHighlightingData.endLines;
+    const startLines = diffHighlightingData.startLines;
+    const endLines = diffHighlightingData.endLines;
 
     singleSpitDiffHighlightingTest(diffId, endLines, startLines, true);
   });
@@ -441,8 +441,8 @@
   it('should highlight split diff from and to lines when selecting them from top-left to bottom-right', function() {
     const diffHighlightingData = diffsHighlightingData['split-from-top-to-bottom'];
     const diffId = diffHighlightingData.diffId;
-    let startLines = diffHighlightingData.startLines;
-    let endLines = diffHighlightingData.endLines;
+    const startLines = diffHighlightingData.startLines;
+    const endLines = diffHighlightingData.endLines;
 
     splitDiffHighlightingTest(diffId, startLines, endLines);
   });
@@ -450,8 +450,8 @@
   it('should highlight split diff from and to lines when selecting them from bottom-right to top-left', function() {
     const diffHighlightingData = diffsHighlightingData['split-from-top-to-bottom'];
     const diffId = diffHighlightingData.diffId;
-    let startLines = diffHighlightingData.startLines;
-    let endLines = diffHighlightingData.endLines;
+    const startLines = diffHighlightingData.startLines;
+    const endLines = diffHighlightingData.endLines;
 
     splitDiffHighlightingTest(diffId, endLines, startLines);
   });
@@ -459,8 +459,8 @@
   it('should highlight split diff from and to lines when selecting them from top-right to bottom-left', function() {
     const diffHighlightingData = diffsHighlightingData['split-to-top-from-bottom'];
     const diffId = diffHighlightingData.diffId;
-    let startLines = diffHighlightingData.startLines;
-    let endLines = diffHighlightingData.endLines;
+    const startLines = diffHighlightingData.startLines;
+    const endLines = diffHighlightingData.endLines;
 
     splitDiffHighlightingTest(diffId, startLines, endLines);
   });
@@ -468,8 +468,8 @@
   it('should highlight split diff from and to lines when selecting them from bottom-left to top-right', function() {
     const diffHighlightingData = diffsHighlightingData['split-to-top-from-bottom'];
     const diffId = diffHighlightingData.diffId;
-    let startLines = diffHighlightingData.startLines;
-    let endLines = diffHighlightingData.endLines;
+    const startLines = diffHighlightingData.startLines;
+    const endLines = diffHighlightingData.endLines;
 
     splitDiffHighlightingTest(diffId, endLines, startLines);
   });
@@ -482,8 +482,8 @@
       .click();
     const diffHighlightingData = diffsHighlightingData['unified'];
     const diffId = diffHighlightingData.diffId;
-    let startLines = diffHighlightingData.startLines;
-    let endLines = diffHighlightingData.endLines;
+    const startLines = diffHighlightingData.startLines;
+    const endLines = diffHighlightingData.endLines;
 
     unifiedDiffHighlightingTest(diffId, startLines, endLines);
 
diff --git a/cypress/integration/vault.spec.js b/cypress/integration/vault.spec.js
--- a/cypress/integration/vault.spec.js
+++ b/cypress/integration/vault.spec.js
@@ -5,7 +5,7 @@
  * See top-level LICENSE file for more information
  */
 
-let vaultItems = [];
+const vaultItems = [];
 
 const progressbarColors = {
   'new': 'rgba(128, 128, 128, 0.5)',
diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js
--- a/cypress/plugins/index.js
+++ b/cypress/plugins/index.js
@@ -13,8 +13,8 @@
   // produce JSON files prior launching browser in order to dynamically generate tests
   on('before:browser:launch', function(browser, launchOptions) {
     return new Promise((resolve) => {
-      let p1 = axios.get(`${config.baseUrl}/tests/data/content/code/extensions/`);
-      let p2 = axios.get(`${config.baseUrl}/tests/data/content/code/filenames/`);
+      const p1 = axios.get(`${config.baseUrl}/tests/data/content/code/extensions/`);
+      const p2 = axios.get(`${config.baseUrl}/tests/data/content/code/filenames/`);
       Promise.all([p1, p2])
         .then(function(responses) {
           fs.writeFileSync('cypress/fixtures/source-file-extensions.json', JSON.stringify(responses[0].data));
diff --git a/cypress/support/index.js b/cypress/support/index.js
--- a/cypress/support/index.js
+++ b/cypress/support/index.js
@@ -121,7 +121,7 @@
   cy.visit('/').window().then(async win => {
     this.Urls = win.Urls;
 
-    for (let origin of this.origin) {
+    for (const origin of this.origin) {
 
       const metadata = await getMetadataForOrigin(origin.url);
       const directoryApiUrl = this.Urls.api_1_directory(metadata.directory);
@@ -130,7 +130,7 @@
       origin.revisions.push(metadata.revision);
       origin.snapshot = metadata.snapshot;
 
-      for (let content of origin.content) {
+      for (const content of origin.content) {
 
         const contentPathApiUrl = this.Urls.api_1_directory(origin.rootDirectory, content.path);
         const contentMetaData = await httpGetJson(contentPathApiUrl);