diff --git a/.github/workflows/node.yml b/.github/workflows/node.yml
index 2bab3b314c74aafa1308e4d09b7de2b1d7729458..568facc2afd3500fd48479927474e6641ba5d300 100644
--- a/.github/workflows/node.yml
+++ b/.github/workflows/node.yml
@@ -23,3 +23,8 @@ jobs:
     - run: npm install --prefix ./assets
     - run: npm run lint --prefix ./assets
     - run: npm run check-format --prefix ./assets
+    - name: Run BundleMon
+      run: npm run bundlemon --prefix ./assets
+      env:
+        BUNDLEMON_PROJECT_ID: "619e0b6ad4a54a00089861ac"
+        CI_COMMIT_SHA: ${{github.event.pull_request.head.sha || github.sha}} # important!
diff --git a/assets/.bundlemonrc.json b/assets/.bundlemonrc.json
new file mode 100644
index 0000000000000000000000000000000000000000..c1ccec260e9802cfbbf506e56ae3a30c4b8ebef9
--- /dev/null
+++ b/assets/.bundlemonrc.json
@@ -0,0 +1,14 @@
+{
+  "baseDir": "../priv/",
+  "files": [
+    {
+      "path": "static/js/*.js"
+    },
+    {
+      "path": "static/css/app.css"
+    },
+    {
+      "path": "tracker/js/plausible.js"
+    }
+  ]
+}
diff --git a/assets/package-lock.json b/assets/package-lock.json
index 11781af6cfed210ef71598b8c6451d25d18f6f60..ec1eff7edfcac252941c8b0de554f98c57b1aa0d 100644
--- a/assets/package-lock.json
+++ b/assets/package-lock.json
@@ -50,6 +50,7 @@
       },
       "devDependencies": {
         "babel-eslint": "^10.1.0",
+        "bundlemon": "^1.2.0",
         "eslint": "^7.2.0",
         "eslint-config-prettier": "^7.0.0",
         "eslint-plugin-import": "^2.22.1",
@@ -1460,10 +1461,14 @@
       }
     },
     "node_modules/@babel/runtime": {
-      "version": "7.14.0",
-      "license": "MIT",
+      "version": "7.16.3",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz",
+      "integrity": "sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==",
       "dependencies": {
         "regenerator-runtime": "^0.13.4"
+      },
+      "engines": {
+        "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/runtime-corejs3": {
@@ -1753,6 +1758,12 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/@types/lodash": {
+      "version": "4.14.177",
+      "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.177.tgz",
+      "integrity": "sha512-0fDwydE2clKe9MNfvXHBHF9WEahRuj+msTuQqOmAApNORFvhMYZKNGGJdCzuhheVjMps/ti0Ak/iJPACMaevvw==",
+      "dev": true
+    },
     "node_modules/@types/mdast": {
       "version": "3.0.3",
       "dev": true,
@@ -2285,6 +2296,15 @@
         "node": ">=4"
       }
     },
+    "node_modules/axios": {
+      "version": "0.21.4",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
+      "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
+      "dev": true,
+      "dependencies": {
+        "follow-redirects": "^1.14.0"
+      }
+    },
     "node_modules/axobject-query": {
       "version": "2.2.0",
       "dev": true,
@@ -2484,6 +2504,24 @@
         "brfs": "bin/cmd.js"
       }
     },
+    "node_modules/brotli-size": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/brotli-size/-/brotli-size-4.0.0.tgz",
+      "integrity": "sha512-uA9fOtlTRC0iqKfzff1W34DXUA3GyVqbUaeo3Rw3d4gd1eavKVCETXrn3NzO74W+UVkG3UHu8WxUi+XvKI/huA==",
+      "dev": true,
+      "dependencies": {
+        "duplexer": "0.1.1"
+      },
+      "engines": {
+        "node": ">= 10.16.0"
+      }
+    },
+    "node_modules/brotli-size/node_modules/duplexer": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
+      "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
+      "dev": true
+    },
     "node_modules/browserslist": {
       "version": "4.16.6",
       "license": "MIT",
@@ -2516,6 +2554,118 @@
       "version": "1.1.1",
       "license": "MIT"
     },
+    "node_modules/bundlemon": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/bundlemon/-/bundlemon-1.2.0.tgz",
+      "integrity": "sha512-HbxsXV2dCCl9hkVMxpYprg4MqpLzJshdvnLg0O0J5UoSTo28mjuCiskr+E4rkukZaxeZWnxNwyIkVK4wUQCOUw==",
+      "dev": true,
+      "dependencies": {
+        "axios": "^0.21.1",
+        "brotli-size": "^4.0.0",
+        "bundlemon-utils": "^0.3.2",
+        "bytes": "^3.1.0",
+        "chalk": "^4.1.1",
+        "commander": "^8.0.0",
+        "cosmiconfig": "^7.0.0",
+        "gzip-size": "^6.0.0",
+        "micromatch": "^4.0.4",
+        "yup": "^0.32.11"
+      },
+      "bin": {
+        "bundlemon": "bin/bundlemon.js"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/bundlemon-utils": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/bundlemon-utils/-/bundlemon-utils-0.3.2.tgz",
+      "integrity": "sha512-xjKeUDInNREYm6jNvGLswIaDEPpfqkw4X0EyGDrlNnwyC/R1xbh6tUHwDqkQYH0i3OiR9JKPFOk0V278MJQuWg==",
+      "dev": true,
+      "dependencies": {
+        "bytes": "^3.1.0"
+      }
+    },
+    "node_modules/bundlemon/node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "dev": true,
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/bundlemon/node_modules/chalk": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
+    "node_modules/bundlemon/node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dev": true,
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/bundlemon/node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "dev": true
+    },
+    "node_modules/bundlemon/node_modules/commander": {
+      "version": "8.3.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+      "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
+      "dev": true,
+      "engines": {
+        "node": ">= 12"
+      }
+    },
+    "node_modules/bundlemon/node_modules/has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/bundlemon/node_modules/supports-color": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/bytes": {
       "version": "3.1.0",
       "license": "MIT",
@@ -4484,6 +4634,26 @@
       "dev": true,
       "license": "ISC"
     },
+    "node_modules/follow-redirects": {
+      "version": "1.14.5",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz",
+      "integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://github.com/sponsors/RubenVerborgh"
+        }
+      ],
+      "engines": {
+        "node": ">=4.0"
+      },
+      "peerDependenciesMeta": {
+        "debug": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/foreach": {
       "version": "2.0.5",
       "license": "MIT"
@@ -5426,6 +5596,12 @@
       "version": "4.17.21",
       "license": "MIT"
     },
+    "node_modules/lodash-es": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
+      "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
+      "dev": true
+    },
     "node_modules/lodash.castarray": {
       "version": "4.4.0",
       "license": "MIT"
@@ -5991,6 +6167,12 @@
       "version": "2.1.2",
       "license": "MIT"
     },
+    "node_modules/nanoclone": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz",
+      "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==",
+      "dev": true
+    },
     "node_modules/nanoid": {
       "version": "3.1.29",
       "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.29.tgz",
@@ -7286,6 +7468,12 @@
         "react-is": "^16.8.1"
       }
     },
+    "node_modules/property-expr": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.4.tgz",
+      "integrity": "sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg==",
+      "dev": true
+    },
     "node_modules/punycode": {
       "version": "2.1.1",
       "license": "MIT",
@@ -8994,6 +9182,12 @@
         "topojson-svg": "bin/topojson-svg"
       }
     },
+    "node_modules/toposort": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
+      "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=",
+      "dev": true
+    },
     "node_modules/totalist": {
       "version": "1.1.0",
       "dev": true,
@@ -9646,6 +9840,24 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/yup": {
+      "version": "0.32.11",
+      "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz",
+      "integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/runtime": "^7.15.4",
+        "@types/lodash": "^4.14.175",
+        "lodash": "^4.17.21",
+        "lodash-es": "^4.17.21",
+        "nanoclone": "^0.2.1",
+        "property-expr": "^2.0.4",
+        "toposort": "^2.0.2"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
     "node_modules/zwitch": {
       "version": "1.0.5",
       "dev": true,
@@ -10452,7 +10664,9 @@
       }
     },
     "@babel/runtime": {
-      "version": "7.14.0",
+      "version": "7.16.3",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz",
+      "integrity": "sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==",
       "requires": {
         "regenerator-runtime": "^0.13.4"
       }
@@ -10648,6 +10862,12 @@
       "version": "0.0.29",
       "dev": true
     },
+    "@types/lodash": {
+      "version": "4.14.177",
+      "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.177.tgz",
+      "integrity": "sha512-0fDwydE2clKe9MNfvXHBHF9WEahRuj+msTuQqOmAApNORFvhMYZKNGGJdCzuhheVjMps/ti0Ak/iJPACMaevvw==",
+      "dev": true
+    },
     "@types/mdast": {
       "version": "3.0.3",
       "dev": true,
@@ -11015,6 +11235,15 @@
       "version": "4.1.1",
       "dev": true
     },
+    "axios": {
+      "version": "0.21.4",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
+      "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
+      "dev": true,
+      "requires": {
+        "follow-redirects": "^1.14.0"
+      }
+    },
     "axobject-query": {
       "version": "2.2.0",
       "dev": true
@@ -11145,6 +11374,23 @@
         "through2": "^2.0.0"
       }
     },
+    "brotli-size": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/brotli-size/-/brotli-size-4.0.0.tgz",
+      "integrity": "sha512-uA9fOtlTRC0iqKfzff1W34DXUA3GyVqbUaeo3Rw3d4gd1eavKVCETXrn3NzO74W+UVkG3UHu8WxUi+XvKI/huA==",
+      "dev": true,
+      "requires": {
+        "duplexer": "0.1.1"
+      },
+      "dependencies": {
+        "duplexer": {
+          "version": "0.1.1",
+          "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
+          "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
+          "dev": true
+        }
+      }
+    },
     "browserslist": {
       "version": "4.16.6",
       "requires": {
@@ -11161,6 +11407,90 @@
     "buffer-from": {
       "version": "1.1.1"
     },
+    "bundlemon": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/bundlemon/-/bundlemon-1.2.0.tgz",
+      "integrity": "sha512-HbxsXV2dCCl9hkVMxpYprg4MqpLzJshdvnLg0O0J5UoSTo28mjuCiskr+E4rkukZaxeZWnxNwyIkVK4wUQCOUw==",
+      "dev": true,
+      "requires": {
+        "axios": "^0.21.1",
+        "brotli-size": "^4.0.0",
+        "bundlemon-utils": "^0.3.2",
+        "bytes": "^3.1.0",
+        "chalk": "^4.1.1",
+        "commander": "^8.0.0",
+        "cosmiconfig": "^7.0.0",
+        "gzip-size": "^6.0.0",
+        "micromatch": "^4.0.4",
+        "yup": "^0.32.11"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+          "dev": true,
+          "requires": {
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.1.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+          "dev": true
+        },
+        "commander": {
+          "version": "8.3.0",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+          "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
+      }
+    },
+    "bundlemon-utils": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/bundlemon-utils/-/bundlemon-utils-0.3.2.tgz",
+      "integrity": "sha512-xjKeUDInNREYm6jNvGLswIaDEPpfqkw4X0EyGDrlNnwyC/R1xbh6tUHwDqkQYH0i3OiR9JKPFOk0V278MJQuWg==",
+      "dev": true,
+      "requires": {
+        "bytes": "^3.1.0"
+      }
+    },
     "bytes": {
       "version": "3.1.0"
     },
@@ -12448,6 +12778,12 @@
       "version": "3.1.0",
       "dev": true
     },
+    "follow-redirects": {
+      "version": "1.14.5",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz",
+      "integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==",
+      "dev": true
+    },
     "foreach": {
       "version": "2.0.5"
     },
@@ -13009,6 +13345,12 @@
     "lodash": {
       "version": "4.17.21"
     },
+    "lodash-es": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
+      "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
+      "dev": true
+    },
     "lodash.castarray": {
       "version": "4.4.0"
     },
@@ -13353,6 +13695,12 @@
     "ms": {
       "version": "2.1.2"
     },
+    "nanoclone": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz",
+      "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==",
+      "dev": true
+    },
     "nanoid": {
       "version": "3.1.29",
       "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.29.tgz",
@@ -14154,6 +14502,12 @@
         "react-is": "^16.8.1"
       }
     },
+    "property-expr": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.4.tgz",
+      "integrity": "sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg==",
+      "dev": true
+    },
     "punycode": {
       "version": "2.1.1"
     },
@@ -15296,6 +15650,12 @@
         "shapefile": "0.3"
       }
     },
+    "toposort": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
+      "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=",
+      "dev": true
+    },
     "totalist": {
       "version": "1.1.0",
       "dev": true
@@ -15668,6 +16028,21 @@
     "yocto-queue": {
       "version": "0.1.0"
     },
+    "yup": {
+      "version": "0.32.11",
+      "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz",
+      "integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==",
+      "dev": true,
+      "requires": {
+        "@babel/runtime": "^7.15.4",
+        "@types/lodash": "^4.14.175",
+        "lodash": "^4.17.21",
+        "lodash-es": "^4.17.21",
+        "nanoclone": "^0.2.1",
+        "property-expr": "^2.0.4",
+        "toposort": "^2.0.2"
+      }
+    },
     "zwitch": {
       "version": "1.0.5",
       "dev": true
diff --git a/assets/package.json b/assets/package.json
index 958e45cbcfc81d4f7ed6a31e3e69697a56256b75..0c74d4683f7ad84e0e0e0a70a97bb70be3f0ed28 100644
--- a/assets/package.json
+++ b/assets/package.json
@@ -7,7 +7,8 @@
     "watch": "$(npm bin)/webpack --mode development --watch",
     "format": "$(npm bin)/prettier --write {css,js}/**",
     "check-format": "$(npm bin)/prettier --check {css,js}/**",
-    "lint": "$(npm bin)/eslint js/**"
+    "lint": "$(npm bin)/eslint js/**",
+    "bundlemon": "$(npm bin)/bundlemon"
   },
   "dependencies": {
     "@babel/core": "^7.14.3",
@@ -52,6 +53,7 @@
   },
   "devDependencies": {
     "babel-eslint": "^10.1.0",
+    "bundlemon": "^1.2.0",
     "eslint": "^7.2.0",
     "eslint-config-prettier": "^7.0.0",
     "eslint-plugin-import": "^2.22.1",