diff --git a/config.xml b/config.xml
index 7e9e138ab3cb6554e45be915104c2f74ab9f5a39..bc6c498dc56be4f6985fc0622443e8e1485ecb13 100644
--- a/config.xml
+++ b/config.xml
@@ -8,7 +8,7 @@
         UMR G-EAU
     </author>
     <content src="index.html" />
-    <icon src="src/android-chrome-512x512.png" />
+    <icon src="src/assets/icons/android/icon.png" />
     <plugin name="cordova-plugin-whitelist" spec="1" />
     <access origin="*" />
     <allow-intent href="http://*/*" />
@@ -19,11 +19,22 @@
     <allow-intent href="geo:*" />
     <platform name="android">
         <allow-intent href="market:*" />
-        <icon src="src/android-chrome-512x512.png" qualifier="ldpi" />
+        <icon src="src/assets/icons/android/icon.png" qualifier="ldpi" />
+        <!-- 2 following files are for notifications big icon: res://icon -->
+        <resource-file src="src/assets/icons/android/icon_96.png" target="app/src/main/res/icon.png" />
+        <resource-file src="src/assets/icons/android/icon_96.png" target="app/src/main/res/drawable/icon.png" />
+        <!-- all following files are for notifications small icon: res://ic_stat_notify -->
+        <resource-file src="src/assets/icons/android/ic_stat_notify.png" target="app/src/main/res/ic_stat_notify.png" />
+        <resource-file src="src/assets/icons/android/ic_stat_notify.png" target="app/src/main/res/drawable/ic_stat_notify.png" />
+        <!-- <resource-file src="src/assets/icons/android/ic_stat_notify_24.png" target="app/src/main/res/drawable-mdpi/ic_stat_notify.png" />
+        <resource-file src="src/assets/icons/android/ic_stat_notify_36.png" target="app/src/main/res/drawable-hdpi/ic_stat_notify.png" />
+        <resource-file src="src/assets/icons/android/ic_stat_notify_48.png" target="app/src/main/res/drawable-xhdpi/ic_stat_notify.png" />
+        <resource-file src="src/assets/icons/android/ic_stat_notify_72.png" target="app/src/main/res/drawable-xxhdpi/ic_stat_notify.png" />
+        <resource-file src="src/assets/icons/android/ic_stat_notify_96.png" target="app/src/main/res/drawable-xxxhdpi/ic_stat_notify.png" /> -->
     </platform>
     <platform name="ios">
         <allow-intent href="itms:*" />
         <allow-intent href="itms-apps:*" />
-        <icon src="src/android-chrome-512x512.png" qualifier="ldpi" />
+        <icon src="src/assets/icons/ios/icon.png" qualifier="ldpi" />
     </platform>
 </widget>
diff --git a/package-lock.json b/package-lock.json
index 739043b2d73c6ef49958dfcbdcbfa8c199d20730..e74b6047b3609f5cfaef7e9a6e04223ca9e382b3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7334,6 +7334,21 @@
         }
       }
     },
+    "cordova-plugin-advanced-http": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/cordova-plugin-advanced-http/-/cordova-plugin-advanced-http-2.4.1.tgz",
+      "integrity": "sha512-6G8MTy/d02jE6n3Y9CVyCtD5hZGiBb+/dR2AIzhKN1RGGz38g1D2C8yE4MqHRvnmry6k/KHQWT1MsHNXrjouXQ=="
+    },
+    "cordova-plugin-app-version": {
+      "version": "0.1.9",
+      "resolved": "https://registry.npmjs.org/cordova-plugin-app-version/-/cordova-plugin-app-version-0.1.9.tgz",
+      "integrity": "sha1-nbBgeGMzenEEiTAuX1CpBPFEm9s="
+    },
+    "cordova-plugin-badge": {
+      "version": "0.8.8",
+      "resolved": "https://registry.npmjs.org/cordova-plugin-badge/-/cordova-plugin-badge-0.8.8.tgz",
+      "integrity": "sha512-RhIBtd5xhD/iLnxjt35jvOae28oNW/wtMZBOmQR3Rf0y4wirvA1bpAZEhBoFqL+rZGhsd6ddOdQXdex1T0DRyQ=="
+    },
     "cordova-plugin-device": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/cordova-plugin-device/-/cordova-plugin-device-2.0.3.tgz",
@@ -7349,6 +7364,11 @@
       "resolved": "https://registry.npmjs.org/cordova-plugin-file-opener2/-/cordova-plugin-file-opener2-3.0.0.tgz",
       "integrity": "sha512-yQcJ5coOlfkDcTfIhFJEL2A7SWtLhy50y51Cb+EEkI7Y0lP74Ec2tsMtIOhe9i8wPSoSfnDcN77Hj6CSeIjogA=="
     },
+    "cordova-plugin-local-notification": {
+      "version": "0.9.0-beta.2",
+      "resolved": "https://registry.npmjs.org/cordova-plugin-local-notification/-/cordova-plugin-local-notification-0.9.0-beta.2.tgz",
+      "integrity": "sha512-63n77K1pt8dnbWnNR8QWETi9Glezi1bvNHvHWmGNIOv0xCb0phZnm+Ku49BQ+omwe8Z5voMvrA4I03SYPpv38w=="
+    },
     "cordova-plugin-whitelist": {
       "version": "1.3.4",
       "resolved": "https://registry.npmjs.org/cordova-plugin-whitelist/-/cordova-plugin-whitelist-1.3.4.tgz",
@@ -9825,10 +9845,12 @@
     },
     "falafel": {
       "version": "2.1.0",
-      "resolved": "",
+      "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.1.0.tgz",
+      "integrity": "sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw=",
       "dev": true,
       "requires": {
         "acorn": "^5.0.0",
+        "foreach": "^2.0.5",
         "isarray": "0.0.1",
         "object-keys": "^1.0.6"
       },
@@ -10270,6 +10292,12 @@
       "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
       "dev": true
     },
+    "foreach": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
+      "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
+      "dev": true
+    },
     "forever-agent": {
       "version": "0.6.1",
       "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
diff --git a/package.json b/package.json
index c37b6221417dda4044fcba220553e640048b0025..04805cfd7357e3e29c88b24186160d55bb40978a 100644
--- a/package.json
+++ b/package.json
@@ -52,9 +52,13 @@
     "angular2-hotkeys": "^2.2.0",
     "chartjs-plugin-zoom": "^0.7.5",
     "cordova-android": "^8.1.0",
+    "cordova-plugin-advanced-http": "^2.4.1",
+    "cordova-plugin-app-version": "^0.1.9",
+    "cordova-plugin-badge": "^0.8.8",
     "cordova-plugin-device": "^2.0.3",
     "cordova-plugin-file": "^6.0.2",
     "cordova-plugin-file-opener2": "^3.0.0",
+    "cordova-plugin-local-notification": "^0.9.0-beta.2",
     "cordova-plugin-whitelist": "^1.3.4",
     "core-js": "^3.6.4",
     "file-saver": "^2.0.2",
@@ -114,7 +118,10 @@
       "cordova-plugin-file-opener2": {
         "ANDROID_SUPPORT_V4_VERSION": "27.+"
       },
-      "cordova-plugin-device": {}
+      "cordova-plugin-device": {},
+      "cordova-plugin-local-notification": {},
+      "cordova-plugin-app-version": {},
+      "cordova-plugin-advanced-http": {}
     },
     "platforms": [
       "android"
diff --git a/src/assets/icons/android/ic_stat_notify.png b/src/assets/icons/android/ic_stat_notify.png
new file mode 100644
index 0000000000000000000000000000000000000000..9b300d9301ed2a18c10f97b850842e50e871c323
Binary files /dev/null and b/src/assets/icons/android/ic_stat_notify.png differ
diff --git a/src/assets/icons/android/icon.png b/src/assets/icons/android/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..67c7918826dd586f53aab4da6d7dbfe3ea96937a
Binary files /dev/null and b/src/assets/icons/android/icon.png differ
diff --git a/src/assets/icons/android/icon_96.png b/src/assets/icons/android/icon_96.png
new file mode 100644
index 0000000000000000000000000000000000000000..518dc99413c402fc7b20a45a44ea94c523ef1b4c
Binary files /dev/null and b/src/assets/icons/android/icon_96.png differ
diff --git a/src/assets/icons/ios/icon.png b/src/assets/icons/ios/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..67c7918826dd586f53aab4da6d7dbfe3ea96937a
Binary files /dev/null and b/src/assets/icons/ios/icon.png differ
diff --git a/src/index.html b/src/index.html
index c129854a24c9aef60d83a4ec5f78aed1f987cf3b..55f7c58334a62541954f33f05d52e71afb42dc62 100644
--- a/src/index.html
+++ b/src/index.html
@@ -182,6 +182,103 @@
 
       </script>
    </nghyd-app>
+
+   <script type="text/javascript">
+      /**
+       * Compares semver strings
+       * @see https://github.com/substack/semver-compare
+       */
+      function semverCompare(a, b) {
+         var pa = a.split('.');
+         var pb = b.split('.');
+         for (var i = 0; i < 3; i++) {
+            var na = Number(pa[i]);
+            var nb = Number(pb[i]);
+            if (na > nb) return 1;
+            if (nb > na) return -1;
+            if (!isNaN(na) && isNaN(nb)) return 1;
+            if (isNaN(na) && !isNaN(nb)) return -1;
+         }
+         return 0;
+      }
+      /**
+       * Calls the Cassiopee update server to check for available updates;
+       * if so, displays a desktop notification which, if clicked, will
+       * trigger the download of the latest version installer for the
+       * current platform
+       * 
+       * Web updates system prerequisites
+       * --------------------------------
+       * 
+       * ${URL} should point to an http-accessible directory containing:
+       * 
+       *  1. a file named "releases.json" with a contents of the form
+       *    {
+       *      "latest": "4.5.0",
+       *      "4.5.0": {
+       *        "darwin": "cassiopee-setup-4.5.0.dmg",
+       *        "linux": "fr.irstea.cassiopee_4.5.0_amd64.deb",
+       *        "win32": "Cassiopée Setup 4.5.0.exe"
+       *      },
+       *      "4.4.2": {
+       *        "darwin": "cassiopee-setup-4.4.2.dmg",
+       *        "linux": "fr.irstea.cassiopee_4.4.2_amd64.deb",
+       *        "win32": "Cassiopée Setup 4.4.2.exe"
+       *      }
+       *    }
+       * 
+       *  2. all platform-dependent installer files specified in "releases.json",
+       *     at the root of the directory (ex: "fr.irstea.cassiopee_4.5.0_amd64.deb")
+       */
+      const lookForUpdates = function() {
+         // Web update resources root directory
+         const URL = "https://cassiopee.g-eau.fr/cassiopee-releases/";
+
+         // detect current app version and platform
+         let version = "4.4.2"; // debug
+         cordova.getAppVersion.getVersionNumber((versionNumber) => {
+            version = versionNumber;
+            // fetch releases information
+            const options = {
+               method: 'get',
+               headers: { "Cache-Control": "no-cache" }
+            };
+            cordova.plugin.http.sendRequest(URL + "releases.json", options, (response) => {
+               var data = JSON.parse(response.data); // This is the resultant JSON in useful form
+               // alert(`Youpi ! ${response.status} version=${version}, latest=${data.latest}, comp=${semverCompare(data.latest, version)}`);
+               // compare current version to latest version
+               if (data.latest && semverCompare(data.latest, version) == 1) {
+                  // get download link for latest version, depending on platform
+                  if (data[data.latest] && data[data.latest]["android"]) {
+                     const latestVersionURL = URL + data[data.latest]["android"];
+                     // show notification
+                     cordova.plugins.notification.local.schedule({
+                        title: `Cassiopee version ${data.latest} is available`,
+                        text: "Download update installer",
+                        foreground: true,
+                        smallIcon: "res://ic_stat_notify",
+                        icon: "res://icon"
+                     });
+                     cordova.plugins.notification.local.on("click", () => {
+                        // ask system to open URL with default browser
+                        // @TODO find a way to get rid of "are you sure you want to leave this page ?" prompt
+                        window.open(latestVersionURL, "_system");
+                     });
+                  } // else could not find link, silent fail
+               } // else you already have the latest version
+            }, (response) => { /* silent fail */});
+         });
+      };
+
+      // execute on Cordova (mobile app) only
+      if (window.cordova && cordova.platformId !== "browser") {
+         document.addEventListener("deviceready", function () {
+            // check updates at app startup
+            lookForUpdates();
+         });
+      }
+   </script>
+
 </body>
 
 </html>
\ No newline at end of file