diff --git a/web/src/App.tsx b/web/src/App.tsx
index d058e48..e851183 100644
--- a/web/src/App.tsx
+++ b/web/src/App.tsx
@@ -1,7 +1,14 @@
-import type { FC } from "react";
+import { useEffect, useState, type FC } from "react";
+import { getDeviceId } from "./util/deviceId";
const App: FC = () => {
- return
Hello
;
+ const [deviceId, setDeviceId] = useState("");
+
+ useEffect(() => {
+ getDeviceId().then((id) => setDeviceId(id));
+ }, []);
+
+ return {deviceId}
;
};
export default App;
diff --git a/web/src/util/deviceId.ts b/web/src/util/deviceId.ts
new file mode 100644
index 0000000..8aa4134
--- /dev/null
+++ b/web/src/util/deviceId.ts
@@ -0,0 +1,31 @@
+export const getDeviceId = async () => {
+ const existing = localStorage.getItem("guard-device-id");
+ if (existing) return existing;
+
+ const fingerprintParts = [
+ navigator.userAgent, // Browser and OS
+ screen.width + "x" + screen.height, // Screen resolution
+ screen.colorDepth, // Color depth
+ Intl.DateTimeFormat().resolvedOptions().timeZone, // Time zone
+ navigator.platform, // OS platform
+ navigator.hardwareConcurrency, // Number of CPU cores
+ navigator.language, // Primary language
+ navigator.maxTouchPoints, // Touch capability
+ ];
+ console.log(fingerprintParts);
+
+ const rawFingerprint = fingerprintParts.join("|");
+ const encoder = new TextEncoder();
+ const data = encoder.encode(rawFingerprint);
+
+ const hashBuffer = await crypto.subtle.digest("SHA-256", data);
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
+
+ const deviceId = hashArray
+ .map((b) => b.toString(16).padStart(2, "0"))
+ .join("");
+
+ localStorage.setItem("guard-device-id", deviceId);
+
+ return deviceId; // A 64-character hex string
+};