diff --git a/src/components/DynamicFavicon.tsx b/src/components/DynamicFavicon.tsx
new file mode 100644
index 0000000..62f2b06
--- /dev/null
+++ b/src/components/DynamicFavicon.tsx
@@ -0,0 +1,56 @@
+"use client";
+
+import { useEffect } from "react";
+
+interface DynamicFaviconProps {
+ logoUrl: string | null;
+ orgName: string;
+ primaryColor: string;
+}
+
+export function DynamicFavicon({ logoUrl, orgName, primaryColor }: DynamicFaviconProps) {
+ useEffect(() => {
+ // If there's a logo URL, use it as favicon
+ if (logoUrl) {
+ // Remove any existing favicon links
+ const existingLinks = document.querySelectorAll("link[rel*='icon']");
+ existingLinks.forEach(link => link.remove());
+
+ // Create new favicon link
+ const link = document.createElement("link");
+ link.rel = "icon";
+ link.type = "image/png";
+ link.href = logoUrl;
+ document.head.appendChild(link);
+
+ // Also add apple touch icon
+ const appleLink = document.createElement("link");
+ appleLink.rel = "apple-touch-icon";
+ appleLink.href = logoUrl;
+ document.head.appendChild(appleLink);
+ } else {
+ // Generate a simple SVG favicon with the first letter
+ const svg = `
+
+ `;
+ const blob = new Blob([svg], { type: "image/svg+xml" });
+ const url = URL.createObjectURL(blob);
+
+ const existingLinks = document.querySelectorAll("link[rel*='icon']");
+ existingLinks.forEach(link => link.remove());
+
+ const link = document.createElement("link");
+ link.rel = "icon";
+ link.type = "image/svg+xml";
+ link.href = url;
+ document.head.appendChild(link);
+ }
+ }, [logoUrl, orgName, primaryColor]);
+
+ return null;
+}
diff --git a/src/components/DynamicTitle.tsx b/src/components/DynamicTitle.tsx
new file mode 100644
index 0000000..a9a49a5
--- /dev/null
+++ b/src/components/DynamicTitle.tsx
@@ -0,0 +1,17 @@
+"use client";
+
+import { useEffect } from "react";
+
+interface DynamicTitleProps {
+ title: string;
+ orgName?: string;
+}
+
+export function DynamicTitle({ title, orgName }: DynamicTitleProps) {
+ useEffect(() => {
+ const fullTitle = orgName ? `${title} | ${orgName}` : title;
+ document.title = fullTitle;
+ }, [title, orgName]);
+
+ return null;
+}
diff --git a/src/components/LoginClient.tsx b/src/components/LoginClient.tsx
index 8da8667..a40d2ff 100644
--- a/src/components/LoginClient.tsx
+++ b/src/components/LoginClient.tsx
@@ -9,6 +9,8 @@ import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Alert, AlertDescription } from "@/components/ui/alert";
+import { DynamicFavicon } from "@/components/DynamicFavicon";
+import { DynamicTitle } from "@/components/DynamicTitle";
type Organization = {
id: string;
@@ -42,6 +44,8 @@ export default function LoginClient({ organization }: { organization: Organizati
return (
+
+
{/* Left Side: Illustration & Info - Hidden on Mobile */}
(
<>
@@ -104,6 +110,25 @@ export function Sidebar({
})}
+ {/* External Links */}
+
+