diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_appcache.xml b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_appcache.xml
index 0381e5b7ba7a838b7f993d9fb5718787c735dd25..f5d56569e68d10a5c4d1b8dc99555924f85bb60a 100644
--- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_appcache.xml
+++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_appcache.xml
@@ -61,12 +61,6 @@
               </tuple>
             </value>
         </item>
-        <item>
-            <key> <string>categories</string> </key>
-            <value>
-              <tuple/>
-            </value>
-        </item>
         <item>
             <key> <string>content_md5</string> </key>
             <value>
@@ -104,160 +98,9 @@
         <item>
             <key> <string>text_content</string> </key>
             <value> <string>CACHE MANIFEST\n
-# generated on Thu, 07 Jan 2020 00:00:00 GMT+0100\n
-# XXX + fonts\n
-# images/ajax-loader.gif\n
 CACHE:\n
-favicon.ico\n
-font-awesome/font-awesome-webfont.eot\n
-font-awesome/font-awesome-webfont.woff\n
-font-awesome/font-awesome-webfont.woff2\n
-font-awesome/font-awesome-webfont.ttf\n
-font-awesome/font-awesome-webfont.svg\n
-gadget_erp5_worklist_empty.svg?format=svg\n
-erp5_launcher_nojqm.js\n
-gadget_erp5_nojqm.css\n
-gadget_erp5_configure_editor.html\n
-gadget_erp5_configure_editor.js\n
-gadget_erp5_editor_panel.html\n
-gadget_erp5_editor_panel.js\n
-gadget_erp5_field_checkbox.html\n
-gadget_erp5_field_checkbox.js\n
-gadget_erp5_field_datetime.html\n
-gadget_erp5_field_datetime.js\n
-gadget_erp5_field_editor.html\n
-gadget_erp5_field_editor.js\n
-gadget_erp5_field_email.html\n
-gadget_erp5_field_email.js\n
-gadget_erp5_field_file.html\n
-gadget_erp5_field_file.js\n
-gadget_erp5_field_float.html\n
-gadget_erp5_field_float.js\n
-gadget_erp5_field_formbox.html\n
-gadget_erp5_field_formbox.js\n
-gadget_erp5_field_gadget.html\n
-gadget_erp5_field_gadget.js\n
-gadget_erp5_field_image.html\n
-gadget_erp5_field_image.js\n
-gadget_erp5_field_integer.html\n
-gadget_erp5_field_integer.js\n
-gadget_erp5_field_list.html\n
-gadget_erp5_field_list.js\n
-gadget_erp5_field_lines.html\n
-gadget_erp5_field_lines.js\n
-gadget_erp5_field_listbox.html\n
-gadget_erp5_field_listbox.js\n
-gadget_erp5_field_matrixbox.html\n
-gadget_erp5_field_matrixbox.js\n
-gadget_erp5_field_multicheckbox.html\n
-gadget_erp5_field_multicheckbox.js\n
-gadget_erp5_field_multilist.html\n
-gadget_erp5_field_multilist.js\n
-gadget_erp5_field_multirelationstring.html\n
-gadget_erp5_field_multirelationstring.js\n
-gadget_erp5_field_radio.html\n
-gadget_erp5_field_radio.js\n
-gadget_erp5_field_readonly.html\n
-gadget_erp5_field_readonly.js\n
-gadget_erp5_field_relationstring.html\n
-gadget_erp5_field_relationstring.js\n
-gadget_erp5_field_string.html\n
-gadget_erp5_field_string.js\n
-gadget_erp5_field_password.html\n
-gadget_erp5_field_password.js\n
-gadget_erp5_field_textarea.html\n
-gadget_erp5_field_textarea.js\n
-gadget_erp5_form.html\n
-gadget_erp5_form.js\n
-gadget_erp5_header.html\n
-gadget_erp5_header.js\n
-gadget_erp5_jio.html\n
-gadget_erp5_jio.js\n
-gadget_erp5_label_field.html\n
-gadget_erp5_label_field.js\n
-gadget_erp5_notification.html\n
-gadget_erp5_notification.js\n
-gadget_erp5_page_action.html\n
-gadget_erp5_page_action.js\n
-gadget_erp5_page_export.html\n
-gadget_erp5_page_export.js\n
-gadget_erp5_page_form.html\n
-gadget_erp5_page_form.js\n
-gadget_erp5_page_front.html\n
-gadget_erp5_page_front.js\n
-gadget_erp5_page_history.html\n
-gadget_erp5_page_history.js\n
-gadget_erp5_page_jump.html\n
-gadget_erp5_page_jump.js\n
-gadget_erp5_page_language.html\n
-gadget_erp5_page_language.js\n
-gadget_erp5_page_logout.html\n
-gadget_erp5_page_logout.js\n
-gadget_erp5_page_preference.html\n
-gadget_erp5_page_preference.js\n
-gadget_erp5_page_relation_search.html\n
-gadget_erp5_page_relation_search.js\n
-gadget_erp5_page_search.html\n
-gadget_erp5_page_search.js\n
-gadget_erp5_page_tab.html\n
-gadget_erp5_page_tab.js\n
-gadget_erp5_page_worklist.html\n
-gadget_erp5_page_worklist.js\n
-gadget_erp5_panel.html\n
-gadget_erp5_panel.js\n
-gadget_erp5_panel.png?format=png\n
-gadget_erp5_pt_embedded_form_render.html\n
-gadget_erp5_pt_embedded_form_render.js\n
-gadget_erp5_pt_form_dialog.html\n
-gadget_erp5_pt_form_dialog.js\n
-gadget_erp5_pt_form_jump.html\n
-gadget_erp5_pt_form_jump.js\n
-gadget_erp5_pt_form_python_action.html\n
-gadget_erp5_pt_form_python_action.js\n
-gadget_erp5_pt_form_list.html\n
-gadget_erp5_pt_form_list.js\n
-gadget_erp5_pt_form_view.html\n
-gadget_erp5_pt_form_view.js\n
-gadget_erp5_pt_form_view_editable.html\n
-gadget_erp5_pt_form_view_editable.js\n
-gadget_erp5_pt_report_view.html\n
-gadget_erp5_pt_report_view.js\n
-gadget_erp5_router.html\n
-gadget_erp5_router.js\n
-gadget_erp5_relation_input.html\n
-gadget_erp5_relation_input.js\n
-gadget_erp5_search_editor.html\n
-gadget_erp5_search_editor.js\n
-gadget_erp5_searchfield.html\n
-gadget_erp5_searchfield.js\n
-gadget_erp5_sort_editor.html\n
-gadget_erp5_sort_editor.js\n
-gadget_global.js\n
-gadget_html5_element.html\n
-gadget_html5_element.js\n
-gadget_html5_input.html\n
-gadget_html5_input.js\n
-gadget_html5_textarea.html\n
-gadget_html5_textarea.js\n
-gadget_html5_select.html\n
-gadget_html5_select.js\n
-gadget_erp5_global.js\n
-gadget_jio.html\n
-gadget_jio.js\n
-gadget_translation.html\n
-gadget_translation.js\n
-gadget_translation_data.js\n
-gadget_editor.html\n
-gadget_editor.js\n
-gadget_button_maximize.html\n
-gadget_button_maximize.js\n
-handlebars.js\n
-jiodev.js\n
-renderjs.js\n
-rsvp.js\n
 NETWORK:\n
-*\n
-</string> </value>
+*</string> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
@@ -298,6 +141,12 @@ NETWORK:\n
                       <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
                     </value>
                 </item>
+                <item>
+                    <key> <string>processing_status_workflow</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
+                    </value>
+                </item>
               </dictionary>
             </value>
         </item>
@@ -343,7 +192,7 @@ NETWORK:\n
                           </tuple>
                           <state>
                             <tuple>
-                              <float>1465381395.69</float>
+                              <float>1583142612.59</float>
                               <string>UTC</string>
                             </tuple>
                           </state>
@@ -392,7 +241,7 @@ NETWORK:\n
                   </item>
                   <item>
                       <key> <string>serial</string> </key>
-                      <value> <string>981.438.11963.4386</string> </value>
+                      <value> <string>982.16557.65503.30958</string> </value>
                   </item>
                   <item>
                       <key> <string>state</string> </key>
@@ -410,7 +259,70 @@ NETWORK:\n
                           </tuple>
                           <state>
                             <tuple>
-                              <float>1578416140.21</float>
+                              <float>1583142606.91</float>
+                              <string>UTC</string>
+                            </tuple>
+                          </state>
+                        </object>
+                      </value>
+                  </item>
+                </dictionary>
+              </list>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="5" aka="AAAAAAAAAAU=">
+    <pickle>
+      <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_log</string> </key>
+            <value>
+              <list>
+                <dictionary>
+                  <item>
+                      <key> <string>action</string> </key>
+                      <value>
+                        <none/>
+                      </value>
+                  </item>
+                  <item>
+                      <key> <string>actor</string> </key>
+                      <value> <string>zope</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>comment</string> </key>
+                      <value> <string></string> </value>
+                  </item>
+                  <item>
+                      <key> <string>error_message</string> </key>
+                      <value> <string></string> </value>
+                  </item>
+                  <item>
+                      <key> <string>external_processing_state</string> </key>
+                      <value> <string>empty</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>serial</string> </key>
+                      <value> <string>0.0.0.0</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>time</string> </key>
+                      <value>
+                        <object>
+                          <klass>
+                            <global name="DateTime" module="DateTime.DateTime"/>
+                          </klass>
+                          <tuple>
+                            <none/>
+                          </tuple>
+                          <state>
+                            <tuple>
+                              <float>1583142315.66</float>
                               <string>UTC</string>
                             </tuple>
                           </state>
diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_html.html b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_html.html
index 4014392ed3e6332316202ab0acaef9ec5e7e68f2..b33718d68f6d6ff280e20d5ccc12ad0462152393 100644
--- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_html.html
+++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_html.html
@@ -4,7 +4,7 @@
     <meta charset="utf-8">
     <meta name="google" content="notranslate">
     <meta name="viewport" content="width=device-width, initial-scale=1">
-    <link rel="shortcut icon" href="favicon.ico">
+    <link rel="shortcut icon" href="${base_prefix}favicon.ico">
     <meta name="theme-color" content="#085078">
 
     <title>${application_title}</title>
@@ -16,6 +16,7 @@
     ${webapp_manifest_full_link_tag}
 
     <script data-renderjs-configuration="application_title" type="text/x-renderjs-configuration">${application_title}</script>
+    <script data-renderjs-configuration="base_prefix" type="text/x-renderjs-configuration">${base_prefix}</script>
     <script data-renderjs-configuration="panel_gadget" type="text/x-renderjs-configuration">${panel_gadget}</script>
     <script data-renderjs-configuration="action_view" type="text/x-renderjs-configuration">${action_view}</script>
     <script data-renderjs-configuration="default_view_reference" type="text/x-renderjs-configuration">${default_view_reference}</script>
@@ -27,16 +28,16 @@
     <script data-renderjs-configuration="website_url_set" type="text/x-renderjs-configuration">${website_url_set}</script>
     <script data-renderjs-configuration="service_worker_url" type="text/x-renderjs-configuration">${service_worker_url}</script>
 
-    <script src="rsvp.js"></script>
-    <script src="renderjs.js"></script>
-    <script src="erp5_launcher_nojqm.js"></script>
+    <script src="${base_prefix}rsvp.js"></script>
+    <script src="${base_prefix}renderjs.js"></script>
+    <script src="${base_prefix}erp5_launcher_nojqm.js"></script>
 
   </head>
 
   <body>
     <div data-role="page">
 
-      <div data-gadget-url="gadget_jio.html"
+      <div data-gadget-url="${base_prefix}gadget_jio.html"
           data-gadget-scope="setting_gadget"
           data-gadget-sandbox="public"></div>
 
@@ -44,7 +45,7 @@
           data-gadget-scope="router"
           data-gadget-sandbox="public"></div>
 
-      <div data-gadget-async-url="gadget_erp5_notification.html"
+      <div data-gadget-async-url="${base_prefix}gadget_erp5_notification.html"
           data-gadget-scope="notification"
           data-gadget-sandbox="public"></div>
 
@@ -61,7 +62,7 @@
           data-gadget-sandbox="public"></div>
 
 
-      <div data-gadget-async-url="gadget_erp5_editor_panel.html"
+      <div data-gadget-async-url="${base_prefix}gadget_erp5_editor_panel.html"
           data-gadget-scope="editor_panel"
           data-gadget-sandbox="public"></div>
 
diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_html.xml b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_html.xml
index 72e440bfd12ecdf075006a56727dad99ef4dbfb0..c8ec97b0599c6766ece88d4daceebae9d6791f1e 100644
--- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_html.xml
+++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_html.xml
@@ -240,7 +240,7 @@
                   </item>
                   <item>
                       <key> <string>serial</string> </key>
-                      <value> <string>981.59416.23022.53862</string> </value>
+                      <value> <string>981.33187.14689.53538</string> </value>
                   </item>
                   <item>
                       <key> <string>state</string> </key>
@@ -258,7 +258,7 @@
                           </tuple>
                           <state>
                             <tuple>
-                              <float>1581954760.5</float>
+                              <float>1580399803.54</float>
                               <string>UTC</string>
                             </tuple>
                           </state>
diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.js b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.js
index 68f125b92e1792f4583507036266e0c7b101bfab..1e55888b88d409bc5cfe85d80b62aa4e162ad6ce 100644
--- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.js
+++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.js
@@ -10,13 +10,25 @@
   var MAIN_SCOPE = "m",
     default_state_json_string = JSON.stringify({
       panel_visible: false,
+      service_worker_claimed: false,
       setting_id: "setting/" + document.head.querySelector(
         'script[data-renderjs-configuration="application_title"]'
+      ).textContent,
+      base_prefix: document.head.querySelector(
+        'script[data-renderjs-configuration="base_prefix"]'
       ).textContent
     });
 
   function renderMainGadget(gadget, url, options) {
     var page_gadget;
+    if (gadget.state.base_prefix) {
+      // For now, we assume the url is always relative
+      // Until one router starts to return absolute url
+      url = new URL(
+        url,
+        new URL(gadget.state.base_prefix, window.location.href).href
+      ).href;
+    }
     return gadget.declareGadget(url, {
       scope: MAIN_SCOPE
     })
@@ -305,7 +317,8 @@
         throw error;
       })
       .push(function (doc) {
-        for (var key in setting_dict) {
+        var key;
+        for (key in setting_dict) {
           if (setting_dict.hasOwnProperty(key)) {
             if (!doc.hasOwnProperty(key) ||
                 doc[key] !== setting_dict[key]) {
@@ -409,13 +422,7 @@
 
           if (setting.hasOwnProperty('service_worker_url') &&
               (setting.service_worker_url !== '')) {
-            if (navigator.serviceWorker !== undefined) {
-              // Check if a ServiceWorker already controls the site on load
-              if (!navigator.serviceWorker.controller) {
-                // Register the ServiceWorker
-                navigator.serviceWorker.register(setting.service_worker_url);
-              }
-            }
+            gadget.registerServiceWorker(setting.service_worker_url);
           }
 
           return setting_gadget.put(gadget.state.setting_id, setting);
@@ -680,6 +687,18 @@
     .allowPublicAcquisition("renderApplication", function renderApplication(
       param_list
     ) {
+      if (this.state.service_worker_claimed &&
+          (this.state.notification_options === undefined)) {
+        // As a new service worker claimed the client,
+        // reload the page to ensure it uses the lastest gadget versions
+        // Do it only if there is no notification to display
+        return location.reload();
+      }
+      if (this.state.service_worker_registration) {
+        // Mimic service worker update rule
+        // when a navigation to an in-scope page
+        this.deferServiceWorkerUpdate(this.state.service_worker_registration);
+      }
       return this.render.apply(this, param_list);
     })
 
@@ -912,7 +931,76 @@
         wallpaper_url = null;
         wallpaper_absolute_url = null;
       }
-    });
+    })
+
+    /////////////////////////////////////////////////////////////////
+    // Service worker handling
+    /////////////////////////////////////////////////////////////////
+    .declareJob('registerServiceWorker',
+                function registerServiceWorker(service_worker_url) {
+        var gadget = this,
+          is_first_worker,
+          install_delay;
+        if (navigator.serviceWorker !== undefined) {
+          is_first_worker = (navigator.serviceWorker.controller === null);
+          install_delay = is_first_worker ? 20000 : 2000;
+          return RSVP.all([
+            // Delay service worker installation, so that:
+            // * it does not slow down the current page rendering
+            // * it is not triggered too often if user click on multiple links
+            // * it is triggered only if the user browse the site
+            RSVP.delay(install_delay)
+              .then(function () {
+                  // Register the ServiceWorker
+                return navigator.serviceWorker
+                  .register(service_worker_url)
+                  .then(function (registration) {
+                    gadget.state.service_worker_registration = registration;
+                  })
+                  .catch(function (error) {
+                    // If service worker installation is rejected,
+                    // do not prevent the site to be usable, even if slower
+                    console.warn("Service worker registration failed", error);
+                  });
+              }),
+            // Check when a new worker has been activated from another tab
+            // XXX Not promise based, but we do not want to add a new dependency
+            navigator.serviceWorker
+                     .addEventListener('message',
+                                       function handleMessage(event) {
+                  if (event.data === 'claim') {
+                    if (is_first_worker) {
+                      // Do not reload if the worker is created after the page
+                      // is loaded, because they probably use the same
+                      // gadgets
+                      is_first_worker = false;
+                    } else {
+                      gadget.state.service_worker_claimed = true;
+                    }
+                  }
+                })
+          ]);
+        }
+      })
+    .declareJob('deferServiceWorkerUpdate',
+                function deferServiceWorkerUpdate(registration) {
+        return new RSVP.Queue()
+          .push(function () {
+            // Delay service worker update, so that:
+            // * it does not slow down the current page rendering
+            // * it is not triggered too often if user click on multiple links
+            // * it is triggered only if the user browse the site
+            return RSVP.delay(20000);
+          })
+          .push(function () {
+            return registration
+              .update()
+              .catch(function (error) {
+                console.warn("Service worker update failed", error);
+              });
+          });
+      });
+
 
 }(window, document, RSVP, rJS,
   XMLHttpRequest, location, console, navigator, Event, URL));
\ No newline at end of file
diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.xml b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.xml
index 2c77f5f2fba9bd142c4c89b6403161a5403c54aa..7378751fbac21165d169d587af0bb026c81ac1fc 100644
--- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.xml
+++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.xml
@@ -234,7 +234,7 @@
                   </item>
                   <item>
                       <key> <string>serial</string> </key>
-                      <value> <string>980.43952.30132.41164</string> </value>
+                      <value> <string>981.63449.54271.9625</string> </value>
                   </item>
                   <item>
                       <key> <string>state</string> </key>
@@ -252,7 +252,7 @@
                           </tuple>
                           <state>
                             <tuple>
-                              <float>1577760448.33</float>
+                              <float>1582196761.8</float>
                               <string>UTC</string>
                             </tuple>
                           </state>
diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_serviceworker.js b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_serviceworker.js
index 18cc8104de0d8dbc75d00f15ae733c9c7a5707c6..0cbf7ace75013cf088af95ba046f3ba9a164e613 100644
--- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_serviceworker.js
+++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_serviceworker.js
@@ -1,149 +1,86 @@
 /*jslint indent: 2*/
-/*global self, caches, fetch*/
-(function (self, caches, fetch) {
+/*global self, caches, fetch, Promise, URL, location, JSON*/
+(function (self, caches, fetch, Promise, URL, location, JSON) {
   "use strict";
 
-  var CACHE_NAME = 'Thu, 12 July 2016 12:00:00 GMT',
-    // Files required to make this app work offline
-    REQUIRED_FILES = [
-      './',
-      'https://netdna.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css',
-      'https://netdna.bootstrapcdn.com/font-awesome/4.2.0/fonts/fontawesome-webfont.eot?v=4.2.0',
-      'https://netdna.bootstrapcdn.com/font-awesome/4.2.0/fonts/fontawesome-webfont.eot?#iefix&v=4.2.0',
-      'https://netdna.bootstrapcdn.com/font-awesome/4.2.0/fonts/fontawesome-webfont.woff?v=4.2.0',
-      'https://netdna.bootstrapcdn.com/font-awesome/4.2.0/fonts/fontawesome-webfont.ttf?v=4.2.0',
-      'https://netdna.bootstrapcdn.com/font-awesome/4.2.0/fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular',
-      'URI.js',
-      'erp5_launcher.js',
-      'gadget_erp5.css',
-      'gadget_erp5_editor_panel.html',
-      'gadget_erp5_editor_panel.js',
-      'gadget_erp5_field_checkbox.html',
-      'gadget_erp5_field_checkbox.js',
-      'gadget_erp5_field_datetime.html',
-      'gadget_erp5_field_datetime.js',
-      'gadget_erp5_field_email.html',
-      'gadget_erp5_field_email.js',
-      'gadget_erp5_field_file.html',
-      'gadget_erp5_field_file.js',
-      'gadget_erp5_field_float.html',
-      'gadget_erp5_field_float.js',
-      'gadget_erp5_field_gadget.html',
-      'gadget_erp5_field_gadget.js',
-      'gadget_erp5_field_image.html',
-      'gadget_erp5_field_image.js',
-      'gadget_erp5_field_integer.html',
-      'gadget_erp5_field_integer.js',
-      'gadget_erp5_field_list.html',
-      'gadget_erp5_field_list.js',
-      'gadget_erp5_field_listbox.html',
-      'gadget_erp5_field_listbox.js',
-      'gadget_erp5_field_multicheckbox.html',
-      'gadget_erp5_field_multicheckbox.js',
-      'gadget_erp5_field_multilist.html',
-      'gadget_erp5_field_multilist.js',
-      'gadget_erp5_field_multirelationstring.html',
-      'gadget_erp5_field_multirelationstring.js',
-      'gadget_erp5_field_radio.html',
-      'gadget_erp5_field_radio.js',
-      'gadget_erp5_field_readonly.html',
-      'gadget_erp5_field_readonly.js',
-      'gadget_erp5_field_relationstring.html',
-      'gadget_erp5_field_relationstring.js',
-      'gadget_erp5_field_string.html',
-      'gadget_erp5_field_string.js',
-      'gadget_erp5_field_password.html',
-      'gadget_erp5_field_password.js',
-      'gadget_erp5_field_textarea.html',
-      'gadget_erp5_field_textarea.js',
-      'gadget_erp5_form.html',
-      'gadget_erp5_form.js',
-      'gadget_erp5_header.html',
-      'gadget_erp5_header.js',
-      'gadget_erp5_jio.html',
-      'gadget_erp5_jio.js',
-      'gadget_erp5_page_action.html',
-      'gadget_erp5_page_action.js',
-      'gadget_erp5_page_form.html',
-      'gadget_erp5_page_form.js',
-      'gadget_erp5_page_front.html',
-      'gadget_erp5_page_front.js',
-      'gadget_erp5_page_history.html',
-      'gadget_erp5_page_history.js',
-      'gadget_erp5_page_jump.html',
-      'gadget_erp5_page_jump.js',
-      'gadget_erp5_page_logout.html',
-      'gadget_erp5_page_logout.js',
-      'gadget_erp5_page_preference.html',
-      'gadget_erp5_page_preference.js',
-      'gadget_erp5_page_relation_search.html',
-      'gadget_erp5_page_relation_search.js',
-      'gadget_erp5_page_search.html',
-      'gadget_erp5_page_search.js',
-      'gadget_erp5_page_tab.html',
-      'gadget_erp5_page_tab.js',
-      'gadget_erp5_page_worklist.html',
-      'gadget_erp5_page_worklist.js',
-      'gadget_erp5_panel.html',
-      'gadget_erp5_panel.js',
-      'gadget_erp5_pt_form_dialog.html',
-      'gadget_erp5_pt_form_dialog.js',
-      'gadget_erp5_pt_form_list.html',
-      'gadget_erp5_pt_form_list.js',
-      'gadget_erp5_pt_form_view.html',
-      'gadget_erp5_pt_form_view.js',
-      'gadget_erp5_pt_form_view_editable.html',
-      'gadget_erp5_pt_form_view_editable.js',
-      'gadget_erp5_pt_report_view.html',
-      'gadget_erp5_pt_report_view.js',
-      'gadget_erp5_router.html',
-      'gadget_erp5_router.js',
-      'gadget_erp5_relation_input.html',
-      'gadget_erp5_relation_input.js',
-      'gadget_erp5_search_editor.html',
-      'gadget_erp5_search_editor.js',
-      'gadget_erp5_searchfield.html',
-      'gadget_erp5_searchfield.js',
-      'gadget_erp5_sort_editor.html',
-      'gadget_erp5_sort_editor.js',
-      'gadget_global.js',
-      'gadget_erp5_global.js',
-      'gadget_jio.html',
-      'gadget_jio.js',
-      'gadget_translation.html',
-      'gadget_translation.js',
-      'gadget_translation_data.js',
-      'handlebars.js',
-      'i18next.js',
-      'jiodev.js',
-      'renderjs.js',
-      'rsvp.js'
-    ];
+  var prefix = location.toString() + '_',
+    CACHE_NAME = prefix + '${modification_date}',
+    REQUIRED_FILES = JSON.parse('${required_url_list}'),
+    required_url_list = [],
+    i,
+    len = REQUIRED_FILES.length;
+
+  for (i = 0; i < len; i += 1) {
+    required_url_list.push(
+      new URL(REQUIRED_FILES[i], location.toString()).toString()
+    );
+  }
 
   self.addEventListener('install', function (event) {
     // Perform install step:  loading each required file into cache
     event.waitUntil(
       caches.open(CACHE_NAME)
         .then(function (cache) {
-          // Add all offline dependencies to the cache
-          return cache.addAll(REQUIRED_FILES);
+          var promise = Promise.resolve();
+
+          function append(url_to_cache) {
+            promise = promise
+              .then(function () {
+                // Use cache.add because safari does not support cache.addAll.
+                return cache.add(url_to_cache);
+              });
+          }
+
+          len = required_url_list.length;
+          for (i = 0; i < len; i += 1) {
+            // Add all offline dependencies to the cache
+            // One by one, to not hammer zopes
+            append(required_url_list[i]);
+          }
+          return promise;
         })
         .then(function () {
-          // At this point everything has been cached
+          // When user accesses ERP5JS web site first time, service worker is
+          // installed but it is not activated yet, service worker is activated
+          // when the page is refreshed or when a new tab opens the site again.
+          // If user does not refresh the page and continue to use the site,
+          // user can't use cache, so everything becomes slow. We must avoid this
+          // situation.
+          // So, we want to activate the new service worker immediately if it was
+          // the first one.
           return self.skipWaiting();
         })
+        .catch(function (error) {
+          // Since we do not allow to override existing cache, if cache installation
+          // failed, we need to delete the cache completely.
+          caches.delete(CACHE_NAME);
+          throw error;
+        })
     );
   });
 
   self.addEventListener('fetch', function (event) {
-    event.respondWith(
-      caches.match(event.request)
+    var url = new URL(event.request.url);
+    url.hash = '';
+    if ((event.request.method !== 'GET') ||
+        (required_url_list.indexOf(url.toString()) === -1)) {
+      // Try not to use the untrustable fetch function
+      // It can only be skip synchronously
+      return;
+    }
+    return event.respondWith(
+      caches.open(CACHE_NAME)
+        .then(function (cache) {
+          // Don't give request object itself. Firefox's Cache Storage
+          // does not work properly when VARY contains Accept-Language.
+          // Give URL string instead, then cache.match works on both Firefox and Chrome.
+          return cache.match(event.request.url);
+        })
         .then(function (response) {
           // Cache hit - return the response from the cached version
           if (response) {
             return response;
           }
-
           // Not in cache - return the result from the live server
           // `fetch` is essentially a "fallback"
           return fetch(event.request);
@@ -168,7 +105,8 @@
               .filter(function (key) {
                 // Filter by keys that don't start with the latest version prefix.
                 // return !key.startsWith(version);
-                return key !== CACHE_NAME;
+                return ((key !== CACHE_NAME) &&
+                        key.startsWith(prefix));
               })
               .map(function (key) {
                 /* Return a promise that's fulfilled
@@ -179,11 +117,21 @@
           );
         })
         .then(function () {
-          self.clients.claim();
+          return self.clients.claim();
+        })
+        .then(function () {
+          return self.clients.matchAll();
+        })
+        .then(function (client_list) {
+          // Notify all clients that they can reload the page
+          var j,
+            client_len = client_list.length;
+          for (j = 0; j < client_len; j += 1) {
+            client_list[j].postMessage('claim');
+          }
+
         })
     );
   });
 
-
-
-}(self, caches, fetch));
+}(self, caches, fetch, Promise, URL, location, JSON));
\ No newline at end of file
diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_serviceworker.xml b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_serviceworker.xml
index 1bf7499acccb10b8c48c8672b04b4b51f0d9795b..7e277c185246b8c3926a5987bb8130ea194e5bdd 100644
--- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_serviceworker.xml
+++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_serviceworker.xml
@@ -95,6 +95,10 @@
               <none/>
             </value>
         </item>
+        <item>
+            <key> <string>text_content_substitution_mapping_method_id</string> </key>
+            <value> <string>WebPage_getRenderJSSubstitutionMappingDict</string> </value>
+        </item>
         <item>
             <key> <string>title</string> </key>
             <value> <string>ERP5 ServiceWorker</string> </value>
@@ -148,171 +152,183 @@
   </record>
   <record id="3" aka="AAAAAAAAAAM=">
     <pickle>
-      <global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
+      <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
     </pickle>
     <pickle>
-      <tuple>
-        <none/>
-        <list>
-          <dictionary>
-            <item>
-                <key> <string>action</string> </key>
-                <value> <string>publish_alive</string> </value>
-            </item>
-            <item>
-                <key> <string>actor</string> </key>
-                <value> <string>zope</string> </value>
-            </item>
-            <item>
-                <key> <string>comment</string> </key>
-                <value> <string></string> </value>
-            </item>
-            <item>
-                <key> <string>error_message</string> </key>
-                <value> <string></string> </value>
-            </item>
-            <item>
-                <key> <string>time</string> </key>
-                <value>
-                  <object>
-                    <klass>
-                      <global name="DateTime" module="DateTime.DateTime"/>
-                    </klass>
-                    <tuple>
-                      <none/>
-                    </tuple>
-                    <state>
-                      <tuple>
-                        <float>1458658259.73</float>
-                        <string>UTC</string>
-                      </tuple>
-                    </state>
-                  </object>
-                </value>
-            </item>
-            <item>
-                <key> <string>validation_state</string> </key>
-                <value> <string>published_alive</string> </value>
-            </item>
-          </dictionary>
-        </list>
-      </tuple>
+      <dictionary>
+        <item>
+            <key> <string>_log</string> </key>
+            <value>
+              <list>
+                <dictionary>
+                  <item>
+                      <key> <string>action</string> </key>
+                      <value> <string>publish_alive</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>actor</string> </key>
+                      <value> <string>zope</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>comment</string> </key>
+                      <value> <string></string> </value>
+                  </item>
+                  <item>
+                      <key> <string>error_message</string> </key>
+                      <value> <string></string> </value>
+                  </item>
+                  <item>
+                      <key> <string>time</string> </key>
+                      <value>
+                        <object>
+                          <klass>
+                            <global name="DateTime" module="DateTime.DateTime"/>
+                          </klass>
+                          <tuple>
+                            <none/>
+                          </tuple>
+                          <state>
+                            <tuple>
+                              <float>1458658259.73</float>
+                              <string>UTC</string>
+                            </tuple>
+                          </state>
+                        </object>
+                      </value>
+                  </item>
+                  <item>
+                      <key> <string>validation_state</string> </key>
+                      <value> <string>published_alive</string> </value>
+                  </item>
+                </dictionary>
+              </list>
+            </value>
+        </item>
+      </dictionary>
     </pickle>
   </record>
   <record id="4" aka="AAAAAAAAAAQ=">
     <pickle>
-      <global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
+      <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
     </pickle>
     <pickle>
-      <tuple>
-        <none/>
-        <list>
-          <dictionary>
-            <item>
-                <key> <string>action</string> </key>
-                <value> <string>edit</string> </value>
-            </item>
-            <item>
-                <key> <string>actor</string> </key>
-                <value> <string>zope</string> </value>
-            </item>
-            <item>
-                <key> <string>comment</string> </key>
-                <value>
-                  <none/>
-                </value>
-            </item>
-            <item>
-                <key> <string>error_message</string> </key>
-                <value> <string></string> </value>
-            </item>
-            <item>
-                <key> <string>serial</string> </key>
-                <value> <string>952.5891.40125.8465</string> </value>
-            </item>
-            <item>
-                <key> <string>state</string> </key>
-                <value> <string>current</string> </value>
-            </item>
-            <item>
-                <key> <string>time</string> </key>
-                <value>
-                  <object>
-                    <klass>
-                      <global name="DateTime" module="DateTime.DateTime"/>
-                    </klass>
-                    <tuple>
-                      <none/>
-                    </tuple>
-                    <state>
-                      <tuple>
-                        <float>1467035757.8</float>
-                        <string>UTC</string>
-                      </tuple>
-                    </state>
-                  </object>
-                </value>
-            </item>
-          </dictionary>
-        </list>
-      </tuple>
+      <dictionary>
+        <item>
+            <key> <string>_log</string> </key>
+            <value>
+              <list>
+                <dictionary>
+                  <item>
+                      <key> <string>action</string> </key>
+                      <value> <string>edit</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>actor</string> </key>
+                      <value> <string>zope</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>comment</string> </key>
+                      <value>
+                        <none/>
+                      </value>
+                  </item>
+                  <item>
+                      <key> <string>error_message</string> </key>
+                      <value> <string></string> </value>
+                  </item>
+                  <item>
+                      <key> <string>serial</string> </key>
+                      <value> <string>981.50754.31879.22749</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>state</string> </key>
+                      <value> <string>current</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>time</string> </key>
+                      <value>
+                        <object>
+                          <klass>
+                            <global name="DateTime" module="DateTime.DateTime"/>
+                          </klass>
+                          <tuple>
+                            <none/>
+                          </tuple>
+                          <state>
+                            <tuple>
+                              <float>1581435049.45</float>
+                              <string>UTC</string>
+                            </tuple>
+                          </state>
+                        </object>
+                      </value>
+                  </item>
+                </dictionary>
+              </list>
+            </value>
+        </item>
+      </dictionary>
     </pickle>
   </record>
   <record id="5" aka="AAAAAAAAAAU=">
     <pickle>
-      <global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
+      <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
     </pickle>
     <pickle>
-      <tuple>
-        <none/>
-        <list>
-          <dictionary>
-            <item>
-                <key> <string>action</string> </key>
-                <value> <string>detect_converted_file</string> </value>
-            </item>
-            <item>
-                <key> <string>actor</string> </key>
-                <value> <string>zope</string> </value>
-            </item>
-            <item>
-                <key> <string>comment</string> </key>
-                <value> <string></string> </value>
-            </item>
-            <item>
-                <key> <string>error_message</string> </key>
-                <value> <string></string> </value>
-            </item>
-            <item>
-                <key> <string>external_processing_state</string> </key>
-                <value> <string>converted</string> </value>
-            </item>
-            <item>
-                <key> <string>serial</string> </key>
-                <value> <string>0.0.0.0</string> </value>
-            </item>
-            <item>
-                <key> <string>time</string> </key>
-                <value>
-                  <object>
-                    <klass>
-                      <global name="DateTime" module="DateTime.DateTime"/>
-                    </klass>
-                    <tuple>
-                      <none/>
-                    </tuple>
-                    <state>
-                      <tuple>
-                        <float>1458654672.71</float>
-                        <string>UTC</string>
-                      </tuple>
-                    </state>
-                  </object>
-                </value>
-            </item>
-          </dictionary>
-        </list>
-      </tuple>
+      <dictionary>
+        <item>
+            <key> <string>_log</string> </key>
+            <value>
+              <list>
+                <dictionary>
+                  <item>
+                      <key> <string>action</string> </key>
+                      <value> <string>detect_converted_file</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>actor</string> </key>
+                      <value> <string>zope</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>comment</string> </key>
+                      <value> <string></string> </value>
+                  </item>
+                  <item>
+                      <key> <string>error_message</string> </key>
+                      <value> <string></string> </value>
+                  </item>
+                  <item>
+                      <key> <string>external_processing_state</string> </key>
+                      <value> <string>converted</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>serial</string> </key>
+                      <value> <string>0.0.0.0</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>time</string> </key>
+                      <value>
+                        <object>
+                          <klass>
+                            <global name="DateTime" module="DateTime.DateTime"/>
+                          </klass>
+                          <tuple>
+                            <none/>
+                          </tuple>
+                          <state>
+                            <tuple>
+                              <float>1458654672.71</float>
+                              <string>UTC</string>
+                            </tuple>
+                          </state>
+                        </object>
+                      </value>
+                  </item>
+                </dictionary>
+              </list>
+            </value>
+        </item>
+      </dictionary>
     </pickle>
   </record>
 </ZopeData>
diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_site_module/renderjs_runner.xml b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_site_module/renderjs_runner.xml
index a611df1bbd44e27a8a9694979123e196bf3bc0f1..8baccec07c75c3da1a6a196c578f819e98b427fa 100644
--- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_site_module/renderjs_runner.xml
+++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_site_module/renderjs_runner.xml
@@ -279,6 +279,16 @@
                       <value> <string>string</string> </value>
                   </item>
                 </dictionary>
+                <dictionary>
+                  <item>
+                      <key> <string>id</string> </key>
+                      <value> <string>configuration_service_worker_url</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>type</string> </key>
+                      <value> <string>string</string> </value>
+                  </item>
+                </dictionary>
               </tuple>
             </value>
         </item>
@@ -353,12 +363,18 @@
         </item>
         <item>
             <key> <string>configuration_manifest_url</string> </key>
-            <value> <string>gadget_erp5.appcache</string> </value>
+            <value>
+              <none/>
+            </value>
         </item>
         <item>
             <key> <string>configuration_panel_gadget_url</string> </key>
             <value> <string>gadget_erp5_panel.html</string> </value>
         </item>
+        <item>
+            <key> <string>configuration_service_worker_url</string> </key>
+            <value> <string>gadget_erp5_serviceworker.js</string> </value>
+        </item>
         <item>
             <key> <string>configuration_translation_gadget_url</string> </key>
             <value> <string>gadget_translation.html</string> </value>
@@ -600,7 +616,7 @@
             </item>
             <item>
                 <key> <string>serial</string> </key>
-                <value> <string>965.19244.13768.6758</string> </value>
+                <value> <string>973.33482.4166.8669</string> </value>
             </item>
             <item>
                 <key> <string>state</string> </key>
@@ -618,7 +634,7 @@
                     </tuple>
                     <state>
                       <tuple>
-                        <float>1517843997.55</float>
+                        <float>1553593373.77</float>
                         <string>UTC</string>
                       </tuple>
                     </state>
diff --git a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_createTranslateData.py b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_createTranslateData.py
index 4e31b799d0e03ae9e303857745848c1edb1d09c3..99b4e1f953add7a18b1e2d55c07b05b38a99ab3f 100644
--- a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_createTranslateData.py
+++ b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_createTranslateData.py
@@ -10,7 +10,7 @@ attribute_filter_re = re.compile(r"""(data-i18n)=["']?((?:.(?!["']?\s+(?:\S+)=|[
 translate_word = []
 
 for web_page in portal.web_page_module.searchFolder(portal_type='Web Page',
-                                                    reference=context.Base_getListFileFromAppcache(only_html=1)):
+                                                    reference=context.Base_getTranslationSourceFileList(only_html=1)):
   data = attribute_filter_re.findall(web_page.getTextContent())
   for attribute in data:
     a = re.sub(r'[{|}]', "", attribute[1])
@@ -45,6 +45,9 @@ content += ";\n}(window));"
 translation_data_file=context.web_page_module.searchFolder(portal_type='Web Script',reference=translation_data_file)[0]
 translation_data_file.edit(text_content = content)
 
+# Edit web section modification date
+context.edit()
+
 if batch_mode:
   return 'done'
 return context.Base_redirect('view', keep_items=dict(portal_status_message=Base_translateString("Translation Data Create")))
diff --git a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_getTranslationSourceFileList.py b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_getTranslationSourceFileList.py
new file mode 100644
index 0000000000000000000000000000000000000000..4d1c55ac57a11607f58a99f15fff1abb82473a9f
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_getTranslationSourceFileList.py
@@ -0,0 +1,15 @@
+filename_list = context.WebSection_getPrecacheManifest()
+
+file_list = []
+translation_data_file = []
+for filename in filename_list:
+  if filename.endswith('.html'):
+    file_list.append(filename)
+    continue
+
+  if filename.endswith('.js') and not only_html:
+    if filename.endswith('translation_data.js'):
+      translation_data_file = [filename]
+      continue
+    file_list.append(filename)
+return translation_data_file + file_list
diff --git a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_getTranslationSourceFileList.xml b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_getTranslationSourceFileList.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3240f07cc5fded60945af1770a9d612e060fcbcc
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_getTranslationSourceFileList.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>Script_magic</string> </key>
+            <value> <int>3</int> </value>
+        </item>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_container</string> </key>
+                                <value> <string>container</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_context</string> </key>
+                                <value> <string>context</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_m_self</string> </key>
+                                <value> <string>script</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_params</string> </key>
+            <value> <string>only_html=0</string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>Base_getTranslationSourceFileList</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSection_getPrecacheManifest.py b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSection_getPrecacheManifest.py
new file mode 100644
index 0000000000000000000000000000000000000000..04bd3e8040855b91889405c3c27566551684ee5a
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSection_getPrecacheManifest.py
@@ -0,0 +1,185 @@
+web_section = context
+
+# Add all ERP5JS gadget
+url_list = [
+  'favicon.ico',
+  'font-awesome/font-awesome-webfont.eot',
+  'font-awesome/font-awesome-webfont.woff',
+  'font-awesome/font-awesome-webfont.woff2',
+  'font-awesome/font-awesome-webfont.ttf',
+  'font-awesome/font-awesome-webfont.svg',
+  'gadget_erp5_worklist_empty.svg?format=svg',
+  'erp5_launcher_nojqm.js',
+  'gadget_erp5_nojqm.css',
+  'gadget_erp5_configure_editor.html',
+  'gadget_erp5_configure_editor.js',
+  'gadget_erp5_editor_panel.html',
+  'gadget_erp5_editor_panel.js',
+  'gadget_erp5_field_checkbox.html',
+  'gadget_erp5_field_checkbox.js',
+  'gadget_erp5_field_datetime.html',
+  'gadget_erp5_field_datetime.js',
+  'gadget_erp5_field_editor.html',
+  'gadget_erp5_field_editor.js',
+  'gadget_erp5_field_email.html',
+  'gadget_erp5_field_email.js',
+  'gadget_erp5_field_file.html',
+  'gadget_erp5_field_file.js',
+  'gadget_erp5_field_float.html',
+  'gadget_erp5_field_float.js',
+  'gadget_erp5_field_formbox.html',
+  'gadget_erp5_field_formbox.js',
+  'gadget_erp5_field_gadget.html',
+  'gadget_erp5_field_gadget.js',
+  'gadget_erp5_field_image.html',
+  'gadget_erp5_field_image.js',
+  'gadget_erp5_field_integer.html',
+  'gadget_erp5_field_integer.js',
+  'gadget_erp5_field_list.html',
+  'gadget_erp5_field_list.js',
+  'gadget_erp5_field_lines.html',
+  'gadget_erp5_field_lines.js',
+  'gadget_erp5_field_listbox.html',
+  'gadget_erp5_field_listbox.js',
+  'gadget_erp5_field_matrixbox.html',
+  'gadget_erp5_field_matrixbox.js',
+  'gadget_erp5_field_multicheckbox.html',
+  'gadget_erp5_field_multicheckbox.js',
+  'gadget_erp5_field_multilist.html',
+  'gadget_erp5_field_multilist.js',
+  'gadget_erp5_field_multirelationstring.html',
+  'gadget_erp5_field_multirelationstring.js',
+  'gadget_erp5_field_radio.html',
+  'gadget_erp5_field_radio.js',
+  'gadget_erp5_field_readonly.html',
+  'gadget_erp5_field_readonly.js',
+  'gadget_erp5_field_relationstring.html',
+  'gadget_erp5_field_relationstring.js',
+  'gadget_erp5_field_string.html',
+  'gadget_erp5_field_string.js',
+  'gadget_erp5_field_password.html',
+  'gadget_erp5_field_password.js',
+  'gadget_erp5_field_textarea.html',
+  'gadget_erp5_field_textarea.js',
+  'gadget_erp5_form.html',
+  'gadget_erp5_form.js',
+  'gadget_erp5_header.html',
+  # 'gadget_erp5_header.js',
+  'gadget_erp5_jio.html',
+  'gadget_erp5_jio.js',
+  'gadget_erp5_label_field.html',
+  'gadget_erp5_label_field.js',
+  'gadget_erp5_notification.html',
+  'gadget_erp5_notification.js',
+  'gadget_erp5_page_action.html',
+  'gadget_erp5_page_action.js',
+  'gadget_erp5_page_export.html',
+  'gadget_erp5_page_export.js',
+  'gadget_erp5_page_form.html',
+  'gadget_erp5_page_form.js',
+  'gadget_erp5_page_front.html',
+  'gadget_erp5_page_front.js',
+  'gadget_erp5_page_history.html',
+  'gadget_erp5_page_history.js',
+  'gadget_erp5_page_jump.html',
+  'gadget_erp5_page_jump.js',
+  'gadget_erp5_page_language.html',
+  'gadget_erp5_page_language.js',
+  'gadget_erp5_page_logout.html',
+  'gadget_erp5_page_logout.js',
+  'gadget_erp5_page_preference.html',
+  'gadget_erp5_page_preference.js',
+  'gadget_erp5_page_relation_search.html',
+  'gadget_erp5_page_relation_search.js',
+  'gadget_erp5_page_search.html',
+  'gadget_erp5_page_search.js',
+  'gadget_erp5_page_tab.html',
+  'gadget_erp5_page_tab.js',
+  'gadget_erp5_page_worklist.html',
+  'gadget_erp5_page_worklist.js',
+  'gadget_erp5_panel.html',
+  'gadget_erp5_panel.js',
+  'gadget_erp5_panel.png?format=png',
+  'gadget_erp5_pt_embedded_form_render.html',
+  'gadget_erp5_pt_embedded_form_render.js',
+  'gadget_erp5_pt_form_dialog.html',
+  'gadget_erp5_pt_form_dialog.js',
+  'gadget_erp5_pt_form_jump.html',
+  'gadget_erp5_pt_form_jump.js',
+  'gadget_erp5_pt_form_list.html',
+  'gadget_erp5_pt_form_list.js',
+  'gadget_erp5_pt_form_python_action.html',
+  'gadget_erp5_pt_form_python_action.js',
+  'gadget_erp5_pt_form_view.html',
+  'gadget_erp5_pt_form_view.js',
+  'gadget_erp5_pt_form_view_editable.html',
+  'gadget_erp5_pt_form_view_editable.js',
+  'gadget_erp5_pt_report_view.html',
+  'gadget_erp5_pt_report_view.js',
+  'gadget_erp5_router.html',
+  'gadget_erp5_router.js',
+  'gadget_erp5_relation_input.html',
+  'gadget_erp5_relation_input.js',
+  'gadget_erp5_search_editor.html',
+  'gadget_erp5_search_editor.js',
+  'gadget_erp5_searchfield.html',
+  'gadget_erp5_searchfield.js',
+  'gadget_erp5_sort_editor.html',
+  'gadget_erp5_sort_editor.js',
+  'gadget_global.js',
+  'gadget_html5_element.html',
+  'gadget_html5_element.js',
+  'gadget_html5_input.html',
+  'gadget_html5_input.js',
+  'gadget_html5_textarea.html',
+  'gadget_html5_textarea.js',
+  'gadget_html5_select.html',
+  'gadget_html5_select.js',
+  'gadget_erp5_global.js',
+  'gadget_jio.html',
+  'gadget_jio.js',
+  'gadget_translation.html',
+  'gadget_translation.js',
+  'gadget_translation_data.js',
+  'gadget_editor.html',
+  'gadget_editor.js',
+  'gadget_button_maximize.html',
+  'gadget_button_maximize.js',
+  'domsugar.js',
+  'jiodev.js',
+  'renderjs.js',
+  'rsvp.js',
+]
+
+# Add all root gadgets
+default_url = './'
+available_language_set = web_section.getLayoutProperty("available_language_set", default=['en'])
+default_language = web_section.getLayoutProperty("default_available_language", default='en')
+for language in available_language_set:
+  if language == default_language:
+    url_list.append(default_url)
+  else:
+    url_list.append('%s/' % language)
+
+# Add all custom gadgets
+url_list.extend([
+  web_section.getLayoutProperty("configuration_wallpaper_url", default=default_url),
+  web_section.getLayoutProperty("configuration_panel_gadget_url", default=default_url),
+  web_section.getLayoutProperty("configuration_router_gadget_url", default=default_url),
+  web_section.getLayoutProperty("configuration_header_gadget_url", default=default_url),
+  web_section.getLayoutProperty("configuration_jio_gadget_url", default=default_url),
+  web_section.getLayoutProperty("configuration_translation_gadget_url", default=default_url),
+  web_section.getLayoutProperty("configuration_stylesheet_url", default=default_url),
+])
+
+# Add all extra dependencies
+precache_manifest_url_list = web_section.getLayoutProperty("configuration_precache_manifest_script_list", default='').splitlines()
+for precache_manifest_script_id in precache_manifest_url_list:
+  url_list.extend(web_section.restrictedTraverse(precache_manifest_script_id)())
+
+if REQUEST is not None:
+  import json
+  REQUEST.RESPONSE.setHeader('Content-Type', 'application/json')
+  return json.dumps(dict.fromkeys(url_list), indent=2)
+
+return list(set(url_list))
diff --git a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSection_getPrecacheManifest.xml b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSection_getPrecacheManifest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5777d61ab7c1721bc7f74a343ef17bc6327f35e2
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSection_getPrecacheManifest.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>Script_magic</string> </key>
+            <value> <int>3</int> </value>
+        </item>
+        <item>
+            <key> <string>_Cacheable__manager_id</string> </key>
+            <value> <string>must_revalidate_http_cache</string> </value>
+        </item>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_container</string> </key>
+                                <value> <string>container</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_context</string> </key>
+                                <value> <string>context</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_m_self</string> </key>
+                                <value> <string>script</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_params</string> </key>
+            <value> <string>REQUEST=None</string> </value>
+        </item>
+        <item>
+            <key> <string>_proxy_roles</string> </key>
+            <value>
+              <tuple>
+                <string>Anonymous</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>WebSection_getPrecacheManifest</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSection_viewRenderJSPreference.xml b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSection_viewRenderJSPreference.xml
index f2c7b3e7d4debe1844060052de02c722dc8d63f6..db617b8a1ad17a9db6fe9f8925c80373f40d1846 100644
--- a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSection_viewRenderJSPreference.xml
+++ b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSection_viewRenderJSPreference.xml
@@ -98,13 +98,15 @@
                     <value>
                       <list>
                         <string>my_configuration_panel_gadget_url</string>
-                        <string>my_configuration_manifest_url</string>
-                        <string>my_configuration_webapp_manifest_url</string>
-                        <string>my_configuration_service_worker_url</string>
                         <string>my_configuration_jio_gadget_url</string>
                         <string>my_configuration_translation_gadget_url</string>
                         <string>my_configuration_router_gadget_url</string>
                         <string>my_configuration_header_gadget_url</string>
+                        <string>my_configuration_manifest_url</string>
+                        <string>my_configuration_webapp_manifest_url</string>
+                        <string>my_configuration_service_worker_url</string>
+                        <string>my_modification_date</string>
+                        <string>my_configuration_precache_manifest_script_list</string>
                       </list>
                     </value>
                 </item>
diff --git a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSection_viewRenderJSPreference/my_configuration_precache_manifest_script_list.xml b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSection_viewRenderJSPreference/my_configuration_precache_manifest_script_list.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a5b8b6228510c0bd39c4e3de4cdacd7f8f2d5aa3
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSection_viewRenderJSPreference/my_configuration_precache_manifest_script_list.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list>
+                <string>title</string>
+                <string>width</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>my_configuration_precache_manifest_script_list</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_text_area_field</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string>Service Worker Precache Manifest Script List</string> </value>
+                </item>
+                <item>
+                    <key> <string>width</string> </key>
+                    <value> <int>40</int> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSection_viewRenderJSPreference/my_modification_date.xml b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSection_viewRenderJSPreference/my_modification_date.xml
new file mode 100644
index 0000000000000000000000000000000000000000..53f350feae6f405929baa0031257b7c21a711db2
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSection_viewRenderJSPreference/my_modification_date.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list>
+                <string>date_only</string>
+                <string>editable</string>
+                <string>title</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>my_modification_date</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>date_only</string> </key>
+                    <value> <int>0</int> </value>
+                </item>
+                <item>
+                    <key> <string>editable</string> </key>
+                    <value> <int>0</int> </value>
+                </item>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_date_time_field</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string>Service Worker Cache Key</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSite_createTranslationData/your_translation_data_file.xml b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSite_createTranslationData/your_translation_data_file.xml
index 1246765abd292e9e581cd0482e20a016e319d36d..73d7ae53e9f73103b39aba4e18c2dd940c7fdb6c 100644
--- a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSite_createTranslationData/your_translation_data_file.xml
+++ b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSite_createTranslationData/your_translation_data_file.xml
@@ -54,6 +54,10 @@
                     <key> <string>field_id</string> </key>
                     <value> <string></string> </value>
                 </item>
+                <item>
+                    <key> <string>first_item</string> </key>
+                    <value> <string></string> </value>
+                </item>
                 <item>
                     <key> <string>form_id</string> </key>
                     <value> <string></string> </value>
@@ -64,6 +68,10 @@
                       <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
                     </value>
                 </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string></string> </value>
+                </item>
               </dictionary>
             </value>
         </item>
@@ -107,7 +115,7 @@
       <dictionary>
         <item>
             <key> <string>_text</string> </key>
-            <value> <string>python: [ (x,x) for x in here.Base_getListFileFromAppcache()]</string> </value>
+            <value> <string>python: [ (x,x) for x in here.Base_getTranslationSourceFileList()]</string> </value>
         </item>
       </dictionary>
     </pickle>
diff --git a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui/WebPage_viewAsWeb.py b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui/WebPage_viewAsWeb.py
index 71fd6b1f4ed7e2a863924cc7e6ca28fb6c324c0f..2fb8f441199ecc072d90dcfdb771299f2a718b50 100644
--- a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui/WebPage_viewAsWeb.py
+++ b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui/WebPage_viewAsWeb.py
@@ -29,6 +29,12 @@ web_content = web_page.getTextContent()
 # set headers depending on type of script
 if (portal_type == "Web Script"):
   response.setHeader('Content-Type', 'application/javascript; charset=utf-8')
+  if web_page.getTextContentSubstitutionMappingMethodId():
+    web_content = web_page.TextDocument_substituteTextContent(web_content, mapping_dict={
+      'modification_date': modification_date_string,
+      # Make JSLint happy for the service worker code
+      'required_url_list': json.dumps(web_section.WebSection_getPrecacheManifest())
+    })
 
 elif (portal_type == "Web Style"):
   response.setHeader('Content-Type', 'text/css; charset=utf-8')
diff --git a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui/WebSection_renderDefaultPageAsGadget.py b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui/WebSection_renderDefaultPageAsGadget.py
index 7f9ac473e2daf1e63206ca4a927ab03b490c64b8..905bb5d427424cbf207ac64dea1381acd9f85ebf 100644
--- a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui/WebSection_renderDefaultPageAsGadget.py
+++ b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui/WebSection_renderDefaultPageAsGadget.py
@@ -1,5 +1,6 @@
 import json
 import re
+from urlparse import urljoin
 
 if REQUEST is None:
   REQUEST = context.REQUEST
@@ -31,23 +32,32 @@ view_as_web_method = default_web_page.getTypeBasedMethod(
   fallback_script_id="WebPage_viewAsWeb"
   )
 
+selected_language = portal.Localizer.get_selected_language()
+
+# base tag
+if selected_language == default_language:
+  base_prefix = ""
+else:
+  base_prefix = '../'
+
 mapping_dict = {
+  "base_prefix": base_prefix,
   "frontpage_gadget": web_section.getLayoutProperty("configuration_frontpage_gadget_url", default="worklist"),
   "jio_document_page_gadget": web_section.getLayoutProperty("configuration_default_jio_document_page_gadget_url", default="form"),
   "application_title": web_section.getLayoutProperty("configuration_application_title", default="ERP5"),
   "action_view": web_section.getLayoutProperty("configuration_view_action_category", default="object_view"),
   "default_view_reference": web_section.getLayoutProperty("configuration_default_view_action_reference", default="view"),
   "hateoas_url": web_section.getLayoutProperty("configuration_hateoas_url", default="hateoas/"),
-  "panel_gadget": web_section.getLayoutProperty("configuration_panel_gadget_url", default="gadget_erp5_panel.html"),
-  "router_gadget": web_section.getLayoutProperty("configuration_router_gadget_url", default="gadget_erp5_router.html"),
-  "header_gadget": web_section.getLayoutProperty("configuration_header_gadget_url", default="gadget_erp5_header.html"),
-  "jio_gadget": web_section.getLayoutProperty("configuration_jio_gadget_url", default="gadget_jio.html"),
-  "translation_gadget": web_section.getLayoutProperty("configuration_translation_gadget_url", default="gadget_translation.html"),
+  "panel_gadget": urljoin(base_prefix, web_section.getLayoutProperty("configuration_panel_gadget_url", default="gadget_erp5_panel.html")),
+  "router_gadget": urljoin(base_prefix, web_section.getLayoutProperty("configuration_router_gadget_url", default="gadget_erp5_router.html")),
+  "header_gadget": urljoin(base_prefix, web_section.getLayoutProperty("configuration_header_gadget_url", default="gadget_erp5_header.html")),
+  "jio_gadget": urljoin(base_prefix, web_section.getLayoutProperty("configuration_jio_gadget_url", default="gadget_jio.html")),
+  "translation_gadget": urljoin(base_prefix, web_section.getLayoutProperty("configuration_translation_gadget_url", default="gadget_translation.html")),
   "manifest_url": web_section.getLayoutProperty("configuration_manifest_url", default="gadget_erp5.appcache"),
-  "stylesheet_url": web_section.getLayoutProperty("configuration_stylesheet_url", default="gadget_erp5_nojqm.css"),
-  "service_worker_url": web_section.getLayoutProperty("configuration_service_worker_url", default=""),
+  "stylesheet_url": urljoin(base_prefix, web_section.getLayoutProperty("configuration_stylesheet_url", default="gadget_erp5_nojqm.css")),
+  "service_worker_url": urljoin(base_prefix, web_section.getLayoutProperty("configuration_service_worker_url", default="")),
   "language_map": json.dumps({tmp['id']: portal.Base_translateString(tmp['title'], lang = tmp['id']) for tmp in portal.Localizer.get_languages_map() if tmp['id'] in available_language_set}),
-  "default_selected_language":  portal.Localizer.get_selected_language(),
+  "default_selected_language": selected_language,
   "website_url_set": json.dumps(website_url_set),
   "site_description": web_section.getLayoutProperty("description", default=""),
   "site_keywords": web_section.getLayoutProperty("subject", default=""),
@@ -89,6 +99,6 @@ else:
     background-attachment: fixed;
     background-image: url("%s");
   }
-  """ % wallpaper_url)
+  """ % urljoin(base_prefix, wallpaper_url))
 
 return view_as_web_method(mapping_dict=mapping_dict)
diff --git a/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_interface_validator_zuite/testERP5Interface.zpt b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_interface_validator_zuite/testERP5Interface.zpt
index 2487119dc276eb01342ef61ff715d1e2d318a8e2..b90a287fa69becd43988820d98b1d6b42b19bf53 100644
--- a/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_interface_validator_zuite/testERP5Interface.zpt
+++ b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_interface_validator_zuite/testERP5Interface.zpt
@@ -12,8 +12,8 @@
 
 <tal:block metal:use-macro="here/Zuite_CommonTemplate/macros/init" />
 
-<tal:block tal:define="check_configuration python: {'app_cache_reference': 'gadget_erp5.appcache',
-                                                    'gadget_count': 65}">
+<tal:block tal:define="check_configuration python: {'precache_reference': '../renderjs_runner/WebSection_getPrecacheManifest',
+                                                    'gadget_count': 66}">
   <tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUiInterface/macros/run_app_interface_check" />
 </tal:block>
 
diff --git a/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_service_worker_zuite.xml b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_service_worker_zuite.xml
new file mode 100644
index 0000000000000000000000000000000000000000..53bbca32f27ac670d7abec576571af364151100b
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_service_worker_zuite.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Zuite" module="Products.Zelenium.zuite"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>renderjs_ui_service_worker_zuite</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_service_worker_zuite/testServiceWorkerInstallation.xml b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_service_worker_zuite/testServiceWorkerInstallation.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8b53af797221080c629c295a1508a75ff6591169
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_service_worker_zuite/testServiceWorkerInstallation.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>expand</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>testServiceWorkerInstallation</string> </value>
+        </item>
+        <item>
+            <key> <string>output_encoding</string> </key>
+            <value> <string>utf-8</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <unicode></unicode> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_service_worker_zuite/testServiceWorkerInstallation.zpt b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_service_worker_zuite/testServiceWorkerInstallation.zpt
new file mode 100644
index 0000000000000000000000000000000000000000..2043010c56127361af860f48c9cc5915b5b8cf65
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_service_worker_zuite/testServiceWorkerInstallation.zpt
@@ -0,0 +1,81 @@
+<html xmlns:tal="http://xml.zope.org/namespaces/tal"
+      xmlns:metal="http://xml.zope.org/namespaces/metal">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Test RenderJS UI</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">Test RenderJS UI</td></tr>
+</thead><tbody>
+<tal:block metal:use-macro="here/Zuite_CommonTemplate/macros/init" />
+
+<tr>
+  <td colspan="3"><b tal:content="python: 'Clone web site'"></b></td>
+</tr>
+<tr>
+  <td>open</td>
+  <td tal:content="python: '${base_url}/web_site_module/renderjs_runner?ignore_layout:int=1&editable_mode:int=1'"></td>
+  <td></td>
+</tr>
+<tr>
+  <td>waitForElementPresent</td>
+  <td>name=Base_createCloneDocument:method</td>
+  <td></td>
+</tr>
+<tr>
+  <td>clickAndWait</td>
+  <td>name=Base_createCloneDocument:method</td>
+  <td></td>
+</tr>
+<tr>
+  <td>verifyTextPresent</td>
+  <td>Created Clone Web Site</td>
+  <td></td>
+</tr>
+<tr>
+  <td>storeValue</td>
+  <td>name=field_my_id</td>
+  <td>install_url</td>
+</tr>
+<tal:block metal:use-macro="here/Zuite_CommonTemplate/macros/wait_for_activities" />
+<tr>
+  <td>open</td>
+  <td>${base_url}/web_site_module/${install_url}/#/?page=test_service_worker</td>
+  <td></td>
+</tr>
+<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_app_loaded" />
+
+<tr>
+  <td>assertTextPresent</td>
+  <td>Has SW: false</td>
+  <td></td>
+</tr>
+
+<tr>
+  <td>waitForTextPresent</td>
+  <td>Has SW: true</td>
+  <td></td>
+</tr>
+
+<tr>
+  <td>assertTextPresent</td>
+  <td>Has SW: true</td>
+  <td></td>
+</tr>
+
+<tal:block tal:define="click_configuration python: {'text': 'Views'}">
+  <tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/click_on_header_link" />
+</tal:block>
+<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
+
+<tr>
+  <td>waitForTextPresent</td>
+  <td>Has SW: true</td>
+  <td></td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
\ No newline at end of file
diff --git a/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_service_worker_zuite/testServiceWorkerUpdate.xml b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_service_worker_zuite/testServiceWorkerUpdate.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fb7307aff5289b9a5b6bd7b320381e50dda97720
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_service_worker_zuite/testServiceWorkerUpdate.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>expand</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>testServiceWorkerUpdate</string> </value>
+        </item>
+        <item>
+            <key> <string>output_encoding</string> </key>
+            <value> <string>utf-8</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <unicode></unicode> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_service_worker_zuite/testServiceWorkerUpdate.zpt b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_service_worker_zuite/testServiceWorkerUpdate.zpt
new file mode 100644
index 0000000000000000000000000000000000000000..e0e720c8401f90232b59f8d5d5bc62c919e49afc
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_service_worker_zuite/testServiceWorkerUpdate.zpt
@@ -0,0 +1,110 @@
+<html xmlns:tal="http://xml.zope.org/namespaces/tal"
+      xmlns:metal="http://xml.zope.org/namespaces/metal">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Test RenderJS UI</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">Test RenderJS UI</td></tr>
+</thead><tbody>
+<tal:block metal:use-macro="here/Zuite_CommonTemplate/macros/init" />
+
+<tr>
+  <td>open</td>
+  <td>${base_url}/web_site_module/renderjs_runner/#/?page=test_service_worker</td>
+  <td></td>
+</tr>
+<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_app_loaded" />
+
+<tr>
+  <td>waitForTextPresent</td>
+  <td>Has SW: true</td>
+  <td></td>
+</tr>
+
+<tr>
+  <td>assertTextPresent</td>
+  <td>Has SW: true</td>
+  <td></td>
+</tr>
+
+<tr>
+  <td>click</td>
+  <td>//button[text()='Proceed']</td>
+  <td></td>
+</tr>
+<tr>
+  <td>waitForTextPresent</td>
+  <td>SW changed on server</td>
+  <td></td>
+</tr>
+<tr>
+  <td>assertTextPresent</td>
+  <td>SW changed on server</td>
+  <td></td>
+</tr>
+
+<!-- Navigating ERP5JS should trigger service worker update -->
+<tal:block tal:define="click_configuration python: {'text': 'Views'}">
+  <tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/click_on_header_link" />
+</tal:block>
+<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
+
+<tr>
+  <td>waitForTextPresent</td>
+  <td>Has SW: true</td>
+  <td></td>
+</tr>
+<tr>
+  <td>assertTextPresent</td>
+  <td>Has SW: true</td>
+  <td></td>
+</tr>
+
+<!-- Update is not triggered immediately -->
+<tr>
+  <td>pause</td>
+  <td>30000</td>
+  <td></td>
+</tr>
+
+<tr>
+  <td>waitForTextPresent</td>
+  <td>New SW ready</td>
+  <td></td>
+</tr>
+<tr>
+  <td>assertTextPresent</td>
+  <td>New SW ready</td>
+  <td></td>
+</tr>
+
+<!-- ERP5JS should reload itself while user is browsing it... -->
+<tal:block tal:define="click_configuration python: {'text': 'Views'}">
+  <tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/click_on_header_link" />
+</tal:block>
+<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_app_loaded" />
+
+<tr>
+  <td>waitForTextPresent</td>
+  <td>Has SW: true</td>
+  <td></td>
+</tr>
+
+<!-- ...But only once -->
+<tal:block tal:define="click_configuration python: {'text': 'Views'}">
+  <tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/click_on_header_link" />
+</tal:block>
+<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
+
+<tr>
+  <td>waitForTextPresent</td>
+  <td>Has SW: true</td>
+  <td></td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
\ No newline at end of file
diff --git a/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/web_page_module/gadget_erp5_page_service_worker_test_html.html b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/web_page_module/gadget_erp5_page_service_worker_test_html.html
new file mode 100644
index 0000000000000000000000000000000000000000..877bc877a796aa301883d252353f87e24cba9a9c
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/web_page_module/gadget_erp5_page_service_worker_test_html.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+    <meta name="viewport" content="width=device-width" />
+    <title>ERP5 Test Service Worker</title>
+    <link rel="http://www.renderjs.org/rel/interface" href="interface_page.html">
+
+    <!-- renderjs -->
+    <script src="rsvp.js" type="text/javascript"></script>
+    <script src="renderjs.js" type="text/javascript"></script>
+
+    <script src="domsugar.js" type="text/javascript"></script>
+    <script src="jiodev.js" type="text/javascript"></script>
+    <script src="gadget_global.js" type="text/javascript"></script>
+
+    <script src="gadget_erp5_page_test_service_worker.js" type="text/javascript"></script>
+
+  </head>
+  <body>
+  </body>
+</html>
\ No newline at end of file
diff --git a/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/web_page_module/gadget_erp5_page_service_worker_test_html.xml b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/web_page_module/gadget_erp5_page_service_worker_test_html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6a52c0088e52b5bf8c07fc44dc85cd828bd4792d
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/web_page_module/gadget_erp5_page_service_worker_test_html.xml
@@ -0,0 +1,334 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Web Page" module="erp5.portal_type"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_Access_contents_information_Permission</string> </key>
+            <value>
+              <tuple>
+                <string>Anonymous</string>
+                <string>Assignee</string>
+                <string>Assignor</string>
+                <string>Associate</string>
+                <string>Auditor</string>
+                <string>Manager</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>_Add_portal_content_Permission</string> </key>
+            <value>
+              <tuple>
+                <string>Assignee</string>
+                <string>Assignor</string>
+                <string>Manager</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>_Change_local_roles_Permission</string> </key>
+            <value>
+              <tuple>
+                <string>Assignor</string>
+                <string>Manager</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>_Modify_portal_content_Permission</string> </key>
+            <value>
+              <tuple>
+                <string>Assignee</string>
+                <string>Assignor</string>
+                <string>Manager</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>_View_Permission</string> </key>
+            <value>
+              <tuple>
+                <string>Anonymous</string>
+                <string>Assignee</string>
+                <string>Assignor</string>
+                <string>Associate</string>
+                <string>Auditor</string>
+                <string>Manager</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>content_md5</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>default_reference</string> </key>
+            <value> <string>gadget_erp5_page_test_service_worker.html</string> </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>gadget_erp5_page_service_worker_test_html</string> </value>
+        </item>
+        <item>
+            <key> <string>language</string> </key>
+            <value> <string>en</string> </value>
+        </item>
+        <item>
+            <key> <string>portal_type</string> </key>
+            <value> <string>Web Page</string> </value>
+        </item>
+        <item>
+            <key> <string>short_title</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string>Gadget Test ERP5 Service Worker</string> </value>
+        </item>
+        <item>
+            <key> <string>version</string> </key>
+            <value> <string>001</string> </value>
+        </item>
+        <item>
+            <key> <string>workflow_history</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="PersistentMapping" module="Persistence.mapping"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>document_publication_workflow</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>edit_workflow</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>processing_status_workflow</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
+                    </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="3" aka="AAAAAAAAAAM=">
+    <pickle>
+      <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_log</string> </key>
+            <value>
+              <list>
+                <dictionary>
+                  <item>
+                      <key> <string>action</string> </key>
+                      <value> <string>publish_alive</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>actor</string> </key>
+                      <value> <string>zope</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>comment</string> </key>
+                      <value> <string></string> </value>
+                  </item>
+                  <item>
+                      <key> <string>error_message</string> </key>
+                      <value> <string></string> </value>
+                  </item>
+                  <item>
+                      <key> <string>time</string> </key>
+                      <value>
+                        <object>
+                          <klass>
+                            <global name="DateTime" module="DateTime.DateTime"/>
+                          </klass>
+                          <tuple>
+                            <none/>
+                          </tuple>
+                          <state>
+                            <tuple>
+                              <float>1583336449.53</float>
+                              <string>UTC</string>
+                            </tuple>
+                          </state>
+                        </object>
+                      </value>
+                  </item>
+                  <item>
+                      <key> <string>validation_state</string> </key>
+                      <value> <string>published_alive</string> </value>
+                  </item>
+                </dictionary>
+              </list>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="4" aka="AAAAAAAAAAQ=">
+    <pickle>
+      <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_log</string> </key>
+            <value>
+              <list>
+                <dictionary>
+                  <item>
+                      <key> <string>action</string> </key>
+                      <value> <string>edit</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>actor</string> </key>
+                      <value> <string>zope</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>comment</string> </key>
+                      <value>
+                        <none/>
+                      </value>
+                  </item>
+                  <item>
+                      <key> <string>error_message</string> </key>
+                      <value> <string></string> </value>
+                  </item>
+                  <item>
+                      <key> <string>serial</string> </key>
+                      <value> <string>982.21176.62804.40994</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>state</string> </key>
+                      <value> <string>current</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>time</string> </key>
+                      <value>
+                        <object>
+                          <klass>
+                            <global name="DateTime" module="DateTime.DateTime"/>
+                          </klass>
+                          <tuple>
+                            <none/>
+                          </tuple>
+                          <state>
+                            <tuple>
+                              <float>1583500034.28</float>
+                              <string>UTC</string>
+                            </tuple>
+                          </state>
+                        </object>
+                      </value>
+                  </item>
+                </dictionary>
+              </list>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="5" aka="AAAAAAAAAAU=">
+    <pickle>
+      <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_log</string> </key>
+            <value>
+              <list>
+                <dictionary>
+                  <item>
+                      <key> <string>action</string> </key>
+                      <value> <string>detect_converted_file</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>actor</string> </key>
+                      <value> <string>zope</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>comment</string> </key>
+                      <value> <string></string> </value>
+                  </item>
+                  <item>
+                      <key> <string>error_message</string> </key>
+                      <value> <string></string> </value>
+                  </item>
+                  <item>
+                      <key> <string>external_processing_state</string> </key>
+                      <value> <string>converted</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>serial</string> </key>
+                      <value> <string>0.0.0.0</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>time</string> </key>
+                      <value>
+                        <object>
+                          <klass>
+                            <global name="DateTime" module="DateTime.DateTime"/>
+                          </klass>
+                          <tuple>
+                            <none/>
+                          </tuple>
+                          <state>
+                            <tuple>
+                              <float>1583336340.78</float>
+                              <string>UTC</string>
+                            </tuple>
+                          </state>
+                        </object>
+                      </value>
+                  </item>
+                </dictionary>
+              </list>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/web_page_module/gadget_erp5_page_service_worker_test_js.js b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/web_page_module/gadget_erp5_page_service_worker_test_js.js
new file mode 100644
index 0000000000000000000000000000000000000000..ac20615b673ff340861f5ec2aa402a7b26183eb9
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/web_page_module/gadget_erp5_page_service_worker_test_js.js
@@ -0,0 +1,73 @@
+/*global window, rJS, RSVP, domsugar, navigator, promiseEventListener, jIO */
+/*jslint nomen: true, indent: 2, maxerr: 3, maxlen: 80 */
+(function (window, rJS, RSVP, domsugar, navigator, promiseEventListener, jIO) {
+  "use strict";
+
+  rJS(window)
+    .declareAcquiredMethod("getUrlFor", "getUrlFor")
+    .declareAcquiredMethod("getUrlForList", "getUrlForList")
+
+    .declareAcquiredMethod("updateHeader", "updateHeader")
+
+    .declareMethod('render', function () {
+      var gadget = this;
+      // Wait a bit a allow the header loader to be displayed
+      return new RSVP.Queue(RSVP.delay(200))
+        .push(function () {
+          return gadget.getUrlForList([
+            // Home page
+            {command: 'display'},
+            // Soft reload the gadget
+            {command: 'change'}
+          ]);
+        })
+        .push(function (url_list) {
+          gadget.checkServiceWorkerStatus();
+          return gadget.updateHeader({
+            page_title: 'Test Service Worker',
+            front_url: url_list[0],
+            tab_url: url_list[1],
+            submit_action: true
+          });
+        });
+    })
+
+    .declareMethod("triggerSubmit", function () {
+      var gadget = this;
+      return new RSVP.Queue(jIO.util.ajax({
+        type: 'POST',
+        url: './Base_changeModificationDateForTest'
+      }))
+        .push(function () {
+          domsugar(gadget.element, {
+            text: "SW changed on server"
+          });
+        });
+    })
+
+    .declareJob("checkServiceWorkerStatus", function () {
+      var gadget = this,
+        has_service_worker = (navigator.serviceWorker.controller !== null);
+
+      domsugar(gadget.element, {
+        text: "Has SW: " + has_service_worker.toString()
+      });
+      return new RSVP.Queue(navigator.serviceWorker.ready)
+        .push(function (worker_container) {
+          domsugar(gadget.element, {
+            text: "Has SW: true"
+          });
+          return promiseEventListener(worker_container.active, 'statechange');
+        })
+        .push(function () {
+          // Wait a bit until the message is propagated
+          return RSVP.delay(2000);
+        })
+        .push(function () {
+          domsugar(gadget.element, {
+            text: "New SW ready"
+          });
+        });
+    });
+
+}(window, rJS, RSVP, domsugar, navigator, promiseEventListener, jIO));
\ No newline at end of file
diff --git a/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/web_page_module/gadget_erp5_page_service_worker_test_js.xml b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/web_page_module/gadget_erp5_page_service_worker_test_js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..912831ac34639dc1c2596bd269cdf49dc2cd5c1f
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui_test/PathTemplateItem/web_page_module/gadget_erp5_page_service_worker_test_js.xml
@@ -0,0 +1,330 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Web Script" module="erp5.portal_type"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_Access_contents_information_Permission</string> </key>
+            <value>
+              <tuple>
+                <string>Anonymous</string>
+                <string>Assignee</string>
+                <string>Assignor</string>
+                <string>Associate</string>
+                <string>Auditor</string>
+                <string>Manager</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>_Add_portal_content_Permission</string> </key>
+            <value>
+              <tuple>
+                <string>Assignee</string>
+                <string>Assignor</string>
+                <string>Manager</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>_Change_local_roles_Permission</string> </key>
+            <value>
+              <tuple>
+                <string>Assignor</string>
+                <string>Manager</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>_Modify_portal_content_Permission</string> </key>
+            <value>
+              <tuple>
+                <string>Assignee</string>
+                <string>Assignor</string>
+                <string>Manager</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>_View_Permission</string> </key>
+            <value>
+              <tuple>
+                <string>Anonymous</string>
+                <string>Assignee</string>
+                <string>Assignor</string>
+                <string>Associate</string>
+                <string>Auditor</string>
+                <string>Manager</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>content_md5</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>default_reference</string> </key>
+            <value> <string>gadget_erp5_page_test_service_worker.js</string> </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>gadget_erp5_page_service_worker_test_js</string> </value>
+        </item>
+        <item>
+            <key> <string>language</string> </key>
+            <value> <string>en</string> </value>
+        </item>
+        <item>
+            <key> <string>portal_type</string> </key>
+            <value> <string>Web Script</string> </value>
+        </item>
+        <item>
+            <key> <string>short_title</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string>Gadget Test ERP5 Service Worker JS</string> </value>
+        </item>
+        <item>
+            <key> <string>version</string> </key>
+            <value> <string>001</string> </value>
+        </item>
+        <item>
+            <key> <string>workflow_history</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="PersistentMapping" module="Persistence.mapping"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>document_publication_workflow</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>edit_workflow</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>processing_status_workflow</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
+                    </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="3" aka="AAAAAAAAAAM=">
+    <pickle>
+      <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_log</string> </key>
+            <value>
+              <list>
+                <dictionary>
+                  <item>
+                      <key> <string>action</string> </key>
+                      <value> <string>publish_alive</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>actor</string> </key>
+                      <value> <string>zope</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>comment</string> </key>
+                      <value> <string></string> </value>
+                  </item>
+                  <item>
+                      <key> <string>error_message</string> </key>
+                      <value> <string></string> </value>
+                  </item>
+                  <item>
+                      <key> <string>time</string> </key>
+                      <value>
+                        <object>
+                          <klass>
+                            <global name="DateTime" module="DateTime.DateTime"/>
+                          </klass>
+                          <tuple>
+                            <none/>
+                          </tuple>
+                          <state>
+                            <tuple>
+                              <float>1583336542.71</float>
+                              <string>UTC</string>
+                            </tuple>
+                          </state>
+                        </object>
+                      </value>
+                  </item>
+                  <item>
+                      <key> <string>validation_state</string> </key>
+                      <value> <string>published_alive</string> </value>
+                  </item>
+                </dictionary>
+              </list>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="4" aka="AAAAAAAAAAQ=">
+    <pickle>
+      <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_log</string> </key>
+            <value>
+              <list>
+                <dictionary>
+                  <item>
+                      <key> <string>action</string> </key>
+                      <value> <string>edit</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>actor</string> </key>
+                      <value> <string>zope</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>comment</string> </key>
+                      <value>
+                        <none/>
+                      </value>
+                  </item>
+                  <item>
+                      <key> <string>error_message</string> </key>
+                      <value> <string></string> </value>
+                  </item>
+                  <item>
+                      <key> <string>serial</string> </key>
+                      <value> <string>982.22503.50107.58589</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>state</string> </key>
+                      <value> <string>current</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>time</string> </key>
+                      <value>
+                        <object>
+                          <klass>
+                            <global name="DateTime" module="DateTime.DateTime"/>
+                          </klass>
+                          <tuple>
+                            <none/>
+                          </tuple>
+                          <state>
+                            <tuple>
+                              <float>1583499736.56</float>
+                              <string>UTC</string>
+                            </tuple>
+                          </state>
+                        </object>
+                      </value>
+                  </item>
+                </dictionary>
+              </list>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="5" aka="AAAAAAAAAAU=">
+    <pickle>
+      <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_log</string> </key>
+            <value>
+              <list>
+                <dictionary>
+                  <item>
+                      <key> <string>action</string> </key>
+                      <value> <string>detect_converted_file</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>actor</string> </key>
+                      <value> <string>zope</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>comment</string> </key>
+                      <value> <string></string> </value>
+                  </item>
+                  <item>
+                      <key> <string>error_message</string> </key>
+                      <value> <string></string> </value>
+                  </item>
+                  <item>
+                      <key> <string>external_processing_state</string> </key>
+                      <value> <string>converted</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>serial</string> </key>
+                      <value> <string>0.0.0.0</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>time</string> </key>
+                      <value>
+                        <object>
+                          <klass>
+                            <global name="DateTime" module="DateTime.DateTime"/>
+                          </klass>
+                          <tuple>
+                            <none/>
+                          </tuple>
+                          <state>
+                            <tuple>
+                              <float>1583336498.71</float>
+                              <string>UTC</string>
+                            </tuple>
+                          </state>
+                        </object>
+                      </value>
+                  </item>
+                </dictionary>
+              </list>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/Base_changeModificationDateForTest.py b/bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/Base_changeModificationDateForTest.py
new file mode 100644
index 0000000000000000000000000000000000000000..e0c6c4d60d24707b7d2d8760966715c93e7ad8e6
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/Base_changeModificationDateForTest.py
@@ -0,0 +1,2 @@
+context.edit()
+return 'OK'
diff --git a/bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/Base_changeModificationDateForTest.xml b/bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/Base_changeModificationDateForTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bafb2011cbb0bd009c83a018d59b6bfcc077021b
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/Base_changeModificationDateForTest.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>Script_magic</string> </key>
+            <value> <int>3</int> </value>
+        </item>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_container</string> </key>
+                                <value> <string>container</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_context</string> </key>
+                                <value> <string>context</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_m_self</string> </key>
+                                <value> <string>script</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_params</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>Base_changeModificationDateForTest</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/Zuite_CommonTemplateForRenderjsUiInterface.zpt b/bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/Zuite_CommonTemplateForRenderjsUiInterface.zpt
index 288ea6dad7c0bdd835142b78d4a8434b6af3cfa9..8a2ead03d280372f07f89b7009d6fb7094fb14d9 100644
--- a/bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/Zuite_CommonTemplateForRenderjsUiInterface.zpt
+++ b/bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/Zuite_CommonTemplateForRenderjsUiInterface.zpt
@@ -12,7 +12,7 @@
     <tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_listbox_loaded" />
 
     <tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/triggle_filter_and" />
-    <tal:block tal:define="filter_section_configuration python: {'key': 'COLUMN_appcache_url', 'value': check_configuration['app_cache_reference'], 'index': 0}">
+    <tal:block tal:define="filter_section_configuration python: {'key': 'COLUMN_precache_url', 'value': check_configuration['precache_reference'], 'index': 0}">
       <tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/set_filter_section" />
     </tal:block>
     <tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/submit_filter" />
diff --git a/bt5/erp5_web_renderjs_ui_test/TestTemplateItem/portal_components/test.erp5.testFunctionalRJSServiceWorker.py b/bt5/erp5_web_renderjs_ui_test/TestTemplateItem/portal_components/test.erp5.testFunctionalRJSServiceWorker.py
new file mode 100644
index 0000000000000000000000000000000000000000..658bd0ad1fb512eca637e1cdb09e5ae3938f724a
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui_test/TestTemplateItem/portal_components/test.erp5.testFunctionalRJSServiceWorker.py
@@ -0,0 +1,49 @@
+##############################################################################
+#
+# Copyright (c) 2011 Nexedi SARL and Contributors. All Rights Reserved.
+#                     Kazuhiko <kazuhiko@nexedi.com>
+#                     Rafael Monnerat <rafael@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+import unittest
+
+from Products.ERP5Type.tests.ERP5TypeFunctionalTestCase import ERP5TypeFunctionalTestCase
+
+class TestRenderJSUIServiceWorker(ERP5TypeFunctionalTestCase):
+  foreground = 0
+  run_only = "renderjs_ui_service_worker_zuite"
+
+  def getBusinessTemplateList(self):
+    return (
+      'erp5_web_renderjs_ui',
+      'erp5_web_renderjs_ui_test',
+      'erp5_ui_test_core',
+      'erp5_accounting',
+      'erp5_test_result',
+    )
+
+def test_suite():
+  suite = unittest.TestSuite()
+  suite.addTest(unittest.makeSuite(TestRenderJSUIServiceWorker))
+  return suite
\ No newline at end of file
diff --git a/bt5/erp5_web_renderjs_ui_test/TestTemplateItem/portal_components/test.erp5.testFunctionalRJSServiceWorker.xml b/bt5/erp5_web_renderjs_ui_test/TestTemplateItem/portal_components/test.erp5.testFunctionalRJSServiceWorker.xml
new file mode 100644
index 0000000000000000000000000000000000000000..45c7d34a538b8a7c4197a81e98381ae0dc5155da
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui_test/TestTemplateItem/portal_components/test.erp5.testFunctionalRJSServiceWorker.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Test Component" module="erp5.portal_type"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_recorded_property_dict</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>default_reference</string> </key>
+            <value> <string>testFunctionalRJSServiceWorker</string> </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>test.erp5.testFunctionalRJSServiceWorker</string> </value>
+        </item>
+        <item>
+            <key> <string>portal_type</string> </key>
+            <value> <string>Test Component</string> </value>
+        </item>
+        <item>
+            <key> <string>sid</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>text_content_error_message</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>text_content_warning_message</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>version</string> </key>
+            <value> <string>erp5</string> </value>
+        </item>
+        <item>
+            <key> <string>workflow_history</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="PersistentMapping" module="Persistence.mapping"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="3" aka="AAAAAAAAAAM=">
+    <pickle>
+      <global name="PersistentMapping" module="Persistence.mapping"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>component_validation_workflow</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
+                    </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="4" aka="AAAAAAAAAAQ=">
+    <pickle>
+      <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_log</string> </key>
+            <value>
+              <list>
+                <dictionary>
+                  <item>
+                      <key> <string>action</string> </key>
+                      <value> <string>validate</string> </value>
+                  </item>
+                  <item>
+                      <key> <string>validation_state</string> </key>
+                      <value> <string>validated</string> </value>
+                  </item>
+                </dictionary>
+              </list>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_web_renderjs_ui_test/bt/template_path_list b/bt5/erp5_web_renderjs_ui_test/bt/template_path_list
index cf468376c02fe448e2986d2e9677a7d7aa0270d7..2a632d6a79dc68aab4bbccca45e85b4c6e3de569 100644
--- a/bt5/erp5_web_renderjs_ui_test/bt/template_path_list
+++ b/bt5/erp5_web_renderjs_ui_test/bt/template_path_list
@@ -44,8 +44,11 @@ portal_tests/renderjs_ui_relation_field_zuite
 portal_tests/renderjs_ui_relation_field_zuite/**
 portal_tests/renderjs_ui_router_zuite
 portal_tests/renderjs_ui_router_zuite/**
+portal_tests/renderjs_ui_service_worker_zuite
+portal_tests/renderjs_ui_service_worker_zuite/**
 portal_tests/renderjs_ui_translate_zuite
 portal_tests/renderjs_ui_translate_zuite/**
 portal_tests/renderjs_ui_zuite
 portal_tests/renderjs_ui_zuite/**
-web_page_module/gadget_erp5_page_router_test_*
\ No newline at end of file
+web_page_module/gadget_erp5_page_router_test_*
+web_page_module/gadget_erp5_page_service_worker_test_*
\ No newline at end of file
diff --git a/bt5/erp5_web_renderjs_ui_test/bt/template_test_id_list b/bt5/erp5_web_renderjs_ui_test/bt/template_test_id_list
index ce56b7ff0c18ee2dcf48bf880838e44a4cca3389..efb5657ba023f665fe12fb60a21173f18fa46125 100644
--- a/bt5/erp5_web_renderjs_ui_test/bt/template_test_id_list
+++ b/bt5/erp5_web_renderjs_ui_test/bt/template_test_id_list
@@ -24,4 +24,5 @@ test.erp5.testFunctionalRJSRecoverPassword
 test.erp5.testFunctionalRJSInterfaceValidator
 test.erp5.testFunctionalRJSDms
 test.erp5.testRJSPortalType
-test.erp5.testRJSUpgrader
\ No newline at end of file
+test.erp5.testRJSUpgrader
+test.erp5.testFunctionalRJSServiceWorker
\ No newline at end of file