streaming mindmap rendering

Streaming Mindmap Rendering

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "streaming mindmap rendering" with this command: npx skills add ssshooter/mind-elixir-core/ssshooter-mind-elixir-core-streaming-mindmap-rendering

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-elixir library

  1. Install Dependencies

First, ensure you have mind-elixir installed.

npm install mind-elixir

  1. 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%' }} /> }

  1. 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') } }

  1. 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) }

  1. Integrating with AI Prompts

When generating mindmaps with LLMs, instruct the model to use the plaintext format.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

mind elixir plaintext format

No summary provided by upstream source.

Repository SourceNeeds Review
General

customize markdown

No summary provided by upstream source.

Repository SourceNeeds Review
General

export mind map as image

No summary provided by upstream source.

Repository SourceNeeds Review