When we need to brainstorm ideas or plan projects, mind mapping tools like Miro are super useful. But the even better aspect is that these tools are collaborative in real-time. Multiple team members can work on the same mind map at once, see each other's cursors, leave comments, and watch changes happen live.
In this blog, I'll show you how to build a collaborative mind mapping tool similar to Miro using a modern development IDE and a super powerful React Collaboration library.
I'll start by generating a clean mind mapping interface using Magic Patterns. Then, I'll use Zed IDE with Velt's Model Context Protocol (MCP) integration to add real-time collaboration features.
Key Features that will be added
- Mind Map Interface:Â A clean, modern mind mapping UI with draggable nodes and smooth connections.
- Live Presence:Â See who else is viewing and editing the mind map in real-time.
- Collaborative Comments:Â Add comments and feedback directly on nodes, just like in Figma or Miro.
- Live State Sync:Â Watch as changes from other users appear instantly on your screen.
By the end of this tutorial, you'll have a working collaborative mind mapping tool and understand how to add real-time features to any web application.
What is Miro and Why Build Something Similar?
Miro is a popular online whiteboard platform where users can create mind maps, diagrams, and visual workflows together. It also supports collaboration between multiple users.
Building something similar might seem complicated, but the core features are straightforward:
- A canvas where you can create and connect nodes
- The ability to drag things around and edit them
- Real-time synchronization so everyone sees the same thing
- Presence indicators to show who's online
- A commenting system for feedback
The challenge is not in the concept but in the implementation. Real-time collaboration requires handling WebSockets, managing state across multiple users, dealing with conflicts, and keeping everything synchronized. This is where using the right tools makes all the difference.
Understanding Why Building Collaborative Features is Complex
Users expect real-time collaboration in almost all their tools. But adding these features yourself means dealing with a lot of complexity that goes beyond just writing React components.
The Traditional Approach: Building Live State Sync from Scratch
Let's say you want to sync the mind map state between users. When someone adds a node, moves it, or changes its text, everyone else should see that change immediately.
If you build this yourself, you need both server and client code.
Example: Server-side code
// server.js - WebSocket server for syncing stateconst WebSocket = require("ws");
const wss = new WebSocket.Server({ port: 8080 });
// Store the current statelet mindMapState = { nodes: [], edges: [] };
wss.on("connection", (ws) => {
// Send current state to new user
ws.send(JSON.stringify({ type: "INITIAL_STATE", state: mindMapState }));
// Handle updates from users
ws.on("message", (message) => {
const update = JSON.parse(message);
// Update the state
mindMapState = update.state;
// Broadcast to all other users
wss.clients.forEach((client) => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify(update));
}
});
});
});
Example: Client-side code
// client.js - Managing state and WebSocket connectionconst socket = new WebSocket("ws://localhost:8080");
// Listen for state updates from other users
socket.onmessage = (event) => {
const update = JSON.parse(event.data);
if (update.type === "INITIAL_STATE") {
// Load the initial statesetMindMapState(update.state);
} else {
// Apply the updateupdateMindMapState(update);
}
};
// Send updates when local state changesfunction handleNodeUpdate(change) {
const update = {
type: "STATE_UPDATE",
state: getCurrentState(),
};
socket.send(JSON.stringify(update));
}
The problems with this approach:
- High Complexity:Â This is extremely simplified. A real implementation needs conflict resolution, undo/redo support, optimistic updates, retry logic, and much more.
- Scalability Issues:Â As more users join, the server load increases dramatically. You need load balancing, database persistence, and caching.
- Time Investment:Â Building and testing all of this could take a lot of time.
The SDK Approach: Using Velt for Live State Sync
Now let's see how Velt handles the same feature. Velt has already built all the infrastructure. You just need to use their hooks and components.
Example: The Velt approach
import { useLiveState } from "@veltdev/react";
function MindMapCanvas() {
// useLiveState handles both setting and getting synced stateconst [mindMapData, setMindMapData] = useLiveState(
"mindMapState",
{ nodes: initialNodes, edges: initialEdges },
{ syncDuration: 100 }
);
// Update state - automatically syncs to all usersconst handleNodeChange = (changes) => {
setMindMapData({
...mindMapData,
nodes: applyNodeChanges(changes, mindMapData.nodes),
});
};
return <YourMindMapComponent />;
}
The benefits:
- Speed:Â You get production-ready real-time sync in minutes, not weeks.
- Reliability:Â Velt has already solved all the edge cases, handled the scaling issues, and tested across browsers.
- Focus:Â Your team can focus on making a great mind mapping tool, not on building WebSocket infrastructure.
- Maintenance:Â When something needs updating, Velt's team handles it.
For this project, using Velt's SDK would be a good choice. It lets me build faster and focus on the features that make the mind mapping tool unique.
Building the Collaborative Mind Map
Step 1: Generate the Mind Map UI with Magic Patterns
The first step is to create the basic mind map interface. I'll use Magic Patterns to generate a clean React component with all the UI elements I need.
Here's the prompt that I used to generate the initial UI:
I want you to build a collaborative mind mapping web app in React + TypeScript with the following requirements:
General Setup:
Use React with Vite or Next.js.
Use TailwindCSS for styling with a clean, minimal, modern design.
Use React Flow for rendering the mind map (nodes and edges).
Use shadcn/ui components for navbar, modals, and UI controls.
Organize code cleanly into components, hooks, and utils.
Navbar:
Fixed at the top.
Left side: App name/logo (e.g., "MindCollab").
Center: Show a list of connected users with circular avatars (for now, use dummy avatars + names).
Right side: Add buttons:
"Add Node" → creates a new node on the canvas.
"Reset Map" → clears all nodes/edges.
Mind Map (React Flow):
The canvas should fill the remaining screen area under the navbar.
Each node should:
Be draggable.
Be editable (click → inline text edit).
Have rounded corners, light shadow, and smooth animations.
Show controls (add child node, delete node).
Edges should be curved, smooth, and styled cleanly.
Support zoom and pan on the canvas.
Example default root node: "Sales Channels".
UI & Interactions:
Clicking "Add Node" → adds a new node at the center of the viewport.
Clicking a node's "+" button → creates a connected child node.
Clicking a node's "x" button → deletes that node (and related edges).
Double-clicking node → allows inline text editing.
Users List (for future collaboration):
Use a simple array of mock users ([{ id, name, avatarUrl }]).
Display avatars in the navbar with a colored border (color assigned per user).
Later, I will connect this to Velt SDK for real-time collaboration.
Code Expectations:
Code must be production-ready and well-structured.
Use React hooks for state management.
Write utility functions for adding/deleting/updating nodes.
Keep the design polished with smooth animations (use Framer Motion if needed).
Include comments where I can integrate Velt later (for live cursors, presence, etc.).
This prompt is detailed and specific about what I need. It tells Magic Patterns exactly how to structure the components, what libraries to use, and how the interactions should work.
After submitting this prompt to Magic Patterns, I get a clean, functional mind mapping interface. Here's what it looks like:
I also asked it to add a dark / light mode:
Later I asked it to add further node types, to make the application look a bit more nicer and provide a bit more functionality to it.
The completed UI then looked like this:
I'll talk about all the commenting and presence aspect of it as we proceed further, but the UI looks so good right?
Now that I have the base UI, I can move on to adding the real-time collaboration features.
Step 2: Add Real-Time Collaboration with Velt MCP in Zed
This is where things get interesting. Instead of manually reading documentation and figuring out how to integrate Velt, I'll use Zed's MCP support to let the AI help me add collaboration features.
What is Model Context Protocol (MCP)?
MCP is a way to give AI assistants direct access to specialized documentation and tools. In this case, Zed can access Velt's documentation through MCP, which means when I ask the AI to add a feature, it already knows exactly how Velt works and can write the correct code.
Setting up Velt MCP in Zed
First, I need to configure Zed to use Velt's MCP server. You can follow this resource for the same.
Once MCP is configured, the AI assistant can reference Velt's documentation when helping me write code.
Here's how it works behind the scenes once it's configured:
As you can see it's using it's MCP tool to figure out what to do.
Adding Comments with AI Assistance
Let's add the commenting feature first. Here's the prompt I used in Zed:
It generated code that:
- Imports the necessary Velt components
- Wraps the app with VeltProvider
- Adds VeltComments and VeltCommentTool components
- Configures dark mode support
- Enables pin-style comments that can be attached to nodes
Here's what the implementation looks like:
Users can now click on any node to add a comment, and those comments will be visible to everyone viewing the mind map.
Adding Live State Sync
Next, I need to sync the mind map state across all users. When someone adds a node, moves it, or changes its text, everyone else should see that change immediately.
I give Zed another prompt asking it to add live state sync.
Here's the prompt and implementation:
The following was implemented:
- Used Velt'sÂ
useLiveState hook - Set up state synchronization for nodes and edges
- Updates automatically sync to all users
- Handled the merging of remote changes with local state
The key code looks something like this:
import { useLiveState } from "@veltdev/react";
export const useMindMap = () => {
// useLiveState syncs data automatically between all usersconst [mindMapData, setMindMapData] = useLiveState(
"mindmap-collaborative-data",
initialData,
{
syncDuration: 100,
resetLiveState: false,
}
);
const nodes = mindMapData?.nodes || initialData.nodes;
const edges = mindMapData?.edges || initialData.edges;
// Changes automatically sync to all usersconst onNodesChange = (changes) => {
const updatedNodes = applyNodeChanges(changes, nodes);
setMindMapData({ ...mindMapData, nodes: updatedNodes });
};
return { nodes, edges, onNodesChange };
};
With just a few prompts, I've added complete real-time collaboration to the mind map.
Adding Presence Indicators
The final touch is adding presence indicators so users can see who else is viewing the mind map. This is as simple as adding Velt's presence components.
I ask the AI to add presence, and it generates code that displays user avatars in the navbar, showing everyone who's currently online. It also adds live cursors so you can see where other users are pointing.
The code is straightforward:
import { VeltPresence } from "@veltdev/react";
function Navbar() {
return (
<nav>
{/* Other navbar content */}
<VeltPresence flockMode={false} />
</nav>
);
}
That's it. With these three features (comments, live state sync, and presence), I have a fully collaborative mind mapping tool.
A Quick Look at the Velt Features I Used
When building collaborative features, it helps to understand what each component does. Here's a breakdown of the Velt features I integrated:
VeltProvider
This component wraps your entire app and handles the connection to Velt's backend. You provide your API key, and it manages authentication, WebSocket connections, and all the real-time infrastructure.
<VeltProvider apiKey="your-api-key">{/* Your app */}</VeltProvider>
Live Presence: VeltPresence
-
VeltPresence:Â Displays avatars of all users currently viewing the page. This usually goes in your navbar or header. You can configure it with props likeÂ
flockMode to control how avatars are displayed.
This component gives users awareness of who else is working on the mind map.
Comments
- VeltComments:Â Handles the display of comment pins and threads. When someone adds a comment, this component renders it on the page.
- VeltCommentTool:Â A button or tool that enables comment mode. When clicked, users can place comment pins anywhere on the mind map.
The commenting system is fully featured with threading, replies, and persistence out of the box.
Live State Sync: useLiveState
This hook gives you a simple way to sync state between all users. It works like React's useState but automatically syncs across users:
- ReturnsÂ
[data, setData]Â just like useState - Automatically syncs changes to all connected users
- Supports options likeÂ
syncDuration for debouncing updates
The hook handles all the complexity of real-time synchronization, so you just call setData() and everyone sees the change.
With these components, I built a collaborative mind mapping tool that rivals commercial products, and I did it in a fraction of the time it would take to build these features from scratch.
Demo Video
You can try the live demo here:Â https://collaborative-mind-mapping-tool.vercel.app/
Conclusion
Building collaborative tools doesn't have to be hard. With Magic Patterns for UI, Zed with MCP, and Velt's SDK for real-time features, I built a working mind map tool in just a few hours. This would have taken a lot of time otherwise.
The main idea is simple: use the right tools for the job. Instead of building everything yourself, let SDKs handle the complex stuff so you can focus on making your product useful. Try this approach on your next project and see how much faster you can ship.







Top comments (0)