chore: add visualizer draft template to workspace
This commit is contained in:
+204
@@ -0,0 +1,204 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Connect AI - Neural Construct</title>
|
||||
<style>
|
||||
body { margin: 0; padding: 0; background: #0a0a0a; overflow: hidden; font-family: 'SF Pro Display', -apple-system, sans-serif; }
|
||||
#ui-layer { position: absolute; top: 20px; left: 24px; z-index: 10; pointer-events: none; }
|
||||
#ui-layer h1 { font-size: 22px; margin: 0 0 4px 0; font-weight: 800; letter-spacing: -0.5px; color: #e0e0e0; }
|
||||
#ui-layer h1 span { color: #00cc44; }
|
||||
#ui-layer p { margin: 0; font-size: 12px; color: #555; letter-spacing: 0.3px; }
|
||||
#mem-status { color: #888; font-family: 'SF Mono', monospace; font-size: 11px; }
|
||||
canvas { cursor: grab; }
|
||||
canvas:active { cursor: grabbing; }
|
||||
</style>
|
||||
<script src="https://unpkg.com/force-graph"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="ui-layer">
|
||||
<h1>✦ <span>Neural Construct</span></h1>
|
||||
<p id="mem-status">loading...</p>
|
||||
</div>
|
||||
|
||||
<div id="graph"></div>
|
||||
|
||||
<script>
|
||||
// ── Realistic knowledge node names ──
|
||||
const clusters = {
|
||||
'AI/ML': [
|
||||
'Transformer Architecture', 'Attention Mechanism', 'Backpropagation', 'Gradient Descent',
|
||||
'Neural Network Layers', 'Loss Function', 'Embedding Space', 'Tokenization',
|
||||
'Fine-tuning', 'Transfer Learning', 'LoRA Adapter', 'RLHF', 'DPO Training',
|
||||
'Prompt Engineering', 'Chain of Thought', 'RAG Pipeline', 'Vector Database',
|
||||
],
|
||||
'Programming': [
|
||||
'TypeScript', 'React Components', 'Node.js Runtime', 'REST API Design',
|
||||
'GraphQL Schema', 'WebSocket Protocol', 'Docker Container', 'Kubernetes',
|
||||
'CI/CD Pipeline', 'Git Version Control', 'Database Schema', 'SQL Optimization',
|
||||
'Redis Caching', 'Message Queue', 'Microservices', 'Load Balancing',
|
||||
],
|
||||
'YouTube/Business': [
|
||||
'YouTube Algorithm', 'CTR Optimization', 'Thumbnail Design', 'Title A/B Testing',
|
||||
'Audience Retention', 'Content Calendar', 'Funnel Strategy', 'Email Marketing',
|
||||
'SEO Fundamentals', 'Analytics Dashboard', 'Conversion Rate', 'Growth Hacking',
|
||||
'Brand Positioning', 'Community Building', 'Monetization', 'Ad Revenue Model',
|
||||
],
|
||||
'Tools/Platform': [
|
||||
'VS Code Extension API', 'Ollama Runtime', 'Gemma Model', 'LLaMA Architecture',
|
||||
'Google Veo', 'Nanobanana Pro', 'NotebookLM', 'Google Stitch',
|
||||
'MCP Protocol', 'Antigravity CLI', 'Agent University', 'Brain Pack Format',
|
||||
'OPAL Framework', 'Gemini API', 'DeepSeek Model', 'Whisper STT',
|
||||
],
|
||||
'Knowledge Mgmt': [
|
||||
'Second Brain Method', 'Zettelkasten System', 'Spaced Repetition', 'Active Recall',
|
||||
'Mind Mapping', 'Knowledge Graph', 'Semantic Search', 'Document Chunking',
|
||||
'Metadata Extraction', 'Tag Taxonomy', 'Bidirectional Links', 'Atomic Notes',
|
||||
],
|
||||
'Content/Korean': [
|
||||
'#AI수익화', '#바이브코딩', '#1인기업', '#AI창업',
|
||||
'#코딩기초', '#시니어전성시대', '#자기개발', '#AI쇼핑몰',
|
||||
'#GPT사용법', '#사이트만들기', '#수익화모델', '#노코드',
|
||||
'#AI자동수익', '#VEO3.1', '#왕초보가이드', '#디지털건물주',
|
||||
],
|
||||
'Math/Science': [
|
||||
'Linear Algebra', 'Probability Theory', 'Calculus', 'Statistics',
|
||||
'Information Theory', 'Game Theory', 'Optimization', 'Graph Theory',
|
||||
],
|
||||
'MrBeast Pack': [
|
||||
'MrBeast Viral Formula', 'Hook Strategy', 'Retention Graph Analysis',
|
||||
'Challenge Video Format', 'Giveaway ROI Model', 'Production Scaling',
|
||||
'Clickbait Psychology', 'First 30s Rule', 'Re-watch Value',
|
||||
'Comment Engagement', 'Shorts Repurposing', 'Thumbnail Contrast',
|
||||
'Emotional Arc Design', 'Pacing Rhythm', 'Sound Design Impact',
|
||||
],
|
||||
};
|
||||
|
||||
let nodeId = 0;
|
||||
const gData = { nodes: [], links: [] };
|
||||
const groupIds = {};
|
||||
|
||||
// Core hub
|
||||
gData.nodes.push({ id: nodeId++, group: -1, name: 'Core Agent', val: 22, connections: 0 });
|
||||
|
||||
// Build nodes per cluster
|
||||
let groupIdx = 0;
|
||||
Object.entries(clusters).forEach(([clusterName, names]) => {
|
||||
groupIds[clusterName] = groupIdx;
|
||||
names.forEach(name => {
|
||||
gData.nodes.push({ id: nodeId++, group: groupIdx, name, val: 2, connections: 0 });
|
||||
});
|
||||
groupIdx++;
|
||||
});
|
||||
|
||||
// ── Build connections ──
|
||||
const nodesByGroup = {};
|
||||
gData.nodes.forEach(n => {
|
||||
if (n.group < 0) return;
|
||||
if (!nodesByGroup[n.group]) nodesByGroup[n.group] = [];
|
||||
nodesByGroup[n.group].push(n);
|
||||
});
|
||||
|
||||
// Dense intra-cluster
|
||||
Object.values(nodesByGroup).forEach(group => {
|
||||
for (let i = 0; i < group.length; i++) {
|
||||
for (let j = i + 1; j < group.length; j++) {
|
||||
if (Math.random() < 0.22) {
|
||||
gData.links.push({ source: group[i].id, target: group[j].id });
|
||||
group[i].connections++;
|
||||
group[j].connections++;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Hub connections
|
||||
gData.nodes.forEach(n => {
|
||||
if (n.group >= 0 && Math.random() < 0.05) {
|
||||
gData.links.push({ source: n.id, target: 0 });
|
||||
n.connections++;
|
||||
gData.nodes[0].connections++;
|
||||
}
|
||||
});
|
||||
|
||||
// Cross-cluster bridges
|
||||
for (let i = 0; i < 35; i++) {
|
||||
const a = 1 + Math.floor(Math.random() * (gData.nodes.length - 1));
|
||||
const b = 1 + Math.floor(Math.random() * (gData.nodes.length - 1));
|
||||
if (a !== b && gData.nodes[a].group !== gData.nodes[b].group) {
|
||||
gData.links.push({ source: a, target: b });
|
||||
gData.nodes[a].connections++;
|
||||
gData.nodes[b].connections++;
|
||||
}
|
||||
}
|
||||
|
||||
// Size by connections
|
||||
gData.nodes.forEach(n => { n.val = Math.max(2, n.connections * 1.5); });
|
||||
|
||||
document.getElementById('mem-status').textContent =
|
||||
gData.nodes.length + ' nodes · ' + gData.links.length + ' synapses';
|
||||
|
||||
// ── Colors per cluster ──
|
||||
const groupColors = ['#00cc44','#00b7ff','#ff6b6b','#ffaa33','#aa66ff','#00cc44','#66cccc','#00ff88'];
|
||||
|
||||
// ── Render ──
|
||||
const Graph = ForceGraph()(document.getElementById('graph'))
|
||||
.backgroundColor('#0a0a0a')
|
||||
.nodeCanvasObject((node, ctx, globalScale) => {
|
||||
const r = Math.sqrt(node.val) * 1.8;
|
||||
ctx.beginPath();
|
||||
ctx.arc(node.x, node.y, r, 0, 2 * Math.PI);
|
||||
|
||||
if (node.group === -1) {
|
||||
ctx.fillStyle = '#333';
|
||||
ctx.fill();
|
||||
ctx.strokeStyle = '#00cc44';
|
||||
ctx.lineWidth = 1.5;
|
||||
ctx.stroke();
|
||||
} else if (node.connections > 4) {
|
||||
ctx.fillStyle = groupColors[node.group] || '#00cc44';
|
||||
ctx.fill();
|
||||
} else {
|
||||
ctx.fillStyle = '#2a2a2a';
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
// Labels — show based on zoom
|
||||
const showLabel = globalScale > 1.2 || node.connections > 3 || node.group === -1;
|
||||
if (showLabel) {
|
||||
const fontSize = Math.max(2.5, Math.min(5, 11 / globalScale));
|
||||
ctx.font = `${fontSize}px -apple-system, sans-serif`;
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.fillStyle = node.connections > 4 ? '#ccc' : '#555';
|
||||
ctx.fillText(node.name, node.x, node.y + r + 1.5);
|
||||
}
|
||||
})
|
||||
.nodePointerAreaPaint((node, color, ctx) => {
|
||||
const r = Math.sqrt(node.val) * 1.8 + 4;
|
||||
ctx.beginPath();
|
||||
ctx.arc(node.x, node.y, r, 0, 2 * Math.PI);
|
||||
ctx.fillStyle = color;
|
||||
ctx.fill();
|
||||
})
|
||||
.linkColor(() => 'rgba(255,255,255,0.04)')
|
||||
.linkWidth(0.3)
|
||||
.d3VelocityDecay(0.3)
|
||||
.warmupTicks(150)
|
||||
.cooldownTicks(300)
|
||||
.graphData(gData);
|
||||
|
||||
Graph.d3Force('charge').strength(-100);
|
||||
Graph.d3Force('link').distance(35);
|
||||
|
||||
// Click to zoom
|
||||
Graph.onNodeClick(node => {
|
||||
Graph.centerAt(node.x, node.y, 800);
|
||||
Graph.zoom(4, 1200);
|
||||
});
|
||||
|
||||
// Start with a nice fit
|
||||
setTimeout(() => Graph.zoomToFit(1500, 40), 500);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user