A personal VS Code / Cursor extension that renders a Markdown file as a navigable, editable mind map. You focus on one node at a time: the left rail is the parent (upline), the right rail is the children (downline), and the center is the current node's editable Markdown — with animated connectors between them. A whole-file overview canvas and a DFS search round it out.
Scope: one file = one self-contained mind map. The heading hierarchy of the currently open file is the whole tree. Links to other files are one-way jumps, not part of the back-chain.
How a note becomes a map
- Inside a file, ATX headings (
#,##,###, …) define the hierarchy. A heading's parent is the nearest shallower heading, so a###directly under a#(skipping##) still nests correctly. - Text before the first heading is the file root block (the map's center).
- Custom inline directives (their
( … )argument may contain nested parens):[image](https://github.com/Harrisous/MindMax/blob/HEAD/link)— renders the image inline. Relative paths resolve against the file's folder;http(s)anddata:URLs work too.[note](https://github.com/Harrisous/MindMax/blob/HEAD/text)— a margin comment (Google-Docs style) anchored to its line. The comment is the text; edit/delete it from the bubble. Plain text only (not math-rendered).[file](https://github.com/Harrisous/MindMax/blob/HEAD/link)— a right-rail jump card (red border + 📄) that opens another file fresh as its own map. One-way: no parent/back-chain.[hyper](https://github.com/Harrisous/MindMax/blob/HEAD/link)— a clickable 🔗 link pill below the center card; opens another file at its main heading.
- Math:
$…$(inline) and$$…$$(display) render with KaTeX right in the editor; the raw source is revealed when the selection touches the formula.
Using it
Run “Mind Map: Open” from the Command Palette and pick any workspace .md
(the last-opened file is pinned). The panel toolbar has:
- 📂 Open — re-target the panel at another file.
- 🗺 Overview — toggle the interactive whole-file canvas (below).
- 🔍 Find (Ctrl/Cmd + F) — search this file (below).
- − / 100% / + — zoom (also Ctrl + −/+/0 and Ctrl + mouse-wheel).
- Auto-save / Manual + Save — editing the center node writes back into the exact byte range of the source file (auto = debounced ~400 ms). A file watcher picks up external edits (the panel ignores its own writes for ~2 s).
Navigation: click a card, or use the keyboard — ← parent, → / Enter focus child, ↑ / ↓ move the child selection, Alt + arrows works while the editor is focused. The gold ⌂ top tab jumps to the file's root.
Add a child from the right rail: a heading in the same file, a brand-new linked file, or a link to an existing file.
Overview canvas (n8n-style)
🗺 Overview shows the whole file as a tidy left-to-right tree you can edit:
- Click a node to re-center the tree on it (an ↑ back-node climbs up); double-click to open it in the focus editor.
- Drag to reposition; drop onto another node to re-parent (migrate).
- Long-press (~400 ms) + drag moves a node with its whole subtree, drawn cheaply as a circle showing the direct-child count.
- + / × (and the Delete key) add / delete heading nodes.
- ▤ Auto-arrange tidies the layout.
Structural edits (add / delete / migrate) are written back to the .md
(delete and migrate ask for confirmation). Node positions are remembered in a
sidecar <dir>/.mindmap/<base>.json and reloaded next time.
Search (Ctrl/Cmd + F)
The find widget runs a depth-first search over the current file and lists the matching blocks in document order. Title and body are matched (case-insensitive); each result shows its heading path and a context snippet. Enter / ↓ steps to the next match, Shift+Enter / ↑ to the previous, clicking a result jumps to it — each step focuses that block and highlights the term in the editor. Esc closes.
Develop / run
npm install
npm run build # webview (Vite) + host (esbuild) -> dist/
Press F5 (uses .vscode/launch.json) to launch the Extension Development
Host with the examples/llm-intro/ demo folder open, then run “Mind Map:
Open”.
| Script | What it does |
|---|---|
npm run build |
Build webview + host into dist/ |
npm run watch:host / watch:webview |
Rebuild on change |
npm run typecheck |
tsc --noEmit |
npm run smoke |
Headless checks: parser, outline, balanced-paren directives, markdown surgery, and DFS search |
npm run package |
Build a .vsix (needs @vscode/vsce) |
The GUI can't run in a headless environment —
smokecovers the pure host logic; the webview behaviors are verified by pressing F5.
Layout of the code
| Area | Files |
|---|---|
| Extension host | src/extension.ts, src/MindMapPanel.ts, src/workspace.ts, src/layout.ts |
| Parsing / graph / edits | src/parser/parseFile.ts, src/parser/buildGraph.ts, src/parser/edit.ts |
| Shared (host + webview) | src/shared/types.ts, src/shared/directives.ts |
| Webview shell (React) | webview/App.tsx, webview/bridge.ts, webview/main.tsx |
| Webview components | webview/components/Editor.tsx, Canvas.tsx, Connectors.tsx |
| CodeMirror extensions | webview/cm/directives.ts, cm/math.ts, cm/search.ts |
| Styles | webview/styles.css |
Protocol: the host owns the parsed model and answers webview messages
(navigate, save, requestOutline, saveLayout, createNode/deleteNode/
moveNode, search, openFile, home); it pushes back render, outline,
searchResults, and error. See src/shared/types.ts.
Settings
mindmap.autoOpen(defaultfalse) — open the map on startup if anindex.mdis found in the workspace root.mindmap.indexFile(defaultindex.md) — file used byautoOpen.
The primary entry point is the “Mind Map: Open” picker, which works on any
.md regardless of these settings.
License
MIT.