<!DOCTYPE html>
<html lang="en" class="scroll-smooth">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ember MCP — Persistent Memory for AI with Shadow-Decay</title>
<meta name="description" content="Give your AI permanent memory that follows you across Claude, Cursor, and any MCP client. Runs locally, uses Shadow-Decay to prevent hallucinations from stale decisions.">
<meta name="keywords" content="MCP, Model Context Protocol, AI memory, persistent memory, Shadow-Decay, HESTIA, drift detection, Claude, Cursor, Windsurf, vector search, FAISS, LLM memory, hallucination prevention, knowledge graph">
<link rel="canonical" href="https://ember.timolabs.dev">
<link rel="llms" href="/llms.txt">
<!-- Open Graph -->
<meta property="og:title" content="Ember MCP — Persistent Memory for AI">
<meta property="og:description" content="Now your AI will remember everything, even after you close the chat. Local-first memory with Shadow-Decay to prevent hallucinations.">
<meta property="og:url" content="https://ember.timolabs.dev">
<meta property="og:type" content="website">
<meta property="og:site_name" content="Ember MCP">
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Ember MCP — Persistent Memory for AI">
<meta name="twitter:description" content="Now your AI will remember everything, even after you close the chat. Local-first memory with Shadow-Decay.">
<!-- Fonts & Tailwind -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700;1,9..40,400&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: {
sans: ['DM Sans', 'system-ui', 'sans-serif'],
mono: ['JetBrains Mono', 'monospace'],
},
}
}
}
</script>
<!-- JSON-LD: SoftwareApplication -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "Ember MCP",
"description": "Persistent memory server for AI with Shadow-Decay framework to prevent hallucinations from stale data. Works with Claude, Cursor, Windsurf, and any MCP client.",
"url": "https://ember.timolabs.dev",
"applicationCategory": "DeveloperApplication",
"operatingSystem": "macOS, Linux, Windows (WSL)",
"softwareRequirements": "Python 3.11+",
"license": "https://opensource.org/licenses/MIT",
"author": {
"@type": "Organization",
"name": "Timo Labs",
"url": "https://github.com/Arkya-AI"
},
"codeRepository": "https://github.com/Arkya-AI/ember-mcp",
"programmingLanguage": "Python",
"offers": { "@type": "Offer", "price": "0", "priceCurrency": "USD" }
}
</script>
<!-- JSON-LD: FAQPage -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{"@type": "Question", "name": "What is Ember MCP?", "acceptedAnswer": {"@type": "Answer", "text": "Ember MCP is a Model Context Protocol server that gives your AI long-term memory with Shadow-Decay intelligence. It stores, retrieves, and manages knowledge across all your conversations and AI tools — locally on your machine with zero cloud dependencies."}},
{"@type": "Question", "name": "Which AI tools does it work with?", "acceptedAnswer": {"@type": "Answer", "text": "Any MCP-compatible client: Claude Desktop, Claude Code, Cursor, Windsurf, and more. Just add the config block to your MCP client settings and restart."}},
{"@type": "Question", "name": "Does my data leave my machine?", "acceptedAnswer": {"@type": "Answer", "text": "No. Everything runs locally — embeddings are generated on CPU, and all data is stored in ~/.ember-v3/ on your filesystem. No API keys, no cloud services."}},
{"@type": "Question", "name": "What is Shadow-Decay?", "acceptedAnswer": {"@type": "Answer", "text": "Shadow-Decay is Ember's framework for managing knowledge freshness. When you store a new memory that's semantically similar to an older one, the newer memory shadows the older one — assigning it a shadow load between 0 and 1. HESTIA scoring then penalizes shadowed memories, naturally pushing stale information down in retrieval rankings."}},
{"@type": "Question", "name": "What is HESTIA scoring?", "acceptedAnswer": {"@type": "Answer", "text": "HESTIA is Ember's retrieval ranking formula that combines semantic similarity with shadow load and topic vitality to ensure you get the most relevant, fresh, and actively-discussed memories."}},
{"@type": "Question", "name": "How much disk space and RAM does it need?", "acceptedAnswer": {"@type": "Answer", "text": "About 500MB disk (mostly the embedding model) and ~200MB RAM. It runs entirely on CPU — no GPU required."}},
{"@type": "Question", "name": "How do I install it?", "acceptedAnswer": {"@type": "Answer", "text": "One command: pip install ember-mcp. Then add the config block to your MCP client settings and restart."}},
{"@type": "Question", "name": "Do I need to manually manage memories?", "acceptedAnswer": {"@type": "Answer", "text": "No. Ember automatically captures important information from your conversations and manages staleness through Shadow-Decay. You just talk to your AI normally."}},
{"@type": "Question", "name": "Can I use it across multiple projects?", "acceptedAnswer": {"@type": "Answer", "text": "Yes. Ember memory is global — it works across all projects, sessions, and MCP clients. You can tag memories by project for organization."}},
{"@type": "Question", "name": "Is it open source?", "acceptedAnswer": {"@type": "Answer", "text": "Yes. MIT licensed. View the source at github.com/Arkya-AI/ember-mcp."}}
]
}
</script>
<style>
:root {
--grad-start: #6366f1;
--grad-mid: #8b5cf6;
--grad-end: #d946ef;
}
.gradient-text {
background: linear-gradient(135deg, var(--grad-start), var(--grad-mid), var(--grad-end));
-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
}
.gradient-border {
position: relative;
}
.gradient-border::before {
content: ''; position: absolute; inset: 0; border-radius: inherit; padding: 1px;
background: linear-gradient(135deg, rgba(99,102,241,.3), rgba(139,92,246,.3), rgba(217,70,239,.3));
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor; mask-composite: exclude; pointer-events: none;
}
.glass {
background: rgba(15,23,42,0.6);
backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
}
.terminal { background: #0a0a0f; border: 1px solid rgba(99,102,241,.2); }
.terminal-header { background: rgba(15,15,25,.8); }
.terminal-dot { width: 10px; height: 10px; border-radius: 50%; }
.copy-btn { opacity: 0.4; transition: opacity 0.2s; }
.copy-btn:hover { opacity: 1; }
details summary { cursor: pointer; list-style: none; }
details summary::-webkit-details-marker { display: none; }
details[open] summary .faq-arrow { transform: rotate(180deg); }
.faq-arrow { transition: transform 0.2s; }
.card-hover { transition: transform 0.25s ease, box-shadow 0.25s ease; }
.card-hover:hover { transform: translateY(-3px); box-shadow: 0 12px 40px rgba(99,102,241,0.12); }
.hero-glow {
position: absolute; width: 600px; height: 600px; border-radius: 50%;
background: radial-gradient(circle, rgba(139,92,246,0.12) 0%, transparent 70%);
pointer-events: none;
}
.section-alt { background: linear-gradient(180deg, rgba(15,23,42,0) 0%, rgba(30,20,50,0.3) 50%, rgba(15,23,42,0) 100%); }
</style>
</head>
<body class="bg-[#08080f] text-slate-300 font-sans antialiased leading-relaxed">
<!-- Nav -->
<nav class="fixed top-0 w-full bg-[#08080f]/70 backdrop-blur-xl border-b border-white/5 z-50">
<div class="max-w-7xl mx-auto px-6 lg:px-8">
<div class="flex items-center justify-between h-16">
<a href="#" class="text-xl font-semibold">
<span class="gradient-text">Ember</span><span class="text-white">MCP</span>
</a>
<div class="hidden md:flex items-center gap-8 text-sm text-slate-500">
<a href="#features" class="hover:text-white transition-colors duration-200">Features</a>
<a href="#shadow-decay" class="hover:text-white transition-colors duration-200">Shadow-Decay</a>
<a href="#how-it-works" class="hover:text-white transition-colors duration-200">How It Works</a>
<a href="#contact" class="hover:text-white transition-colors duration-200">Contact</a>
<a href="#faq" class="hover:text-white transition-colors duration-200">FAQ</a>
<a href="https://github.com/Arkya-AI/ember-mcp" target="_blank" rel="noopener" class="inline-flex items-center gap-2 px-4 py-1.5 rounded-full border border-white/10 text-slate-300 hover:border-white/20 hover:text-white transition-all duration-200 text-sm">
<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
GitHub
</a>
</div>
<button id="mobile-menu-btn" class="md:hidden text-slate-400 hover:text-white">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4 6h16M4 12h16M4 18h16"/></svg>
</button>
</div>
<div id="mobile-menu" class="hidden md:hidden pb-4 space-y-1">
<a href="#features" class="block py-2 text-slate-400 hover:text-white">Features</a>
<a href="#shadow-decay" class="block py-2 text-slate-400 hover:text-white">Shadow-Decay</a>
<a href="#how-it-works" class="block py-2 text-slate-400 hover:text-white">How It Works</a>
<a href="#contact" class="block py-2 text-slate-400 hover:text-white">Contact</a>
<a href="#faq" class="block py-2 text-slate-400 hover:text-white">FAQ</a>
</div>
</div>
</nav>
<main>
<!-- Hero -->
<section class="relative pt-40 pb-32 px-6 lg:px-8 overflow-hidden">
<div class="hero-glow top-20 left-1/2 -translate-x-1/2"></div>
<div class="max-w-4xl mx-auto text-center relative z-10">
<div class="inline-flex items-center gap-2 px-4 py-1.5 rounded-full border border-white/10 text-xs text-slate-400 mb-10 tracking-wide">
<span class="w-1.5 h-1.5 rounded-full bg-violet-400 animate-pulse"></span>
Open Source · MIT Licensed · 100% Local
</div>
<h1 class="text-5xl sm:text-6xl lg:text-7xl font-bold text-white leading-[1.1] mb-8">
Now Your AI Will Remember Everything<br>
<span class="gradient-text">& Stop Hallucinating.</span>
</h1>
<p class="text-lg sm:text-xl text-slate-400 max-w-2xl mx-auto mb-14 leading-relaxed">
Persistent memory for Claude, Cursor, Windsurf, Codex, and any MCP client.
Runs locally. Zero cloud dependencies. Shadow-Decay ensures your AI
never hallucinates based on stale decisions.
</p>
<div class="flex flex-col sm:flex-row items-center justify-center gap-4 mb-16">
<a href="https://github.com/Arkya-AI/ember-mcp" target="_blank" rel="noopener" class="px-8 py-3.5 rounded-full border border-white/10 text-slate-300 hover:border-white/25 hover:text-white font-medium transition-all duration-300 text-base">
View on GitHub
</a>
</div>
<!-- Quick Start — email gate -->
<div class="max-w-lg mx-auto">
<div id="hero-install-gate" class="glass rounded-2xl p-8 gradient-border text-center">
<p class="text-white font-medium mb-2">Enter your email to get the install command</p>
<p class="text-slate-500 text-sm mb-6">We'll follow up to hear how Ember is working for you — no spam, ever.</p>
<form id="hero-install-form" class="flex flex-col sm:flex-row gap-3" onsubmit="handleHeroInstallSubmit(event)">
<input id="hero-install-email" type="email" required placeholder="your@email.com" class="flex-1 px-4 py-3 rounded-full bg-white/5 border border-white/10 text-white placeholder-slate-600 focus:outline-none focus:border-violet-500/50 text-sm" />
<button type="submit" class="px-6 py-3 rounded-full text-white font-medium text-sm transition-all duration-300 whitespace-nowrap" style="background: linear-gradient(135deg, #6366f1, #8b5cf6, #d946ef);">Get Install Command →</button>
</form>
<p id="hero-install-form-error" class="text-red-400 text-xs mt-3 hidden">Please enter a valid email address.</p>
</div>
<div id="hero-install-reveal" class="hidden">
<div class="glass rounded-2xl p-6 gradient-border text-center mb-6">
<p class="text-white font-medium mb-1">We were just kidding about emailing you — here's your command right now! 🎉</p>
<p class="text-slate-500 text-sm">We noted your email and will follow up to hear how Ember is working for you.</p>
</div>
<div class="terminal rounded-2xl overflow-hidden shadow-2xl shadow-violet-950/20 text-left">
<div class="terminal-header px-5 py-3 flex items-center gap-2 border-b border-white/5">
<span class="terminal-dot bg-[#ff5f57]"></span>
<span class="terminal-dot bg-[#febc2e]"></span>
<span class="terminal-dot bg-[#28c840]"></span>
<span class="ml-auto copy-btn text-slate-600 text-xs cursor-pointer hover:text-slate-300 font-mono" onclick="copyCommand(this, 'pip install git+https://github.com/Arkya-AI/ember-mcp.git')">copy</span>
</div>
<div class="px-6 py-6 font-mono text-[13px] leading-relaxed space-y-1">
<p class="text-slate-300"><span class="text-violet-400">$</span> pip install git+https://github.com/Arkya-AI/ember-mcp.git</p>
<p class="text-slate-600 mt-3">Collecting ember-mcp...</p>
<p class="text-slate-600">Installing...</p>
<p class="text-violet-400"> ✓ ember-mcp 3.0.0 installed</p>
<p class="text-slate-600 mt-5">Add to your MCP config (Claude Desktop / Claude Code):</p>
<p class="text-slate-600 mt-2"> “ember”: {</p>
<p class="text-slate-300"> “command”: “ember-mcp”,</p>
<p class="text-slate-300"> “args”: []</p>
<p class="text-slate-600"> }</p>
<p class="text-white mt-5 font-medium">Restart your AI client to activate Ember.</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Pain Points -->
<section class="py-24 px-6 lg:px-8 section-alt">
<div class="max-w-7xl mx-auto">
<div class="grid md:grid-cols-3 gap-6">
<div class="glass rounded-2xl p-8 gradient-border card-hover">
<div class="w-10 h-10 rounded-xl bg-violet-500/10 flex items-center justify-center mb-5">
<svg class="w-5 h-5 text-violet-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/></svg>
</div>
<h3 class="text-lg font-semibold text-white mb-3">Tired of Re-Explaining Your Stack?</h3>
<p class="text-slate-400 text-[15px] leading-relaxed">Every new chat window starts from zero. You explain your tech stack, your architecture decisions, your naming conventions — again. Ember remembers everything across sessions, clients, and projects — so your chats never start from zero.</p>
</div>
<div class="glass rounded-2xl p-8 gradient-border card-hover">
<div class="w-10 h-10 rounded-xl bg-fuchsia-500/10 flex items-center justify-center mb-5">
<svg class="w-5 h-5 text-fuchsia-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z"/></svg>
</div>
<h3 class="text-lg font-semibold text-white mb-3">Getting Suggestions for Code You Abandoned?</h3>
<p class="text-slate-400 text-[15px] leading-relaxed">You migrated from JWT to OAuth last week, but your AI still suggests JWT patterns. Shadow-Decay detects the evolution and automatically deprioritizes outdated memories.</p>
</div>
<div class="glass rounded-2xl p-8 gradient-border card-hover">
<div class="w-10 h-10 rounded-xl bg-indigo-500/10 flex items-center justify-center mb-5">
<svg class="w-5 h-5 text-indigo-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/></svg>
</div>
<h3 class="text-lg font-semibold text-white mb-3">Context Doesn't Follow You?</h3>
<p class="text-slate-400 text-[15px] leading-relaxed">Debug in Claude Desktop during the day, refactor in Cursor at night — but each tool starts fresh. Ember shares memory across all MCP clients, so you pick up exactly where you left off.</p>
</div>
</div>
</div>
</section>
<!-- Features -->
<section id="features" class="py-24 px-6 lg:px-8">
<div class="max-w-7xl mx-auto">
<div class="text-center mb-16">
<h2 class="text-3xl sm:text-4xl font-bold text-white mb-4">Key Features</h2>
<p class="text-slate-500 max-w-lg mx-auto">Everything you need for AI that actually remembers.</p>
</div>
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-5">
<div class="glass rounded-2xl p-7 gradient-border card-hover group">
<div class="w-10 h-10 rounded-xl bg-indigo-500/10 flex items-center justify-center mb-5 group-hover:bg-indigo-500/20 transition-colors">
<svg class="w-5 h-5 text-indigo-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4"/></svg>
</div>
<h3 class="text-base font-semibold text-white mb-2">Cross-Session Memory</h3>
<p class="text-slate-400 text-sm leading-relaxed">Close your laptop Friday, open a fresh chat Monday — the AI picks up exactly where you left off. No summaries needed.</p>
</div>
<div class="glass rounded-2xl p-7 gradient-border card-hover group">
<div class="w-10 h-10 rounded-xl bg-violet-500/10 flex items-center justify-center mb-5 group-hover:bg-violet-500/20 transition-colors">
<svg class="w-5 h-5 text-violet-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/></svg>
</div>
<h3 class="text-base font-semibold text-white mb-2">100% Private & Local</h3>
<p class="text-slate-400 text-sm leading-relaxed">Runs on CPU (~500MB disk, ~200MB RAM). No API keys, no cloud. Paste NDAs, proprietary code — nothing leaves your machine.</p>
</div>
<div class="glass rounded-2xl p-7 gradient-border card-hover group">
<div class="w-10 h-10 rounded-xl bg-fuchsia-500/10 flex items-center justify-center mb-5 group-hover:bg-fuchsia-500/20 transition-colors">
<svg class="w-5 h-5 text-fuchsia-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/></svg>
</div>
<h3 class="text-base font-semibold text-white mb-2">Shadow-Decay</h3>
<p class="text-slate-400 text-sm leading-relaxed">Newer memories automatically shadow older similar ones. HESTIA scoring penalizes stale content via (1−Φ)γ, so outdated info drops in rankings without being deleted.</p>
</div>
<div class="glass rounded-2xl p-7 gradient-border card-hover group">
<div class="w-10 h-10 rounded-xl bg-purple-500/10 flex items-center justify-center mb-5 group-hover:bg-purple-500/20 transition-colors">
<svg class="w-5 h-5 text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
</div>
<h3 class="text-base font-semibold text-white mb-2">Temporal Intelligence</h3>
<p class="text-slate-400 text-sm leading-relaxed">Memories ranked by recency and access frequency with importance-based half-lives. Upgrade from React 17 to 19? It stops suggesting the old syntax.</p>
</div>
<div class="glass rounded-2xl p-7 gradient-border card-hover group">
<div class="w-10 h-10 rounded-xl bg-indigo-500/10 flex items-center justify-center mb-5 group-hover:bg-indigo-500/20 transition-colors">
<svg class="w-5 h-5 text-indigo-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zm0 8a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zm12 0a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z"/></svg>
</div>
<h3 class="text-base font-semibold text-white mb-2">Knowledge Graph</h3>
<p class="text-slate-400 text-sm leading-relaxed">Semantic edges connect related memories. Graph search traverses connections via BFS to discover correlated context across topics.</p>
</div>
<div class="glass rounded-2xl p-7 gradient-border card-hover group">
<div class="w-10 h-10 rounded-xl bg-violet-500/10 flex items-center justify-center mb-5 group-hover:bg-violet-500/20 transition-colors">
<svg class="w-5 h-5 text-violet-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/></svg>
</div>
<h3 class="text-base font-semibold text-white mb-2">Source Linking</h3>
<p class="text-slate-400 text-sm leading-relaxed">Every memory traces back to its origin. When the AI says “we chose Kubernetes,” it points to the exact doc where that was recorded.</p>
</div>
</div>
</div>
</section>
<!-- Shadow-Decay Scenario -->
<section id="shadow-decay" class="py-24 px-6 lg:px-8 section-alt">
<div class="max-w-5xl mx-auto">
<div class="text-center mb-16">
<h2 class="text-3xl sm:text-4xl font-bold text-white mb-4">Why Shadow-Decay Matters</h2>
<p class="text-slate-500 max-w-2xl mx-auto">Standard vector stores suffer from “semantic collision” — old memories match new queries because they’re semantically similar. Ember’s Shadow-Decay framework detects the shift and penalizes stale content.</p>
</div>
<!-- Timeline -->
<div class="grid md:grid-cols-2 gap-5 mb-8">
<div class="glass rounded-2xl p-7 gradient-border">
<div class="text-xs font-mono text-violet-400 uppercase tracking-widest mb-3">January</div>
<p class="text-white font-medium mb-2">You tell Claude your project uses PostgreSQL.</p>
<p class="text-slate-400 text-sm">Ember stores memories about schemas and SQL drivers in the “databases” region of the vector space.</p>
</div>
<div class="glass rounded-2xl p-7 gradient-border">
<div class="text-xs font-mono text-fuchsia-400 uppercase tracking-widest mb-3">April</div>
<p class="text-white font-medium mb-2">You migrate to MongoDB.</p>
<p class="text-slate-400 text-sm">New memories about documents and collections flow into the same region. Shadow-Decay begins.</p>
</div>
</div>
<!-- Before / After -->
<div class="grid md:grid-cols-2 gap-5">
<div class="rounded-2xl p-7 border border-red-500/20 bg-red-950/10">
<div class="flex items-center gap-2 mb-4">
<div class="w-6 h-6 rounded-full bg-red-500/10 flex items-center justify-center">
<svg class="w-3.5 h-3.5 text-red-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/></svg>
</div>
<h3 class="text-base font-semibold text-red-400">Without Ember</h3>
</div>
<p class="text-slate-400 text-sm leading-relaxed">The old “we use PostgreSQL” memory has high similarity to “database queries.” Claude confidently gives you SQL syntax for a database you no longer use.</p>
<p class="text-red-400/80 text-sm mt-4 font-medium">Hallucination based on stale memory.</p>
</div>
<div class="rounded-2xl p-7 border border-violet-500/20 bg-violet-950/10">
<div class="flex items-center gap-2 mb-4">
<div class="w-6 h-6 rounded-full bg-violet-500/10 flex items-center justify-center">
<svg class="w-3.5 h-3.5 text-violet-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>
</div>
<h3 class="text-base font-semibold text-violet-400">With Ember</h3>
</div>
<p class="text-slate-400 text-sm leading-relaxed">Newer MongoDB memories shadow the older PostgreSQL ones. Shadow load (Φ) approaches 1.0. HESTIA scoring applies (1−Φ)<sup>γ</sup> penalty, ranking PostgreSQL 10x lower.</p>
<p class="text-violet-400/80 text-sm mt-4 font-medium">Claude retrieves only MongoDB context.</p>
</div>
</div>
</div>
</section>
<!-- How It Works -->
<section id="how-it-works" class="py-24 px-6 lg:px-8">
<div class="max-w-7xl mx-auto">
<div class="text-center mb-16">
<h2 class="text-3xl sm:text-4xl font-bold text-white mb-4">How It Works</h2>
<p class="text-slate-500 max-w-2xl mx-auto">You just talk to your AI normally. Behind the scenes, Ember clusters your conversations by topic, tracks freshness through Shadow-Decay, and injects only relevant context.</p>
</div>
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-6">
<div class="text-center group">
<div class="w-14 h-14 rounded-2xl flex items-center justify-center mx-auto mb-5 border border-white/10 group-hover:border-violet-500/30 transition-colors" style="background: linear-gradient(135deg, rgba(99,102,241,0.1), rgba(139,92,246,0.1))">
<span class="gradient-text font-bold text-xl">1</span>
</div>
<h3 class="text-white font-medium mb-2">Local Embeddings</h3>
<p class="text-slate-500 text-sm">all-MiniLM-L6-v2 generates 384-dim vectors on CPU. No API calls.</p>
</div>
<div class="text-center group">
<div class="w-14 h-14 rounded-2xl flex items-center justify-center mx-auto mb-5 border border-white/10 group-hover:border-violet-500/30 transition-colors" style="background: linear-gradient(135deg, rgba(99,102,241,0.1), rgba(139,92,246,0.1))">
<span class="gradient-text font-bold text-xl">2</span>
</div>
<h3 class="text-white font-medium mb-2">Semantic Clustering</h3>
<p class="text-slate-500 text-sm">16 frozen centroids cluster knowledge by topic automatically.</p>
</div>
<div class="text-center group">
<div class="w-14 h-14 rounded-2xl flex items-center justify-center mx-auto mb-5 border border-white/10 group-hover:border-violet-500/30 transition-colors" style="background: linear-gradient(135deg, rgba(99,102,241,0.1), rgba(139,92,246,0.1))">
<span class="gradient-text font-bold text-xl">3</span>
</div>
<h3 class="text-white font-medium mb-2">FAISS Search</h3>
<p class="text-slate-500 text-sm">Meta's FAISS handles high-speed similarity search with custom ID mapping.</p>
</div>
<div class="text-center group">
<div class="w-14 h-14 rounded-2xl flex items-center justify-center mx-auto mb-5 border border-white/10 group-hover:border-violet-500/30 transition-colors" style="background: linear-gradient(135deg, rgba(99,102,241,0.1), rgba(139,92,246,0.1))">
<span class="gradient-text font-bold text-xl">4</span>
</div>
<h3 class="text-white font-medium mb-2">Shadow-Decay</h3>
<p class="text-slate-500 text-sm">Newer memories shadow older similar ones. HESTIA scoring: S = cos · (1−Φ)<sup>γ</sup> · vitality.</p>
</div>
<div class="text-center group">
<div class="w-14 h-14 rounded-2xl flex items-center justify-center mx-auto mb-5 border border-white/10 group-hover:border-violet-500/30 transition-colors" style="background: linear-gradient(135deg, rgba(99,102,241,0.1), rgba(139,92,246,0.1))">
<span class="gradient-text font-bold text-xl">5</span>
</div>
<h3 class="text-white font-medium mb-2">Knowledge Graph</h3>
<p class="text-slate-500 text-sm">Semantic edges connect related embers. BFS traversal discovers correlated context.</p>
</div>
<div class="text-center group">
<div class="w-14 h-14 rounded-2xl flex items-center justify-center mx-auto mb-5 border border-white/10 group-hover:border-violet-500/30 transition-colors" style="background: linear-gradient(135deg, rgba(99,102,241,0.1), rgba(139,92,246,0.1))">
<span class="gradient-text font-bold text-xl">6</span>
</div>
<h3 class="text-white font-medium mb-2">Drift Detection</h3>
<p class="text-slate-500 text-sm">Per-cell statistics with Welford’s algorithm and Laplacian smoothing auto-flag stale regions.</p>
</div>
</div>
</div>
</section>
<!-- Contact Us -->
<section id="contact" class="py-24 px-6 lg:px-8 section-alt">
<div class="max-w-2xl mx-auto">
<div class="text-center mb-12">
<h2 class="text-3xl sm:text-4xl font-bold text-white mb-4">Get in Touch</h2>
<p class="text-slate-500">Questions, enterprise enquiries, or just want to say hi — we read every message.</p>
</div>
<div class="glass rounded-2xl p-8 gradient-border">
<form id="contact-form" onsubmit="handleContactSubmit(event)" class="space-y-5">
<div class="grid sm:grid-cols-2 gap-5">
<div>
<label class="block text-sm text-slate-400 mb-2" for="contact-name">Your Name</label>
<input id="contact-name" name="name" type="text" required placeholder="Jane Smith" class="w-full px-4 py-3 rounded-xl bg-white/5 border border-white/10 text-white placeholder-slate-600 focus:outline-none focus:border-violet-500/50 text-sm" />
</div>
<div>
<label class="block text-sm text-slate-400 mb-2" for="contact-email">Email Address</label>
<input id="contact-email" name="email" type="email" required placeholder="jane@company.com" class="w-full px-4 py-3 rounded-xl bg-white/5 border border-white/10 text-white placeholder-slate-600 focus:outline-none focus:border-violet-500/50 text-sm" />
</div>
</div>
<div>
<label class="block text-sm text-slate-400 mb-2" for="contact-subject">Subject</label>
<input id="contact-subject" name="subject" type="text" required placeholder="Enterprise enquiry / Bug report / General question" class="w-full px-4 py-3 rounded-xl bg-white/5 border border-white/10 text-white placeholder-slate-600 focus:outline-none focus:border-violet-500/50 text-sm" />
</div>
<div>
<label class="block text-sm text-slate-400 mb-2" for="contact-message">Message</label>
<textarea id="contact-message" name="message" required rows="5" placeholder="Tell us what you're working on..." class="w-full px-4 py-3 rounded-xl bg-white/5 border border-white/10 text-white placeholder-slate-600 focus:outline-none focus:border-violet-500/50 text-sm resize-none"></textarea>
</div>
<div id="contact-error" class="hidden text-red-400 text-sm">Something went wrong. Please try again in a moment.</div>
<div id="contact-success" class="hidden glass rounded-xl p-4 border border-violet-500/20 text-center">
<p class="text-violet-300 font-medium">Message sent! We'll get back to you within 24 hours.</p>
</div>
<button id="contact-submit" type="submit" class="w-full py-3.5 rounded-full text-white font-medium transition-all duration-300 text-sm" style="background: linear-gradient(135deg, #6366f1, #8b5cf6, #d946ef);">
Send Message →
</button>
</form>
</div>
</div>
</section>
<!-- Tools -->
<section id="tools" class="py-24 px-6 lg:px-8">
<div class="max-w-7xl mx-auto">
<div class="text-center mb-16">
<h2 class="text-3xl sm:text-4xl font-bold text-white mb-4">16 Tools for Your AI</h2>
<p class="text-slate-500 max-w-lg mx-auto">Exposed via the Model Context Protocol to any connected LLM.</p>
</div>
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-8">
<div>
<h3 class="text-xs font-semibold text-violet-400 uppercase tracking-widest mb-5">Store & Recall</h3>
<div class="space-y-3">
<div class="glass rounded-xl p-5 gradient-border">
<code class="text-violet-300 text-sm font-mono">ember_store</code>
<p class="text-slate-500 text-sm mt-1.5">Save a named memory with importance level and tags</p>
</div>
<div class="glass rounded-xl p-5 gradient-border">
<code class="text-violet-300 text-sm font-mono">ember_recall</code>
<p class="text-slate-500 text-sm mt-1.5">Semantic search ranked by HESTIA score</p>
</div>
<div class="glass rounded-xl p-5 gradient-border">
<code class="text-violet-300 text-sm font-mono">ember_deep_recall</code>
<p class="text-slate-500 text-sm mt-1.5">Recall + read source files for full context</p>
</div>
<div class="glass rounded-xl p-5 gradient-border">
<code class="text-violet-300 text-sm font-mono">ember_learn</code>
<p class="text-slate-500 text-sm mt-1.5">Auto-capture facts, preferences, decisions</p>
</div>
</div>
</div>
<div>
<h3 class="text-xs font-semibold text-fuchsia-400 uppercase tracking-widest mb-5">Management</h3>
<div class="space-y-3">
<div class="glass rounded-xl p-5 gradient-border">
<code class="text-fuchsia-300 text-sm font-mono">ember_list</code>
<p class="text-slate-500 text-sm mt-1.5">List all memories with pagination, filter by tag</p>
</div>
<div class="glass rounded-xl p-5 gradient-border">
<code class="text-fuchsia-300 text-sm font-mono">ember_delete</code>
<p class="text-slate-500 text-sm mt-1.5">Remove a memory by ID</p>
</div>
<div class="glass rounded-xl p-5 gradient-border">
<code class="text-fuchsia-300 text-sm font-mono">ember_contradict</code>
<p class="text-slate-500 text-sm mt-1.5">Mark stale, store corrected version</p>
</div>
<div class="glass rounded-xl p-5 gradient-border">
<code class="text-fuchsia-300 text-sm font-mono">ember_read</code>
<p class="text-slate-500 text-sm mt-1.5">Read full content of a specific memory</p>
</div>
</div>
</div>
<div>
<h3 class="text-xs font-semibold text-indigo-400 uppercase tracking-widest mb-5">Intelligence</h3>
<div class="space-y-3">
<div class="glass rounded-xl p-5 gradient-border">
<code class="text-indigo-300 text-sm font-mono">ember_auto</code>
<p class="text-slate-500 text-sm mt-1.5">Auto-retrieve context at conversation start</p>
</div>
<div class="glass rounded-xl p-5 gradient-border">
<code class="text-indigo-300 text-sm font-mono">ember_inspect</code>
<p class="text-slate-500 text-sm mt-1.5">View Voronoi cell distribution and density</p>
</div>
<div class="glass rounded-xl p-5 gradient-border">
<code class="text-indigo-300 text-sm font-mono">ember_save_session</code>
<p class="text-slate-500 text-sm mt-1.5">Save session summary with source linking</p>
</div>
<div class="glass rounded-xl p-5 gradient-border">
<code class="text-indigo-300 text-sm font-mono">ember_drift_check</code>
<p class="text-slate-500 text-sm mt-1.5">Analyze region health, flag stale memories</p>
</div>
</div>
</div>
<div>
<h3 class="text-xs font-semibold text-purple-400 uppercase tracking-widest mb-5">Advanced</h3>
<div class="space-y-3">
<div class="glass rounded-xl p-5 gradient-border">
<code class="text-purple-300 text-sm font-mono">ember_graph_search</code>
<p class="text-slate-500 text-sm mt-1.5">Vector search + BFS via knowledge graph</p>
</div>
<div class="glass rounded-xl p-5 gradient-border">
<code class="text-purple-300 text-sm font-mono">ember_health</code>
<p class="text-slate-500 text-sm mt-1.5">Hallucination risk score with trend</p>
</div>
<div class="glass rounded-xl p-5 gradient-border">
<code class="text-purple-300 text-sm font-mono">ember_recompute_shadows</code>
<p class="text-slate-500 text-sm mt-1.5">Recalculate all shadow loads</p>
</div>
<div class="glass rounded-xl p-5 gradient-border">
<code class="text-purple-300 text-sm font-mono">ember_explain</code>
<p class="text-slate-500 text-sm mt-1.5">HESTIA score breakdown for any memory</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- FAQ -->
<section id="faq" class="py-24 px-6 lg:px-8 section-alt">
<div class="max-w-3xl mx-auto">
<div class="text-center mb-16">
<h2 class="text-3xl sm:text-4xl font-bold text-white mb-4">Frequently Asked Questions</h2>
</div>
<div class="space-y-3">
<details class="glass rounded-xl overflow-hidden gradient-border">
<summary class="flex items-center justify-between px-6 py-5 text-white font-medium hover:bg-white/[0.02] transition-colors">
What is Ember MCP?
<svg class="faq-arrow w-4 h-4 text-slate-500 flex-shrink-0 ml-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
</summary>
<div class="px-6 pb-5 text-slate-400 text-sm leading-relaxed">Ember MCP is a Model Context Protocol server that gives your AI long-term memory with Shadow-Decay intelligence. It stores, retrieves, and manages knowledge across all your conversations and AI tools — locally on your machine with zero cloud dependencies. The Shadow-Decay framework ensures stale information is automatically deprioritized.</div>
</details>
<details class="glass rounded-xl overflow-hidden gradient-border">
<summary class="flex items-center justify-between px-6 py-5 text-white font-medium hover:bg-white/[0.02] transition-colors">
Which AI tools does it work with?
<svg class="faq-arrow w-4 h-4 text-slate-500 flex-shrink-0 ml-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
</summary>
<div class="px-6 pb-5 text-slate-400 text-sm leading-relaxed">Any MCP-compatible client: Claude Desktop, Claude Code, Cursor, Windsurf, and more. Just add the config block to your MCP client settings and restart.</div>
</details>
<details class="glass rounded-xl overflow-hidden gradient-border">
<summary class="flex items-center justify-between px-6 py-5 text-white font-medium hover:bg-white/[0.02] transition-colors">
Does my data leave my machine?
<svg class="faq-arrow w-4 h-4 text-slate-500 flex-shrink-0 ml-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
</summary>
<div class="px-6 pb-5 text-slate-400 text-sm leading-relaxed">No. Everything runs locally — embeddings are generated on CPU using all-MiniLM-L6-v2, and all data is stored in <code class="text-violet-300">~/.ember-v3/</code> on your filesystem. No API keys, no cloud services, no external calls.</div>
</details>
<details class="glass rounded-xl overflow-hidden gradient-border">
<summary class="flex items-center justify-between px-6 py-5 text-white font-medium hover:bg-white/[0.02] transition-colors">
What is Shadow-Decay?
<svg class="faq-arrow w-4 h-4 text-slate-500 flex-shrink-0 ml-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
</summary>
<div class="px-6 pb-5 text-slate-400 text-sm leading-relaxed">Shadow-Decay is Ember's framework for managing knowledge freshness. When you store a new memory that's semantically similar to an older one, the newer memory “shadows” the older one — assigning it a shadow load (Φ) between 0 and 1. HESTIA scoring then penalizes shadowed memories by (1−Φ)<sup>γ</sup>, naturally pushing stale information down in retrieval rankings without deleting it.</div>
</details>
<details class="glass rounded-xl overflow-hidden gradient-border">
<summary class="flex items-center justify-between px-6 py-5 text-white font-medium hover:bg-white/[0.02] transition-colors">
What is HESTIA scoring?
<svg class="faq-arrow w-4 h-4 text-slate-500 flex-shrink-0 ml-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
</summary>
<div class="px-6 pb-5 text-slate-400 text-sm leading-relaxed">HESTIA is Ember's retrieval ranking formula: S = cos_sim × (1−Φ)<sup>γ</sup> × vitality_factor. It combines semantic similarity with shadow load and topic vitality to ensure you get the most relevant, fresh, and actively-discussed memories — not just the most similar ones.</div>
</details>
<details class="glass rounded-xl overflow-hidden gradient-border">
<summary class="flex items-center justify-between px-6 py-5 text-white font-medium hover:bg-white/[0.02] transition-colors">
How much disk space and RAM does it need?
<svg class="faq-arrow w-4 h-4 text-slate-500 flex-shrink-0 ml-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
</summary>
<div class="px-6 pb-5 text-slate-400 text-sm leading-relaxed">About 300MB disk (mostly the embedding model, only if using semantic search) and ~150MB RAM. It runs entirely on CPU — no GPU required.</div>
</details>
<details class="glass rounded-xl overflow-hidden gradient-border">
<summary class="flex items-center justify-between px-6 py-5 text-white font-medium hover:bg-white/[0.02] transition-colors">
How do I install it?
<svg class="faq-arrow w-4 h-4 text-slate-500 flex-shrink-0 ml-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
</summary>
<div class="px-6 pb-5 text-slate-400 text-sm leading-relaxed">One command: <code class="text-violet-300">pip install git+https://github.com/Arkya-AI/ember-mcp.git</code>. Then add the MCP config block to your AI client settings and restart. Semantic search is optional — add <code class="text-violet-300">pip install "ember-mcp[semantic]"</code> afterwards to enable vector search.</div>
</details>
<details class="glass rounded-xl overflow-hidden gradient-border">
<summary class="flex items-center justify-between px-6 py-5 text-white font-medium hover:bg-white/[0.02] transition-colors">
Do I need to manually manage memories?
<svg class="faq-arrow w-4 h-4 text-slate-500 flex-shrink-0 ml-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
</summary>
<div class="px-6 pb-5 text-slate-400 text-sm leading-relaxed">No. Ember automatically captures important information from your conversations (decisions, preferences, facts) and manages staleness through Shadow-Decay. You just talk to your AI normally.</div>
</details>
<details class="glass rounded-xl overflow-hidden gradient-border">
<summary class="flex items-center justify-between px-6 py-5 text-white font-medium hover:bg-white/[0.02] transition-colors">
Can I use it across multiple projects?
<svg class="faq-arrow w-4 h-4 text-slate-500 flex-shrink-0 ml-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
</summary>
<div class="px-6 pb-5 text-slate-400 text-sm leading-relaxed">Yes. Ember memory is global — it works across all projects, sessions, and MCP clients. You can tag memories by project for organization.</div>
</details>
<details class="glass rounded-xl overflow-hidden gradient-border">
<summary class="flex items-center justify-between px-6 py-5 text-white font-medium hover:bg-white/[0.02] transition-colors">
Is it open source?
<svg class="faq-arrow w-4 h-4 text-slate-500 flex-shrink-0 ml-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
</summary>
<div class="px-6 pb-5 text-slate-400 text-sm leading-relaxed">Yes. MIT licensed. View the source at <a href="https://github.com/Arkya-AI/ember-mcp" target="_blank" rel="noopener" class="text-violet-400 hover:text-violet-300 transition-colors">github.com/Arkya-AI/ember-mcp</a>.</div>
</details>
</div>
</div>
</section>
</main>
<!-- Footer -->
<footer class="border-t border-white/5 py-12 px-6 lg:px-8">
<div class="max-w-7xl mx-auto flex flex-col sm:flex-row items-center justify-between gap-4">
<div class="text-sm text-slate-600">
<span class="gradient-text font-medium">Ember</span><span class="text-slate-400 font-medium">MCP</span>
<span class="mx-1">·</span> Built by <a href="https://github.com/Arkya-AI" target="_blank" rel="noopener" class="text-slate-400 hover:text-white transition-colors">Timo Labs</a>
<span class="mx-1">·</span> MIT License
</div>
<div class="flex items-center gap-6 text-sm text-slate-600">
<a href="https://github.com/Arkya-AI/ember-mcp" target="_blank" rel="noopener" class="hover:text-slate-300 transition-colors">GitHub</a>
<a href="/llms.txt" class="hover:text-slate-300 transition-colors">llms.txt</a>
</div>
</div>
</footer>
<script>
document.getElementById('mobile-menu-btn').addEventListener('click', function() {
document.getElementById('mobile-menu').classList.toggle('hidden');
});
document.querySelectorAll('#mobile-menu a').forEach(link => {
link.addEventListener('click', () => document.getElementById('mobile-menu').classList.add('hidden'));
});
function copyCommand(btn, text) {
navigator.clipboard.writeText(text).then(() => {
const original = btn.textContent;
btn.textContent = 'copied!';
btn.style.color = '#8b5cf6';
setTimeout(() => { btn.textContent = original; btn.style.color = ''; }, 2000);
});
}
async function handleHeroInstallSubmit(e) {
e.preventDefault();
const email = document.getElementById('hero-install-email').value.trim();
const errEl = document.getElementById('hero-install-form-error');
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) { errEl.classList.remove('hidden'); return; }
errEl.classList.add('hidden');
document.getElementById('hero-install-gate').classList.add('hidden');
document.getElementById('hero-install-reveal').classList.remove('hidden');
document.getElementById('hero-install-reveal').scrollIntoView({ behavior: 'smooth', block: 'nearest' });
try { await fetch('/api/subscribe', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email }) }); } catch (_) {}
}
async function handleContactSubmit(e) {
e.preventDefault();
const btn = document.getElementById('contact-submit');
const errEl = document.getElementById('contact-error');
const successEl = document.getElementById('contact-success');
btn.disabled = true;
btn.textContent = 'Sending…';
errEl.classList.add('hidden');
successEl.classList.add('hidden');
const payload = {
name: document.getElementById('contact-name').value.trim(),
email: document.getElementById('contact-email').value.trim(),
subject: document.getElementById('contact-subject').value.trim(),
message: document.getElementById('contact-message').value.trim(),
};
try {
const res = await fetch('/api/contact', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) });
if (!res.ok) throw new Error();
document.getElementById('contact-form').reset();
successEl.classList.remove('hidden');
btn.textContent = 'Sent!';
} catch (_) {
errEl.classList.remove('hidden');
btn.disabled = false;
btn.textContent = 'Send Message →';
}
}
</script>
</body>
</html>