67 lines
3 KiB
HTML
Executable file
67 lines
3 KiB
HTML
Executable file
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
|
<link rel="manifest" href="/site.webmanifest" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<link rel="canonical" href="https://familiar-os.com/" />
|
|
<meta name="robots" content="index,follow,max-image-preview:large,max-snippet:-1,max-video-preview:-1" />
|
|
<meta name="description" content="FamiliarOS is a local-first AI companion platform. Create a persistent desktop Familiar that remembers, speaks, and acts across your system." />
|
|
<meta name="keywords" content="AI companion, local-first AI, desktop companion, MCP tools, voice AI, personal agent, FamiliarOS" />
|
|
<title>FamiliarOS — Local-first AI companion platform</title>
|
|
<!-- Socket.IO v0.9 - Load from CDN to avoid bundling issues -->
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.17/socket.io.min.js"></script>
|
|
</head>
|
|
<body>
|
|
<div id="root"></div>
|
|
<script>
|
|
(function () {
|
|
const BACKDROP_ID = 'familiaros-auth-shell-backdrop';
|
|
|
|
function isAuthRoute(pathname) {
|
|
return pathname === '/login' || pathname.startsWith('/login/') || pathname.startsWith('/auth/');
|
|
}
|
|
|
|
function syncAuthChrome() {
|
|
const shouldRender = isAuthRoute(window.location.pathname);
|
|
const existingBackdrop = document.getElementById(BACKDROP_ID);
|
|
|
|
if (!shouldRender) {
|
|
if (existingBackdrop) existingBackdrop.remove();
|
|
return;
|
|
}
|
|
|
|
if (!existingBackdrop) {
|
|
const backdrop = document.createElement('div');
|
|
backdrop.id = BACKDROP_ID;
|
|
backdrop.setAttribute('data-testid', 'supertokens-auth-backdrop');
|
|
backdrop.setAttribute('aria-hidden', 'true');
|
|
backdrop.style.position = 'fixed';
|
|
backdrop.style.inset = '0';
|
|
backdrop.style.zIndex = '0';
|
|
backdrop.style.pointerEvents = 'none';
|
|
backdrop.style.background = 'radial-gradient(circle at top, rgba(216,203,175,0.12), transparent 40%), linear-gradient(180deg, rgba(18,20,24,0.97), rgba(10,12,17,0.99))';
|
|
document.body.appendChild(backdrop);
|
|
}
|
|
}
|
|
|
|
function startAuthChromeObserver() {
|
|
syncAuthChrome();
|
|
window.addEventListener('popstate', syncAuthChrome);
|
|
window.addEventListener('hashchange', syncAuthChrome);
|
|
}
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', startAuthChromeObserver, { once: true });
|
|
} else {
|
|
startAuthChromeObserver();
|
|
}
|
|
})();
|
|
</script>
|
|
<script type="module" src="/src/main.tsx"></script>
|
|
</body>
|
|
</html>
|