← Back to Kontasks
Graph Visualization Library Decision
Comparing Mermaid.js vs Cytoscape.js vs alternatives for flow/kontask visualization
Output
📊 Graph Visualization: Mermaid vs Cytoscape vs Alternatives
You're absolutely right. The current Mermaid graph is basically a glorified timeline - nodes in a row. It doesn't show:
- Relationships between flows, sessions, and kontasks
- Clustering by type, status, or scope
- Interactive exploration (zoom, pan, click-to-expand)
- Temporal depth (kontasks branching from flows)
📊 Library Comparison
| Feature | Mermaid.js | Cytoscape.js | D3.js Force | vis.js Network |
|---|---|---|---|---|
| Interactive (zoom/pan) | ❌ | ✅ | ✅ | ✅ |
| Click node actions | ❌ | ✅ | ✅ | ✅ |
| Force-directed layout | ❌ | ✅ | ✅ | ✅ |
| Hierarchical layout | ✅ | ✅ | ⚠️ | ✅ |
| Clustering/grouping | ⚠️ | ✅ | ⚠️ | ✅ |
| Node expand/collapse | ❌ | ✅ | ⚠️ | ✅ |
| Setup complexity | Easy | Medium | Hard | Easy |
| Bundle size | ~100KB | ~400KB | ~200KB | ~500KB |
| Mobile friendly | ⚠️ | ✅ | ✅ | ✅ |
🎯 My Recommendation: Cytoscape.js
Why Cytoscape?
- Purpose-built for graphs - not a diagramming tool repurposed
- Layout algorithms - CoSE, dagre, breadthfirst, cose-bilkent for compound nodes
- Compound nodes - flows can contain kontasks visually as parent/child
- Extensions ecosystem - popper (tooltips), navigator (minimap), expand-collapse
- Style with selectors - CSS-like styling:
node[type="flow"],edge[type="spawned"] - Event handling - click, hover, drag, box-select built in
🗺️ What the Graph Could Show
// Our graph model has these relationships: Flow ───contains───▶ Kontask │ └──genesis────▶ Turn (first turn that created flow) Turn ───produces──▶ Kontask Kontask ──spawned──▶ Kontask (follow-up work) Session ──contains──▶ Turn (1:many) Flow ◀──decision──▶ Decision
✨ Interactive Features We'd Get
- Click flow → Expand to show contained kontasks
- Click kontask → Navigate to kontask detail or show tooltip
- Drag nodes → Rearrange the graph manually
- Box select → Batch operations on selected nodes
- Minimap → Navigator for large graphs
- Layout toggle → Switch between hierarchical, force, radial views
- Filter by type → Show only flows, only kontasks, etc.
- Timeline slider → Animate graph evolution over time
⚠️ Considerations
- Bundle size: +400KB (but we can lazy-load for /gv/flows page only)
- Learning curve: Medium - more complex than Mermaid but well-documented
- Mermaid coexistence: Keep Mermaid for kontask output diagrams (architecture, sequence); use Cytoscape for platform-level graphs
🔧 Migration Path
- Phase 1: Add Cytoscape.js to konui (lazy-loaded)
- Phase 2: Replace flow graph with Cytoscape version
- Phase 3: Add interactivity (click handlers, tooltips)
- Phase 4: Add compound nodes (flows containing kontasks)
- Phase 5: Timeline animation / filtering
Quick Actions
Original Request
No layout configured
Details
Type
General
Status
Completed
Scope
vibetools
Tags
uikontasksflowsvisualization
Created
10 Jan 2026, 12:45 am
Updated
10 Jan 2026, 12:45 am
Timing
⏱️ 82.8s
0 tools
● TTFE 0%
● Thinking 100%
● Tools 0%
Created By
claude
📋 Claude's Context
Session
ses_793682af...
Raw Data
{
"id": "94292cff-87c4-47e6-88f6-0b6b2e163938",
"type": "general",
"status": "completed",
"title": "Graph Visualization Library Decision",
"description": "Comparing Mermaid.js vs Cytoscape.js vs alternatives for flow/kontask visualization",
"context": {
"output": "<div style=\"background:#1e1e1e;color:#e0e0e0;padding:20px;border-radius:8px;font-family:'Consolas','Monaco',monospace;\">\n<h2 style=\"font-family:sans-serif;color:#fff;margin:0 0 16px 0;\">📊 Graph Visualization: Mermaid vs Cytoscape vs Alternatives</h2>\n\n<p style=\"color:#e5c07b;margin-bottom:20px;\">You're absolutely right. The current Mermaid graph is basically a <strong>glorified timeline</strong> - nodes in a row. It doesn't show:</p>\n\n<ul style=\"color:#e0e0e0;margin-bottom:24px;\">\n<li>Relationships between flows, sessions, and kontasks</li>\n<li>Clustering by type, status, or scope</li>\n<li>Interactive exploration (zoom, pan, click-to-expand)</li>\n<li>Temporal depth (kontasks branching from flows)</li>\n</ul>\n\n<h3 style=\"color:#98c379;margin:24px 0 16px 0;\">📊 Library Comparison</h3>\n\n<table style=\"width:100%;border-collapse:collapse;margin-bottom:24px;\">\n<thead>\n<tr style=\"background:#2d2d2d;\">\n<th style=\"padding:12px;text-align:left;border-bottom:2px solid #444;\">Feature</th>\n<th style=\"padding:12px;text-align:center;border-bottom:2px solid #444;\">Mermaid.js</th>\n<th style=\"padding:12px;text-align:center;border-bottom:2px solid #444;\">Cytoscape.js</th>\n<th style=\"padding:12px;text-align:center;border-bottom:2px solid #444;\">D3.js Force</th>\n<th style=\"padding:12px;text-align:center;border-bottom:2px solid #444;\">vis.js Network</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"padding:10px;border-bottom:1px solid #333;\">Interactive (zoom/pan)</td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#e06c75;\">❌</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n</tr>\n<tr>\n<td style=\"padding:10px;border-bottom:1px solid #333;\">Click node actions</td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#e06c75;\">❌</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n</tr>\n<tr>\n<td style=\"padding:10px;border-bottom:1px solid #333;\">Force-directed layout</td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#e06c75;\">❌</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n</tr>\n<tr>\n<td style=\"padding:10px;border-bottom:1px solid #333;\">Hierarchical layout</td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#e5c07b;\">⚠️</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n</tr>\n<tr>\n<td style=\"padding:10px;border-bottom:1px solid #333;\">Clustering/grouping</td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#e5c07b;\">⚠️</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#e5c07b;\">⚠️</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n</tr>\n<tr>\n<td style=\"padding:10px;border-bottom:1px solid #333;\">Node expand/collapse</td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#e06c75;\">❌</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#e5c07b;\">⚠️</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n</tr>\n<tr>\n<td style=\"padding:10px;border-bottom:1px solid #333;\">Setup complexity</td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">Easy</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#e5c07b;\">Medium</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#e06c75;\">Hard</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">Easy</span></td>\n</tr>\n<tr>\n<td style=\"padding:10px;border-bottom:1px solid #333;\">Bundle size</td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\">~100KB</td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\">~400KB</td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\">~200KB</td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\">~500KB</td>\n</tr>\n<tr>\n<td style=\"padding:10px;border-bottom:1px solid #333;\">Mobile friendly</td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#e5c07b;\">⚠️</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n<td style=\"padding:10px;text-align:center;border-bottom:1px solid #333;\"><span style=\"color:#98c379;\">✅</span></td>\n</tr>\n</tbody>\n</table>\n\n<h3 style=\"color:#61afef;margin:24px 0 16px 0;\">🎯 My Recommendation: Cytoscape.js</h3>\n\n<div style=\"background:#2d2d2d;padding:16px;border-radius:6px;margin-bottom:20px;border-left:4px solid #98c379;\">\n<p style=\"margin:0 0 12px 0;\"><strong style=\"color:#98c379;\">Why Cytoscape?</strong></p>\n<ol style=\"margin:0;padding-left:20px;color:#e0e0e0;\">\n<li><strong>Purpose-built for graphs</strong> - not a diagramming tool repurposed</li>\n<li><strong>Layout algorithms</strong> - CoSE, dagre, breadthfirst, cose-bilkent for compound nodes</li>\n<li><strong>Compound nodes</strong> - flows can contain kontasks visually as parent/child</li>\n<li><strong>Extensions ecosystem</strong> - popper (tooltips), navigator (minimap), expand-collapse</li>\n<li><strong>Style with selectors</strong> - CSS-like styling: <code>node[type=\"flow\"]</code>, <code>edge[type=\"spawned\"]</code></li>\n<li><strong>Event handling</strong> - click, hover, drag, box-select built in</li>\n</ol>\n</div>\n\n<h3 style=\"color:#c678dd;margin:24px 0 16px 0;\">🗺️ What the Graph Could Show</h3>\n\n<pre style=\"background:#2d2d2d;padding:16px;border-radius:6px;overflow-x:auto;line-height:1.6;color:#e0e0e0;\">\n<span style=\"color:#7f848e;\">// Our graph model has these relationships:</span>\n\n<span style=\"color:#61afef;\">Flow</span> ───<span style=\"color:#e5c07b;\">contains</span>───▶ <span style=\"color:#98c379;\">Kontask</span>\n │\n └──<span style=\"color:#e5c07b;\">genesis</span>────▶ <span style=\"color:#c678dd;\">Turn</span> (first turn that created flow)\n\n<span style=\"color:#c678dd;\">Turn</span> ───<span style=\"color:#e5c07b;\">produces</span>──▶ <span style=\"color:#98c379;\">Kontask</span>\n\n<span style=\"color:#98c379;\">Kontask</span> ──<span style=\"color:#e5c07b;\">spawned</span>──▶ <span style=\"color:#98c379;\">Kontask</span> (follow-up work)\n\n<span style=\"color:#56b6c2;\">Session</span> ──<span style=\"color:#e5c07b;\">contains</span>──▶ <span style=\"color:#c678dd;\">Turn</span> (1:many)\n\n<span style=\"color:#61afef;\">Flow</span> ◀──<span style=\"color:#e5c07b;\">decision</span>──▶ <span style=\"color:#e06c75;\">Decision</span>\n</pre>\n\n<h3 style=\"color:#e5c07b;margin:24px 0 16px 0;\">✨ Interactive Features We'd Get</h3>\n\n<ul style=\"color:#e0e0e0;line-height:2;\">\n<li><strong>Click flow</strong> → Expand to show contained kontasks</li>\n<li><strong>Click kontask</strong> → Navigate to kontask detail or show tooltip</li>\n<li><strong>Drag nodes</strong> → Rearrange the graph manually</li>\n<li><strong>Box select</strong> → Batch operations on selected nodes</li>\n<li><strong>Minimap</strong> → Navigator for large graphs</li>\n<li><strong>Layout toggle</strong> → Switch between hierarchical, force, radial views</li>\n<li><strong>Filter by type</strong> → Show only flows, only kontasks, etc.</li>\n<li><strong>Timeline slider</strong> → Animate graph evolution over time</li>\n</ul>\n\n<h3 style=\"color:#e06c75;margin:24px 0 16px 0;\">⚠️ Considerations</h3>\n\n<div style=\"background:#2d2d2d;padding:16px;border-radius:6px;margin-bottom:20px;\">\n<ul style=\"margin:0;color:#e0e0e0;\">\n<li><strong>Bundle size</strong>: +400KB (but we can lazy-load for /gv/flows page only)</li>\n<li><strong>Learning curve</strong>: Medium - more complex than Mermaid but well-documented</li>\n<li><strong>Mermaid coexistence</strong>: Keep Mermaid for kontask output diagrams (architecture, sequence); use Cytoscape for platform-level graphs</li>\n</ul>\n</div>\n\n<h3 style=\"color:#56b6c2;margin:24px 0 16px 0;\">🔧 Migration Path</h3>\n\n<ol style=\"color:#e0e0e0;line-height:2;\">\n<li><strong>Phase 1:</strong> Add Cytoscape.js to konui (lazy-loaded)</li>\n<li><strong>Phase 2:</strong> Replace flow graph with Cytoscape version</li>\n<li><strong>Phase 3:</strong> Add interactivity (click handlers, tooltips)</li>\n<li><strong>Phase 4:</strong> Add compound nodes (flows containing kontasks)</li>\n<li><strong>Phase 5:</strong> Timeline animation / filtering</li>\n</ol>\n\n</div>",
"requestedAt": "2026-01-10T12:43:00.000Z",
"requestId": "a227d4cb-3179-4eb0-879e-a8ac36fc2b15",
"choices": [
{
"label": "Go with Cytoscape",
"value": "Let's implement Cytoscape.js for the flow graph visualization. Start with Phase 1 - adding Cytoscape to konui as a lazy-loaded dependency.",
"primary": true
},
{
"label": "Try vis.js first",
"value": "Let's try vis.js Network instead - it's simpler to set up and has good mobile support. Create a quick prototype."
},
{
"label": "Improve Mermaid first",
"value": "Before switching libraries, let's see if we can improve the Mermaid graph layout - maybe use a different diagram type or better node arrangement."
},
{
"label": "More research",
"value": "I'd like to see more research - maybe a working prototype of each option before deciding."
}
],
"turnTiming": {
"totalMs": 82786,
"ttfeMs": 133,
"thinkingMs": 82651,
"toolExecutionMs": 0,
"toolCallCount": 0,
"thinkingPct": 100,
"toolsPct": 0,
"ttfePct": 0
}
},
"createdBy": "claude",
"createdAt": "2026-01-09T14:45:36.240Z",
"updatedAt": "2026-01-09T14:45:44.000Z",
"requestId": "a227d4cb-3179-4eb0-879e-a8ac36fc2b15",
"scope": "vibetools",
"tags": [
"ui",
"kontasks",
"flows",
"visualization"
],
"sessionId": "ses_793682af-433",
"flowId": "flow_01KEHFNV42KC3ZT34N4MJJFWXB",
"flowLinks": [
{
"flowId": "flow_01KEHFNV42KC3ZT34N4MJJFWXB",
"edgeType": "evidence",
"createdAt": "2026-01-09T14:45:36.240Z"
}
]
}