streaming-mindmap-rendering
Enables real-time, streaming mindmap visualization in web applications using the Mind Elixir library.
Install
mkdir -p .claude/skills/streaming-mindmap-rendering && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/1557" && unzip -o skill.zip -d .claude/skills/streaming-mindmap-rendering && rm skill.zipInstalls to .claude/skills/streaming-mindmap-rendering
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Implement real-time streaming mindmap rendering using Mind Elixir in web applications. Supports streaming text parsing and incremental updates.Key capabilities
- →Initialize mindmap instances in React
- →Convert plaintext to Mind Elixir JSON format
- →Update mindmap graphs incrementally
- →Throttle UI updates for performance
- →Scroll to specific nodes programmatically
How it works
The component maintains a reference to a Mind Elixir instance and uses a plaintext converter to parse incoming data chunks into a hierarchical graph structure.
Inputs & outputs
When to use streaming-mindmap-rendering
- →Build real-time mindmap visualization
- →Stream AI-generated hierarchical data
- →Implement incremental UI updates
- →Integrate Mind Elixir into React
About this skill
Streaming Mindmap Rendering
This skill guides you through implementing a streaming mindmap renderer using mind-elixir. This technique allows you to display a mindmap that grows in real-time as data is generated by an AI model or fetched from a stream.
Prerequisites
- React (or any frontend framework, examples use React)
mind-elixirlibrary
1. Install Dependencies
First, ensure you have mind-elixir installed.
npm install mind-elixir
2. Component Structure
Create a wrapper component for mind-elixir to handle the lifecycle and updates.
import MindElixir, { type MindElixirData, type MindElixirInstance } from 'mind-elixir'
import { useEffect, useRef } from 'react'
export function MindmapRenderer({ data }: { data: MindElixirData | null }) {
const elRef = useRef<HTMLDivElement>(null)
const meRef = useRef<MindElixirInstance | null>(null)
useEffect(() => {
if (!elRef.current) return
meRef.current = new MindElixir({
el: elRef.current,
direction: MindElixir.RIGHT,
})
// Initial empty state or loading state
meRef.current.init(data || { nodeData: { topic: 'Loading...', id: 'root' } })
return () => {
// Cleanup if necessary
}
}, [])
// Update effect
useEffect(() => {
if (meRef.current && data) {
// Refresh the graph with new data
meRef.current.refresh(data)
}
}, [data])
return <div ref={elRef} style={{ height: '500px', width: '100%' }} />
}
3. Streaming & Parsing Logic
The core of this skill is efficiently handling the stream and parsing potentially incomplete data.
Data Formats
Mind Elixir supports two main formats:
- JSON (Native): Hierarchical tree structure. Hard to stream because JSON is invalid until complete.
- Plain Text (Recommended for Streaming): Indentation-based or markdown-list-based text. Easier to parse partially.
Plain Text Format Example
- Root Node
- Child Node 1
- Child Node 1-1
- Child Node 1-2
- Child Node 1-3
- }:2 Summary of first two nodes
- Child Node 2
- Child Node 2-1 [^id1]
- Child Node 2-2 [^id2]
- Child Node 2-3 {color: "#e87a90"}
- > [^id1] <-Bidirectional Link-> [^id2]
- Child Node 3
- Child Node 3-1 [^id3]
- Child Node 3-2 [^id4]
- Child Node 3-3 [^id5]
- > [^id3] >-Unidirectional Link-> [^id4]
- > [^id3] <-Unidirectional Link-< [^id5]
- Child Node 4
- Child Node 4-1 [^id6]
- Child Node 4-2 [^id7]
- Child Node 4-3 [^id8]
- } Summary of all previous nodes
- Child Node 4-4
- > [^id1] <-Link position is not restricted, as long as the id can be found during rendering-> [^id8]
Parsing Implementation
Use mind-elixir/plaintextConverter (or a custom parser) to convert text to the Mind Elixir JSON format.
import { plaintextToMindElixir } from 'mind-elixir/plaintextConverter'
// Helper to clean Markdown code blocks if your stream includes them
function cleanStreamContent(content: string): string {
return content
.replace(/^```[\w]*\n?/gm, '')
.replace(/```$/gm, '')
.trim()
}
// State hooks in your parent component
const [mindmapData, setMindmapData] = useState<MindElixirData | null>(null)
const accumulatedText = useRef('')
const lastRenderTime = useRef(0)
// Streaming function (Generic Example)
async function startStreaming(url: string) {
const response = await fetch(url)
const reader = response.body?.getReader()
const decoder = new TextDecoder()
if (!reader) return
while (true) {
const { done, value } = await reader.read()
if (done) break
const chunk = decoder.decode(value)
accumulatedText.current += chunk
// Throttle updates to avoid freezing the UI
const now = Date.now()
if (now - lastRenderTime.current > 500) {
// 500ms throttle
updateMindmap()
lastRenderTime.current = now
}
}
// Final update
updateMindmap()
}
function updateMindmap() {
try {
const cleanText = cleanStreamContent(accumulatedText.current)
const data = plaintextToMindElixir(cleanText)
setMindmapData(data) // This triggers the useEffect in MindmapRenderer
} catch (e) {
// Ignore parse errors from incomplete chunks
console.warn('Partial parse error ignored')
}
}
4. Optimization Tips
- Throttling: Do not re-parse and re-render on every single byte. Use a throttle (e.g., 200-500ms).
- Stable Root: Ensure the parsing logic maintains a stable root ID if possible, to prevent the whole graph from flashing.
- Scroll to Last: To follow the generation, you can programmatically scroll to the last added node.
// Scroll to last node (inside MindmapRenderer update effect)
const lastNode = findLastNode(data.nodeData) // Implement traversal to find last node
if (lastNode?.id) {
const nodeEle = meRef.current.findEle(lastNode.id)
if (nodeEle) meRef.current.scrollIntoView(nodeEle)
}
5. Integrating with AI Prompts
When generating mindmaps with LLMs, instruct the model to use the plaintext format.
When not to use it
- →When the data structure is static and does not require streaming
Prerequisites
Limitations
- →Parsing incomplete data chunks can trigger errors
- →Requires manual throttling to prevent UI freezing
- →Complex graph layouts may require stable root IDs
How it compares
This approach enables real-time visualization of hierarchical data as it is generated, rather than waiting for a complete JSON payload.
Compared to similar skills
streaming-mindmap-rendering side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| streaming-mindmap-rendering (this skill) | 5 | 5mo | Review | Advanced |
| vchart-development-assistant | 1 | 4mo | Review | Intermediate |
| infographic-structure-creator | 1 | 5mo | No flags | Intermediate |
| data-table-filters | 0 | 4mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
vchart-development-assistant
VisActor
VChart图表库专家助手,支持问题诊断、配置生成、图片/Figma设计稿还原等场景,基于结构化知识库提供精确的图表开发解决方案
infographic-structure-creator
antvis
Generate or update infographic Structure components for this repo (TypeScript/TSX in src/designs/structures). Use when asked to design, implement, or modify structure layouts (list/compare/sequence/hierarchy/relation/geo/chart), including layout logic, component composition, and registration.
data-table-filters
openstatusHQ
>
recharts
ihmorol
Build composable, responsive React charts with Recharts library. Use when creating data visualizations including line charts, area charts, bar charts, pie charts, scatter plots, and composed charts. Handles chart customization, responsive sizing, tooltips, legends, axes configuration, performance op
building-data-apps
ironkid90
|
dashboard-ui
Akshat685
Next.js App Router page (`src/app/page.tsx`) renders `Dashboard.tsx`, which composes every panel and owns filter state.