Skip to content

Instantly share code, notes, and snippets.

@unforced
Created June 3, 2025 07:15
Show Gist options
  • Select an option

  • Save unforced/95673d4832ea7b2ca1538ac95f9627f2 to your computer and use it in GitHub Desktop.

Select an option

Save unforced/95673d4832ea7b2ca1538ac95f9627f2 to your computer and use it in GitHub Desktop.
A better second brain
<!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>The Future of AI Memory: An Interactive Exploration</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
body {
font-family: 'Inter', sans-serif;
}
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
.active-nav {
color: #0d9488;
border-bottom-color: #0d9488;
}
.nav-link {
border-bottom: 2px solid transparent;
transition: all 0.3s ease;
}
.nav-link:hover {
color: #14b8a6;
border-bottom-color: #14b8a6;
}
.content-section {
display: none;
}
.content-section.active {
display: block;
animation: fadeIn 0.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.tech-card {
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.tech-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.modal {
transition: opacity 0.3s ease-in-out;
}
.modal-content {
transition: transform 0.3s ease-in-out;
}
.chart-container {
position: relative;
width: 100%;
max-width: 800px;
margin-left: auto;
margin-right: auto;
height: 400px;
max-height: 50vh;
}
.accordion-icon {
transition: transform 0.3s ease;
}
</style>
</head>
<body class="bg-[#fdfbf7] text-slate-700 antialiased">
<div id="app-container" class="min-h-screen flex flex-col">
<header class="bg-white/80 backdrop-blur-lg sticky top-0 z-40 shadow-sm">
<nav class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between h-16">
<a href="#overview" class="flex items-center space-x-2">
<span class="text-xl font-bold text-teal-700">Living Intelligence</span>
</a>
<div class="hidden md:block">
<div class="ml-10 flex items-baseline space-x-4">
<a href="#overview" class="nav-link px-3 py-2 rounded-md text-sm font-medium text-slate-600">Overview</a>
<a href="#ecosystem" class="nav-link px-3 py-2 rounded-md text-sm font-medium text-slate-600">Ecosystem</a>
<a href="#technologies" class="nav-link px-3 py-2 rounded-md text-sm font-medium text-slate-600">Core Technologies</a>
<a href="#human-factor" class="nav-link px-3 py-2 rounded-md text-sm font-medium text-slate-600">The Human Factor</a>
<a href="#outlook" class="nav-link px-3 py-2 rounded-md text-sm font-medium text-slate-600">Outlook</a>
</div>
</div>
<div class="md:hidden">
<button id="mobile-menu-button" class="inline-flex items-center justify-center p-2 rounded-md text-slate-500 hover:text-teal-600 hover:bg-teal-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-white focus:ring-teal-500">
<span class="sr-only">Open main menu</span>
<div id="hamburger-icon">
<div class="w-6 h-0.5 bg-slate-600 my-1"></div>
<div class="w-6 h-0.5 bg-slate-600 my-1"></div>
<div class="w-6 h-0.5 bg-slate-600 my-1"></div>
</div>
</button>
</div>
</div>
<div id="mobile-menu" class="md:hidden hidden pb-4">
<a href="#overview" class="block nav-link px-3 py-2 rounded-md text-base font-medium text-slate-600">Overview</a>
<a href="#ecosystem" class="block nav-link px-3 py-2 rounded-md text-base font-medium text-slate-600">Ecosystem</a>
<a href="#technologies" class="block nav-link px-3 py-2 rounded-md text-base font-medium text-slate-600">Core Technologies</a>
<a href="#human-factor" class="block nav-link px-3 py-2 rounded-md text-base font-medium text-slate-600">The Human Factor</a>
<a href="#outlook" class="block nav-link px-3 py-2 rounded-md text-base font-medium text-slate-600">Outlook</a>
</div>
</nav>
</header>
<main class="flex-grow">
<section id="overview" class="content-section">
<div class="container mx-auto px-4 sm:px-6 lg:px-8 py-16 text-center">
<h1 class="text-4xl md:text-5xl font-extrabold text-slate-800 leading-tight">The Converging Horizons of</h1>
<h2 class="text-4xl md:text-5xl font-extrabold text-teal-600 leading-tight mt-2">Personal Knowledge & AI Memory</h2>
<p class="mt-6 max-w-3xl mx-auto text-lg text-slate-600">A profound shift is underway, moving us toward unified memory systems for people and LLMs. This interactive report explores the vision of "Living Intelligence"—a future where our externalized knowledge becomes a dynamic, co-evolving partner, seamlessly integrated with AI. The goal is to create systems that are not just powerful, but also preserve human agency and intentionality.</p>
<div class="mt-12 flex flex-col md:flex-row items-center justify-center gap-8 relative p-8 h-64 md:h-auto">
<div class="absolute inset-0 flex items-center justify-center">
<div class="w-24 h-24 md:w-32 md:h-32 bg-teal-500 rounded-full flex items-center justify-center text-white font-bold text-center text-sm md:text-base shadow-2xl z-10 p-2">Living Intelligence</div>
</div>
<div class="group relative flex items-center justify-center z-20">
<div class="w-40 h-40 md:w-48 md:h-48 bg-amber-400/80 rounded-full flex items-center justify-center p-4 text-center font-semibold text-amber-900 shadow-lg -mr-12 md:-mr-16">Personal Knowledge Management (PKM)</div>
<div class="absolute bottom-full mb-2 w-64 bg-slate-800 text-white text-xs rounded py-2 px-3 opacity-0 group-hover:opacity-100 transition-opacity duration-300 pointer-events-none">
User-curated knowledge systems (e.g., Tana) focusing on structured, intentional data organization.
<div class="absolute h-2 w-2 bg-slate-800 transform rotate-45 -bottom-1 left-1/2 -ml-1"></div>
</div>
</div>
<div class="group relative flex items-center justify-center z-20">
<div class="w-40 h-40 md:w-48 md:h-48 bg-sky-400/80 rounded-full flex items-center justify-center p-4 text-center font-semibold text-sky-900 shadow-lg -ml-12 md:-ml-16">LLM Memory</div>
<div class="absolute bottom-full mb-2 w-64 bg-slate-800 text-white text-xs rounded py-2 px-3 opacity-0 group-hover:opacity-100 transition-opacity duration-300 pointer-events-none">
AI-native systems (e.g., Mem0.ai) providing persistent, contextual memory for AI agents.
<div class="absolute h-2 w-2 bg-slate-800 transform rotate-45 -bottom-1 left-1/2 -ml-1"></div>
</div>
</div>
</div>
<p class="mt-8 max-w-3xl mx-auto text-lg text-slate-600">Hover over the circles to explore the core concepts. The ultimate goal is to fuse the structured intent of PKM with the dynamic power of LLM memory, creating a truly unified knowledge ecosystem.</p>
</div>
</section>
<section id="ecosystem" class="content-section">
<div class="container mx-auto px-4 sm:px-6 lg:px-8 py-16">
<div class="text-center">
<h2 class="text-3xl font-bold text-slate-800">The Emerging Ecosystem</h2>
<p class="mt-4 max-w-2xl mx-auto text-lg text-slate-600">A diverse landscape of companies, tools, and protocols is shaping the future of interoperable memory. Explore the key players and use the filters to navigate the different categories of innovation.</p>
</div>
<div id="filters" class="flex flex-wrap justify-center gap-2 mt-8"></div>
<div id="tech-grid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-8 mt-12"></div>
<div class="mt-20 text-center">
<h3 class="text-2xl font-bold text-slate-800">Comparative Feature Analysis</h3>
<p class="mt-2 max-w-2xl mx-auto text-slate-600">This chart provides a high-level comparison of key solutions based on their approach to ownership, data dynamics, and open-source availability. Use the filters above to update the chart.</p>
<div class="chart-container mt-8">
<canvas id="ecosystemChart"></canvas>
</div>
</div>
</div>
</section>
<section id="technologies" class="content-section">
<div class="container mx-auto px-4 sm:px-6 lg:px-8 py-16">
<div class="text-center">
<h2 class="text-3xl font-bold text-slate-800">Core Technologies & Architectures</h2>
<p class="mt-4 max-w-2xl mx-auto text-lg text-slate-600">Building an interoperable memory system relies on a sophisticated tech stack. Below, we compare key architectural approaches that determine how these systems handle and reason with data.</p>
</div>
<div class="mt-12 space-y-16">
<div class="bg-white p-8 rounded-xl shadow-lg border border-slate-200">
<h3 class="text-2xl font-bold text-center text-slate-800 mb-6">Data Interfacing: Static vs. Dynamic Knowledge Graphs</h3>
<div class="grid md:grid-cols-2 gap-8">
<div class="border-r-0 md:border-r border-slate-200 pr-0 md:pr-8">
<h4 class="text-xl font-semibold text-sky-600">GraphRAG (Static Approach)</h4>
<p class="mt-2 text-slate-600">Designed for enhancing information recall from <strong class="font-semibold text-sky-700">static document collections</strong>. It pre-processes data, building an entity-centric knowledge graph and pre-calculating community summaries.</p>
<div class="mt-4 p-4 bg-sky-50 rounded-lg">
<p class="font-semibold text-sky-800">Workflow:</p>
<ol class="list-decimal list-inside mt-2 space-y-1 text-sm text-sky-700">
<li>Source Documents → Ingest</li>
<li>Build Full Knowledge Graph</li>
<li>Pre-compute Community Summaries</li>
<li>Query → Slow, Multi-Step LLM Synthesis</li>
</ol>
</div>
<p class="mt-4 text-sm"><strong class="font-semibold">Best for:</strong> Analyzing fixed datasets, generating rich overviews.</p>
<p class="text-sm"><strong class="font-semibold text-red-600">Limitation:</strong> Inefficient for data that changes frequently.</p>
</div>
<div>
<h4 class="text-xl font-semibold text-teal-600">Graphiti (Dynamic Approach)</h4>
<p class="mt-2 text-slate-600">Engineered for <strong class="font-semibold text-teal-700">real-time, evolving data</strong>. It ingests information as discrete "episodes" and uses temporal metadata to update the graph, enabling low-latency queries.</p>
<div class="mt-4 p-4 bg-teal-50 rounded-lg">
<p class="font-semibold text-teal-800">Workflow:</p>
<ol class="list-decimal list-inside mt-2 space-y-1 text-sm text-teal-700">
<li>Dynamic Data Stream → Ingest Episode</li>
<li>Update KG with Temporal Metadata</li>
<li>Query → Fast, Hybrid Search (No LLM)</li>
<li>Optional LLM for final answer generation</li>
</ol>
</div>
<p class="mt-4 text-sm"><strong class="font-semibold">Best for:</strong> Conversational AI, agentic memory, evolving knowledge.</p>
<p class="text-sm"><strong class="font-semibold text-green-600">Advantage:</strong> Highly responsive; built for "living intelligence".</p>
</div>
</div>
</div>
<div class="bg-white p-8 rounded-xl shadow-lg border border-slate-200">
<h3 class="text-2xl font-bold text-center text-slate-800 mb-6">Foundational Database Model: The Hybrid Graph-Vector Approach</h3>
<p class="text-center max-w-3xl mx-auto text-slate-600 mb-8">A dominant architectural pattern is emerging that combines two database types to satisfy two different needs: the precision of graph structures and the "fuzziness" of semantic search.</p>
<div class="flex flex-col md:flex-row items-stretch justify-center gap-8">
<div class="flex-1 text-center p-6 bg-slate-50 rounded-lg flex flex-col items-center">
<div class="text-5xl" aria-hidden="true">🕸️</div>
<h4 class="text-xl font-semibold text-slate-700 mt-2">Graph Database</h4>
<p class="mt-2 text-slate-600 text-sm">(e.g., Neo4j)</p>
<p class="mt-4 font-semibold text-teal-700 flex-grow">Enables: Hyper-specific queries, pathfinding, and understanding direct connections. ("How is Project A related to Person B?")</p>
</div>
<div class="text-4xl font-bold text-slate-400 mx-4 flex items-center">+</div>
<div class="flex-1 text-center p-6 bg-slate-50 rounded-lg flex flex-col items-center">
<div class="text-5xl" aria-hidden="true">🔍</div>
<h4 class="text-xl font-semibold text-slate-700 mt-2">Vector Database</h4>
<p class="mt-2 text-slate-600 text-sm">(e.g., LanceDB)</p>
<p class="mt-4 font-semibold text-sky-700 flex-grow">Enables: Semantic "fuzzy" search and finding conceptually similar information. ("Find me documents about cognitive augmentation.")</p>
</div>
</div>
</div>
</div>
</div>
</section>
<section id="human-factor" class="content-section">
<div class="container mx-auto px-4 sm:px-6 lg:px-8 py-16">
<div class="text-center">
<h2 class="text-3xl font-bold text-slate-800">The Human Factor: Agency, Cognition & Co-Creation</h2>
<p class="mt-4 max-w-2xl mx-auto text-lg text-slate-600">Beyond technology, the success of these systems hinges on how they interact with us. The goal is not to replace human thinking, but to create a symbiotic partnership that enhances our intelligence while respecting our agency.</p>
</div>
<div class="max-w-4xl mx-auto mt-12 space-y-4" id="accordion-container"></div>
</div>
</section>
<section id="outlook" class="content-section">
<div class="container mx-auto px-4 sm:px-6 lg:px-8 py-16">
<div class="text-center">
<h2 class="text-3xl font-bold text-slate-800">Outlook & Future Trajectories</h2>
<p class="mt-4 max-w-3xl mx-auto text-lg text-slate-600">The journey towards a truly unified human-AI knowledge ecosystem is ongoing. While no perfect, all-in-one solution exists today, the path forward is illuminated by key challenges and research directions that will define the next generation of these powerful tools.</p>
</div>
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8 mt-12 max-w-6xl mx-auto">
<div class="bg-white p-6 rounded-lg shadow-md border border-slate-200">
<div class="flex items-center">
<span class="text-2xl mr-4" aria-hidden="true">🧩</span>
<h3 class="font-bold text-lg text-slate-800">The Unified Interface</h3>
</div>
<p class="mt-2 text-slate-600">The primary challenge is creating a single, fluid interface that merges direct, human-driven graph manipulation with "fuzzy," AI-powered natural language interaction. This is the key to unlocking true co-creation.</p>
</div>
<div class="bg-white p-6 rounded-lg shadow-md border border-slate-200">
<div class="flex items-center">
<span class="text-2xl mr-4" aria-hidden="true">🤝</span>
<h3 class="font-bold text-lg text-slate-800">Collaborative Evolution</h3>
</div>
<p class="mt-2 text-slate-600">Future systems must allow humans and AI to collaboratively evolve the knowledge structure (ontology) itself, not just the data within it. This moves beyond validation to a continuous, shared design process.</p>
</div>
<div class="bg-white p-6 rounded-lg shadow-md border border-slate-200">
<div class="flex items-center">
<span class="text-2xl mr-4" aria-hidden="true">🌐</span>
<h3 class="font-bold text-lg text-slate-800">Semantic Interoperability</h3>
</div>
<p class="mt-2 text-slate-600">Moving beyond basic communication protocols to shared understanding (semantic) is a major hurdle. This requires standards for enabling different knowledge systems to truly understand each other's context.</p>
</div>
<div class="bg-white p-6 rounded-lg shadow-md border border-slate-200">
<div class="flex items-center">
<span class="text-2xl mr-4" aria-hidden="true">🔐</span>
<h3 class="font-bold text-lg text-slate-800">Radical User Sovereignty</h3>
</div>
<p class="mt-2 text-slate-600">The demand for user agency will continue to drive open-source and self-hostable solutions. True ownership means control over data, the AI models used, and the inferencing processes, ensuring privacy and avoiding vendor lock-in.</p>
</div>
<div class="bg-white p-6 rounded-lg shadow-md border border-slate-200">
<div class="flex items-center">
<span class="text-2xl mr-4" aria-hidden="true">🧠</span>
<h3 class="font-bold text-lg text-slate-800">Cognitive Impact Studies</h3>
</div>
<p class="mt-2 text-slate-600">As these tools become more powerful, research into their long-term effects on human cognition, learning, and well-being is critical. Frameworks like a "Human Flourishing Benchmark" will be needed to evaluate AI's true value.</p>
</div>
<div class="bg-white p-6 rounded-lg shadow-md border border-slate-200">
<div class="flex items-center">
<span class="text-2xl mr-4" aria-hidden="true">👨‍👩‍👧‍👦</span>
<h3 class="font-bold text-lg text-slate-800">"Social Second Brains"</h3>
</div>
<p class="mt-2 text-slate-600">The evolution from individual to shared AI memory opens the possibility of "social second brains" for enhanced coordination. This introduces immense challenges in privacy, governance, and conflict resolution.</p>
</div>
</div>
</div>
</section>
</main>
<footer class="bg-slate-800 text-white">
<div class="container mx-auto px-4 sm:px-6 lg:px-8 py-6 text-center text-sm text-slate-400">
<p>Interactive Report created from "The Converging Horizons of Personal Knowledge and AI Memory."</p>
<p>&copy; 2024. For educational and illustrative purposes.</p>
</div>
</footer>
</div>
<div id="modal" class="modal fixed inset-0 bg-black bg-opacity-60 z-50 flex items-center justify-center p-4 opacity-0 pointer-events-none">
<div id="modal-content" class="modal-content bg-white rounded-2xl shadow-2xl w-full max-w-2xl max-h-[90vh] overflow-y-auto p-8 relative transform scale-95">
<button id="modal-close" class="absolute top-4 right-4 text-slate-500 hover:text-red-600 transition">
<span class="w-6 h-6 inline-block" aria-hidden="true">✖</span>
</button>
<h3 id="modal-title" class="text-2xl font-bold text-slate-800"></h3>
<p id="modal-category" class="text-sm font-semibold text-teal-600 uppercase mt-1"></p>
<p id="modal-description" class="mt-4 text-slate-600"></p>
<div id="modal-details" class="mt-6 border-t border-slate-200 pt-6 space-y-4"></div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const ecosystemData = [
{ id: 'tana', name: 'Tana.inc', category: 'PKM', description: 'A PKM tool built around a knowledge graph core, moving beyond document-centric approaches. It uses "supertags" to embed structured data within a flexible outline editor.', strengths: 'Flexible, human-centric knowledge graph structuring; emergent deep structure.', limitations: 'Cloud-based only; AI cannot yet query the entire graph; visual graph manipulation is a highly requested but missing feature.' },
{ id: 'supermemory', name: 'Supermemory.ai', category: 'LLM Memory', description: 'Pitched as "ChatGPT for your bookmarks," it serves as a persistent, developer-friendly memory layer for AI applications with a focus on semantic search and RAG.', strengths: 'Interoperable with any LLM provider; offers flexible deployment (cloud, on-prem, on-device); strong RAG support.', limitations: 'Direct human shaping of the memory graph is not a primary feature; clarity on current self-hosting options could be improved.' },
{ id: 'mem0', name: 'Mem0.ai', category: 'LLM Memory', description: 'An LLM memory system designed to give AI assistants persistent, contextual memory. It uses a hybrid vector and graph database to store and relate memories, with active conflict resolution.', strengths: 'Persistent, adaptive memory with performance improvements over native LLM memory; open-source option available for self-hosting.', limitations: 'Interaction is primarily LLM-mediated, with limited support for direct, intentional human manipulation of the graph structure.' },
{ id: 'neo4j_builder', name: 'Neo4j LLM KG Builder', category: 'KG Tooling', description: 'A tool to convert unstructured text from diverse sources (PDFs, web pages) into a structured knowledge graph within a Neo4j database, using LLMs for entity extraction.', strengths: 'Powerful KG creation from various sources; supports local deployment via Docker; allows schema customization for user control.', limitations: 'Primarily a batch-processing tool, less focused on real-time updates from conversational AI; graph editing requires separate Neo4j tools.' },
{ id: 'graphiti', name: 'Graphiti (Zep AI)', category: 'KG Tooling', description: 'A real-time, temporally-aware knowledge graph engine designed specifically for dynamic, evolving data, addressing the limitations of static approaches like GraphRAG.', strengths: 'Excellent handling of dynamic data; low-latency retrieval without LLM calls at query time; temporal awareness for historical context.', limitations: 'It is a backend engine/library, requiring significant development effort to build a complete user-facing application on top of it.' },
{ id: 'lancedb', name: 'LanceDB', category: 'Database', description: 'An embedded vector database optimized for high-performance AI applications, particularly for local or edge deployments. It is a core component of Microsoft\'s GraphRAG.', strengths: 'High-performance vector search; serverless and embeddable; ideal for local-first AI development and RAG applications.', limitations: 'Primarily a vector store, it needs to be paired with a graph database to realize the full hybrid architecture vision.' },
{ id: 'mcp', name: 'Model Context Protocol (MCP)', category: 'Protocol', description: 'An open protocol from Anthropic and others to standardize how LLM-powered applications and agents access context, tools, and actions.', strengths: 'Open standard with major backing (e.g., AWS); supports flexible communication patterns; enables context sharing between agents.', limitations: 'Still evolving; does not solve semantic interoperability (shared understanding) on its own; reliant on widespread adoption.' },
{ id: 'ai_kg_github', name: 'ai-knowledge-graph', category: 'KG Tooling', description: 'An open-source GitHub project that uses an LLM to extract Subject-Predicate-Object triplets from text and visualizes them as an interactive knowledge graph.', strengths: 'Open-source and self-hostable; supports local LLMs via Ollama; provides a simple path to personal KG generation.', limitations: 'Basic visualization and features; no built-in direct graph editing; not designed for dynamic, real-time updates.' },
];
const humanFactorData = [
{ title: 'The Goal: User Sovereignty & Data Control', content: 'A core principle is ensuring users have full ownership of their knowledge graph. This is achieved through self-hosting and open-source solutions, allowing users to run the entire system on their own hardware, control their data, and avoid corporate exploitation. Tools like Mem0.ai (open-source) and the local deployment option for the Neo4j KG Builder are key enablers of this vision.' },
{ title: 'The Balance: AI Augmentation vs. Cognitive Preservation', content: 'AI offers cognitive "superpowers" like perfect memory and cognitive offloading. However, this carries risks: over-dependency, erosion of critical thinking skills, and a potential for "lazy thinking." A key challenge is designing systems that augment our intelligence without diminishing our core human capabilities like curiosity, creativity, and critical engagement.' },
{ title: 'The Method: Human-AI Co-Creation', content: 'The ideal relationship is not one of delegation, but of collaboration. This involves a Human-in-the-Loop (HITL) process where humans define the knowledge schema, validate AI-generated content, and directly manipulate the graph. This is evolving towards "co-creation," where humans and AI work together to build and refine the knowledge graph in a continuous, symbiotic feedback loop.' },
{ title: 'The Challenge: Bridging Precision and "Fuzziness"', content: 'A significant UI/UX challenge is creating an interface that allows users to seamlessly switch between two modes of interaction: the "hyper-specific" control of directly editing a graph\'s structure, and the "fuzzy" exploration possible through natural language conversations with an LLM. The system must provide clear traceability between these two modes.' }
];
const techGrid = document.getElementById('tech-grid');
const filtersContainer = document.getElementById('filters');
const modal = document.getElementById('modal');
const modalContent = document.getElementById('modal-content');
const modalClose = document.getElementById('modal-close');
const accordionContainer = document.getElementById('accordion-container');
const navLinks = document.querySelectorAll('.nav-link');
const sections = document.querySelectorAll('.content-section');
const mobileMenuButton = document.getElementById('mobile-menu-button');
const mobileMenu = document.getElementById('mobile-menu');
let chartInstance = null;
function renderTechCards(filteredData) {
techGrid.innerHTML = '';
filteredData.forEach(item => {
const card = document.createElement('div');
card.className = 'tech-card bg-white p-6 rounded-xl shadow-md border border-slate-100 cursor-pointer flex flex-col';
card.dataset.id = item.id;
card.dataset.category = item.category;
card.innerHTML = `
<div class="flex-grow">
<h3 class="font-bold text-lg text-slate-800">${item.name}</h3>
<p class="text-sm font-semibold text-teal-600 uppercase mt-1">${item.category}</p>
<p class="mt-2 text-sm text-slate-600">${item.description.substring(0, 100)}...</p>
</div>
<span class="block mt-4 text-sm font-semibold text-sky-600 hover:text-sky-700">Learn More →</span>
`;
techGrid.appendChild(card);
});
}
function renderFilters() {
const categories = ['All', ...new Set(ecosystemData.map(item => item.category))];
filtersContainer.innerHTML = categories.map(cat =>
`<button class="filter-btn px-4 py-2 text-sm font-medium rounded-full transition ${cat === 'All' ? 'bg-teal-600 text-white' : 'bg-white text-slate-600 hover:bg-teal-100'}" data-filter="${cat}">${cat}</button>`
).join('');
}
function updateChart(filteredData) {
const labels = filteredData.map(d => d.name);
const datasets = [
{
label: 'Open Source / Self-Host',
data: filteredData.map(d => (d.id === 'mem0' || d.id === 'neo4j_builder' || d.id === 'lancedb' || d.id === 'ai_kg_github' || d.id === 'supermemory') ? 1 : 0.2),
backgroundColor: 'rgba(13, 148, 136, 0.6)',
borderColor: 'rgba(13, 148, 136, 1)', borderWidth: 1
},
{
label: 'Handles Dynamic Data',
data: filteredData.map(d => (d.id === 'graphiti' || d.id === 'mem0' || d.id ==='tana' || d.id === 'supermemory') ? 1 : 0.2),
backgroundColor: 'rgba(56, 189, 248, 0.6)',
borderColor: 'rgba(56, 189, 248, 1)', borderWidth: 1
},
{
label: 'Human-centric Structuring',
data: filteredData.map(d => (d.id === 'tana' || d.id === 'neo4j_builder') ? 1 : 0.2),
backgroundColor: 'rgba(245, 158, 11, 0.6)',
borderColor: 'rgba(245, 158, 11, 1)', borderWidth: 1
}
];
if (chartInstance) {
chartInstance.data.labels = labels;
chartInstance.data.datasets = datasets;
chartInstance.update();
} else {
const ctx = document.getElementById('ecosystemChart').getContext('2d');
chartInstance = new Chart(ctx, {
type: 'bar',
data: { labels, datasets },
options: {
indexAxis: 'y', maintainAspectRatio: false, responsive: true,
plugins: {
title: { display: false },
legend: { position: 'bottom', labels: { boxWidth: 12, font: {size: 10} } },
tooltip: {
callbacks: {
label: (context) => (context.raw === 1) ? ' Yes' : ' No / Limited'
}
}
},
scales: {
x: { stacked: false, ticks: { display: false }, grid: { display: false } },
y: { stacked: false, ticks: { font: { size: 10 } } }
}
}
});
}
}
filtersContainer.addEventListener('click', e => {
if (e.target.classList.contains('filter-btn')) {
const filter = e.target.dataset.filter;
document.querySelectorAll('.filter-btn').forEach(btn => {
btn.classList.remove('bg-teal-600', 'text-white');
btn.classList.add('bg-white', 'text-slate-600', 'hover:bg-teal-100');
});
e.target.classList.add('bg-teal-600', 'text-white');
e.target.classList.remove('bg-white', 'text-slate-600', 'hover:bg-teal-100');
const filteredData = filter === 'All' ? ecosystemData : ecosystemData.filter(item => item.category === filter);
renderTechCards(filteredData);
updateChart(filteredData);
}
});
techGrid.addEventListener('click', e => {
const card = e.target.closest('.tech-card');
if (card) {
const item = ecosystemData.find(d => d.id === card.dataset.id);
if (item) {
document.getElementById('modal-title').textContent = item.name;
document.getElementById('modal-category').textContent = item.category;
document.getElementById('modal-description').textContent = item.description;
document.getElementById('modal-details').innerHTML = `
<div><h4 class="font-semibold text-slate-700">Strengths:</h4><p class="text-slate-600 text-sm mt-1">${item.strengths}</p></div>
<div><h4 class="font-semibold text-slate-700">Limitations/Gaps:</h4><p class="text-slate-600 text-sm mt-1">${item.limitations}</p></div>`;
modal.classList.remove('opacity-0', 'pointer-events-none');
modalContent.classList.remove('scale-95');
}
}
});
const closeModal = () => {
modal.classList.add('opacity-0', 'pointer-events-none');
modalContent.classList.add('scale-95');
};
modalClose.addEventListener('click', closeModal);
modal.addEventListener('click', e => e.target === modal && closeModal());
document.addEventListener('keydown', e => e.key === 'Escape' && closeModal());
function renderAccordion() {
accordionContainer.innerHTML = humanFactorData.map((item, index) => `
<div class="accordion-item bg-white rounded-lg shadow-sm border border-slate-200">
<h2><button class="flex items-center justify-between w-full p-5 font-medium text-left text-slate-700" data-index="${index}">
<span>${item.title}</span>
<span class="accordion-icon ${index === 0 ? '' : 'rotate-180'} w-6 h-6 shrink-0" aria-hidden="true">▼</span>
</button></h2>
<div class="accordion-body ${index === 0 ? '' : 'hidden'} p-5 border-t border-slate-200"><p class="text-slate-600">${item.content}</p></div>
</div>`).join('');
}
accordionContainer.addEventListener('click', e => {
const button = e.target.closest('button');
if (button) {
const body = button.parentElement.nextElementSibling;
const icon = button.querySelector('.accordion-icon');
body.classList.toggle('hidden');
icon.classList.toggle('rotate-180');
}
});
function switchTab(hash) {
sections.forEach(section => section.classList.remove('active'));
const activeSection = document.querySelector(hash);
if (activeSection) activeSection.classList.add('active');
navLinks.forEach(link => {
link.classList.remove('active-nav');
if (link.getAttribute('href') === hash) link.classList.add('active-nav');
});
}
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const hash = this.getAttribute('href');
history.pushState(null, null, hash);
switchTab(hash);
mobileMenu.classList.add('hidden');
});
});
window.addEventListener('popstate', () => {
const hash = window.location.hash || '#overview';
switchTab(hash);
});
mobileMenuButton.addEventListener('click', () => mobileMenu.classList.toggle('hidden'));
renderFilters();
renderTechCards(ecosystemData);
updateChart(ecosystemData);
renderAccordion();
const initialHash = window.location.hash || '#overview';
history.replaceState(null, null, initialHash);
switchTab(initialHash);
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment