diff --git a/apps/web/src/app/token/page.tsx b/apps/web/src/app/token/page.tsx
new file mode 100644
index 0000000..833f6e4
--- /dev/null
+++ b/apps/web/src/app/token/page.tsx
@@ -0,0 +1,30 @@
+"use client";
+
+import { useEffect } from "react";
+
+const TokenPage = () => {
+ useEffect(() => {
+ // 1️⃣ Generate a fake token (for testing)
+ const token = `test_token_${Math.random().toString(36).slice(2)}`;
+ console.log("🔑 Generated token:", token);
+
+ // 2️⃣ Save token to localStorage
+ localStorage.setItem("token", token);
+ console.log("💾 Token stored in localStorage");
+
+ // 3️⃣ Send token to window event (for extension content script)
+ setTimeout(() => {
+ console.log("📤 Posting token to window event:", token);
+ window.postMessage({ type: "SAVE_TO_EXTENSION", token }, "*");
+ }, 500); // small delay to make sure content script is ready
+ }, []);
+
+ return (
+
+
Token Page
+
Generated token is saved and sent to extension.
+
+ );
+};
+
+export default TokenPage;
diff --git a/browser-extension/manifest.config.ts b/browser-extension/manifest.config.ts
index a81bbce..0d815ee 100644
--- a/browser-extension/manifest.config.ts
+++ b/browser-extension/manifest.config.ts
@@ -27,6 +27,14 @@ export default defineManifest({
js: ["src/content/main.tsx"],
matches: ["https://*/*", "http://*/*"],
},
+ {
+ js: ["src/content/test.js"],
+ matches: ["https://*/*", "http://*/*"],
+ },
+ {
+ matches: ["http://localhost:3000/*","https://untangle.rookie.house/*"],
+ js:["src/content.ts"]
+ }
],
side_panel: {
default_path: "src/sidepanel/index.html",
diff --git a/browser-extension/package.json b/browser-extension/package.json
index e5bac39..d85f8c6 100644
--- a/browser-extension/package.json
+++ b/browser-extension/package.json
@@ -16,7 +16,7 @@
"zod": "^4.1.8"
},
"devDependencies": {
- "@crxjs/vite-plugin": "^2.0.3",
+ "@crxjs/vite-plugin": "^2.2.0",
"@types/chrome": "^0.1.11",
"@types/node": "^24.3.2",
"@types/react": "^19.1.8",
diff --git a/browser-extension/src/content.ts b/browser-extension/src/content.ts
new file mode 100644
index 0000000..fd85885
--- /dev/null
+++ b/browser-extension/src/content.ts
@@ -0,0 +1,23 @@
+console.log("🚀 content.ts loaded on", window.location.href);
+
+window.addEventListener("message", (event) => {
+ console.log("🟢 Content script received window message:", event);
+
+ // if (event.origin !== "https://untangle.rookie.house") {
+ // console.warn("Blocked message from origin:", event.origin);
+ // return;
+ // }
+
+ if (event.data.type === "SAVE_TO_EXTENSION") {
+ console.log("🟠 Forwarding token to service worker:", event.data.token);
+ chrome.runtime.sendMessage(
+ {
+ action: "SAVE_TOKEN",
+ token: event.data.token,
+ },
+ (response) => {
+ console.log("🟡 Got response from service worker:", response);
+ }
+ );
+ }
+});
diff --git a/browser-extension/src/content/main.tsx b/browser-extension/src/content/main.tsx
index 4ced6ec..74bc493 100644
--- a/browser-extension/src/content/main.tsx
+++ b/browser-extension/src/content/main.tsx
@@ -2,13 +2,82 @@ import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./views/App.tsx";
-console.log("[CRXJS] Hello world from content script!");
-
-const container = document.createElement("div");
-container.id = "crxjs-app";
-document.body.appendChild(container);
-createRoot(container).render(
-
-
-
+console.log("[UNTANGLE] Content script loaded!", window.location.href);
+
+// Check if we're in an iframe or restricted context
+const isInIframe = window !== window.top;
+const isRestrictedDomain = ['extension://', 'chrome://', 'moz-extension://'].some(protocol =>
+ window.location.href.startsWith(protocol)
);
+
+console.log("[UNTANGLE] Context check:", { isInIframe, isRestrictedDomain });
+
+// Wait for DOM to be ready and create the app
+const initializeApp = () => {
+ try {
+ // Check if our container already exists (avoid duplicate mounting)
+ if (document.getElementById("crxjs-app")) {
+ console.log("[UNTANGLE] App already mounted, skipping...");
+ return;
+ }
+
+ if (!document.body) {
+ console.log("[UNTANGLE] Body not ready, retrying...");
+ setTimeout(initializeApp, 100);
+ return;
+ }
+
+ console.log("[UNTANGLE] Creating container...");
+ const container = document.createElement("div");
+ container.id = "crxjs-app";
+
+ // Add inline styles as fallback
+ container.style.cssText = `
+ position: fixed !important;
+ right: 20px !important;
+ bottom: 20px !important;
+ z-index: 2147483647 !important;
+ width: auto !important;
+ height: auto !important;
+ pointer-events: auto !important;
+ `;
+
+ document.body.appendChild(container);
+ console.log("[UNTANGLE] Container added to DOM");
+
+ const root = createRoot(container);
+ root.render(
+
+
+
+ );
+
+ console.log("[UNTANGLE] Viewport button mounted successfully!");
+
+ // Verify the button is actually visible
+ setTimeout(() => {
+ const button = container.querySelector('.toggle-button');
+ if (button) {
+ console.log("[UNTANGLE] Button found in DOM:", button);
+ } else {
+ console.error("[UNTANGLE] Button not found in DOM!");
+ }
+ }, 1000);
+
+ } catch (error) {
+ console.error("[UNTANGLE] Error initializing app:", error);
+ }
+};
+
+// Don't load in iframes or restricted domains
+if (!isInIframe && !isRestrictedDomain) {
+ // Initialize when DOM is ready
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', initializeApp);
+ } else {
+ // DOM is already ready
+ initializeApp();
+ }
+} else {
+ console.log("[UNTANGLE] Skipping initialization due to context restrictions");
+}
diff --git a/browser-extension/src/content/test.js b/browser-extension/src/content/test.js
new file mode 100644
index 0000000..5b62d1f
--- /dev/null
+++ b/browser-extension/src/content/test.js
@@ -0,0 +1,37 @@
+// Simple test script to verify content script injection works
+console.log("[UNTANGLE TEST] Content script injection working!");
+
+// Create a simple test element
+const testDiv = document.createElement('div');
+testDiv.id = 'untangle-test';
+testDiv.style.cssText = `
+ position: fixed;
+ top: 10px;
+ right: 10px;
+ background: red;
+ color: white;
+ padding: 10px;
+ z-index: 999999;
+ font-family: monospace;
+`;
+testDiv.textContent = 'UNTANGLE TEST';
+
+// Add when DOM is ready
+const addTest = () => {
+ if (document.body) {
+ document.body.appendChild(testDiv);
+ console.log("[UNTANGLE TEST] Test element added");
+
+ // Remove after 3 seconds
+ setTimeout(() => {
+ if (testDiv.parentNode) {
+ testDiv.parentNode.removeChild(testDiv);
+ console.log("[UNTANGLE TEST] Test element removed");
+ }
+ }, 3000);
+ } else {
+ setTimeout(addTest, 100);
+ }
+};
+
+addTest();
\ No newline at end of file
diff --git a/browser-extension/src/content/views/App.css b/browser-extension/src/content/views/App.css
index 2a6d764..af7185f 100644
--- a/browser-extension/src/content/views/App.css
+++ b/browser-extension/src/content/views/App.css
@@ -60,15 +60,91 @@ body {
opacity: 0;
}
+/* Reset any potential conflicts */
+* {
+ box-sizing: border-box;
+}
+
+body {
+ background: transparent !important;
+}
+
#crxjs-app {
- position: fixed;
- right: 0;
- bottom: 0;
- z-index: 9999;
+ position: fixed !important;
+ right: 20px !important;
+ bottom: 20px !important;
+ z-index: 2147483647 !important; /* Maximum z-index */
+ background: transparent !important;
+ padding: 0 !important;
+ margin: 0 !important;
+ width: auto !important;
+ height: auto !important;
+ box-shadow: none !important;
+ pointer-events: auto !important;
+ font-family: ui-sans-serif, system-ui, sans-serif !important;
+ border: none !important;
+ outline: none !important;
+}
+
+.toggle-button {
+ position: relative !important;
+ display: flex !important;
+ align-items: center !important;
+ justify-content: center !important;
+ width: 56px !important;
+ height: 56px !important;
+ border-radius: 50% !important;
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15), 0 8px 32px rgba(0, 0, 0, 0.1) !important;
+ cursor: pointer !important;
+ border: none !important;
+ background: linear-gradient(135deg, #288cd7, #1e6aa3) !important;
+ transition: all 0.3s ease !important;
+ overflow: hidden !important;
+ font-size: 24px !important;
+ color: white !important;
+ text-decoration: none !important;
+ font-family: inherit !important;
+ outline: none !important;
+ user-select: none !important;
+ -webkit-user-select: none !important;
+ -moz-user-select: none !important;
+ -ms-user-select: none !important;
+}
+
+.toggle-button:hover {
+ background: linear-gradient(135deg, #1e6aa3, #155a87) !important;
+ transform: translateY(-2px) !important;
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2), 0 12px 40px rgba(0, 0, 0, 0.15) !important;
+}
+
+.toggle-button:active {
+ transform: translateY(0) !important;
+}
+
+.toggle-button:focus {
+ outline: 2px solid rgba(40, 140, 215, 0.5) !important;
+ outline-offset: 2px !important;
+}
+
+/* Ensure button is always visible */
+.toggle-button::before {
+ content: '' !important;
+ position: absolute !important;
+ top: 0 !important;
+ left: 0 !important;
+ right: 0 !important;
+ bottom: 0 !important;
+ background: inherit !important;
+ border-radius: inherit !important;
+ z-index: -1 !important;
+}
+
+/* Remove any potential inherited styles */
+.toggle-button * {
+ margin: 0 !important;
+ padding: 0 !important;
+ border: none !important;
background: transparent !important;
- padding: 1rem;
- margin: 0.5rem;
- width: auto;
- height: auto;
- box-shadow: none;
+ font-size: inherit !important;
+ color: inherit !important;
}
diff --git a/browser-extension/src/content/views/App.tsx b/browser-extension/src/content/views/App.tsx
index 636535f..e718151 100644
--- a/browser-extension/src/content/views/App.tsx
+++ b/browser-extension/src/content/views/App.tsx
@@ -1,24 +1,59 @@
-import Logo from "@/assets/crx.svg";
import "./App.css";
+import { useState, useEffect } from "react";
function App() {
+ const [mounted, setMounted] = useState(false);
+
+ useEffect(() => {
+ setMounted(true);
+ console.log("[UNTANGLE] App component mounted");
+ }, []);
+
const openSidePanel = async () => {
try {
- await chrome.runtime.sendMessage({
+ console.log("[UNTANGLE] Button clicked, sending message...");
+ const response = await chrome.runtime.sendMessage({
action: "openSidePanelRequest",
});
- console.log("Request sent to open side panel.");
+ console.log("[UNTANGLE] Message sent successfully, response:", response);
} catch (error) {
- console.error("Error sending message:", error);
- alert(
- "Could not send a request to open side panel. See console for details."
- );
+ console.error("[UNTANGLE] Error sending message:", error);
+ // Show user-friendly error
+ alert("Could not open sidepanel. Please refresh the page and try again.");
}
};
+ if (!mounted) {
+ return null;
+ }
+
return (
-