diff --git a/package-lock.json b/package-lock.json
index ed750d69585d76c7d3f9d3c9af0b5b07b02e8126..aac4365c145df2276e626c9152f58a9009190219 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "geocontrib-frontend",
-  "version": "2.1.0",
+  "version": "2.2.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -1104,6 +1104,54 @@
         "to-fast-properties": "^2.0.0"
       }
     },
+    "@fortawesome/fontawesome-common-types": {
+      "version": "0.2.36",
+      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz",
+      "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg=="
+    },
+    "@fortawesome/fontawesome-free": {
+      "version": "5.15.4",
+      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz",
+      "integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==",
+      "dev": true
+    },
+    "@fortawesome/fontawesome-svg-core": {
+      "version": "1.2.36",
+      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.36.tgz",
+      "integrity": "sha512-YUcsLQKYb6DmaJjIHdDWpBIGCcyE/W+p/LMGvjQem55Mm2XWVAP5kWTMKWLv9lwpCVjpLxPyOMOyUocP1GxrtA==",
+      "requires": {
+        "@fortawesome/fontawesome-common-types": "^0.2.36"
+      }
+    },
+    "@fortawesome/free-brands-svg-icons": {
+      "version": "5.15.4",
+      "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.15.4.tgz",
+      "integrity": "sha512-f1witbwycL9cTENJegcmcZRYyawAFbm8+c6IirLmwbbpqz46wyjbQYLuxOc7weXFXfB7QR8/Vd2u5R3q6JYD9g==",
+      "requires": {
+        "@fortawesome/fontawesome-common-types": "^0.2.36"
+      }
+    },
+    "@fortawesome/free-regular-svg-icons": {
+      "version": "5.15.4",
+      "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.4.tgz",
+      "integrity": "sha512-9VNNnU3CXHy9XednJ3wzQp6SwNwT3XaM26oS4Rp391GsxVYA+0oDR2J194YCIWf7jNRCYKjUCOduxdceLrx+xw==",
+      "requires": {
+        "@fortawesome/fontawesome-common-types": "^0.2.36"
+      }
+    },
+    "@fortawesome/free-solid-svg-icons": {
+      "version": "5.15.4",
+      "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz",
+      "integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==",
+      "requires": {
+        "@fortawesome/fontawesome-common-types": "^0.2.36"
+      }
+    },
+    "@fortawesome/vue-fontawesome": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-2.0.6.tgz",
+      "integrity": "sha512-V3vT3flY15AKbUS31aZOP12awQI3aAzkr2B1KnqcHLmwrmy51DW3pwyBczKdypV8QxBZ8U68Hl2XxK2nudTxpg=="
+    },
     "@hapi/address": {
       "version": "2.1.4",
       "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz",
@@ -1154,6 +1202,19 @@
         "postcss": "^7.0.0"
       }
     },
+    "@mapbox/point-geometry": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz",
+      "integrity": "sha1-ioP5M1x4YO/6Lu7KJUMyqgru2PI="
+    },
+    "@mapbox/vector-tile": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-1.3.1.tgz",
+      "integrity": "sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==",
+      "requires": {
+        "@mapbox/point-geometry": "~0.1.0"
+      }
+    },
     "@mrmlnc/readdir-enhanced": {
       "version": "2.2.1",
       "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
@@ -2174,6 +2235,12 @@
       "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
       "dev": true
     },
+    "array-back": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz",
+      "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==",
+      "dev": true
+    },
     "array-flatten": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
@@ -3419,11 +3486,22 @@
         "delayed-stream": "~1.0.0"
       }
     },
+    "command-line-args": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.0.tgz",
+      "integrity": "sha512-4zqtU1hYsSJzcJBOcNZIbW5Fbk9BkjCp1pZVhQKoRaWL5J7N4XphDLwo8aWwdQpTugxwu+jf9u2ZhkXiqp5Z6A==",
+      "dev": true,
+      "requires": {
+        "array-back": "^3.1.0",
+        "find-replace": "^3.0.0",
+        "lodash.camelcase": "^4.3.0",
+        "typical": "^4.0.0"
+      }
+    },
     "commander": {
       "version": "2.17.1",
       "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
-      "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
-      "dev": true
+      "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg=="
     },
     "common-tags": {
       "version": "1.8.0",
@@ -3766,6 +3844,16 @@
       "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
       "dev": true
     },
+    "cors": {
+      "version": "2.8.5",
+      "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
+      "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
+      "dev": true,
+      "requires": {
+        "object-assign": "^4",
+        "vary": "^1"
+      }
+    },
     "cosmiconfig": {
       "version": "5.2.1",
       "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
@@ -5373,6 +5461,15 @@
         "pkg-dir": "^4.1.0"
       }
     },
+    "find-replace": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz",
+      "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==",
+      "dev": true,
+      "requires": {
+        "array-back": "^3.0.1"
+      }
+    },
     "find-up": {
       "version": "4.1.0",
       "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
@@ -6084,8 +6181,7 @@
     "ieee754": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
-      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
-      "dev": true
+      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
     },
     "iferr": {
       "version": "0.1.5",
@@ -6882,6 +6978,17 @@
       "resolved": "https://registry.npmjs.org/leaflet-draw/-/leaflet-draw-1.0.4.tgz",
       "integrity": "sha512-rsQ6saQO5ST5Aj6XRFylr5zvarWgzWnrg46zQ1MEOEIHsppdC/8hnN8qMoFvACsPvTioAuysya/TVtog15tyAQ=="
     },
+    "leaflet.vectorgrid": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/leaflet.vectorgrid/-/leaflet.vectorgrid-1.3.0.tgz",
+      "integrity": "sha512-kWmj1pKM+MVdo/7Mg5zsB3YrGZvo/uIuiANV9MvWUFOG+Y2xAJzrteDhoIcCgTjHSSRJ36xdeGdIQVhuWjnCZw==",
+      "requires": {
+        "pbf": "^3.0.2",
+        "topojson-client": "^2.1.0",
+        "vector-tile": "^1.3.0",
+        "whatwg-fetch": "^2.0.3"
+      }
+    },
     "less": {
       "version": "3.13.1",
       "resolved": "https://registry.npmjs.org/less/-/less-3.13.1.tgz",
@@ -7047,6 +7154,19 @@
         }
       }
     },
+    "local-cors-proxy": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/local-cors-proxy/-/local-cors-proxy-1.1.0.tgz",
+      "integrity": "sha512-1UVrdG10HAT58TNZBhYSeMPkwQANuJunFsWBgEYOd1RChLDHGhvNPjUT8JsOlcqoJyr0QOH9cLx9IOLATf4j5w==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.3.2",
+        "command-line-args": "^5.0.2",
+        "cors": "^2.8.4",
+        "express": "^4.16.3",
+        "request": "^2.85.0"
+      }
+    },
     "locate-path": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@@ -7068,6 +7188,12 @@
       "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=",
       "dev": true
     },
+    "lodash.camelcase": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+      "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=",
+      "dev": true
+    },
     "lodash.debounce": {
       "version": "4.0.8",
       "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@@ -8213,6 +8339,15 @@
         }
       }
     },
+    "pbf": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz",
+      "integrity": "sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==",
+      "requires": {
+        "ieee754": "^1.1.12",
+        "resolve-protobuf-schema": "^2.1.0"
+      }
+    },
     "pbkdf2": {
       "version": "3.1.2",
       "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz",
@@ -8277,6 +8412,11 @@
         "ts-pnp": "^1.1.6"
       }
     },
+    "point-geometry": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/point-geometry/-/point-geometry-0.0.0.tgz",
+      "integrity": "sha1-b8vK16gDtkGCR91uScKFPFhNr/c="
+    },
     "portfinder": {
       "version": "1.0.28",
       "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz",
@@ -8952,6 +9092,11 @@
       "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
       "dev": true
     },
+    "protocol-buffers-schema": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz",
+      "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw=="
+    },
     "proxy-addr": {
       "version": "2.0.7",
       "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -9398,6 +9543,14 @@
       "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
       "dev": true
     },
+    "resolve-protobuf-schema": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz",
+      "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==",
+      "requires": {
+        "protocol-buffers-schema": "^3.3.1"
+      }
+    },
     "resolve-url": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
@@ -10846,6 +10999,14 @@
       "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
       "dev": true
     },
+    "topojson-client": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-2.1.0.tgz",
+      "integrity": "sha1-/59784mRGF4LQoTCsGroNPDqxsg=",
+      "requires": {
+        "commander": "2"
+      }
+    },
     "toposort": {
       "version": "1.0.7",
       "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz",
@@ -10932,6 +11093,12 @@
       "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
       "dev": true
     },
+    "typical": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz",
+      "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==",
+      "dev": true
+    },
     "uglify-js": {
       "version": "3.4.10",
       "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz",
@@ -11249,6 +11416,14 @@
       "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
       "dev": true
     },
+    "vector-tile": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/vector-tile/-/vector-tile-1.3.0.tgz",
+      "integrity": "sha1-BtUWqDsGPwTILvU5zxuxrr62lrQ=",
+      "requires": {
+        "point-geometry": "0.0.0"
+      }
+    },
     "vendors": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz",
@@ -12075,6 +12250,11 @@
       "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
       "dev": true
     },
+    "whatwg-fetch": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz",
+      "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng=="
+    },
     "which": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
diff --git a/package.json b/package.json
index b00e1bc1fb224879e7bf41aa88986e07e8b768e7..6288ae767b382e24b599d969739e7d3d9c545a0e 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,11 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
+    "@fortawesome/fontawesome-svg-core": "^1.2.36",
+    "@fortawesome/free-brands-svg-icons": "^5.15.4",
+    "@fortawesome/free-regular-svg-icons": "^5.15.4",
+    "@fortawesome/free-solid-svg-icons": "^5.15.4",
+    "@fortawesome/vue-fontawesome": "^2.0.6",
     "@mapbox/vector-tile": "^1.3.1",
     "@turf/flip": "^6.5.0",
     "axios": "^0.21.1",
@@ -26,6 +31,7 @@
     "vuex": "^3.6.2"
   },
   "devDependencies": {
+    "@fortawesome/fontawesome-free": "^5.15.4",
     "@vue/cli-plugin-babel": "~4.5.0",
     "@vue/cli-plugin-eslint": "~4.5.0",
     "@vue/cli-plugin-pwa": "~4.5.0",
diff --git a/public/config/config.json b/public/config/config.json
index 859464c3401983ee073000a70601cb67c0223024..65038a32551262edcccf998e4c66e7707f44de04 100644
--- a/public/config/config.json
+++ b/public/config/config.json
@@ -5,7 +5,7 @@
     "VUE_APP_LOCALE":"fr-FR",
     "VUE_APP_APPLICATION_NAME":"GéoContrib",
     "VUE_APP_APPLICATION_ABSTRACT":"Application de saisie d'informations géographiques contributive",
-    "VUE_APP_LOGO_PATH":"@/assets/img/logo-neogeo-circle.png",
+    "VUE_APP_LOGO_PATH":"/geocontrib/img/logo-neogeo-circle.png",
     "VUE_APP_DJANGO_BASE":"http://localhost:8010",
     "VUE_APP_DJANGO_API_BASE":"http://localhost:8010/api/",
     "DEFAULT_BASE_MAP":{
diff --git a/public/img/icons/android-chrome-192x192.png b/public/img/icons/android-chrome-192x192.png
index b02aa64d97167ad649e496908b35f14c603d9249..6cdb47eaf1fe19d451367d181cc4f817e65a655e 100644
Binary files a/public/img/icons/android-chrome-192x192.png and b/public/img/icons/android-chrome-192x192.png differ
diff --git a/public/img/icons/android-chrome-512x512.png b/public/img/icons/android-chrome-512x512.png
index 06088b011eccebb820b6e8de0cd244aa443208ba..226124806a29ad052689654f7e8fb70af5c72f9b 100644
Binary files a/public/img/icons/android-chrome-512x512.png and b/public/img/icons/android-chrome-512x512.png differ
diff --git a/public/img/icons/android-chrome-maskable-192x192.png b/public/img/icons/android-chrome-maskable-192x192.png
deleted file mode 100644
index 791e9c8c2c69ddb7be30cef2517dd6050b079cf0..0000000000000000000000000000000000000000
Binary files a/public/img/icons/android-chrome-maskable-192x192.png and /dev/null differ
diff --git a/public/img/icons/android-chrome-maskable-512x512.png b/public/img/icons/android-chrome-maskable-512x512.png
deleted file mode 100644
index 5f2098ed27e2f2878de62894b6c3bc31d07c585f..0000000000000000000000000000000000000000
Binary files a/public/img/icons/android-chrome-maskable-512x512.png and /dev/null differ
diff --git a/public/img/icons/apple-touch-icon-120x120.png b/public/img/icons/apple-touch-icon-120x120.png
deleted file mode 100644
index 1427cf62752646ad7217df0a61aa01fdef7475d1..0000000000000000000000000000000000000000
Binary files a/public/img/icons/apple-touch-icon-120x120.png and /dev/null differ
diff --git a/public/img/icons/apple-touch-icon-152x152.png b/public/img/icons/apple-touch-icon-152x152.png
deleted file mode 100644
index f24d454a2ecb8851bb893192b64ee09386d30e24..0000000000000000000000000000000000000000
Binary files a/public/img/icons/apple-touch-icon-152x152.png and /dev/null differ
diff --git a/public/img/icons/apple-touch-icon-180x180.png b/public/img/icons/apple-touch-icon-180x180.png
deleted file mode 100644
index 404e192a95ccccbede087203c42b1f25f6bc6e67..0000000000000000000000000000000000000000
Binary files a/public/img/icons/apple-touch-icon-180x180.png and /dev/null differ
diff --git a/public/img/icons/apple-touch-icon-60x60.png b/public/img/icons/apple-touch-icon-60x60.png
deleted file mode 100644
index cf10a5602e653bb126332934e2b7f34081c19a01..0000000000000000000000000000000000000000
Binary files a/public/img/icons/apple-touch-icon-60x60.png and /dev/null differ
diff --git a/public/img/icons/apple-touch-icon-76x76.png b/public/img/icons/apple-touch-icon-76x76.png
deleted file mode 100644
index c500769e3df9d6a6f1977ace8be4e63a8095e36a..0000000000000000000000000000000000000000
Binary files a/public/img/icons/apple-touch-icon-76x76.png and /dev/null differ
diff --git a/public/img/icons/apple-touch-icon.png b/public/img/icons/apple-touch-icon.png
index 03c0c5d5ec302ed7b0ee2c401df9427fb9d3c117..5ffc54a4f8b1f2a0b716fb4f5dc0cb045aa28b12 100644
Binary files a/public/img/icons/apple-touch-icon.png and b/public/img/icons/apple-touch-icon.png differ
diff --git a/public/img/icons/favicon-16x16.png b/public/img/icons/favicon-16x16.png
index 42af00963d81b8e39a30435c60ac482d1f8756e0..dfaab576ca4b539b968467eecdec33567bb0bafc 100644
Binary files a/public/img/icons/favicon-16x16.png and b/public/img/icons/favicon-16x16.png differ
diff --git a/public/img/icons/favicon-32x32.png b/public/img/icons/favicon-32x32.png
index 46ca04dee251a4fa85a2891a145fbe20cc619d96..c7dca04bdb68a81e35dd3d383097cc07a7f08604 100644
Binary files a/public/img/icons/favicon-32x32.png and b/public/img/icons/favicon-32x32.png differ
diff --git a/public/img/icons/favicon.ico b/public/img/icons/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..05ea7edf1b8b946f3407db8b22353d908f31fd2d
Binary files /dev/null and b/public/img/icons/favicon.ico differ
diff --git a/public/img/icons/msapplication-icon-144x144.png b/public/img/icons/msapplication-icon-144x144.png
deleted file mode 100644
index 7808237a18d4009501f950044f8388d13c5e1044..0000000000000000000000000000000000000000
Binary files a/public/img/icons/msapplication-icon-144x144.png and /dev/null differ
diff --git a/public/img/icons/mstile-150x150.png b/public/img/icons/mstile-150x150.png
deleted file mode 100644
index 3b37a43ae2fdef53050291d95da2e49f78cf398e..0000000000000000000000000000000000000000
Binary files a/public/img/icons/mstile-150x150.png and /dev/null differ
diff --git a/public/img/icons/safari-pinned-tab.svg b/public/img/icons/safari-pinned-tab.svg
deleted file mode 100644
index e44c0d5b0ff35e7facaed6353e0be801d4f3b10d..0000000000000000000000000000000000000000
--- a/public/img/icons/safari-pinned-tab.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M8.00251 14.9297L0 1.07422H6.14651L8.00251 4.27503L9.84583 1.07422H16L8.00251 14.9297Z" fill="black"/>
-</svg>
diff --git a/public/img/logo-neogeo-circle.png b/public/img/logo-neogeo-circle.png
new file mode 100644
index 0000000000000000000000000000000000000000..427c1c63b8051722f05406349a48a073ac7ba927
Binary files /dev/null and b/public/img/logo-neogeo-circle.png differ
diff --git a/src/App.vue b/src/App.vue
index 940e4ea9c7ee80e27d188c66d6a644d4be5a1ef1..954fe28fa431592cd8f246ee7d8b0e35c8a0c703 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -4,10 +4,7 @@
       <div class="menu container">
         <div class="ui inverted icon menu">
           <router-link to="/" class="header item">
-            <img
-              class="ui mini right spaced image"
-              src="@/assets/img/logo-neogeo-circle.png"
-            />
+            <img class="ui mini right spaced image" :src="logo" />
             <span class="desktop">
               {{ APPLICATION_NAME }}
             </span>
@@ -202,16 +199,19 @@ export default {
       "loader",
     ]),
     ...mapGetters(["project"]),
-    APPLICATION_NAME: function () {
+    APPLICATION_NAME() {
       return this.configuration.VUE_APP_APPLICATION_NAME;
     },
     PACKAGE_VERSION: () => process.env.PACKAGE_VERSION || "0",
-    userFullname: function () {
+    logo() {
+      return this.configuration.VUE_APP_LOGO_PATH;
+    },
+    userFullname() {
       if (this.user.first_name || this.user.last_name)
         return this.user.first_name + " " + this.user.last_name;
       return null;
     },
-    isAdmin: function () {
+    isAdmin() {
       return this.USER_LEVEL_PROJECTS &&
         this.USER_LEVEL_PROJECTS[this.project.slug] === "Administrateur projet"
         ? true
diff --git a/src/assets/icons/fa-icons.js b/src/assets/icons/fa-icons.js
new file mode 100644
index 0000000000000000000000000000000000000000..5e9fff5abcbe8853af77ce58452a4b98f77eb614
--- /dev/null
+++ b/src/assets/icons/fa-icons.js
@@ -0,0 +1,1005 @@
+const faIcons = [
+  'ad',
+  'address-book',
+  'address-card',
+  'adjust',
+  'air-freshener',
+  'align-center',
+  'align-justify',
+  'align-left',
+  'align-right',
+  'allergies',
+  'ambulance',
+  'american-sign-language-interpreting',
+  'anchor',
+  'angle-double-down',
+  'angle-double-left',
+  'angle-double-right',
+  'angle-double-up',
+  'angle-down',
+  'angle-left',
+  'angle-right',
+  'angle-up',
+  'angry',
+  'ankh',
+  'apple-alt',
+  'archive',
+  'archway',
+  'arrow-alt-circle-down',
+  'arrow-alt-circle-left',
+  'arrow-alt-circle-right',
+  'arrow-alt-circle-up',
+  'arrow-circle-down',
+  'arrow-circle-left',
+  'arrow-circle-right',
+  'arrow-circle-up',
+  'arrow-down',
+  'arrow-left',
+  'arrow-right',
+  'arrow-up',
+  'arrows-alt',
+  'arrows-alt-h',
+  'arrows-alt-v',
+  'assistive-listening-systems',
+  'asterisk',
+  'at',
+  'atlas',
+  'atom',
+  'audio-description',
+  'award',
+  'baby',
+  'baby-carriage',
+  'backspace',
+  'backward',
+  'bacon',
+  'bacteria',
+  'bacterium',
+  'bahai',
+  'balance-scale',
+  'balance-scale-left',
+  'balance-scale-right',
+  'ban',
+  'band-aid',
+  'barcode',
+  'bars',
+  'baseball-ball',
+  'basketball-ball',
+  'bath',
+  'battery-empty',
+  'battery-full',
+  'battery-half',
+  'battery-quarter',
+  'battery-three-quarters',
+  'bed',
+  'beer',
+  'bell',
+  'bell-slash',
+  'bezier-curve',
+  'bible',
+  'bicycle',
+  'biking',
+  'binoculars',
+  'biohazard',
+  'birthday-cake',
+  'blender',
+  'blender-phone',
+  'blind',
+  'blog',
+  'bold',
+  'bolt',
+  'bomb',
+  'bone',
+  'bong',
+  'book',
+  'book-dead',
+  'book-medical',
+  'book-open',
+  'book-reader',
+  'bookmark',
+  'border-all',
+  'border-none',
+  'border-style',
+  'bowling-ball',
+  'box',
+  'box-open',
+  'box-tissue',
+  'boxes',
+  'braille',
+  'brain',
+  'bread-slice',
+  'briefcase',
+  'briefcase-medical',
+  'broadcast-tower',
+  'broom',
+  'brush',
+  'bug',
+  'building',
+  'bullhorn',
+  'bullseye',
+  'burn',
+  'bus',
+  'bus-alt',
+  'business-time',
+  'calculator',
+  'calendar',
+  'calendar-alt',
+  'calendar-check',
+  'calendar-day',
+  'calendar-minus',
+  'calendar-plus',
+  'calendar-times',
+  'calendar-week',
+  'camera',
+  'camera-retro',
+  'campground',
+  'candy-cane',
+  'cannabis',
+  'capsules',
+  'car',
+  'car-alt',
+  'car-battery',
+  'car-crash',
+  'car-side',
+  'caravan',
+  'caret-down',
+  'caret-left',
+  'caret-right',
+  'caret-square-down',
+  'caret-square-left',
+  'caret-square-right',
+  'caret-square-up',
+  'caret-up',
+  'carrot',
+  'cart-arrow-down',
+  'cart-plus',
+  'cash-register',
+  'cat',
+  'certificate',
+  'chair',
+  'chalkboard',
+  'chalkboard-teacher',
+  'charging-station',
+  'chart-area',
+  'chart-bar',
+  'chart-line',
+  'chart-pie',
+  'check',
+  'check-circle',
+  'check-double',
+  'check-square',
+  'cheese',
+  'chess',
+  'chess-bishop',
+  'chess-board',
+  'chess-king',
+  'chess-knight',
+  'chess-pawn',
+  'chess-queen',
+  'chess-rook',
+  'chevron-circle-down',
+  'chevron-circle-left',
+  'chevron-circle-right',
+  'chevron-circle-up',
+  'chevron-down',
+  'chevron-left',
+  'chevron-right',
+  'chevron-up',
+  'child',
+  'church',
+  'circle',
+  'circle-notch',
+  'city',
+  'clinic-medical',
+  'clipboard',
+  'clipboard-check',
+  'clipboard-list',
+  'clock',
+  'clone',
+  'closed-captioning',
+  'cloud',
+  'cloud-download-alt',
+  'cloud-meatball',
+  'cloud-moon',
+  'cloud-moon-rain',
+  'cloud-rain',
+  'cloud-showers-heavy',
+  'cloud-sun',
+  'cloud-sun-rain',
+  'cloud-upload-alt',
+  'cocktail',
+  'code',
+  'code-branch',
+  'coffee',
+  'cog',
+  'cogs',
+  'coins',
+  'columns',
+  'comment',
+  'comment-alt',
+  'comment-dollar',
+  'comment-dots',
+  'comment-medical',
+  'comment-slash',
+  'comments',
+  'comments-dollar',
+  'compact-disc',
+  'compass',
+  'compress',
+  'compress-alt',
+  'compress-arrows-alt',
+  'concierge-bell',
+  'cookie',
+  'cookie-bite',
+  'copy',
+  'copyright',
+  'couch',
+  'credit-card',
+  'crop',
+  'crop-alt',
+  'cross',
+  'crosshairs',
+  'crow',
+  'crown',
+  'crutch',
+  'cube',
+  'cubes',
+  'cut',
+  'database',
+  'deaf',
+  'democrat',
+  'desktop',
+  'dharmachakra',
+  'diagnoses',
+  'dice',
+  'dice-d20',
+  'dice-d6',
+  'dice-five',
+  'dice-four',
+  'dice-one',
+  'dice-six',
+  'dice-three',
+  'dice-two',
+  'digital-tachograph',
+  'directions',
+  'disease',
+  'divide',
+  'dizzy',
+  'dna',
+  'dog',
+  'dollar-sign',
+  'dolly',
+  'dolly-flatbed',
+  'donate',
+  'door-closed',
+  'door-open',
+  'dot-circle',
+  'dove',
+  'download',
+  'drafting-compass',
+  'dragon',
+  'draw-polygon',
+  'drum',
+  'drum-steelpan',
+  'drumstick-bite',
+  'dumbbell',
+  'dumpster',
+  'dumpster-fire',
+  'dungeon',
+  'edit',
+  'egg',
+  'eject',
+  'ellipsis-h',
+  'ellipsis-v',
+  'envelope',
+  'envelope-open',
+  'envelope-open-text',
+  'envelope-square',
+  'equals',
+  'eraser',
+  'ethernet',
+  'euro-sign',
+  'exchange-alt',
+  'exclamation',
+  'exclamation-circle',
+  'exclamation-triangle',
+  'expand',
+  'expand-alt',
+  'expand-arrows-alt',
+  'external-link-alt',
+  'external-link-square-alt',
+  'eye',
+  'eye-dropper',
+  'eye-slash',
+  'fan',
+  'fast-backward',
+  'fast-forward',
+  'faucet',
+  'fax',
+  'feather',
+  'feather-alt',
+  'female',
+  'fighter-jet',
+  'file',
+  'file-alt',
+  'file-archive',
+  'file-audio',
+  'file-code',
+  'file-contract',
+  'file-csv',
+  'file-download',
+  'file-excel',
+  'file-export',
+  'file-image',
+  'file-import',
+  'file-invoice',
+  'file-invoice-dollar',
+  'file-medical',
+  'file-medical-alt',
+  'file-pdf',
+  'file-powerpoint',
+  'file-prescription',
+  'file-signature',
+  'file-upload',
+  'file-video',
+  'file-word',
+  'fill',
+  'fill-drip',
+  'film',
+  'filter',
+  'fingerprint',
+  'fire',
+  'fire-alt',
+  'fire-extinguisher',
+  'first-aid',
+  'fish',
+  'fist-raised',
+  'flag',
+  'flag-checkered',
+  'flag-usa',
+  'flask',
+  'flushed',
+  'folder',
+  'folder-minus',
+  'folder-open',
+  'folder-plus',
+  'font',
+  'football-ball',
+  'forward',
+  'frog',
+  'frown',
+  'frown-open',
+  'funnel-dollar',
+  'futbol',
+  'gamepad',
+  'gas-pump',
+  'gavel',
+  'gem',
+  'genderless',
+  'ghost',
+  'gift',
+  'gifts',
+  'glass-cheers',
+  'glass-martini',
+  'glass-martini-alt',
+  'glass-whiskey',
+  'glasses',
+  'globe',
+  'globe-africa',
+  'globe-americas',
+  'globe-asia',
+  'globe-europe',
+  'golf-ball',
+  'gopuram',
+  'graduation-cap',
+  'greater-than',
+  'greater-than-equal',
+  'grimace',
+  'grin',
+  'grin-alt',
+  'grin-beam',
+  'grin-beam-sweat',
+  'grin-hearts',
+  'grin-squint',
+  'grin-squint-tears',
+  'grin-stars',
+  'grin-tears',
+  'grin-tongue',
+  'grin-tongue-squint',
+  'grin-tongue-wink',
+  'grin-wink',
+  'grip-horizontal',
+  'grip-lines',
+  'grip-lines-vertical',
+  'grip-vertical',
+  'guitar',
+  'h-square',
+  'hamburger',
+  'hammer',
+  'hamsa',
+  'hand-holding',
+  'hand-holding-heart',
+  'hand-holding-medical',
+  'hand-holding-usd',
+  'hand-holding-water',
+  'hand-lizard',
+  'hand-middle-finger',
+  'hand-paper',
+  'hand-peace',
+  'hand-point-down',
+  'hand-point-left',
+  'hand-point-right',
+  'hand-point-up',
+  'hand-pointer',
+  'hand-rock',
+  'hand-scissors',
+  'hand-sparkles',
+  'hand-spock',
+  'hands',
+  'hands-helping',
+  'hands-wash',
+  'handshake',
+  'handshake-alt-slash',
+  'handshake-slash',
+  'hanukiah',
+  'hard-hat',
+  'hashtag',
+  'hat-cowboy',
+  'hat-cowboy-side',
+  'hat-wizard',
+  'hdd',
+  'head-side-cough',
+  'head-side-cough-slash',
+  'head-side-mask',
+  'head-side-virus',
+  'heading',
+  'headphones',
+  'headphones-alt',
+  'headset',
+  'heart',
+  'heart-broken',
+  'heartbeat',
+  'helicopter',
+  'highlighter',
+  'hiking',
+  'hippo',
+  'history',
+  'hockey-puck',
+  'holly-berry',
+  'home',
+  'horse',
+  'horse-head',
+  'hospital',
+  'hospital-alt',
+  'hospital-symbol',
+  'hospital-user',
+  'hot-tub',
+  'hotdog',
+  'hotel',
+  'hourglass',
+  'hourglass-end',
+  'hourglass-half',
+  'hourglass-start',
+  'house-damage',
+  'house-user',
+  'hryvnia',
+  'i-cursor',
+  'ice-cream',
+  'icicles',
+  'icons',
+  'id-badge',
+  'id-card',
+  'id-card-alt',
+  'igloo',
+  'image',
+  'images',
+  'inbox',
+  'indent',
+  'industry',
+  'infinity',
+  'info',
+  'info-circle',
+  'italic',
+  'jedi',
+  'joint',
+  'journal-whills',
+  'kaaba',
+  'key',
+  'keyboard',
+  'khanda',
+  'kiss',
+  'kiss-beam',
+  'kiss-wink-heart',
+  'kiwi-bird',
+  'landmark',
+  'language',
+  'laptop',
+  'laptop-code',
+  'laptop-house',
+  'laptop-medical',
+  'laugh',
+  'laugh-beam',
+  'laugh-squint',
+  'laugh-wink',
+  'layer-group',
+  'leaf',
+  'lemon',
+  'less-than',
+  'less-than-equal',
+  'level-down-alt',
+  'level-up-alt',
+  'life-ring',
+  'lightbulb',
+  'link',
+  'lira-sign',
+  'list',
+  'list-alt',
+  'list-ol',
+  'list-ul',
+  'location-arrow',
+  'lock',
+  'lock-open',
+  'long-arrow-alt-down',
+  'long-arrow-alt-left',
+  'long-arrow-alt-right',
+  'long-arrow-alt-up',
+  'low-vision',
+  'luggage-cart',
+  'lungs',
+  'lungs-virus',
+  'magic',
+  'magnet',
+  'mail-bulk',
+  'male',
+  'map',
+  'map-marked',
+  'map-marked-alt',
+  'map-marker',
+  'map-marker-alt',
+  'map-pin',
+  'map-signs',
+  'marker',
+  'mars',
+  'mars-double',
+  'mars-stroke',
+  'mars-stroke-h',
+  'mars-stroke-v',
+  'mask',
+  'medal',
+  'medkit',
+  'meh',
+  'meh-blank',
+  'meh-rolling-eyes',
+  'memory',
+  'menorah',
+  'mercury',
+  'meteor',
+  'microchip',
+  'microphone',
+  'microphone-alt',
+  'microphone-alt-slash',
+  'microphone-slash',
+  'microscope',
+  'minus',
+  'minus-circle',
+  'minus-square',
+  'mitten',
+  'mobile',
+  'mobile-alt',
+  'money-bill',
+  'money-bill-alt',
+  'money-bill-wave',
+  'money-bill-wave-alt',
+  'money-check',
+  'money-check-alt',
+  'monument',
+  'moon',
+  'mortar-pestle',
+  'mosque',
+  'motorcycle',
+  'mountain',
+  'mouse',
+  'mouse-pointer',
+  'mug-hot',
+  'music',
+  'network-wired',
+  'neuter',
+  'newspaper',
+  'not-equal',
+  'notes-medical',
+  'object-group',
+  'object-ungroup',
+  'oil-can',
+  'om',
+  'otter',
+  'outdent',
+  'pager',
+  'paint-brush',
+  'paint-roller',
+  'palette',
+  'pallet',
+  'paper-plane',
+  'paperclip',
+  'parachute-box',
+  'paragraph',
+  'parking',
+  'passport',
+  'pastafarianism',
+  'paste',
+  'pause',
+  'pause-circle',
+  'paw',
+  'peace',
+  'pen',
+  'pen-alt',
+  'pen-fancy',
+  'pen-nib',
+  'pen-square',
+  'pencil-alt',
+  'pencil-ruler',
+  'people-arrows',
+  'people-carry',
+  'pepper-hot',
+  'percent',
+  'percentage',
+  'person-booth',
+  'phone',
+  'phone-alt',
+  'phone-slash',
+  'phone-square',
+  'phone-square-alt',
+  'phone-volume',
+  'photo-video',
+  'piggy-bank',
+  'pills',
+  'pizza-slice',
+  'place-of-worship',
+  'plane',
+  'plane-arrival',
+  'plane-departure',
+  'plane-slash',
+  'play',
+  'play-circle',
+  'plug',
+  'plus',
+  'plus-circle',
+  'plus-square',
+  'podcast',
+  'poll',
+  'poll-h',
+  'poo',
+  'poo-storm',
+  'poop',
+  'portrait',
+  'pound-sign',
+  'power-off',
+  'pray',
+  'praying-hands',
+  'prescription',
+  'prescription-bottle',
+  'prescription-bottle-alt',
+  'print',
+  'procedures',
+  'project-diagram',
+  'pump-medical',
+  'pump-soap',
+  'puzzle-piece',
+  'qrcode',
+  'question',
+  'question-circle',
+  'quidditch',
+  'quote-left',
+  'quote-right',
+  'quran',
+  'radiation',
+  'radiation-alt',
+  'rainbow',
+  'random',
+  'receipt',
+  'record-vinyl',
+  'recycle',
+  'redo',
+  'redo-alt',
+  'registered',
+  'remove-format',
+  'reply',
+  'reply-all',
+  'republican',
+  'restroom',
+  'retweet',
+  'ribbon',
+  'ring',
+  'road',
+  'robot',
+  'rocket',
+  'route',
+  'rss',
+  'rss-square',
+  'ruble-sign',
+  'ruler',
+  'ruler-combined',
+  'ruler-horizontal',
+  'ruler-vertical',
+  'running',
+  'rupee-sign',
+  'sad-cry',
+  'sad-tear',
+  'satellite',
+  'satellite-dish',
+  'save',
+  'school',
+  'screwdriver',
+  'scroll',
+  'sd-card',
+  'search',
+  'search-dollar',
+  'search-location',
+  'search-minus',
+  'search-plus',
+  'seedling',
+  'server',
+  'shapes',
+  'share',
+  'share-alt',
+  'share-alt-square',
+  'share-square',
+  'shekel-sign',
+  'shield-alt',
+  'shield-virus',
+  'ship',
+  'shipping-fast',
+  'shoe-prints',
+  'shopping-bag',
+  'shopping-basket',
+  'shopping-cart',
+  'shower',
+  'shuttle-van',
+  'sign',
+  'sign-in-alt',
+  'sign-language',
+  'sign-out-alt',
+  'signal',
+  'signature',
+  'sim-card',
+  'sink',
+  'sitemap',
+  'skating',
+  'skiing',
+  'skiing-nordic',
+  'skull',
+  'skull-crossbones',
+  'slash',
+  'sleigh',
+  'sliders-h',
+  'smile',
+  'smile-beam',
+  'smile-wink',
+  'smog',
+  'smoking',
+  'smoking-ban',
+  'sms',
+  'snowboarding',
+  'snowflake',
+  'snowman',
+  'snowplow',
+  'soap',
+  'socks',
+  'solar-panel',
+  'sort',
+  'sort-alpha-down',
+  'sort-alpha-down-alt',
+  'sort-alpha-up',
+  'sort-alpha-up-alt',
+  'sort-amount-down',
+  'sort-amount-down-alt',
+  'sort-amount-up',
+  'sort-amount-up-alt',
+  'sort-down',
+  'sort-numeric-down',
+  'sort-numeric-down-alt',
+  'sort-numeric-up',
+  'sort-numeric-up-alt',
+  'sort-up',
+  'spa',
+  'space-shuttle',
+  'spell-check',
+  'spider',
+  'spinner',
+  'splotch',
+  'spray-can',
+  'square',
+  'square-full',
+  'square-root-alt',
+  'stamp',
+  'star',
+  'star-and-crescent',
+  'star-half',
+  'star-half-alt',
+  'star-of-david',
+  'star-of-life',
+  'step-backward',
+  'step-forward',
+  'stethoscope',
+  'sticky-note',
+  'stop',
+  'stop-circle',
+  'stopwatch',
+  'stopwatch-20',
+  'store',
+  'store-alt',
+  'store-alt-slash',
+  'store-slash',
+  'stream',
+  'street-view',
+  'strikethrough',
+  'stroopwafel',
+  'subscript',
+  'subway',
+  'suitcase',
+  'suitcase-rolling',
+  'sun',
+  'superscript',
+  'surprise',
+  'swatchbook',
+  'swimmer',
+  'swimming-pool',
+  'synagogue',
+  'sync',
+  'sync-alt',
+  'syringe',
+  'table',
+  'table-tennis',
+  'tablet',
+  'tablet-alt',
+  'tablets',
+  'tachometer-alt',
+  'tag',
+  'tags',
+  'tape',
+  'tasks',
+  'taxi',
+  'teeth',
+  'teeth-open',
+  'temperature-high',
+  'temperature-low',
+  'tenge',
+  'terminal',
+  'text-height',
+  'text-width',
+  'th',
+  'th-large',
+  'th-list',
+  'theater-masks',
+  'thermometer',
+  'thermometer-empty',
+  'thermometer-full',
+  'thermometer-half',
+  'thermometer-quarter',
+  'thermometer-three-quarters',
+  'thumbs-down',
+  'thumbs-up',
+  'thumbtack',
+  'ticket-alt',
+  'times',
+  'times-circle',
+  'tint',
+  'tint-slash',
+  'tired',
+  'toggle-off',
+  'toggle-on',
+  'toilet',
+  'toilet-paper',
+  'toilet-paper-slash',
+  'toolbox',
+  'tools',
+  'tooth',
+  'torah',
+  'torii-gate',
+  'tractor',
+  'trademark',
+  'traffic-light',
+  'trailer',
+  'train',
+  'tram',
+  'transgender',
+  'transgender-alt',
+  'trash',
+  'trash-alt',
+  'trash-restore',
+  'trash-restore-alt',
+  'tree',
+  'trophy',
+  'truck',
+  'truck-loading',
+  'truck-monster',
+  'truck-moving',
+  'truck-pickup',
+  'tshirt',
+  'tty',
+  'tv',
+  'umbrella',
+  'umbrella-beach',
+  'underline',
+  'undo',
+  'undo-alt',
+  'universal-access',
+  'university',
+  'unlink',
+  'unlock',
+  'unlock-alt',
+  'upload',
+  'user',
+  'user-alt',
+  'user-alt-slash',
+  'user-astronaut',
+  'user-check',
+  'user-circle',
+  'user-clock',
+  'user-cog',
+  'user-edit',
+  'user-friends',
+  'user-graduate',
+  'user-injured',
+  'user-lock',
+  'user-md',
+  'user-minus',
+  'user-ninja',
+  'user-nurse',
+  'user-plus',
+  'user-secret',
+  'user-shield',
+  'user-slash',
+  'user-tag',
+  'user-tie',
+  'user-times',
+  'users',
+  'users-cog',
+  'users-slash',
+  'utensil-spoon',
+  'utensils',
+  'vector-square',
+  'venus',
+  'venus-double',
+  'venus-mars',
+  'vest',
+  'vest-patches',
+  'vial',
+  'vials',
+  'video',
+  'video-slash',
+  'vihara',
+  'virus',
+  'virus-slash',
+  'viruses',
+  'voicemail',
+  'volleyball-ball',
+  'volume-down',
+  'volume-mute',
+  'volume-off',
+  'volume-up',
+  'vote-yea',
+  'vr-cardboard',
+  'walking',
+  'wallet',
+  'warehouse',
+  'water',
+  'wave-square',
+  'weight',
+  'weight-hanging',
+  'wheelchair',
+  'wifi',
+  'wind',
+  'window-close',
+  'window-maximize',
+  'window-minimize',
+  'window-restore',
+  'wine-bottle',
+  'wine-glass',
+  'wine-glass-alt',
+  'won-sign',
+  'wrench',
+  'x-ray',
+  'yen-sign',
+  'yin-yang'
+];
+
+export default faIcons;
diff --git a/src/assets/js/map-util.js b/src/assets/js/map-util.js
index 3d948ff93327e48bb516b64e3f1487a161ff87bc..eab2239b783a756ba2d1fbc2f1e296d1db03495f 100644
--- a/src/assets/js/map-util.js
+++ b/src/assets/js/map-util.js
@@ -18,7 +18,7 @@ import { FillSymbolizer, PointSymbolizer, LineSymbolizer } from "@/assets/js/vec
 let map;
 let dictLayersToLeaflet = {};
 var layerMVT;
-let statusList=[
+let statusList = [
   {
     name: "Brouillon",
     value: "draft",
@@ -66,20 +66,20 @@ L.TileLayer.BetterWMS = L.TileLayer.WMS.extend({
             params: params,
             //dataType: "json",
           }
-            ).then(response => {
-              let data=response.data;
-              var err = typeof data === 'object' ? null : data;
-              if (data.features || err) {
-                showResults(err, evt.latlng, data);
-              }
-            })
-            .catch(error => {
-              throw (error)
-              //xhr.status;
-              //xhr.responseText;
-              //console.log(status)
-            }
-            )
+        ).then(response => {
+          let data = response.data;
+          var err = typeof data === 'object' ? null : data;
+          if (data.features || err) {
+            showResults(err, evt.latlng, data);
+          }
+        })
+          .catch(error => {
+            throw (error)
+            //xhr.status;
+            //xhr.responseText;
+            //console.log(status)
+          }
+          )
 
       }
     }
@@ -165,7 +165,7 @@ const mapUtil = {
     return map;
   },
 
-  createMap: function (options) {
+  createMap: function (el, options) {
     const {
       lat,
       lng,
@@ -175,8 +175,9 @@ const mapUtil = {
       zoomControl = true,
     } = options;
 
-    map = L.map('map', {
+    map = L.map(el, {
       maxZoom: 18,
+      minZoom: 1,
       zoomControl: false,
     }).setView(
       [
@@ -200,7 +201,7 @@ const mapUtil = {
 
     return map;
   },
-  addGeocoders: function(configuration){
+  addGeocoders: function (configuration) {
     let geocoder;
     const geocoderLabel = configuration.SELECTED_GEOCODER.PROVIDER;
     if (geocoderLabel) {
@@ -278,7 +279,7 @@ const mapUtil = {
       }
     });
   },
-  
+
   updateOrder(layers) {
     // First remove existing layers undefined
     layers = layers.filter(function (x) {
@@ -298,87 +299,89 @@ const mapUtil = {
     this.addLayers(layers);
   },
   // eslint-disable-next-line no-unused-vars
-  addVectorTileLayer: function (url,project_slug,featureTypes,form_filters) {
+  addVectorTileLayer: function (url, project_slug, featureTypes, form_filters) {
     layerMVT = L.vectorGrid.protobuf(url, {
       vectorTileLayerStyles: {
-        "default": function(properties, zoom) {
-           // console.log(properties);
-           
-           let featureType=featureTypes.find((x)=>x.slug.split('-')[0]===''+properties.feature_type_id);
-           let color=featureType.color;
-           if(featureType.colors_style && featureType.colors_style.custom_field_name){
-            let currentValue=properties[featureType.colors_style.custom_field_name];
-            let colorValue=featureType.colors_style.colors[currentValue];
-            if(colorValue) {
-              color=colorValue;
+        "default": function (properties, zoom) {
+          // console.log(properties);
+
+          let featureType = featureTypes.find((x) => x.slug.split('-')[0] === '' + properties.feature_type_id);
+          let color = featureType.color;
+          if (featureType.colors_style && featureType.colors_style.custom_field_name) {
+            let currentValue = properties[featureType.colors_style.custom_field_name];
+            let colorValue = featureType.colors_style.colors[currentValue];
+            if (colorValue) {
+              color = colorValue;
             }
-           }
-           let hiddenStyle=({
-                        radius: 0,
-                        fillOpacity: 0.5,
-                        weight: 0,
-                        fill: false,
-                        color: featureType.color,
-                    })
-           // Filtre sur le feature type
-           if (form_filters && form_filters.type.selected) {
-             if(featureType.title !== form_filters.type.selected){
-                return hiddenStyle;
-             }
+
+          }
+          let hiddenStyle = ({
+            radius: 0,
+            fillOpacity: 0.5,
+            weight: 0,
+            fill: false,
+            color: featureType.color,
+          })
+          // Filtre sur le feature type
+          if (form_filters && form_filters.type.selected) {
+            if (featureType.title !== form_filters.type.selected) {
+              return hiddenStyle;
             }
+          }
           // Filtre sur le statut
           if (form_filters && form_filters.status.selected.value) {
-            if(properties.status !== form_filters.status.selected.value){
+            if (properties.status !== form_filters.status.selected.value) {
               return hiddenStyle;
             }
           }
           // Filtre sur le titre
           if (form_filters && form_filters.title) {
-            if(!properties.title.toLowerCase().includes(form_filters.title.toLowerCase())){
+            if (!properties.title.toLowerCase().includes(form_filters.title.toLowerCase())) {
               return hiddenStyle;
             }
           }
-              return ({
-                        radius: 4,
-                        fillOpacity: 0.5,
-                        weight: 3,
-                        fill: true,
-                        color: color,
-                    });
-          
+          return ({
+            radius: 4,
+            fillOpacity: 0.5,
+            weight: 3,
+            fill: true,
+            color: color,
+          });
+
         },
-    },
+      },
       // subdomains: "0123",
       // key: 'abcdefghi01234567890',
-      interactive:true,
+      interactive: true,
       maxNativeZoom: 14,
-      getFeatureId: function(f) {
-				return f.properties.id;
-			}
+      getFeatureId: function (f) {
+        return f.properties.id;
+      }
     });
-    let self=this;
-    layerMVT.on('click', function(e) {    // The .on method attaches an event handler
-      console.log(e);
-      const popupContent = self._createContentPopup(e.layer,featureTypes,project_slug);
+    let self = this;
+    layerMVT.on('click', function (e) {    // The .on method attaches an event handler
+      console.log("click on mvt", e);
+      const popupContent = self._createContentPopup(e.layer, featureTypes, project_slug);
       L.popup()
-          .setContent(popupContent)
-          .setLatLng(e.latlng)
-          .openOn(map)
-        });
+        .setContent(popupContent)
+        .setLatLng(e.latlng)
+        .openOn(map)
+    });
     layerMVT.addTo(map);
-    window.layerMVT=layerMVT;
-  }, 
+    window.layerMVT = layerMVT;
+  },
 
-  addFeatures: function (features, filter,addToMap=true,featureTypes) {
+  addFeatures: function (features, filter, addToMap = true, featureTypes) {
     let featureGroup = new L.FeatureGroup();
     features.forEach((feature) => {
-      
-      let featureType=featureTypes.find((x)=>x.slug.split('-')[0]===''+feature.properties.feature_type_id);
-      if(feature.properties.feature_type != undefined){
-        featureType=featureTypes.find((x)=>x.slug===''+feature.properties.feature_type);
+
+      let featureType = featureTypes.find((x) => x.slug === feature.properties.feature_type.slug);
+      if (!featureType) {
+        featureType = feature.properties.feature_type;
       }
+
       let filters = [];
- 
+
       if (filter) {
         const typeCheck = filter.featureType && feature.properties.feature_type.slug === filter.featureType;
         const statusCheck = filter.featureStatus && feature.properties.status.value === filter.featureStatus;
@@ -391,19 +394,54 @@ const mapUtil = {
         const geomJSON = flip(feature.geometry);
 
         const popupContent = this._createContentPopup(feature);
-        let color=feature.properties.color;
-        if(color==undefined){
-          color=featureType.color;
+
+        // Look for a custom field
+        let customField;
+        let customFieldOption;
+        if (Object.keys(feature.properties).some(el => featureType.customfield_set.map(e => e.name).includes(el))) {
+          customField = Object.keys(feature.properties).filter(el => featureType.customfield_set.map(e => e.name).includes(el));
+          customFieldOption = feature.properties[customField[0]];
+        }
+
+        let color;
+        if (customFieldOption && featureType.colors_style) {
+          color = featureType.colors_style.value.colors[customFieldOption].value
+        } else {
+          color = feature.properties.color;
+        }
+        if (color == undefined) {
+          color = featureType.color;
         }
         if (geomJSON.type === 'Point') {
-          L.circleMarker(geomJSON.coordinates, {
-            color: color,
-            radius: 4,
-            fillOpacity: 0.5,
-            weight: 3,
-          })
-            .bindPopup(popupContent)
-            .addTo(featureGroup);
+          if (customFieldOption && featureType.colors_style) {
+            const iconHTML = `
+              <i
+                class="fas fa-${featureType.colors_style.value.icons[customFieldOption]} fa-2x"
+                style="color: ${color}"
+              ></i>
+            `;
+            const customMapIcon = L.divIcon({
+              html: iconHTML,
+              iconSize: [20, 20],
+              className: 'myDivIcon',
+            });
+            L.marker(geomJSON.coordinates, {
+              icon: customMapIcon,
+              color: color,
+              zIndexOffset: 100
+            })
+              .bindPopup(popupContent)
+              .addTo(featureGroup);
+          } else {
+            L.circleMarker(geomJSON.coordinates, {
+              color: color,
+              radius: 4,
+              fillOpacity: 0.5,
+              weight: 3,
+            })
+              .bindPopup(popupContent)
+              .addTo(featureGroup);
+          }
         } else if (geomJSON.type === 'LineString') {
           L.polyline(geomJSON.coordinates, {
             color: color,
@@ -422,39 +460,39 @@ const mapUtil = {
         }
       }
     });
-    if(addToMap){
+    if (addToMap) {
       map.addLayer(featureGroup);
     }
-    
+
     return featureGroup;
   },
   addMapEventListener: function (eventName, callback) {
     map.on(eventName, callback);
   },
 
-  _createContentPopup: function (feature,featureTypes,project_slug) {
-    const formatDate = (current_datetime)=>{
-        let formatted_date = current_datetime.getFullYear() + "-" + ("0" + (current_datetime.getMonth() + 1)).slice(-2) + "-" + ("0" + current_datetime.getDate()).slice(-2) + " " + 
+  _createContentPopup: function (feature, featureTypes, project_slug) {
+    const formatDate = (current_datetime) => {
+      let formatted_date = current_datetime.getFullYear() + "-" + ("0" + (current_datetime.getMonth() + 1)).slice(-2) + "-" + ("0" + current_datetime.getDate()).slice(-2) + " " +
         ("0" + current_datetime.getHours()).slice(-2) + ":" + ("0" + current_datetime.getMinutes()).slice(-2);
-        return formatted_date;
+      return formatted_date;
     }
     let feature_type;
-    let status=feature.properties.status;
-    let date_maj=feature.properties.updated_on;
-    let feature_type_url=feature.properties.feature_type_url;
-    let feature_url=feature.properties.feature_url;
-    if(featureTypes){ // => VectorTile
-      feature_type=featureTypes.find((x)=>x.slug.split('-')[0]===''+feature.properties.feature_type_id);
-      status=statusList.find((x)=>x.value==feature.properties.status).name;
-      date_maj=formatDate(new Date(feature.properties.updated_on));
-      feature_type_url='/geocontrib/projet/'+project_slug+'/type_signalement/'+feature_type.slug+'/';
-      feature_url=feature_type_url+'signalement/'+feature.properties.feature_id+'/';
+    let status = feature.properties.status;
+    let date_maj = feature.properties.updated_on;
+    let feature_type_url = feature.properties.feature_type_url;
+    let feature_url = feature.properties.feature_url;
+    if (featureTypes) { // => VectorTile
+      feature_type = featureTypes.find((x) => x.slug.split('-')[0] === '' + feature.properties.feature_type_id);
+      status = statusList.find((x) => x.value == feature.properties.status).name;
+      date_maj = formatDate(new Date(feature.properties.updated_on));
+      feature_type_url = '/geocontrib/projet/' + project_slug + '/type_signalement/' + feature_type.slug + '/';
+      feature_url = feature_type_url + 'signalement/' + feature.properties.feature_id + '/';
       //status=feature.properties.status;
-    }else{
-      feature_type=feature.properties.feature_type;
-      status=feature.properties.status.label;
+    } else {
+      feature_type = feature.properties.feature_type;
+      status = feature.properties.status.label;
     }
-     
+
     let author = "";
     if (feature.properties.creator) {
       author = feature.properties.creator.full_name
diff --git a/src/assets/styles/base.css b/src/assets/styles/base.css
index 366f47bf0cdf9eb658d75a55f0261e18de9ed0e1..d49a7d4750077875a1d26d66f025feef2eba7b9d 100644
--- a/src/assets/styles/base.css
+++ b/src/assets/styles/base.css
@@ -52,6 +52,10 @@ main {
   word-wrap: normal;
 }
 
+.ui.checkbox.disabled > input {
+  cursor: default !important;
+}
+
 
 /* Add basemap view */
 #form-layers .ui.buttons{
diff --git a/src/components/feature/FeatureListTable.vue b/src/components/feature/FeatureListTable.vue
index 47b2d1fd5507d95ace501dd54e5e480c6d3db262..d19aa0160cc080fc976e5a8adb21190885a1acef 100644
--- a/src/components/feature/FeatureListTable.vue
+++ b/src/components/feature/FeatureListTable.vue
@@ -77,12 +77,20 @@
       <tbody>
         <tr v-for="(feature, index) in paginatedFeatures" :key="index">
           <td class="center">
-            <div class="ui checkbox">
+            <div
+              class="ui checkbox"
+              :class="
+                feature.properties.creator.username !== user.username && !user.is_superuser && !isUserProjectAdministrator ?
+                  'disabled' :
+                  ''
+              "
+            >
               <input
                 type="checkbox"
                 :id="feature.id"
                 :value="feature.id"
                 v-model="checked"
+                :disabled="feature.properties.creator.username !== user.username && !user.is_superuser && !isUserProjectAdministrator"
               />
               <label></label>
             </div>
@@ -217,10 +225,12 @@
 </template>
 
 <script>
+import { mapState, mapGetters } from 'vuex';
+
 export default {
   name: "FeatureListTable",
 
-  props: ["filteredFeatures", "user", "checkedFeatures"],
+  props: ["filteredFeatures", "checkedFeatures"],
 
   data() {
     return {
@@ -238,6 +248,18 @@ export default {
   },
 
   computed: {
+    ...mapState([
+      'user',
+    ]),
+    ...mapGetters([
+      'project',
+      'permissions'
+    ]),
+
+    isUserProjectAdministrator() {
+      return this.permissions.is_project_administrator;
+    },
+
     paginatedFeatures() {
       let filterdFeatures = [...this.filteredFeatures];
       // Ajout du tri
diff --git a/src/components/feature_type/SymbologySelector.vue b/src/components/feature_type/SymbologySelector.vue
new file mode 100644
index 0000000000000000000000000000000000000000..73d5ab4279e35eef88cc55a5d8c209f53da08460
--- /dev/null
+++ b/src/components/feature_type/SymbologySelector.vue
@@ -0,0 +1,196 @@
+<template>
+  <div>
+    <div class="three fields">
+      <div class="row-title">
+        {{ title }}
+      </div>
+      <div class="required inline field">
+        <label :for="form.color.id_for_label">{{ form.color.label }}</label>
+        <input
+          type="color"
+          required
+          :name="form.color.html_name"
+          :id="form.color.id_for_label"
+          v-model.lazy="form.color.value"
+        />
+      </div>
+      <div class="required inline field">
+        <label>Symbole</label>
+        <button
+          class="ui icon button picker-button"
+          type="button"
+          @click="openIconSelectionModal"
+        >
+          <font-awesome-icon
+            :icon="['fas', form.icon]"
+            :style="{ color: form.color.value }"
+            class="icon alt"
+          />
+        </button>
+      </div>
+    </div>
+    <div
+      :class="isIconPickerModalOpen ? 'active' : ''"
+      class="ui dimmer modal transition"
+      ref="iconsPickerModal"
+    >
+      <div class="header">Sélectionnez le symbole pour ce type de signalement :</div>
+      <div class="scrolling content">
+        <div
+          v-for="icon of iconsNamesList"
+          :key="icon"
+          :class="form.icon === icon ? 'active' : ''"
+          class="icon-container"
+          @click="selectIcon(icon)"
+        >
+          <font-awesome-icon
+            :icon="['fas', icon]"
+            class="icon alt"
+          />
+        </div>
+      </div>
+      <div class="actions">
+        <div class="ui cancel button" @click="isIconPickerModalOpen = false;">Fermer</div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import faIconsNames from '@/assets/icons/fa-icons.js';
+
+export default {
+  name: 'SymbologySelector',
+
+  props: {
+    title: {
+      type: String,
+      default: 'Symbologie par défault :'
+    },
+    initColor: {
+      type: String,
+      default: '#000000'
+    },
+    initIcon: {
+      type: String,
+      default: 'circle'
+    },
+    geomType: {
+      type: String,
+      default: 'Point'
+    }
+  },
+
+  data() {
+    return {
+      isIconPickerModalOpen: false,
+      iconsNamesList: faIconsNames,
+      form: {
+        icon: 'circle',
+        color: {
+          id_for_label: 'couleur',
+          label: 'Couleur',
+          field: {
+            max_length: 128, // ! Vérifier la valeur dans django
+          },
+          html_name: 'couleur',
+          value: '#000000',
+        },
+      }
+    }
+  },
+
+  watch: {
+    form: {
+      deep: true,
+      handler(newValue) {
+        this.$emit('set', {
+          name: this.title === 'Symbologie par défault :' ? null : this.title,
+          value: newValue
+        });
+      }
+    }
+  },
+
+  created() {
+    this.form.color.value = this.initColor;
+    this.form.icon = this.initIcon;
+    this.$emit('set', {
+      name: this.title,
+      value: this.form
+    });
+  },
+
+  methods: {
+    openIconSelectionModal() {
+      this.isIconPickerModalOpen = true;
+    },
+
+    selectIcon(icon) {
+      this.form.icon = icon;
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+
+.fields {
+  align-items: center;
+  justify-content: space-between;
+  margin-top: 3em !important;
+}
+
+.row-title {
+  display: inline;
+  font-size: 1.4em;
+  width: 33%;
+  text-align: left;
+  margin-left: 0.5em;
+}
+
+#couleur {
+  width: 66%;
+  cursor: pointer;
+  box-shadow: 0 0 1px 1px rgb(189, 189, 189);
+}
+
+.picker-button {
+  height: 50px;
+  width: 50px;
+  border-radius: 3px;
+  box-shadow: 0 0 2px 1px rgb(131, 131, 131);
+  .icon.alt {
+    color: rgb(75, 75, 75);
+    width: 30px;
+    height: 30px;
+  }
+}
+.picker-button:hover {
+  box-shadow: 0 0 2px 1px rgb(165, 165, 165);
+}
+
+.modal {
+  height: fit-content;
+  .content {
+    display: flex;
+    flex-flow: row wrap;
+    .icon-container {
+      padding: 7px;
+      .icon.alt {
+        color: rgb(75, 75, 75);
+        width: 30px;
+        height: 30px;
+      }
+    }
+    .icon-container:hover {
+      cursor: pointer;
+      background-color: rgba(130, 216, 219, 0.589);
+    }
+    .icon-container.active {
+      background-color: rgba(130, 216, 219, 0.589);
+    }
+  }
+}
+
+</style>
diff --git a/src/main.js b/src/main.js
index edda9a1c273cc6f4ba771411c3e3ae8617dc3ed9..3e5f6956593ac0d53834bdcd46cf80970188613a 100644
--- a/src/main.js
+++ b/src/main.js
@@ -8,6 +8,16 @@ import store from './store'
 import 'leaflet/dist/leaflet.css';
 import 'leaflet-draw/dist/leaflet.draw.css';
 import '@/assets/resources/leaflet-control-geocoder-1.13.0/Control.Geocoder.css';
+import '@fortawesome/fontawesome-free/css/all.css'
+import '@fortawesome/fontawesome-free/js/all.js'
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { fas } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
+
+library.add(fas)
+
+Vue.component('font-awesome-icon', FontAwesomeIcon);
+
 Vue.config.productionTip = false
 
 // gestion mise à jour du serviceWorker et du precache
@@ -61,6 +71,3 @@ axios.get("./config/config.json")
   .catch((error) => {
     throw error;
   });
-
-
-
diff --git a/src/router/index.js b/src/router/index.js
index f0eb56d71e8a8442ffd6d914291a1114e2eb3281..ab603a745eef79c6de3269be2f61f017c08eb4e8 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -92,6 +92,11 @@ const routes = [
     name: 'editer-type-signalement',
     component: () => import('../views/feature_type/Feature_type_edit.vue')
   },
+  {
+    path: '/projet/:slug/type-signalement/:slug_type_signal/symbologie/',
+    name: 'editer-symbologie-signalement',
+    component: () => import('../views/feature_type/Feature_type_symbology.vue')
+  },
   // * FEATURE 
   {
     path: '/projet/:slug/signalement/lister/',
diff --git a/src/service-worker.js b/src/service-worker.js
index 7497fb0ca7f6f2d73661d696f8fa189c69640695..c9c0d32fee26672dbdc0b2f24959aee7e9eb3381 100644
--- a/src/service-worker.js
+++ b/src/service-worker.js
@@ -13,7 +13,9 @@ if (workbox) {
     // Make sure to return a specific response for all navigation requests.
     // Since we have a SPA here, this should be index.html always.
     // https://stackoverflow.com/questions/49963982/vue-router-history-mode-with-pwa-in-offline-mode
-    workbox.routing.registerNavigationRoute('/geocontrib/index.html')
+    workbox.routing.registerNavigationRoute('/geocontrib/index.html', {
+        blacklist: [/\/api/,/\/admin/],
+      })
 
     workbox.routing.registerRoute(
         new RegExp('.*/config/config.json'),
diff --git a/src/services/map-api.js b/src/services/map-api.js
index 1a877e6370cfb88ae7360aad200df69a05fa72a8..fa4c5ddba7178edc5d26a91095d1dedb3c976e46 100644
--- a/src/services/map-api.js
+++ b/src/services/map-api.js
@@ -1,5 +1,11 @@
 import axios from 'axios';
-import store from '../store'
+import store from '../store';
+
+axios.defaults.headers.common['X-CSRFToken'] = (name => {
+  var re = new RegExp(name + "=([^;]+)");
+  var value = re.exec(document.cookie);
+  return (value !== null) ? unescape(value[1]) : null;
+})('csrftoken');
 
 const baseUrl = store.state.configuration.VUE_APP_DJANGO_API_BASE;
 
diff --git a/src/store/modules/feature_type.js b/src/store/modules/feature_type.js
index 204776cbb1d252e9e058b931e40eddc267da535b..bed583d904949de35706a19a93ea4d10a95e725d 100644
--- a/src/store/modules/feature_type.js
+++ b/src/store/modules/feature_type.js
@@ -139,6 +139,26 @@ const feature_type = {
       }
     },
 
+    async SEND_FEATURE_SYMBOLOGY({ getters, rootGetters }, symbology) {
+      const data = {
+        title: getters.feature_type.title,
+        project: rootGetters.project.slug,
+        ...symbology
+      };
+      return axios
+        .put(`${this.state.configuration.VUE_APP_DJANGO_API_BASE}feature-types/${getters.feature_type.slug}/`, data)
+        .then((response) => {
+          if (response) {
+            const feature_type_slug = response.data.slug;
+            const status = response.status;
+            return { feature_type_slug, status };
+          }
+        })
+        .catch((error) => {
+          throw (error);
+        });
+    },
+
     SEND_FEATURES_FROM_GEOJSON({ state, dispatch }, payload) {
       const { feature_type_slug } = payload
 
diff --git a/src/store/modules/map.js b/src/store/modules/map.js
index d47afc9ef721f6a3201ff1db473b051c92552a1e..c8e5ce93eab03a485b06f5a409be781a95cbe313 100644
--- a/src/store/modules/map.js
+++ b/src/store/modules/map.js
@@ -110,11 +110,11 @@ const map = {
         });
     },
 
-    INITIATE_MAP({ state, rootGetters }) {
+    INITIATE_MAP({ state, rootGetters }, el) {
       const project = rootGetters.project
       let mapDefaultViewCenter = [46, 2]; // defaultMapView.center;
       let mapDefaultViewZoom = 5; // defaultMapView.zoom;
-      mapUtil.createMap({
+      mapUtil.createMap(el, {
         mapDefaultViewCenter,
         mapDefaultViewZoom,
       });
diff --git a/src/views/Index.vue b/src/views/Index.vue
index e199657757733fb9d0874e0c72e2a47fd9f04d8b..b751999169c005a0a90fc93e2df3ffc4156c7912 100644
--- a/src/views/Index.vue
+++ b/src/views/Index.vue
@@ -1,9 +1,6 @@
 <template>
   <div class="fourteen wide column">
-    <img
-      class="ui centered small image"
-      src="@/assets/img/logo-neogeo-circle.png"
-    />
+    <img class="ui centered small image" :src="logo" />
     <!-- :src="LOGO_PATH" -->
     <h2 class="ui center aligned icon header">
       <div class="content">
@@ -15,14 +12,14 @@
     <h4 id="les_projets" class="ui horizontal divider header">PROJETS</h4>
     <div class="flex">
       <router-link
-        v-if="user && user.can_create_project && isOffline()!=true"
+        v-if="user && user.can_create_project && isOffline() != true"
         :to="{ name: 'project_create', params: { action: 'create' } }"
         class="ui green basic button"
       >
         <i class="plus icon"></i> Créer un nouveau projet
       </router-link>
       <router-link
-        v-if="user && user.can_create_project && isOffline()!=true"
+        v-if="user && user.can_create_project && isOffline() != true"
         :to="{
           name: 'project_type_list',
         }"
@@ -110,22 +107,26 @@ import { mapState } from "vuex";
 
 export default {
   name: "Index",
+
   computed: {
     ...mapState(["projects", "user", "USER_LEVEL_PROJECTS"]),
-    APPLICATION_NAME: function () {
+    APPLICATION_NAME() {
       return this.$store.state.configuration.VUE_APP_APPLICATION_NAME;
     },
-    APPLICATION_ABSTRACT: function () {
+    APPLICATION_ABSTRACT() {
       return this.$store.state.configuration.VUE_APP_APPLICATION_ABSTRACT;
     },
-    DJANGO_BASE_URL: function () {
+    DJANGO_BASE_URL() {
       return this.$store.state.configuration.VUE_APP_DJANGO_BASE;
     },
+    logo() {
+      return this.$store.state.configuration.VUE_APP_LOGO_PATH;
+    },
   },
 
   methods: {
-    isOffline(){
-      return navigator.onLine==false;
+    isOffline() {
+      return navigator.onLine == false;
     },
     refreshId() {
       //* change path of thumbnail to update image
diff --git a/src/views/feature/Feature_detail.vue b/src/views/feature/Feature_detail.vue
index f17ed17535733e41a07dd7627703bed7e7ba7ce5..24514f13d3786d43b7de0a829c2011b413a2a135 100644
--- a/src/views/feature/Feature_detail.vue
+++ b/src/views/feature/Feature_detail.vue
@@ -353,6 +353,12 @@ import { mapUtil } from "@/assets/js/map-util.js";
 import featureAPI from "@/services/feature-api";
 const axios = require("axios");
 
+axios.defaults.headers.common['X-CSRFToken'] = (name => {
+  var re = new RegExp(name + "=([^;]+)");
+  var value = re.exec(document.cookie);
+  return (value !== null) ? unescape(value[1]) : null;
+})('csrftoken');
+
 export default {
   name: "Feature_detail",
 
@@ -573,7 +579,7 @@ export default {
         this.$store.state.configuration.DEFAULT_MAP_VIEW.center;
       var mapDefaultViewZoom =
         this.$store.state.configuration.DEFAULT_MAP_VIEW.zoom;
-      this.map = mapUtil.createMap({
+      this.map = mapUtil.createMap(this.$refs.map, {
         mapDefaultViewCenter,
         mapDefaultViewZoom,
       });
@@ -680,12 +686,10 @@ export default {
       this.$store
         .dispatch("GET_PROJECT_INFO", this.$route.params.slug)
         .then(() => {
-          console.log("map", this.$refs.map);
           this.$store.commit("DISCARD_LOADER");
           this.initMap();
         });
     } else {
-      console.log("map", this.$refs.map);
       this.$store.commit("DISCARD_LOADER");
       this.initMap();
     }
diff --git a/src/views/feature/Feature_edit.vue b/src/views/feature/Feature_edit.vue
index ef384ad43fb80e2802015cf24da2084c88b3975d..40e10c25703b2a6db077fb1bf2736aa092422899 100644
--- a/src/views/feature/Feature_edit.vue
+++ b/src/views/feature/Feature_edit.vue
@@ -187,7 +187,7 @@
             @blur="updateStore"
           />
           <div class="ui tab active map-container" data-tab="map">
-            <div id="map"></div>
+            <div id="map" ref="map"></div>
             <!-- // todo: ajouter v-if -->
             <!-- {% if serialized_base_maps|length > 0 %} {% include
             "geocontrib/map-layers/sidebar-layers.html" with
@@ -928,7 +928,7 @@ export default {
         this.$store.state.configuration.DEFAULT_MAP_VIEW.zoom;
 
       // Create the map, then init the layers and features
-      this.map = mapUtil.createMap({
+      this.map = mapUtil.createMap(this.$refs.map, {
         mapDefaultViewCenter,
         mapDefaultViewZoom,
       });
@@ -959,7 +959,7 @@ export default {
             mapUtil.addFeatures(
               allFeaturesExceptCurrent,
               {},
-              false,
+              true,
               this.$store.state.feature_type.feature_types
             );
             if (this.currentRouteName === "editer-signalement") {
diff --git a/src/views/feature/Feature_list.vue b/src/views/feature/Feature_list.vue
index 6190906d0f8f840a324e67679c09497d0e3c4f69..2263ae1eff68f3927df9a0d0822d792163fa7b0a 100644
--- a/src/views/feature/Feature_list.vue
+++ b/src/views/feature/Feature_list.vue
@@ -144,7 +144,6 @@
     <FeatureListTable
       v-show="!showMap"
       :filteredFeatures="filteredFeatures"
-      :user="user"
       :checkedFeatures.sync="checkedFeatures"
     />
 
@@ -189,6 +188,12 @@ import FeatureListTable from "@/components/feature/FeatureListTable";
 import Dropdown from "@/components/Dropdown.vue";
 const axios = require("axios");
 
+axios.defaults.headers.common['X-CSRFToken'] = (name => {
+  var re = new RegExp(name + "=([^;]+)");
+  var value = re.exec(document.cookie);
+  return (value !== null) ? unescape(value[1]) : null;
+})('csrftoken');
+
 export default {
   name: "Feature_list",
 
@@ -248,7 +253,6 @@ export default {
 
   computed: {
     ...mapGetters(["project", "permissions"]),
-    ...mapState(["user"]),
     ...mapState("feature", ["checkedFeatures"]),
     ...mapState("feature_type", ["feature_types"]),
 
@@ -337,7 +341,7 @@ export default {
         this.featureGroup = mapUtil.addFeatures(
           features,
           {},
-          false,
+          true,
           this.$store.state.feature_type.feature_types
         );
         mapUtil.getMap().invalidateSize();
@@ -362,7 +366,7 @@ export default {
       var mapDefaultViewZoom =
         this.$store.state.configuration.DEFAULT_MAP_VIEW.zoom;
 
-      this.map = mapUtil.createMap({
+      this.map = mapUtil.createMap(this.$refs.map, {
         zoom: this.zoom,
         lat: this.lat,
         lng: this.lng,
@@ -428,7 +432,7 @@ export default {
           featureStatus,
           featureTitle,
         },
-        false,
+        true,
         this.$store.state.feature_type.feature_types
       );
       // Fit the map to bound only if no initial zoom and center are defined
@@ -451,13 +455,11 @@ export default {
 
   created() {
     if (!this.project) {
-      //this.$store.dispatch("GET_PROJECT_MESSAGES", this.$route.params.slug);
       this.$store.dispatch("GET_PROJECT_INFO", this.$route.params.slug, "noFeatures");
     }
   },
 
   mounted() {
-    console.log("map", this.$refs.map);
     this.initMap();
   },
 
diff --git a/src/views/feature_type/Feature_type_symbology.vue b/src/views/feature_type/Feature_type_symbology.vue
new file mode 100644
index 0000000000000000000000000000000000000000..f1d82fe21f8c5f0471e52bc4b8dd09090414b227
--- /dev/null
+++ b/src/views/feature_type/Feature_type_symbology.vue
@@ -0,0 +1,203 @@
+<template>
+  <div>
+    <div :class="{ active: loading }" class="ui inverted dimmer">
+      <div class="ui loader" />
+    </div>
+    <div id="message" class="fullwidth">
+      <div v-if="error" class="ui negative message">
+        <p><i class="cross icon"></i> {{ error }}</p>
+      </div>
+    </div>
+    <div class="fourteen wide column">
+      <form
+        id="form-symbology-edit"
+        action=""
+        method="post"
+        enctype="multipart/form-data"
+        class="ui form"
+      >
+        <h1 v-if="feature_type">
+          Éditer la symbologie du type de signalement "{{ feature_type.title }}" pour le
+          projet "{{ project.title }}"
+        </h1>
+        <SymbologySelector
+          v-if="feature_type"
+          :initColor="feature_type.color"
+          :geomType="feature_type.geom_type"
+          @set="setDefaultStyle"
+        />
+        <div
+          v-if="
+            feature_type &&
+            feature_type.customfield_set.length > 0 &&
+            feature_type.customfield_set.some(el => el.field_type === 'list')
+          "
+        >
+          <div class="ui divider" />
+          <label
+            for="customfield-select"
+            id="customfield-select-label">
+            Personnaliser la symbologie d'une liste de valeurs:
+          </label>
+          <select
+            v-model="selectedCustomfield"
+            id="customfield-select"
+            class="ui dropdown"
+          >
+             <option
+              v-for="customfieldList of feature_type.customfield_set.filter(el => el.field_type === 'list')"
+              :key="customfieldList.name"
+              :value="customfieldList.name"
+            >
+               {{ customfieldList.label }}
+              </option>
+          </select>
+        </div>
+        <div v-if="selectedCustomfield">
+          <div 
+            v-for="option of feature_type.customfield_set.find(el => el.name === selectedCustomfield).options"
+            :key="option"
+          >
+            <SymbologySelector
+              :title="option"
+              :initColor="feature_type.colors_style.value.colors[option].value"
+              :initIcon="feature_type.colors_style.value.icons[option]"
+              :geomType="feature_type.customfield_set.geomType"
+              @set="setColorsStyle"
+            />
+          </div>
+        </div>
+        <div class="ui divider"></div>
+        <button
+          class="ui teal icon button margin-25"
+          type="button"
+          @click="sendFeatureSymbology"
+        >
+          <i class="white save icon"></i>
+            Sauvegarder la symbologie du type de signalement
+        </button>
+      </form>
+    </div>
+  </div>
+</template>
+
+<script>
+import frag from 'vue-frag';
+
+import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';
+
+import SymbologySelector from '@/components/feature_type/SymbologySelector.vue';
+
+export default {
+  name: 'FeatureTypeSymbology',
+
+  directives: {
+    frag,
+  },
+
+  components: {
+    SymbologySelector
+  },
+
+  data() {
+    return {
+      loading: false,
+      error: null,
+      selectedCustomfield: null,
+      form: {
+        color: '#000000',
+        icon: 'circle',
+        colors_style: {
+          fields: [],
+          value: {
+            colors: {},
+            icons: {},
+            custom_field_name: '',
+          },
+        },
+      }
+    }
+  },
+
+  computed: {
+    ...mapGetters(['project']),
+    ...mapState('feature_type', [
+      'customForms',
+      'colorsStyleList'
+    ]),
+    ...mapGetters('feature_type', [
+      'feature_type'
+    ]),
+  },
+
+  watch: {
+    selectedCustomfield(newValue) {
+      this.form.colors_style.value.custom_field_name = newValue;
+    }
+  },
+
+  created() {
+    if (!this.project) {
+      this.GET_PROJECT_INFO(this.$route.params.slug);
+    }
+    this.SET_CURRENT_FEATURE_TYPE_SLUG(this.$route.params.slug_type_signal);
+  },
+
+  methods: {
+    ...mapMutations('feature_type', [
+      'SET_CURRENT_FEATURE_TYPE_SLUG'
+    ]),
+    ...mapActions('feature_type', [
+      'SEND_FEATURE_SYMBOLOGY'
+    ]),
+    ...mapActions([
+      'GET_PROJECT_INFO'
+    ]),
+
+    setDefaultStyle(e) {
+      const value  = e.value;
+      this.form.color = value.color.value;
+      this.form.icon = value.icon;
+    },
+
+    setColorsStyle(e) {
+      const { name, value } = e;
+      this.form.colors_style.value.colors[name] = value.color;
+      this.form.colors_style.value.icons[name] = value.icon;
+    },
+
+    sendFeatureSymbology() {
+      this.loading = true;
+      this.SEND_FEATURE_SYMBOLOGY(this.form)
+        .then(() => {
+          this.loading = false;
+        })
+        .catch(() => {
+          this.loading = false;
+        })
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+
+h1 {
+  margin-top: 1em;
+}
+
+form {
+  text-align: left;
+
+  #customfield-select-label {
+    cursor: pointer;
+    font-weight: 600;
+    font-size: 1.1em;
+  }
+  #customfield-select {
+    width: 50% !important;
+  }
+
+}
+
+</style>
diff --git a/src/views/project/Project_detail.vue b/src/views/project/Project_detail.vue
index 1efc2288a4dba7c83ec75172ca668f023dbb5e68..e866ac9cde74c9360d6b95906e846170198f9a7d 100644
--- a/src/views/project/Project_detail.vue
+++ b/src/views/project/Project_detail.vue
@@ -228,6 +228,33 @@
                 >
                   <i class="inverted grey pencil alternate icon"></i>
                 </router-link>
+                <router-link
+                  :to="{
+                    name: 'editer-symbologie-signalement',
+                    params: { slug_type_signal: type.slug },
+                  }"
+                  v-if="
+                    project &&
+                    type.is_editable &&
+                    permissions &&
+                    permissions.can_create_feature_type &&
+                    isOffline() != true
+                  "
+                  class="
+                    ui
+                    compact
+                    small
+                    icon
+                    right
+                    floated
+                    button button-hover-green
+                  "
+                  data-tooltip="Éditer la symbologie du type de signalement"
+                  data-position="left center"
+                  data-variation="mini"
+                >
+                  <i class="inverted grey paint brush alternate icon"></i>
+                </router-link>
               </div>
             </div>
             <div v-if="feature_types.length === 0">
@@ -298,7 +325,7 @@
           </div>
         </div>
         <div class="seven wide column">
-          <div id="map"></div>
+          <div id="map" ref="map"></div>
         </div>
       </div>
 
@@ -483,7 +510,7 @@
 
         <div class="content">
           <button
-            @click="subsribeProject"
+            @click="subscribeProject"
             :class="['ui compact fluid button', is_suscriber ? 'red' : 'green']"
           >
             {{
@@ -506,6 +533,12 @@ import projectAPI from "@/services/project-api";
 
 const axios = require("axios");
 
+axios.defaults.headers.common['X-CSRFToken'] = (name => {
+  var re = new RegExp(name + "=([^;]+)");
+  var value = re.exec(document.cookie);
+  return (value !== null) ? unescape(value[1]) : null;
+})('csrftoken');
+
 export default {
   name: "Project_details",
 
@@ -549,9 +582,12 @@ export default {
     DJANGO_BASE_URL() {
       return this.$store.state.configuration.VUE_APP_DJANGO_BASE;
     },
+    API_BASE_URL() {
+      return this.$store.state.configuration.VUE_APP_DJANGO_API_BASE;
+    },
     last_features() {
       // * limit to last five element of array (looks sorted chronologically, but not sure...)
-      return this.$store.state.feature.features.slice(-5);
+      return this.features.slice(-5);
     },
   },
 
@@ -559,9 +595,11 @@ export default {
     refreshId() {
       return "?ver=" + Math.random();
     },
+
     isOffline() {
       return navigator.onLine === false;
     },
+
     checkForOfflineFeature() {
       let arraysOffline = [];
       let localStorageArray = localStorage.getItem("geocontrib_offline");
@@ -572,6 +610,7 @@ export default {
         );
       }
     },
+
     sendOfflineFeatures() {
       var promises = [];
       this.arraysOffline.forEach((feature, index, object) => {
@@ -579,10 +618,7 @@ export default {
         if (feature.type === "post") {
           promises.push(
             axios
-              .post(
-                `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}features/`,
-                feature.geojson
-              )
+              .post(`${this.API_BASE_URL}features/`, feature.geojson)
               .then((response) => {
                 console.log(response);
                 if (response.status === 201 && response.data) {
@@ -597,7 +633,7 @@ export default {
           promises.push(
             axios
               .put(
-                `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}features/${feature.featureId}`,
+                `${this.API_BASE_URL}features/${feature.featureId}`,
                 feature.geojson
               )
               .then((response) => {
@@ -617,6 +653,7 @@ export default {
         window.location.reload();
       });
     },
+
     updateLocalStorage() {
       let arraysOffline = [];
       let localStorageArray = localStorage.getItem("geocontrib_offline");
@@ -629,6 +666,7 @@ export default {
       arraysOffline = arraysOfflineOtherProject.concat(this.arraysOffline);
       localStorage.setItem("geocontrib_offline", JSON.stringify(arraysOffline));
     },
+
     toNewFeatureType() {
       this.$router.push({
         name: "ajouter-type-signalement",
@@ -659,8 +697,7 @@ export default {
       }
     },
 
-    subsribeProject() {
-      this.$store.state.configuration.VUE_APP_DJANGO_API_BASE;
+    subscribeProject() {
       projectAPI
         .subscribeProject({
           suscribe: !this.is_suscriber,
@@ -680,11 +717,11 @@ export default {
     },
     initMap() {
       if (this.project && this.permissions.can_view_project) {
-        this.$store.dispatch("map/INITIATE_MAP");
-        const url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}projects/${this.$route.params.slug}/feature/?output=geojson`;
+        this.$store.dispatch("map/INITIATE_MAP", this.$refs.map);
+        const url = `${this.API_BASE_URL}projects/${this.$route.params.slug}/feature/?output=geojson`;
         this.checkForOfflineFeature();
         let project_id = this.$route.params.slug.split("-")[0];
-        const mvtUrl = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}features.mvt/?tile={z}/{x}/{y}&project_id=${project_id}`;
+        const mvtUrl = `${this.API_BASE_URL}features.mvt/?tile={z}/{x}/{y}&project_id=${project_id}`;
         mapUtil.addVectorTileLayer(
           mvtUrl,
           this.$route.params.slug,
@@ -703,7 +740,7 @@ export default {
             const featureGroup = mapUtil.addFeatures(
               features,
               {},
-              false,
+              true,
               this.$store.state.feature_type.feature_types
             );
 
@@ -735,8 +772,9 @@ export default {
   mounted() {
     this.$store.dispatch("GET_PROJECT_INFO", this.slug).then(() => {
       this.featureTypeLoading = false;
-      setTimeout(() => this.initMap, 1000);
+      setTimeout(this.initMap, 1000);
     });
+
     if (this.message) {
       this.tempMessage = this.message;
       document
diff --git a/src/views/project/Project_edit.vue b/src/views/project/Project_edit.vue
index 8076625edbacd260d3c379e9d32f03da064026f4..4779af2c603dd93c5694cb7646a466b049bdd265 100644
--- a/src/views/project/Project_edit.vue
+++ b/src/views/project/Project_edit.vue
@@ -409,52 +409,50 @@ export default {
         is_project_type: this.form.is_project_type,
         moderation: this.form.moderation,
       };
+      let url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}projects/`;
 
-      if (this.action === "create" || this.action === "create_from") {
-        this.loading = true;
+      if (this.action === "edit") {
         await axios
-          .post(
-            `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}projects/`,
-            projectData
-          )
+          .put((url += `${this.project.slug}/`), projectData)
           .then((response) => {
-            if (response && response.status === 201 && response.data) {
-              //* send thumbnail after feature_type was created
+            if (response && response.status === 200) {
+              //* send thumbnail after feature_type was updated
               if (this.fileToImport.size > 0) {
-                this.postProjectThumbnail(response.data.slug);
+                this.postProjectThumbnail(this.project.slug);
               } else {
-                this.goBackNrefresh(response.data.slug);
+                this.goBackNrefresh(this.project.slug);
               }
             }
-            this.loading = false;
           })
           .catch((error) => {
             if (error.response && error.response.data.title[0]) {
               this.errors.title.push(error.response.data.title[0]);
             }
-            this.loading = false;
             throw error;
           });
-      } else if (this.action === "edit") {
+      } else {
+        if (this.action === "create_from") {
+          url += `${this.project.slug}/duplicate/`;
+        }
+        this.loading = true;
         await axios
-          .put(
-            `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}projects/${this.project.slug}/`,
-            projectData
-          )
+          .post(url, projectData)
           .then((response) => {
-            if (response && response.status === 200) {
-              //* send thumbnail after feature_type was updated
+            if (response && response.status === 201 && response.data) {
+              //* send thumbnail after feature_type was created
               if (this.fileToImport.size > 0) {
-                this.postProjectThumbnail(this.project.slug);
+                this.postProjectThumbnail(response.data.slug);
               } else {
-                this.goBackNrefresh(this.project.slug);
+                this.goBackNrefresh(response.data.slug);
               }
             }
+            this.loading = false;
           })
           .catch((error) => {
             if (error.response && error.response.data.title[0]) {
               this.errors.title.push(error.response.data.title[0]);
             }
+            this.loading = false;
             throw error;
           });
       }
diff --git a/src/views/project/Project_members.vue b/src/views/project/Project_members.vue
index ed96cae6d4cc9b97abb62ab97c64a1a41d9c63a0..34c89ac5718fa7b0dd64f1eeb0e3ac2ad83865d9 100644
--- a/src/views/project/Project_members.vue
+++ b/src/views/project/Project_members.vue
@@ -111,6 +111,12 @@ import frag from "vue-frag";
 import { mapGetters } from "vuex";
 import Dropdown from "@/components/Dropdown.vue";
 
+axios.defaults.headers.common['X-CSRFToken'] = (name => {
+  var re = new RegExp(name + "=([^;]+)");
+  var value = re.exec(document.cookie);
+  return (value !== null) ? unescape(value[1]) : null;
+})('csrftoken');
+
 export default {
   name: "Project_members",