diff --git a/angular.json b/angular.json
index 234f2a3174faa46f416d6ec31b32448326e38376..a5fea2de64406e50055b7fc578064a21dac76719 100644
--- a/angular.json
+++ b/angular.json
@@ -35,7 +35,8 @@
                 "glob": "**/*.png",
                 "input": "src/",
                 "output": "/"
-              }
+              },
+              "src/manifest.webmanifest"
             ],
             "styles": [
               "src/styles.scss",
@@ -75,7 +76,9 @@
             "buildOptimizer": false,
             "sourceMap": true,
             "optimization": false,
-            "namedChunks": true
+            "namedChunks": true,
+            "serviceWorker": true,
+            "ngswConfigPath": "ngsw-config.json"
           },
           "configurations": {
             "production": {
@@ -105,7 +108,7 @@
         "serve": {
           "builder": "@angular-devkit/build-angular:dev-server",
           "options": {
-            "browserTarget": "ngHyd:build",
+            "browserTarget": "ngHyd:build"
           },
           "configurations": {
             "production": {
@@ -136,7 +139,8 @@
               "src/favicon.ico",
               "src/**/*.json",
               "src/**/*.md",
-              "src/**/*.png"
+              "src/**/*.png",
+              "src/manifest.webmanifest"
             ]
           }
         }
diff --git a/ngsw-config.json b/ngsw-config.json
new file mode 100644
index 0000000000000000000000000000000000000000..f8bf2102ea5690789e37f553f304f8970bc719ae
--- /dev/null
+++ b/ngsw-config.json
@@ -0,0 +1,30 @@
+{
+  "$schema": "./node_modules/@angular/service-worker/config/schema.json",
+  "index": "/index.html",
+  "assetGroups": [
+    {
+      "name": "app",
+      "installMode": "prefetch",
+      "resources": {
+        "files": [
+          "/favicon.ico",
+          "/index.html",
+          "/manifest.webmanifest",
+          "/*.css",
+          "/*.js"
+        ]
+      }
+    },
+    {
+      "name": "assets",
+      "installMode": "lazy",
+      "updateMode": "prefetch",
+      "resources": {
+        "files": [
+          "/assets/**",
+          "/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)"
+        ]
+      }
+    }
+  ]
+}
diff --git a/package-lock.json b/package-lock.json
index 8d29777e1fe175b492357b9437ba58477676dae4..597641a64fa49e3b7dc5be9dc4451292d7dfb9f2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -22,6 +22,7 @@
         "@angular/platform-browser": "^14.0.4",
         "@angular/platform-browser-dynamic": "^14.0.4",
         "@angular/router": "^14.0.4",
+        "@angular/service-worker": "^14.0.4",
         "@ngx-matomo/tracker": "^3.0.0",
         "@types/pako": "^1.0.4",
         "@types/sprintf-js": "^1.1.2",
@@ -59,7 +60,7 @@
       },
       "devDependencies": {
         "@angular-devkit/core": "^14.0.4",
-        "@angular-eslint/eslint-plugin": "^14.0.0",
+        "@angular-eslint/eslint-plugin": "^14.0.4",
         "@angular/cli": "^14.0.4",
         "@angular/compiler-cli": "^14.0.4",
         "@angular/language-service": "^14.0.4",
@@ -927,6 +928,24 @@
         "rxjs": "^6.5.3 || ^7.4.0"
       }
     },
+    "node_modules/@angular/service-worker": {
+      "version": "14.2.11",
+      "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-14.2.11.tgz",
+      "integrity": "sha512-RIRhkSxjah2f4sFDduPFGS/9rXZADYPYLVO9zkOHiX9IlCzFwqOZnL9UkMrlKC1AoGr6seXkGHHtC+7gOiszoQ==",
+      "dependencies": {
+        "tslib": "^2.3.0"
+      },
+      "bin": {
+        "ngsw-config": "ngsw-config.js"
+      },
+      "engines": {
+        "node": "^14.15.0 || >=16.10.0"
+      },
+      "peerDependencies": {
+        "@angular/common": "14.2.11",
+        "@angular/core": "14.2.11"
+      }
+    },
     "node_modules/@assemblyscript/loader": {
       "version": "0.10.1",
       "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz",
@@ -23295,6 +23314,14 @@
         "tslib": "^2.3.0"
       }
     },
+    "@angular/service-worker": {
+      "version": "14.2.11",
+      "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-14.2.11.tgz",
+      "integrity": "sha512-RIRhkSxjah2f4sFDduPFGS/9rXZADYPYLVO9zkOHiX9IlCzFwqOZnL9UkMrlKC1AoGr6seXkGHHtC+7gOiszoQ==",
+      "requires": {
+        "tslib": "^2.3.0"
+      }
+    },
     "@assemblyscript/loader": {
       "version": "0.10.1",
       "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz",
diff --git a/package.json b/package.json
index bf035e0b322f4b80799cb257e9b46ee00dac401a..5abbd69aed925f383812edec1ba9a9fd9db3a7d2 100644
--- a/package.json
+++ b/package.json
@@ -48,6 +48,7 @@
     "@angular/platform-browser": "^14.0.4",
     "@angular/platform-browser-dynamic": "^14.0.4",
     "@angular/router": "^14.0.4",
+    "@angular/service-worker": "^14.0.4",
     "@ngx-matomo/tracker": "^3.0.0",
     "@types/pako": "^1.0.4",
     "@types/sprintf-js": "^1.1.2",
@@ -85,7 +86,7 @@
   },
   "devDependencies": {
     "@angular-devkit/core": "^14.0.4",
-    "@angular-eslint/eslint-plugin": "^14.0.0",
+    "@angular-eslint/eslint-plugin": "^14.0.4",
     "@angular/cli": "^14.0.4",
     "@angular/compiler-cli": "^14.0.4",
     "@angular/language-service": "^14.0.4",
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index c39a646e4ea262213bbe5d71352749971cef5120..6a0be9102e5fb73c3a08ddb67bdbf611be4dc494 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -123,6 +123,8 @@ import { DialogConfirmLoadSessionURLComponent } from "./components/dialog-confir
 import { StructureFieldsetContainerComponent } from "./components/structure-fieldset-container/structure-fieldset-container.component";
 import { BasinFieldsetContainerComponent } from "./components/basin-fieldset-container/basin-fieldset-container.component";
 import { PrebarrageService } from "./services/prebarrage.service";
+import { ServiceWorkerModule } from '@angular/service-worker';
+import { environment } from '../environments/environment';
 
 const appRoutes: Routes = [
     { path: "list/search", component: CalculatorListComponent },
@@ -187,7 +189,13 @@ const appRoutes: Routes = [
             enableTracing: false,
             relativeLinkResolution: 'legacy'
         }),
-        TableModule
+        TableModule,
+        ServiceWorkerModule.register('ngsw-worker.js', {
+          enabled: environment.production,
+          // Register the ServiceWorker as soon as the application is stable
+          // or after 30 seconds (whichever comes first).
+          registrationStrategy: 'registerWhenStable:30000'
+        })
     ],
     declarations: [
         AppComponent,
diff --git a/src/assets/icons/icon-128x128.png b/src/assets/icons/icon-128x128.png
new file mode 100644
index 0000000000000000000000000000000000000000..9f9241f0be40661db1eed29384231e76d33b6e7c
Binary files /dev/null and b/src/assets/icons/icon-128x128.png differ
diff --git a/src/assets/icons/icon-144x144.png b/src/assets/icons/icon-144x144.png
new file mode 100644
index 0000000000000000000000000000000000000000..4a5f8c16389c261b3291ef34a9ef8b2222f76d69
Binary files /dev/null and b/src/assets/icons/icon-144x144.png differ
diff --git a/src/assets/icons/icon-152x152.png b/src/assets/icons/icon-152x152.png
new file mode 100644
index 0000000000000000000000000000000000000000..34a1a8d645872c776c9425de45c3fcfba12c271e
Binary files /dev/null and b/src/assets/icons/icon-152x152.png differ
diff --git a/src/assets/icons/icon-192x192.png b/src/assets/icons/icon-192x192.png
new file mode 100644
index 0000000000000000000000000000000000000000..9172e5dd29e4b2c35cbf4da874e778934fa27e77
Binary files /dev/null and b/src/assets/icons/icon-192x192.png differ
diff --git a/src/assets/icons/icon-384x384.png b/src/assets/icons/icon-384x384.png
new file mode 100644
index 0000000000000000000000000000000000000000..e54e8d3eafe56a617b9de13c361ed68657371e84
Binary files /dev/null and b/src/assets/icons/icon-384x384.png differ
diff --git a/src/assets/icons/icon-512x512.png b/src/assets/icons/icon-512x512.png
new file mode 100644
index 0000000000000000000000000000000000000000..51ee297df1cbeb0354814ffe95afa6e4bc86ea23
Binary files /dev/null and b/src/assets/icons/icon-512x512.png differ
diff --git a/src/assets/icons/icon-72x72.png b/src/assets/icons/icon-72x72.png
new file mode 100644
index 0000000000000000000000000000000000000000..2814a3f30caf3abf4de2ac85082ef83888b4b479
Binary files /dev/null and b/src/assets/icons/icon-72x72.png differ
diff --git a/src/assets/icons/icon-96x96.png b/src/assets/icons/icon-96x96.png
new file mode 100644
index 0000000000000000000000000000000000000000..d271025c4f22c7ba3c5f43ccfcab0e52ebbe80ca
Binary files /dev/null and b/src/assets/icons/icon-96x96.png differ
diff --git a/src/index.html b/src/index.html
index 24fc414e26f12665c3ac6a32851b93ac0a8cf0a7..4bef6793898f050aa1de1f863c688fbdc14ffd4f 100644
--- a/src/index.html
+++ b/src/index.html
@@ -14,6 +14,8 @@
    <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#ffffff">
 
    <meta name="viewport" content="width=device-width, initial-scale=1">
+  <link rel="manifest" href="manifest.webmanifest">
+  <meta name="theme-color" content="#1976d2">
 </head>
 
 <body>
@@ -41,57 +43,32 @@
       </style>
       <div class="app-loading">
          <div class="logo">
-            <svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#"
-               xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg"
-               xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-               xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" id="svg3406" version="1.1"
-               inkscape:version="0.92.3 (2405546, 2018-03-11)" width="167.55714" height="167.55714"
-               viewBox="0 0 167.55714 167.55714" sodipodi:docname="cassiopee_logo.svg">
+            <svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" id="svg3406" version="1.1" inkscape:version="0.92.3 (2405546, 2018-03-11)" width="167.55714" height="167.55714" viewBox="0 0 167.55714 167.55714" sodipodi:docname="cassiopee_logo.svg">
                <metadata id="metadata3412">
-                  <rdf:RDF>
-                     <cc:Work rdf:about="">
+                  <rdf:rdf>
+                     <cc:work rdf:about="">
                         <dc:format>image/svg+xml</dc:format>
-                        <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" ></dc:type>
+                        <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"></dc:type>
                         <dc:title></dc:title>
-                     </cc:Work>
-                  </rdf:RDF>
+                     </cc:work>
+                  </rdf:rdf>
                </metadata>
                <defs id="defs3410"></defs>
                <g inkscape:groupmode="layer" id="layer1" inkscape:label="background">
-                  <rect
-                     style="fill:#003a80;stroke:none;stroke-width:8;stroke-miterlimit:4;stroke-dasharray:none;fill-opacity:1;stroke-opacity:1;stroke-linejoin:round"
-                     id="fond" width="165.55714" height="165.55714" x="1" y="1"></rect>
+                  <rect style="fill:#003a80;stroke:none;stroke-width:8;stroke-miterlimit:4;stroke-dasharray:none;fill-opacity:1;stroke-opacity:1;stroke-linejoin:round" id="fond" width="165.55714" height="165.55714" x="1" y="1"></rect>
                </g>
                <g inkscape:groupmode="layer" id="calque_traits" inkscape:label="traits">
-                  <path
-                     style="fill:#80b3ff;fill-rule:evenodd;stroke:#4dbbe9;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-                     d="M 16.234557,39.786389 36.297745,77.631687" id="trait_1" inkscape:connector-curvature="0"></path>
-                  <path
-                     style="fill:#80b3ff;fill-rule:evenodd;stroke:#4dbbe9;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-                     d="m 47.234816,83.975938 27.27422,0.39174" id="trait_2" inkscape:connector-curvature="0"></path>
-                  <path
-                     style="fill:#80b3ff;fill-rule:evenodd;stroke:#4dbbe9;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-                     d="M 85.615846,92.002058 101.01379,128.05358" id="trait_3" inkscape:connector-curvature="0"></path>
-                  <path
-                     style="fill:#80b3ff;fill-rule:evenodd;stroke:#4dbbe9;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-                     d="m 145.82968,107.86632 -35.62153,23.78874" id="trait_4" inkscape:connector-curvature="0"></path>
+                  <path style="fill:#80b3ff;fill-rule:evenodd;stroke:#4dbbe9;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M 16.234557,39.786389 36.297745,77.631687" id="trait_1" inkscape:connector-curvature="0"></path>
+                  <path style="fill:#80b3ff;fill-rule:evenodd;stroke:#4dbbe9;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="m 47.234816,83.975938 27.27422,0.39174" id="trait_2" inkscape:connector-curvature="0"></path>
+                  <path style="fill:#80b3ff;fill-rule:evenodd;stroke:#4dbbe9;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M 85.615846,92.002058 101.01379,128.05358" id="trait_3" inkscape:connector-curvature="0"></path>
+                  <path style="fill:#80b3ff;fill-rule:evenodd;stroke:#4dbbe9;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="m 145.82968,107.86632 -35.62153,23.78874" id="trait_4" inkscape:connector-curvature="0"></path>
                </g>
                <g inkscape:groupmode="layer" id="calque_points" inkscape:label="points">
-                  <circle
-                     style="fill:#ffffff;stroke:#003a80;stroke-width:10;stroke-miterlimit:66;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke markers fill"
-                     id="point_1" cx="12.879179" cy="34.64555" r="6"></circle>
-                  <circle
-                     style="fill:#ffffff;stroke:#003a80;stroke-width:10;stroke-miterlimit:66;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke markers fill"
-                     id="point_2" cx="39.734871" cy="83.581924" r="10"></circle>
-                  <circle
-                     style="fill:#ffffff;stroke:#003a80;stroke-width:10;stroke-linejoin:round;stroke-miterlimit:66;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke markers fill"
-                     id="point_3" cx="82.500542" cy="84.860001" r="10"></circle>
-                  <circle
-                     style="fill:#ffffff;stroke:#003a80;stroke-width:10;stroke-miterlimit:66;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke markers fill"
-                     id="point_4" cx="104.12913" cy="135.35852" r="10"></circle>
-                  <circle
-                     style="fill:#ffffff;stroke:#003a80;stroke-width:10;stroke-miterlimit:66;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke markers fill"
-                     id="point_5" cx="151.57199" cy="103.73587" r="10"></circle>
+                  <circle style="fill:#ffffff;stroke:#003a80;stroke-width:10;stroke-miterlimit:66;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke markers fill" id="point_1" cx="12.879179" cy="34.64555" r="6"></circle>
+                  <circle style="fill:#ffffff;stroke:#003a80;stroke-width:10;stroke-miterlimit:66;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke markers fill" id="point_2" cx="39.734871" cy="83.581924" r="10"></circle>
+                  <circle style="fill:#ffffff;stroke:#003a80;stroke-width:10;stroke-linejoin:round;stroke-miterlimit:66;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke markers fill" id="point_3" cx="82.500542" cy="84.860001" r="10"></circle>
+                  <circle style="fill:#ffffff;stroke:#003a80;stroke-width:10;stroke-miterlimit:66;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke markers fill" id="point_4" cx="104.12913" cy="135.35852" r="10"></circle>
+                  <circle style="fill:#ffffff;stroke:#003a80;stroke-width:10;stroke-miterlimit:66;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke markers fill" id="point_5" cx="151.57199" cy="103.73587" r="10"></circle>
                </g>
             </svg>
          </div>
@@ -282,6 +259,7 @@
       }
    </script>
 
+  <noscript>Please enable JavaScript to continue using this application.</noscript>
 </body>
 
 </html>
\ No newline at end of file
diff --git a/src/manifest.webmanifest b/src/manifest.webmanifest
new file mode 100644
index 0000000000000000000000000000000000000000..43b4e9d2bdac1dba56b159d308cd217ded25b056
--- /dev/null
+++ b/src/manifest.webmanifest
@@ -0,0 +1,59 @@
+{
+  "name": "Cassiopee, tools for designing fish crossing devices for upstream and downstream migrations and hydraulic calculation for environmental and agricultural engineering",
+  "short_name": "Cassiopee",
+  "theme_color": "#1976d2",
+  "background_color": "#fafafa",
+  "display": "standalone",
+  "scope": "./",
+  "start_url": "./",
+  "icons": [
+    {
+      "src": "assets/icons/icon-72x72.png",
+      "sizes": "72x72",
+      "type": "image/png",
+      "purpose": "maskable any"
+    },
+    {
+      "src": "assets/icons/icon-96x96.png",
+      "sizes": "96x96",
+      "type": "image/png",
+      "purpose": "maskable any"
+    },
+    {
+      "src": "assets/icons/icon-128x128.png",
+      "sizes": "128x128",
+      "type": "image/png",
+      "purpose": "maskable any"
+    },
+    {
+      "src": "assets/icons/icon-144x144.png",
+      "sizes": "144x144",
+      "type": "image/png",
+      "purpose": "maskable any"
+    },
+    {
+      "src": "assets/icons/icon-152x152.png",
+      "sizes": "152x152",
+      "type": "image/png",
+      "purpose": "maskable any"
+    },
+    {
+      "src": "assets/icons/icon-192x192.png",
+      "sizes": "192x192",
+      "type": "image/png",
+      "purpose": "maskable any"
+    },
+    {
+      "src": "assets/icons/icon-384x384.png",
+      "sizes": "384x384",
+      "type": "image/png",
+      "purpose": "maskable any"
+    },
+    {
+      "src": "assets/icons/icon-512x512.png",
+      "sizes": "512x512",
+      "type": "image/png",
+      "purpose": "maskable any"
+    }
+  ]
+}