diff --git a/shotgun/src/main/scala/services/GithubClient.scala b/shotgun/src/main/scala/services/GithubClient.scala
index c867d1d..fbd7cb9 100644
--- a/shotgun/src/main/scala/services/GithubClient.scala
+++ b/shotgun/src/main/scala/services/GithubClient.scala
@@ -29,6 +29,7 @@ class GithubClient(implicit val system: ActorSystem, implicit val executionConte
| login
| name
| avatarUrl
+ | url
| }
| }
| }
diff --git a/webapp/package-lock.json b/webapp/package-lock.json
index 0d0f120..61dd3fb 100644
--- a/webapp/package-lock.json
+++ b/webapp/package-lock.json
@@ -8,9 +8,12 @@
"name": "deflock",
"version": "0.0.0",
"dependencies": {
+ "@types/leaflet.markercluster": "^1.5.5",
"@unhead/vue": "^1.11.14",
"axios": "^1.7.7",
"countup.js": "^2.8.0",
+ "leaflet.markercluster": "^1.5.3",
+ "pinia": "^2.3.0",
"vue": "^3.4.29",
"vue-router": "^4.3.3",
"vuetify": "^3.7.2"
@@ -18,9 +21,9 @@
"devDependencies": {
"@mdi/font": "^7.4.47",
"@tsconfig/node20": "^20.1.4",
+ "@types/leaflet": "^1.9.15",
"@types/node": "^20.14.5",
"@vitejs/plugin-vue": "^5.0.5",
- "@vue-leaflet/vue-leaflet": "^0.10.1",
"@vue/tsconfig": "^0.5.1",
"leaflet": "^1.9.4",
"npm-run-all2": "^6.2.0",
@@ -46,11 +49,11 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.26.1",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.1.tgz",
- "integrity": "sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw==",
+ "version": "7.26.3",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz",
+ "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==",
"dependencies": {
- "@babel/types": "^7.26.0"
+ "@babel/types": "^7.26.3"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -60,9 +63,9 @@
}
},
"node_modules/@babel/types": {
- "version": "7.26.0",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz",
- "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==",
+ "version": "7.26.3",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz",
+ "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==",
"dependencies": {
"@babel/helper-string-parser": "^7.25.9",
"@babel/helper-validator-identifier": "^7.25.9"
@@ -670,6 +673,27 @@
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
"dev": true
},
+ "node_modules/@types/geojson": {
+ "version": "7946.0.15",
+ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.15.tgz",
+ "integrity": "sha512-9oSxFzDCT2Rj6DfcHF8G++jxBKS7mBqXl5xrRW+Kbvjry6Uduya2iiwqHPhVXpasAVMBYKkEPGgKhd3+/HZ6xA=="
+ },
+ "node_modules/@types/leaflet": {
+ "version": "1.9.15",
+ "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.15.tgz",
+ "integrity": "sha512-7UuggAuAs+mva66gtf2OTB1nEhzU/9JED93TIaOEgvFMvG/dIGQaukHE7izHo1Zd+Ko1L4ETUw7TBc8yUxevpg==",
+ "dependencies": {
+ "@types/geojson": "*"
+ }
+ },
+ "node_modules/@types/leaflet.markercluster": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@types/leaflet.markercluster/-/leaflet.markercluster-1.5.5.tgz",
+ "integrity": "sha512-TkWOhSHDM1ANxmLi+uK0PjsVcjIKBr8CLV2WoF16dIdeFmC0Cj5P5axkI3C1Xsi4+ht6EU8+BfEbbqEF9icPrg==",
+ "dependencies": {
+ "@types/leaflet": "*"
+ }
+ },
"node_modules/@types/node": {
"version": "20.16.6",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.6.tgz",
@@ -771,68 +795,50 @@
"vscode-uri": "^3.0.8"
}
},
- "node_modules/@vue-leaflet/vue-leaflet": {
- "version": "0.10.1",
- "resolved": "https://registry.npmjs.org/@vue-leaflet/vue-leaflet/-/vue-leaflet-0.10.1.tgz",
- "integrity": "sha512-RNEDk8TbnwrJl8ujdbKgZRFygLCxd0aBcWLQ05q/pGv4+d0jamE3KXQgQBqGAteE1mbQsk3xoNcqqUgaIGfWVg==",
- "dev": true,
- "dependencies": {
- "vue": "^3.2.25"
- },
- "peerDependencies": {
- "@types/leaflet": "^1.5.7",
- "leaflet": "^1.6.0"
- },
- "peerDependenciesMeta": {
- "@types/leaflet": {
- "optional": true
- }
- }
- },
"node_modules/@vue/compiler-core": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.8.tgz",
- "integrity": "sha512-Uzlxp91EPjfbpeO5KtC0KnXPkuTfGsNDeaKQJxQN718uz+RqDYarEf7UhQJGK+ZYloD2taUbHTI2J4WrUaZQNA==",
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz",
+ "integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==",
"dependencies": {
"@babel/parser": "^7.25.3",
- "@vue/shared": "3.5.8",
+ "@vue/shared": "3.5.13",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.2.0"
}
},
"node_modules/@vue/compiler-dom": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.8.tgz",
- "integrity": "sha512-GUNHWvoDSbSa5ZSHT9SnV5WkStWfzJwwTd6NMGzilOE/HM5j+9EB9zGXdtu/fCNEmctBqMs6C9SvVPpVPuk1Eg==",
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz",
+ "integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==",
"dependencies": {
- "@vue/compiler-core": "3.5.8",
- "@vue/shared": "3.5.8"
+ "@vue/compiler-core": "3.5.13",
+ "@vue/shared": "3.5.13"
}
},
"node_modules/@vue/compiler-sfc": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.8.tgz",
- "integrity": "sha512-taYpngQtSysrvO9GULaOSwcG5q821zCoIQBtQQSx7Uf7DxpR6CIHR90toPr9QfDD2mqHQPCSgoWBvJu0yV9zjg==",
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz",
+ "integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==",
"dependencies": {
"@babel/parser": "^7.25.3",
- "@vue/compiler-core": "3.5.8",
- "@vue/compiler-dom": "3.5.8",
- "@vue/compiler-ssr": "3.5.8",
- "@vue/shared": "3.5.8",
+ "@vue/compiler-core": "3.5.13",
+ "@vue/compiler-dom": "3.5.13",
+ "@vue/compiler-ssr": "3.5.13",
+ "@vue/shared": "3.5.13",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.11",
- "postcss": "^8.4.47",
+ "postcss": "^8.4.48",
"source-map-js": "^1.2.0"
}
},
"node_modules/@vue/compiler-ssr": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.8.tgz",
- "integrity": "sha512-W96PtryNsNG9u0ZnN5Q5j27Z/feGrFV6zy9q5tzJVyJaLiwYxvC0ek4IXClZygyhjm+XKM7WD9pdKi/wIRVC/Q==",
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz",
+ "integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==",
"dependencies": {
- "@vue/compiler-dom": "3.5.8",
- "@vue/shared": "3.5.8"
+ "@vue/compiler-dom": "3.5.13",
+ "@vue/shared": "3.5.13"
}
},
"node_modules/@vue/compiler-vue2": {
@@ -875,49 +881,49 @@
}
},
"node_modules/@vue/reactivity": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.8.tgz",
- "integrity": "sha512-mlgUyFHLCUZcAYkqvzYnlBRCh0t5ZQfLYit7nukn1GR96gc48Bp4B7OIcSfVSvlG1k3BPfD+p22gi1t2n9tsXg==",
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.13.tgz",
+ "integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==",
"dependencies": {
- "@vue/shared": "3.5.8"
+ "@vue/shared": "3.5.13"
}
},
"node_modules/@vue/runtime-core": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.8.tgz",
- "integrity": "sha512-fJuPelh64agZ8vKkZgp5iCkPaEqFJsYzxLk9vSC0X3G8ppknclNDr61gDc45yBGTaN5Xqc1qZWU3/NoaBMHcjQ==",
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.13.tgz",
+ "integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==",
"dependencies": {
- "@vue/reactivity": "3.5.8",
- "@vue/shared": "3.5.8"
+ "@vue/reactivity": "3.5.13",
+ "@vue/shared": "3.5.13"
}
},
"node_modules/@vue/runtime-dom": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.8.tgz",
- "integrity": "sha512-DpAUz+PKjTZPUOB6zJgkxVI3GuYc2iWZiNeeHQUw53kdrparSTG6HeXUrYDjaam8dVsCdvQxDz6ZWxnyjccUjQ==",
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz",
+ "integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==",
"dependencies": {
- "@vue/reactivity": "3.5.8",
- "@vue/runtime-core": "3.5.8",
- "@vue/shared": "3.5.8",
+ "@vue/reactivity": "3.5.13",
+ "@vue/runtime-core": "3.5.13",
+ "@vue/shared": "3.5.13",
"csstype": "^3.1.3"
}
},
"node_modules/@vue/server-renderer": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.8.tgz",
- "integrity": "sha512-7AmC9/mEeV9mmXNVyUIm1a1AjUhyeeGNbkLh39J00E7iPeGks8OGRB5blJiMmvqSh8SkaS7jkLWSpXtxUCeagA==",
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.13.tgz",
+ "integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==",
"dependencies": {
- "@vue/compiler-ssr": "3.5.8",
- "@vue/shared": "3.5.8"
+ "@vue/compiler-ssr": "3.5.13",
+ "@vue/shared": "3.5.13"
},
"peerDependencies": {
- "vue": "3.5.8"
+ "vue": "3.5.13"
}
},
"node_modules/@vue/shared": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.8.tgz",
- "integrity": "sha512-mJleSWbAGySd2RJdX1RBtcrUBX6snyOc0qHpgk3lGi4l9/P/3ny3ELqFWqYdkXIwwNN/kdm8nD9ky8o6l/Lx2A=="
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz",
+ "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ=="
},
"node_modules/@vue/tsconfig": {
"version": "0.5.1",
@@ -1159,13 +1165,20 @@
"node_modules/leaflet": {
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
- "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==",
- "dev": true
+ "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA=="
+ },
+ "node_modules/leaflet.markercluster": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz",
+ "integrity": "sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA==",
+ "peerDependencies": {
+ "leaflet": "^1.3.1"
+ }
},
"node_modules/magic-string": {
- "version": "0.30.11",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz",
- "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==",
+ "version": "0.30.17",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
+ "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0"
}
@@ -1286,9 +1299,9 @@
}
},
"node_modules/picocolors": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz",
- "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw=="
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
},
"node_modules/pidtree": {
"version": "0.6.0",
@@ -1302,10 +1315,31 @@
"node": ">=0.10"
}
},
+ "node_modules/pinia": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.3.0.tgz",
+ "integrity": "sha512-ohZj3jla0LL0OH5PlLTDMzqKiVw2XARmC1XYLdLWIPBMdhDW/123ZWr4zVAhtJm+aoSkFa13pYXskAvAscIkhQ==",
+ "dependencies": {
+ "@vue/devtools-api": "^6.6.3",
+ "vue-demi": "^0.14.10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/posva"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.4.4",
+ "vue": "^2.7.0 || ^3.5.11"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
"node_modules/postcss": {
- "version": "8.4.47",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
- "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
+ "version": "8.4.49",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
+ "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
"funding": [
{
"type": "opencollective",
@@ -1322,7 +1356,7 @@
],
"dependencies": {
"nanoid": "^3.3.7",
- "picocolors": "^1.1.0",
+ "picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
"engines": {
@@ -1531,15 +1565,15 @@
"dev": true
},
"node_modules/vue": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.8.tgz",
- "integrity": "sha512-hvuvuCy51nP/1fSRvrrIqTLSvrSyz2Pq+KQ8S8SXCxTWVE0nMaOnSDnSOxV1eYmGfvK7mqiwvd1C59CEEz7dAQ==",
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.13.tgz",
+ "integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==",
"dependencies": {
- "@vue/compiler-dom": "3.5.8",
- "@vue/compiler-sfc": "3.5.8",
- "@vue/runtime-dom": "3.5.8",
- "@vue/server-renderer": "3.5.8",
- "@vue/shared": "3.5.8"
+ "@vue/compiler-dom": "3.5.13",
+ "@vue/compiler-sfc": "3.5.13",
+ "@vue/runtime-dom": "3.5.13",
+ "@vue/server-renderer": "3.5.13",
+ "@vue/shared": "3.5.13"
},
"peerDependencies": {
"typescript": "*"
@@ -1550,6 +1584,31 @@
}
}
},
+ "node_modules/vue-demi": {
+ "version": "0.14.10",
+ "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
+ "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
+ "hasInstallScript": true,
+ "bin": {
+ "vue-demi-fix": "bin/vue-demi-fix.js",
+ "vue-demi-switch": "bin/vue-demi-switch.js"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "@vue/composition-api": "^1.0.0-rc.1",
+ "vue": "^3.0.0-0 || ^2.6.0"
+ },
+ "peerDependenciesMeta": {
+ "@vue/composition-api": {
+ "optional": true
+ }
+ }
+ },
"node_modules/vue-router": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.4.5.tgz",
@@ -1646,17 +1705,17 @@
"integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="
},
"@babel/parser": {
- "version": "7.26.1",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.1.tgz",
- "integrity": "sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw==",
+ "version": "7.26.3",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz",
+ "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==",
"requires": {
- "@babel/types": "^7.26.0"
+ "@babel/types": "^7.26.3"
}
},
"@babel/types": {
- "version": "7.26.0",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz",
- "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==",
+ "version": "7.26.3",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz",
+ "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==",
"requires": {
"@babel/helper-string-parser": "^7.25.9",
"@babel/helper-validator-identifier": "^7.25.9"
@@ -1958,6 +2017,27 @@
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
"dev": true
},
+ "@types/geojson": {
+ "version": "7946.0.15",
+ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.15.tgz",
+ "integrity": "sha512-9oSxFzDCT2Rj6DfcHF8G++jxBKS7mBqXl5xrRW+Kbvjry6Uduya2iiwqHPhVXpasAVMBYKkEPGgKhd3+/HZ6xA=="
+ },
+ "@types/leaflet": {
+ "version": "1.9.15",
+ "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.15.tgz",
+ "integrity": "sha512-7UuggAuAs+mva66gtf2OTB1nEhzU/9JED93TIaOEgvFMvG/dIGQaukHE7izHo1Zd+Ko1L4ETUw7TBc8yUxevpg==",
+ "requires": {
+ "@types/geojson": "*"
+ }
+ },
+ "@types/leaflet.markercluster": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@types/leaflet.markercluster/-/leaflet.markercluster-1.5.5.tgz",
+ "integrity": "sha512-TkWOhSHDM1ANxmLi+uK0PjsVcjIKBr8CLV2WoF16dIdeFmC0Cj5P5axkI3C1Xsi4+ht6EU8+BfEbbqEF9icPrg==",
+ "requires": {
+ "@types/leaflet": "*"
+ }
+ },
"@types/node": {
"version": "20.16.6",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.6.tgz",
@@ -2038,59 +2118,50 @@
"vscode-uri": "^3.0.8"
}
},
- "@vue-leaflet/vue-leaflet": {
- "version": "0.10.1",
- "resolved": "https://registry.npmjs.org/@vue-leaflet/vue-leaflet/-/vue-leaflet-0.10.1.tgz",
- "integrity": "sha512-RNEDk8TbnwrJl8ujdbKgZRFygLCxd0aBcWLQ05q/pGv4+d0jamE3KXQgQBqGAteE1mbQsk3xoNcqqUgaIGfWVg==",
- "dev": true,
- "requires": {
- "vue": "^3.2.25"
- }
- },
"@vue/compiler-core": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.8.tgz",
- "integrity": "sha512-Uzlxp91EPjfbpeO5KtC0KnXPkuTfGsNDeaKQJxQN718uz+RqDYarEf7UhQJGK+ZYloD2taUbHTI2J4WrUaZQNA==",
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz",
+ "integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==",
"requires": {
"@babel/parser": "^7.25.3",
- "@vue/shared": "3.5.8",
+ "@vue/shared": "3.5.13",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.2.0"
}
},
"@vue/compiler-dom": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.8.tgz",
- "integrity": "sha512-GUNHWvoDSbSa5ZSHT9SnV5WkStWfzJwwTd6NMGzilOE/HM5j+9EB9zGXdtu/fCNEmctBqMs6C9SvVPpVPuk1Eg==",
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz",
+ "integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==",
"requires": {
- "@vue/compiler-core": "3.5.8",
- "@vue/shared": "3.5.8"
+ "@vue/compiler-core": "3.5.13",
+ "@vue/shared": "3.5.13"
}
},
"@vue/compiler-sfc": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.8.tgz",
- "integrity": "sha512-taYpngQtSysrvO9GULaOSwcG5q821zCoIQBtQQSx7Uf7DxpR6CIHR90toPr9QfDD2mqHQPCSgoWBvJu0yV9zjg==",
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz",
+ "integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==",
"requires": {
"@babel/parser": "^7.25.3",
- "@vue/compiler-core": "3.5.8",
- "@vue/compiler-dom": "3.5.8",
- "@vue/compiler-ssr": "3.5.8",
- "@vue/shared": "3.5.8",
+ "@vue/compiler-core": "3.5.13",
+ "@vue/compiler-dom": "3.5.13",
+ "@vue/compiler-ssr": "3.5.13",
+ "@vue/shared": "3.5.13",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.11",
- "postcss": "^8.4.47",
+ "postcss": "^8.4.48",
"source-map-js": "^1.2.0"
}
},
"@vue/compiler-ssr": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.8.tgz",
- "integrity": "sha512-W96PtryNsNG9u0ZnN5Q5j27Z/feGrFV6zy9q5tzJVyJaLiwYxvC0ek4IXClZygyhjm+XKM7WD9pdKi/wIRVC/Q==",
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz",
+ "integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==",
"requires": {
- "@vue/compiler-dom": "3.5.8",
- "@vue/shared": "3.5.8"
+ "@vue/compiler-dom": "3.5.13",
+ "@vue/shared": "3.5.13"
}
},
"@vue/compiler-vue2": {
@@ -2125,46 +2196,46 @@
}
},
"@vue/reactivity": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.8.tgz",
- "integrity": "sha512-mlgUyFHLCUZcAYkqvzYnlBRCh0t5ZQfLYit7nukn1GR96gc48Bp4B7OIcSfVSvlG1k3BPfD+p22gi1t2n9tsXg==",
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.13.tgz",
+ "integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==",
"requires": {
- "@vue/shared": "3.5.8"
+ "@vue/shared": "3.5.13"
}
},
"@vue/runtime-core": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.8.tgz",
- "integrity": "sha512-fJuPelh64agZ8vKkZgp5iCkPaEqFJsYzxLk9vSC0X3G8ppknclNDr61gDc45yBGTaN5Xqc1qZWU3/NoaBMHcjQ==",
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.13.tgz",
+ "integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==",
"requires": {
- "@vue/reactivity": "3.5.8",
- "@vue/shared": "3.5.8"
+ "@vue/reactivity": "3.5.13",
+ "@vue/shared": "3.5.13"
}
},
"@vue/runtime-dom": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.8.tgz",
- "integrity": "sha512-DpAUz+PKjTZPUOB6zJgkxVI3GuYc2iWZiNeeHQUw53kdrparSTG6HeXUrYDjaam8dVsCdvQxDz6ZWxnyjccUjQ==",
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz",
+ "integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==",
"requires": {
- "@vue/reactivity": "3.5.8",
- "@vue/runtime-core": "3.5.8",
- "@vue/shared": "3.5.8",
+ "@vue/reactivity": "3.5.13",
+ "@vue/runtime-core": "3.5.13",
+ "@vue/shared": "3.5.13",
"csstype": "^3.1.3"
}
},
"@vue/server-renderer": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.8.tgz",
- "integrity": "sha512-7AmC9/mEeV9mmXNVyUIm1a1AjUhyeeGNbkLh39J00E7iPeGks8OGRB5blJiMmvqSh8SkaS7jkLWSpXtxUCeagA==",
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.13.tgz",
+ "integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==",
"requires": {
- "@vue/compiler-ssr": "3.5.8",
- "@vue/shared": "3.5.8"
+ "@vue/compiler-ssr": "3.5.13",
+ "@vue/shared": "3.5.13"
}
},
"@vue/shared": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.8.tgz",
- "integrity": "sha512-mJleSWbAGySd2RJdX1RBtcrUBX6snyOc0qHpgk3lGi4l9/P/3ny3ELqFWqYdkXIwwNN/kdm8nD9ky8o6l/Lx2A=="
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz",
+ "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ=="
},
"@vue/tsconfig": {
"version": "0.5.1",
@@ -2348,13 +2419,18 @@
"leaflet": {
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
- "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==",
- "dev": true
+ "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA=="
+ },
+ "leaflet.markercluster": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz",
+ "integrity": "sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA==",
+ "requires": {}
},
"magic-string": {
- "version": "0.30.11",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz",
- "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==",
+ "version": "0.30.17",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
+ "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
"requires": {
"@jridgewell/sourcemap-codec": "^1.5.0"
}
@@ -2432,9 +2508,9 @@
"dev": true
},
"picocolors": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz",
- "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw=="
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
},
"pidtree": {
"version": "0.6.0",
@@ -2442,13 +2518,22 @@
"integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
"dev": true
},
+ "pinia": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.3.0.tgz",
+ "integrity": "sha512-ohZj3jla0LL0OH5PlLTDMzqKiVw2XARmC1XYLdLWIPBMdhDW/123ZWr4zVAhtJm+aoSkFa13pYXskAvAscIkhQ==",
+ "requires": {
+ "@vue/devtools-api": "^6.6.3",
+ "vue-demi": "^0.14.10"
+ }
+ },
"postcss": {
- "version": "8.4.47",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
- "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
+ "version": "8.4.49",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
+ "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
"requires": {
"nanoid": "^3.3.7",
- "picocolors": "^1.1.0",
+ "picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
}
},
@@ -2567,17 +2652,23 @@
"dev": true
},
"vue": {
- "version": "3.5.8",
- "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.8.tgz",
- "integrity": "sha512-hvuvuCy51nP/1fSRvrrIqTLSvrSyz2Pq+KQ8S8SXCxTWVE0nMaOnSDnSOxV1eYmGfvK7mqiwvd1C59CEEz7dAQ==",
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.13.tgz",
+ "integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==",
"requires": {
- "@vue/compiler-dom": "3.5.8",
- "@vue/compiler-sfc": "3.5.8",
- "@vue/runtime-dom": "3.5.8",
- "@vue/server-renderer": "3.5.8",
- "@vue/shared": "3.5.8"
+ "@vue/compiler-dom": "3.5.13",
+ "@vue/compiler-sfc": "3.5.13",
+ "@vue/runtime-dom": "3.5.13",
+ "@vue/server-renderer": "3.5.13",
+ "@vue/shared": "3.5.13"
}
},
+ "vue-demi": {
+ "version": "0.14.10",
+ "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
+ "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
+ "requires": {}
+ },
"vue-router": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.4.5.tgz",
diff --git a/webapp/package.json b/webapp/package.json
index 70c1fb7..469f372 100644
--- a/webapp/package.json
+++ b/webapp/package.json
@@ -12,8 +12,11 @@
},
"dependencies": {
"@unhead/vue": "^1.11.14",
+ "@types/leaflet.markercluster": "^1.5.5",
"axios": "^1.7.7",
"countup.js": "^2.8.0",
+ "leaflet.markercluster": "^1.5.3",
+ "pinia": "^2.3.0",
"vue": "^3.4.29",
"vue-router": "^4.3.3",
"vuetify": "^3.7.2"
@@ -21,9 +24,9 @@
"devDependencies": {
"@mdi/font": "^7.4.47",
"@tsconfig/node20": "^20.1.4",
+ "@types/leaflet": "^1.9.15",
"@types/node": "^20.14.5",
"@vitejs/plugin-vue": "^5.0.5",
- "@vue-leaflet/vue-leaflet": "^0.10.1",
"@vue/tsconfig": "^0.5.1",
"leaflet": "^1.9.4",
"npm-run-all2": "^6.2.0",
diff --git a/webapp/public/404media.svg b/webapp/public/404media.svg
new file mode 100644
index 0000000..8748ee2
--- /dev/null
+++ b/webapp/public/404media.svg
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/webapp/public/deflock-logo-grey.svg b/webapp/public/deflock-logo-grey.svg
new file mode 100644
index 0000000..a448b6e
--- /dev/null
+++ b/webapp/public/deflock-logo-grey.svg
@@ -0,0 +1,27 @@
+
+
+
diff --git a/webapp/public/icon-discord-white.svg b/webapp/public/icon-discord-white.svg
new file mode 100644
index 0000000..1a47495
--- /dev/null
+++ b/webapp/public/icon-discord-white.svg
@@ -0,0 +1 @@
+
diff --git a/webapp/public/icon-discord.svg b/webapp/public/icon-discord.svg
new file mode 100644
index 0000000..d57ac7e
--- /dev/null
+++ b/webapp/public/icon-discord.svg
@@ -0,0 +1 @@
+
diff --git a/webapp/public/map-icon.svg b/webapp/public/map-icon.svg
new file mode 100644
index 0000000..213d7b5
--- /dev/null
+++ b/webapp/public/map-icon.svg
@@ -0,0 +1,10 @@
+
+
+
diff --git a/webapp/public/white-logos/404media.svg b/webapp/public/white-logos/404media.svg
new file mode 100644
index 0000000..5b6f564
--- /dev/null
+++ b/webapp/public/white-logos/404media.svg
@@ -0,0 +1,7 @@
+
diff --git a/webapp/public/white-logos/forbes.svg b/webapp/public/white-logos/forbes.svg
new file mode 100644
index 0000000..a1a62de
--- /dev/null
+++ b/webapp/public/white-logos/forbes.svg
@@ -0,0 +1,4 @@
+
+
diff --git a/webapp/public/white-logos/latimes.svg b/webapp/public/white-logos/latimes.svg
new file mode 100644
index 0000000..5de0dca
--- /dev/null
+++ b/webapp/public/white-logos/latimes.svg
@@ -0,0 +1,93 @@
+
+
+
+
diff --git a/webapp/src/App.vue b/webapp/src/App.vue
index 581de5c..5ea27b7 100644
--- a/webapp/src/App.vue
+++ b/webapp/src/App.vue
@@ -1,10 +1,11 @@
diff --git a/webapp/src/components/DFMapPopup.vue b/webapp/src/components/DFMapPopup.vue
index 8fa93be..19c0701 100644
--- a/webapp/src/components/DFMapPopup.vue
+++ b/webapp/src/components/DFMapPopup.vue
@@ -5,13 +5,13 @@
- DeFlock is a tool to help you learn about Automated License Plate Readers (ALPRs) in your area. Here's how it works: -
-Welcome to DeFlock, your go-to resource for understanding and addressing the growing presence of Automated License Plate Readers (ALPRs) in our communities. @@ -48,22 +48,13 @@ Share our site with your friends, family, and social networks to help raise awareness about the dangers of ALPRs.
- -+ Want to see your name here? Become a sponsor, and your name will appear on this page! +
+© {{ new Date().getFullYear() }} DeFlock. All rights reserved.
+ +Special thanks to Jason Koebler at 404 Media for popularizing this project. Be sure to support them, as they are fellow privacy advocates.
+- Automated License Plate Readers (ALPRs) are monitoring your every move. Learn more about how they work and how you can protect your privacy. -
-- ALPRs are a threat to your privacy and civil liberties. They can be used to track your movements, profile you, and even stalk you. Learn more about the dangers of ALPRs and how you can protect yourself. -
- -+ Automated License Plate Readers (ALPRs) are cameras that capture images of all passing license plates, storing details like the car's location, date, and time. These cameras collect data on millions of vehicles—regardless of whether the driver is suspected of a crime. While these systems can be useful for tracking stolen cars or wanted individuals, they are mostly used to track the movements of innocent people. +
- -+ ALPRs are a threat to your privacy and civil liberties. They can be used to track your movements and profile you, and even stalk you. Learn more about the dangers of ALPRs and how you can protect yourself. +
+ +- This website uses data from OpenStreetMap. OpenStreetMap is open data, licensed under the Open Data Commons Open Database License (ODbL). -
-- Geocoding services are provided by Nominatim, a project of OpenStreetMap. -
- -- We use Plausible Analytics to track anonymous usage data. Plausible does not use cookies or collect personally identifiable information. The data collected is used solely to understand how people are using the site and to improve user experience. -
-- No data is shared with third parties, and no personally identifiable information is stored or collected. -
- -- At this time, DeFlock.me does not collect or store user-submitted reports. Users are directed to submit ALPR camera locations directly to OpenStreetMap via their editing platform, which has its own privacy policy and data practices. -
- -- DeFlock.me provides a service to help users locate and report Automated License Plate Reader (ALPR) cameras through external services like OpenStreetMap. By using this site, you agree to use the tools and resources in a lawful and ethical manner. -
- -- DeFlock.me provides information and directs users to third-party services for ALPR reporting. We do not guarantee the accuracy or completeness of the data presented on the map. -
-- DeFlock.me and its operators are not liable for any direct or indirect damages arising from the use of the site, including reliance on third-party data or the submission of ALPR locations via OpenStreetMap. -
- -- DeFlock.me does not currently accept user-generated reports directly. All ALPR camera reports are directed to OpenStreetMap's editing platform. Users should follow OSM's guidelines and policies when submitting data. -
-- In the future, we may add the ability to report ALPR cameras directly on this site. At that time, additional policies will be introduced regarding the use and storage of user-generated content. -
- -- All original content, design, and features of DeFlock.me are © {{ thisYear }} DeFlock.me. All rights reserved. Reproduction, distribution, or use of site content without permission is prohibited. -
-- OpenStreetMap data is © OpenStreetMap contributors and is licensed under the Open Data Commons Open Database License (ODbL). -
- -- Automated License Plate Readers (ALPRs) are monitoring your every move. Learn more about how they work and how you can protect your privacy. -
-- ALPRs are a threat to your privacy and civil liberties. They can be used to track your movements, profile you, and even stalk you. Learn more about the dangers of ALPRs and how you can protect yourself. -
- -- We're working on a feature that will allow you to report ALPRs directly on this site. In the meantime, you can follow the steps below to add the ALPR to OpenStreetMap. -
-If you've spotted an ALPR in your area, you can help us track it by reporting it to OpenStreetMap, where we source our information. Here's how you can do it:
-
- Before you report an ALPR, please read our
+ Sign up for an OpenStreetMap account in order to submit changes. +
+- Sign up for an OpenStreetMap account in order to submit changes. -
++ Launch OpenStreetMap and search for the location of the ALPR. You can use the search bar at the top of the page to find the location. +
+- Launch OpenStreetMap and search for the location of the ALPR. You can use the search bar at the top of the page to find the location. -
++ Once you've found the location of the ALPR, click the Edit button in the top left corner of the page. This will open the OpenStreetMap editor, where you can add the ALPR to the map. +
++ To add the ALPR, click the Point button in the top left corner of the editor, then click on the location of the ALPR on the map. In the popup that appears, paste one of the following sets of tags based on the brand of the ALPR: +
-- Once you've found the location of the ALPR, click the Edit button in the top left corner of the page. This will open the OpenStreetMap editor, where you can add the ALPR to the map. -
+- To add the ALPR, click the Point button in the top left corner of the editor, then click on the location of the ALPR on the map. In the popup that appears, paste one of the following sets of tags based on the brand of the ALPR: -
++ After copying the tags, paste them into the Tags field in the popup. +
++ If you know the direction that the ALPR is facing, you can use the up and down arrows to set the direction it faces. +
+- After copying the tags, paste them into the Tags field in the popup. -
++ Once you've added the ALPR to the map, click the Save button in the top left corner of the editor. You'll be asked to provide a brief description of your changes. Once you've submitted your changes, the ALPR will be added to OpenStreetMap. +
++ We pull data from OpenStreetMap daily, so it may take up to 24 hours for your changes to appear on this site. Rest assured that your changes will be reflected here soon. As we continue to scale, we hope to reduce this delay. +
++ Download our ALPR sign and hang it near the ALPR to help raise awareness about the device. Be sure to follow all local laws and regulations when hanging signs. +
-+ If you find an ALPR that's missing information and would like to update it, you can follow the same steps as above. Each ALPR on DeFlock has a Node ID that you can use to find it on OpenStreetMap. +
-- If you know the direction that the ALPR is facing, you can use the up and down arrows to set the direction it faces. -
+
+ Simply click on the ALPR with missing information, and find the Node ID (e.g. node/1237489334) at the bottom of the popup. In the OSM editor search field, paste the numerical portion of the Node ID to find the ALPR and make your changes.
+
- Once you've added the ALPR to the map, click the Save button in the top left corner of the editor. You'll be asked to provide a brief description of your changes. Once you've submitted your changes, the ALPR will be added to OpenStreetMap. -
- -- Download our ALPR sign and hang it near the ALPR to help raise awareness about the device. Be sure to follow all local laws and regulations when hanging signs. -
- -Effective Date: 12/26/2024
+ ++ Welcome to DeFlock. By accessing or using our site, you agree to these Terms of Service. If you do not agree, please refrain from using DeFlock. +
+ ++ DeFlock provides access to map data sourced from OpenStreetMap (OSM). Our platform allows users to view maps and provides examples of OSM tags for contributing Automatic License Plate Recognition (ALPR) data or other information to OSM. +
+ ++ While DeFlock provides examples of OSM tags that may be relevant for your contributions, it is the user’s responsibility to ensure the accuracy and appropriateness of the tags used when uploading to OSM. DeFlock is not liable for any consequences arising from incorrect or inappropriate tagging. +
+ ++ DeFlock must not be used for any of the following purposes: +
+ ++ By using DeFlock, you agree to comply with all applicable laws and regulations. +
+ ++ DeFlock integrates with OpenStreetMap, and any interactions with OSM are governed by their terms of use. DeFlock is not responsible for the collection, storage, or use of data by OSM or any third-party services. For more information, please review the OpenStreetMap Terms of Use. +
+ ++ DeFlock is provided "as is" without warranties of any kind. We do not guarantee the accuracy, reliability, or completeness of any map data or tagging guidance provided. DeFlock is not liable for any issues arising from: +
+ ++ All content provided by DeFlock, including design, text, and logos, is the intellectual property of DeFlock unless otherwise noted. Users may not copy, distribute, or modify this content without prior written permission. +
++ DeFlock's source code is licensed under the MIT License. For details, please refer to the LICENSE file. +
+ ++ We reserve the right to suspend or terminate access to DeFlock at our sole discretion if we believe a user has violated these Terms of Service. +
+ ++ DeFlock reserves the right to update or modify these Terms of Service at any time. Changes will be effective upon posting to our website. Continued use of DeFlock constitutes acceptance of the updated terms. +
+ ++ If you have any questions or concerns regarding these Terms of Service, please contact us at: +
++ Email: contact@deflock.me +
+
-
Automated License Plate Readers (ALPRs) are cameras that capture images of all passing license plates, storing details like the car's location, date, and time. These cameras collect data on millions of vehicles—regardless of whether the driver is suspected of a crime. While these systems can be useful for tracking stolen cars or wanted individuals, they are mostly used to track the movements of innocent people.
@@ -12,111 +13,159 @@For a detailed explanation of how ALPRs are a threat to privacy, see this ACLU article as well as this EFF article on ALPRs.
+
ALPRs invade your privacy and violate your civil liberties. Here's how:
- While Flock Safety is a common brand of ALPRs in the US, there are several others, including Vigilant Solutions, owned by Motorola Solutions. Flock Safety ALPRs are easy to spot as they almost all look the same, typically mounted on poles with a solar panel on top. In rural areas, they are likely to be on standalone black poles, while in cities, they are more likely to be on existing utility or traffic poles. The cameras are often placed near intersections or on main roads at the edge of a city or town. Vigilant Solutions ALPRs, on the other hand, are typically mounted on traffic poles at or near intersections, with a distinctive white box mounted nearby. -
+
+
+ {{ isMobile ? 'Tap' : 'Hover over' }} an image below to identify the make. + Click an image to enlarge. +
+- Not all cameras near roads are ALPRs operated by law enforcement. Many people mistakenly assume that every traffic camera or intersection camera is an ALPR, but the reality is more nuanced. Here are some common types of cameras you might see near roads: -
+Standard traffic cameras typically capture live video or images of intersections to monitor traffic flow and manage signals. They do not specifically focus on reading license plates or storing data long-term.
-These cameras are set up to capture violations, such as running a red light or speeding. They may record plate numbers when a violation is detected, but they do not perform continuous surveillance or collect location data over time.
-Cameras on toll roads are used to capture license plates for billing purposes. They are not designed to track vehicles or store data beyond the transaction.
-