diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 04e1295f315d2c0ac8a64abbfe4fb77a9f5bf396..2a11ebf4d1e979775199857a82966c303283cd13 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -27,7 +27,9 @@ pages:
     - mkdir public
     - mv generated/coverage public/
     - mv generated/jscpd/html public/jscpd
+    - mv generated/maintainability public/
     - mv generated/jscpd/*.svg public/
+    - mv generated/*.svg public/
   artifacts:
     untracked: true
     paths:
diff --git a/CI/plato-badges.js b/CI/plato-badges.js
index ce2edfcffe60459321b10106b4a323e2cc3a9ef4..8f25e827b72f44a2691c5002bf7e8de77873725c 100644
--- a/CI/plato-badges.js
+++ b/CI/plato-badges.js
@@ -1,40 +1,60 @@
 const {badgen} = require('badgen');
 const fs = require('fs');
 
-function badgeColor(percent) {
-	let color = 'red';
-	if (percent > 25) color = 'orange';
-	if (percent > 50) color = 'yellow';
-	if (percent > 70) color = 'yellowgreen';
-	if (percent > 80) color = 'green';
-	if (percent > 90) color = 'brightgreen';
+function badgeColor(percent) { // #9f9f9f lightgrey / inactive
+	let color = 'e05d44'; // 'red';
+	if (percent > 25) color = 'fe7d37'; // 'orange';
+	if (percent > 50) color = 'dfb317'; // 'yellow';
+	if (percent > 70) color = 'a4a61d'; // 'yellowgreen';
+	if (percent > 80) color = '97ca00'; // 'green';
+	if (percent > 90) color = '4c1'; // 'brightgreen';
 	return color;
 }
 
-const report = require('../generated/complexity/report.json');
-const maintainabilityScore = Math.round(Number.parseFloat(report.summary.average.maintainability));
-const maintainabilityColor = badgeColor(maintainabilityScore);
+const report = require('../generated/maintainability/report.json');
+const config = require('../package.json');
+const maintainabilityThreshold = config.maintainabilityThreshold;
+
+const avgMaintainabilityScore = Math.round(Number.parseFloat(report.summary.average.maintainability));
+const avgMaintainabilityColor = badgeColor(avgMaintainabilityScore);
+const worstMaintainabilityScore = Math.floor(report.reports.reduce((acc, cur) => Math.min(acc, Number.parseFloat(cur.complexity.maintainability)), 100));
+const worstMaintainabilityColor = badgeColor(worstMaintainabilityScore);
 
 const sloc = report.summary.total.sloc;
+
+try {
+	fs.writeFileSync('generated/avg-maintainability.svg', badgen({
+		label: 'maintainability',
+		status: `${avgMaintainabilityScore}`,
+		color: avgMaintainabilityColor
+	}), 'utf8');
+} catch (error) {
+	console.error(error);
+}
+
 try {
-	fs.writeFileSync('../generated/maintainability.svg', badgen({
+	fs.writeFileSync('generated/worst-maintainability.svg', badgen({
 		label: 'maintainability',
-		status: maintainabilityScore,
-		color: maintainabilityColor
+		status: `${worstMaintainabilityScore}`,
+		color: worstMaintainabilityColor
 	}), 'utf8');
 } catch (error) {
 	console.error(error);
 }
+
 try {
-	fs.writeFileSync('../generated/total-sloc.svg', badgen({
-		label: 'total sloc',
-		status: sloc,
-		color: 'blue'
+	fs.writeFileSync('generated/total-sloc.svg', badgen({
+		label: 'code lines',
+		status: `${sloc}`,
+		color: '007ec6' // 'blue'
 	}), 'utf8');
 } catch (error) {
 	console.error(error);
 }
 
-//const execSync = require('child_process').execSync;
-//execSync('wget -q -O ../plato/maintainability.svg https://img.shields.io/badge/maintainability-'+maintainabilityScore+'-'+maintainabilityColor+'.svg');
-//execSync('wget -q -O ../plato/total-sloc.svg "https://img.shields.io/badge/total sloc-'+sloc+'-blue.svg"');
+if (avgMaintainabilityScore >= maintainabilityThreshold.global) {
+	console.log(`Global project maintainability : ${avgMaintainabilityScore} ( >= ${maintainabilityThreshold.global} )`);
+} else throw new Error(`Global project maintainability too low : ${avgMaintainabilityScore} < ${maintainabilityThreshold.global}`);
+if (worstMaintainabilityScore >= maintainabilityThreshold.file) {
+	console.log(`Worst project file maintainability : ${worstMaintainabilityScore} ( >= ${maintainabilityThreshold.file} )`);
+} else throw new Error(`Worst project file maintainability too low : ${worstMaintainabilityScore} < ${maintainabilityThreshold.file}`);
diff --git a/README.fr.md b/README.fr.md
index f06b4533177bb9f5e4721ba4e137dedfb5425b4b..95f6f470043f26d8ebe044dbbde74c094db4b9e8 100644
--- a/README.fr.md
+++ b/README.fr.md
@@ -3,7 +3,9 @@
 [![coverage report](https://framagit.org/g1/g1lib.js/badges/main/coverage.svg)](https://g1.frama.io/g1lib.js/coverage/)
 
 [![duplication](https://g1.frama.io/g1lib.js/jscpd-badge.svg)](https://g1.frama.io/g1lib.js/jscpd/)
-[![complexity](https://mycelia.tools/ci/mycelia-front-app/plato/maintainability.svg)](https://mycelia.tools/ci/mycelia-front-app/plato/)
+[![maintainability](https://g1.frama.io/g1lib.js/worst-maintainability.svg)](https://g1.frama.io/g1lib.js/maintainability/)
+[![code lines](https://g1.frama.io/g1lib.js/total-sloc.svg)](https://g1.frama.io/g1lib.js/maintainability/)
+
 
 [![release](https://img.shields.io/npm/v/g1lib.svg)](https://www.npmjs.com/package/g1lib)
 [![usage as download](https://img.shields.io/npm/dy/g1lib.svg)](https://www.npmjs.com/package/g1lib)
diff --git a/README.md b/README.md
index f0cc23a6a5298e6283707100869f4b0bec0f71ec..096bd21b661069771e0072fd60d7d2b7e99da520 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,9 @@
-[![pipeline status](https://framagit.org/g1/g1lib.js/badges/main/pipeline.svg)](https://framagit.org/g1/g1lib.js/-/commits/main)
-[![coverage report](https://framagit.org/g1/g1lib.js/badges/main/coverage.svg)](https://framagit.org/g1/g1lib.js/-/commits/main)
-[![maintainability](https://mycelia.tools/ci/mycelia-front-app/plato/maintainability.svg)](https://mycelia.tools/ci/mycelia-front-app/plato/)
+[![pipeline status](https://framagit.org/g1/g1lib.js/badges/main/pipeline.svg)](https://framagit.org/g1/g1lib.js/-/pipelines)
+[![coverage report](https://framagit.org/g1/g1lib.js/badges/main/coverage.svg)](https://g1.frama.io/g1lib.js/coverage/)
+
+[![duplication](https://g1.frama.io/g1lib.js/jscpd-badge.svg)](https://g1.frama.io/g1lib.js/jscpd/)
+[![maintainability](https://g1.frama.io/g1lib.js/worst-maintainability.svg)](https://g1.frama.io/g1lib.js/maintainability/)
+[![code lines](https://g1.frama.io/g1lib.js/total-sloc.svg)](https://g1.frama.io/g1lib.js/maintainability/)
 
 [![release](https://img.shields.io/npm/v/g1lib.svg)](https://www.npmjs.com/package/g1lib)
 [![usage as download](https://img.shields.io/npm/dy/g1lib.svg)](https://www.npmjs.com/package/g1lib)
diff --git a/package.json b/package.json
index 4941a6ed55402a7e36a2d1e4cbe8d444bba8686c..15e3034cd0f65331c4c334b997da6fef78172677 100644
--- a/package.json
+++ b/package.json
@@ -18,12 +18,12 @@
     "test:dev:qualityCheck": "xo",
     "test:dev:runTests": "ava",
     "test:dev:duplication": "jscpd ./ -s",
-    "test:dev:complexity": "codehawk ./",
+    "xtest:dev:complexity": "codehawk ./",
     "test:production": "run-s test:production:**",
     "test:production:qualityCheck": "xo",
     "test:production:duplication": "jscpd ./",
-		"test:production:complexity": "./node_modules/.bin/es6-plato -r -d generated/complexity ./src/*",
-		"test:production:complexity:badges": "node CI/plato-badges.js",
+		"test:production:complexity": "./node_modules/.bin/es6-plato -r -d generated/maintainability ./src/*",
+		"test:production:complexity:badgesAndThreshold": "node CI/plato-badges.js",
     "test:production:test2npm": "cp src/*.test.mjs generated/npm/",
     "test:production:runTests": "cd generated/npm/ && c8 ava",
     "test:production:clean": "rm -rf generated/npm/*.test.mjs generated/npm/node_modules"
@@ -37,7 +37,6 @@
     "ava": "^3.14.0",
     "badgen": "^3.2.2",
     "c8": "^7.3.5",
-    "codehawk-cli": "^6.0.3",
     "es6-plato": "https://github.com/1000i100/es6-plato#master",
     "jscpd": "^3.3.22",
     "mkdirp": "^1.0.4",
@@ -46,11 +45,19 @@
     "xo": "^0.34.2"
   },
   "disabledDependenciesTODOAddComplexityQualityCheck": {
-    "es6-plato": "https://github.com/1000i100/es6-plato#master",
-    "code-forensics": "^2.3.1",
     "codehawk-cli": "^6.0.3"
   },
   "ava": {},
+	"xo": {
+		"rules": {
+			"curly": 0,
+			"unicorn/no-reduce": 0
+		}
+	},
+	"maintainabilityThreshold": {
+		"global": 75,
+		"file": 50
+	},
   "jscpd": {
     "threshold": 0.1,
     "reporters": [