Vancetope — Document Kind mindmap
Specifies the
mindmappayload for documents that carry a hierarchical, ordered set of items rendered as a radial mindmap. Reuses thetreeschema 1:1 and adds optional per-node visual metadata (color, icon, link, tags) plus document-level rendering options. See also: doc-kind-tree | doc-kind-items | web-ui
1. Purpose
kind: tree (see doc-kind-tree) models hierarchical items with an outliner UX. kind: mindmap is the same hierarchy, but:
- with optional per-node metadata for visual styling (color, icon, link, tags),
- with a Mindmap renderer instead of an outliner editor — radial layout starting from the root item.
Design principle: The topic text per node and fluid editing are central. The additional fields are all optional — a Mindmap Document can consist solely of text + children and remain fully functional. There are intentionally no mandatory fields beyond text.
Separation from tree:
- tree is a textually-structured outliner. Edit-focused.
- mindmap is a visually-structured mindmap. View-focused; in v1, read-only render on a second tab, editing still in the Tree-View.
What this spec defines:
- Extended items model (tree fields + optional
color,icon,link,tags). - Top-level Mindmap options (
mindmap:block —theme,direction,initialExpandLevel). - Format mapping md/json/yaml — the same codec as tree, with pass-through for the new fields.
- Web-UI activation (Tab
Mindmapin addition toTreeandRaw).
What it does not define:
- Free-form node positions (
x/y). Mindmap layouts are automatically calculated from the Tree topology — bothmarkmapandmind-elixirwork this way. Concept-map-like free-positioning would be a separate kind (graph). - In-place Mindmap editing (dragging & dropping nodes directly in the radial layout). See §6.
- Mindmap-specific server indexing — items continue to live in the
inlineTextbody. - Embedded images per node. Intentionally excluded to keep the spec simple — images in mindmaps are rarely the value driver, and hosting (Document attachment vs. remote URL) would be a separate spec step.
2. Items Model
Per item, same base as tree:
| Field | Type | Required | Meaning |
|---|---|---|---|
text |
string |
yes | Node topic, single- to multi-line. |
children |
Item[] |
no | Subordinate nodes, recursive. Missing / empty array = leaf. |
Mindmap-specific additional fields (all optional — none are required, a node with only text is valid):
| Field | Type | Meaning |
|---|---|---|
color |
string |
Line and text color of the node as HTML hex (#rrggbb or #rgb). Inherited by children if they don’t have their own color. |
background |
string |
Background fill of the node bubble as HTML hex. |
icon |
string |
Glyph before the topic — emoji or short text. A single icon (not an array). |
link |
string |
Hyperlink of the node (URL) — opened on click. |
tags |
string[] |
Tag chips on the node. Pure display, no semantic link to Document tags. |
Color format: Canonical is HTML hex — #rrggbb (e.g., #3b82f6) or as shorthand #rgb (e.g., #39f). Rationale:
- Unambiguously parseable — no locale, no token resolution, no theme dependency.
- Round-trip stable without normalization leeway (exactly one string per color).
- Universal in mindmap/diagram tools (markmap, mind-elixir, draw.io, Mermaid).
- LLM output is reliable here — hex codes are well represented in training data.
When reading, CSS named colors (red, blue, …) and rgb(…)/hsl(…) are also accepted; when writing, the codec normalizes to #rrggbb (canonical lower-case six-hex form). Alpha/transparency is not planned for v1 — those who want transparent nodes will wait for a later spec point.
Forward compatibility: As with tree, additional, unknown fields are passed through via an extra map. Known Mindmap fields live flat next to text/children — the Tree codec does not know them by name but passes them through (see §3.4).
Markdown limitation: Markdown can only express text + children. All Mindmap additional fields are lost during the md round-trip. Those who maintain a Mindmap Document with colors/icons keep it in JSON or YAML — same convention as for tree for multi-field items.
Canonical form (JSON):
{
"$meta": { "kind": "mindmap" },
"mindmap": {
"theme": "default",
"direction": "right",
"initialExpandLevel": -1
},
"items": [
{
"text": "Vancetope",
"color": "#3b82f6",
"children": [
{
"text": "Brain",
"icon": "🧠",
"children": [
{ "text": "Engines", "tags": ["arthur", "ford"], "children": [] }
]
},
{
"text": "Foot",
"icon": "🐾",
"link": "https://example.com/docs/foot",
"children": []
},
{
"text": "Face",
"children": []
}
]
}
]
}
Header convention: as in doc-kind-items §2 — both JSON and YAML carry kind in a $meta mapping at the top level. The mindmap: block remains at the body top level (nested object, filtered out in $meta anyway).
Exactly one top-level item is the canonical Mindmap form (the root item is radially centered). Multiple top-level items are allowed — the renderer treats them as a “Forest” and renders them as parallel trees side-by-side.
3. On-Disk Formats
3.1 Markdown
---
kind: mindmap
mindmap:
theme: default
direction: right
---
- Vancetope
- Brain
- Engines
- Foot
Reading rules:
- Front-Matter like tree (
----fences).mindmap:block (Mindmap options) is optional and placed underkind:. - Body: identical to tree —
\s*[-*]\s+-bullets with 2-space indent, tabs = 4 spaces, skip-level is clamped to the next shallowest. - No per-node fields — Markdown has no syntax for Color/Icon/Link at the bullet level that would be round-trip stable. Documented limitation.
Writing rules:
- Pre-order DFS, identical to tree.
- Per-node Mindmap fields are not written (would be lost on reading — so not included at all).
- Top-level
mindmap:block is preserved in the Front-Matter (pass-through like all Front-Matter keys).
3.2 JSON
Identical to tree, with:
$metawrapper forkind(see doc-kind-items §2).- Top-level key
mindmap(Object) beforeitems. - Any additional keys from §2 (color/icon/etc.) per item as pass-through.
When writing:
- 2-space indent.
- Order of top-level keys:
$meta,mindmap,items, then unknown pass-through keys in insertion order. - Order of item keys:
text,children, then mindmap fields (color,background,icon,link,tags) in exactly this order — followed by unknown pass-through keys. Fields not set for a node are omitted (nonullwriting).
3.3 YAML
$meta:
kind: mindmap
mindmap:
theme: default
direction: right
initialExpandLevel: -1
items:
- text: Vancetope
color: "#3b82f6"
children:
- text: Brain
icon: "🧠"
children:
- text: Engines
tags: [arthur, ford]
children: []
- text: Foot
icon: "🐾"
link: https://example.com/docs/foot
children: []
Single-Document: Top-level mapping with $meta: { kind: mindmap } as the first key, followed by mindmap: block and items at the same level. Block-style sequences, 2-space indent. No string shorthand for items (same rule as tree — otherwise, the separation of item text vs. sub-item would remain ambiguous).
3.4 Codec Impact
Important: The existing tree codec (treeItemsCodec.ts + Server HeaderStrategy) remains unchanged. Mindmap fields automatically pass through TreeItem.extra: Record<string, unknown>. The Mindmap View reads them from extra, and the Mindmap Edit View (when it arrives) also writes them to extra. This means kind: mindmap does not require a new codec, no new server mapping — only renderer code in the Web-UI.
Only when the Mindmap-specific fields become first-class in the editor UI (color picker, icon picker), the codec will promote them from extra to typed properties on a MindmapItem subtype. This is an additive extension, not a breaking change.
4. Server Path
Like tree and list: no dedicated endpoint, no server-side Mindmap parser. The HeaderStrategy path automatically mirrors kind: mindmap to DocumentDocument.kind.
The mindmap: top-level block is transparent to the server — like all Front-Matter keys (Markdown) or all top-level JSON/YAML keys, it lands unparsed in the body and is returned unchanged.
5. Web-UI
5.1 Editor Activation
kind === 'mindmap'+ Format ∈ {md, json, yaml} → three tabs:Mindmap(Default) /Tree/Raw.- Otherwise (not a Mindmap Document): unchanged.
The Tree tab uses the existing <TreeView> component unchanged — the hierarchy is the same. Per-node Mindmap fields are not displayed or edited in v1 in the Tree-View (but they remain round-trip stable via extra).
The Mindmap tab is read-only render based on markmap-lib + markmap-view. Rationale:
- markmap directly accepts our Markdown bullet form — the adapter is trivial.
- markmap is ~50 KB minified, MIT, actively maintained.
- Read-only Mindmap covers the viewing use case (brainstorming template, strategy draft), editing remains convenient in the Tree-View.
5.2 Feature Scope v1
| Feature | v1 | Note |
|---|---|---|
| Mindmap render (radial layout) | ✓ | markmap |
| Pan / Zoom | ✓ | markmap built-in |
| Expand / Collapse per node | ✓ | markmap built-in (click on disclosure) |
| Edit (via Tree tab) | ✓ | existing <TreeView> |
| Per-node Color/Icon/Link/Tags | (◯) | persisted (round-trip), but not editable and only partially rendered in v1 |
| In-place edit in Mindmap layout | ✗ | see §6 |
| Custom Theme / direction options | (◯) | persisted in the mindmap: block, but UI operation only via Raw in v1 |
| Forest (multiple roots) | ✓ | markmap renders multiple top-level bullets side-by-side |
(◯) = Feature is not actively editable in v1, but data passes through round-trip stably.
5.3 Components
<MindmapView>— top-level Mindmap tab. Receives:doc: TreeDocument(same type as TreeView), converts it to markmap Markdown, instantiates markmap. Read-only.<TreeView>— existing Tree editor, unchanged. Serves theTreetab.- Tab bar like for tree (
content-tabclass fromDocumentApp.vue), extended to three tabs.
5.4 Markmap Adapter
The adapter is a function treeToMarkmapMarkdown(doc: TreeDocument): string:
- Pre-order DFS.
- Per item: Indent (depth × 2 Spaces) +
-+ first topic line. - If
linkis set: Topic becomes[<text>](<link>). iconis prefixed to the topic text (emoji directly, followed by a space).tags/color/backgroundare not passed to markmap in v1 (no direct markmap equivalent — color is handled globally viacolorFreezeLevel, markmap does not have tags render). However, they are in the Document and will be active in a later edit/render iteration.- Top-level:
mindmap:block from the Document is prepended as markmap Front-Matter (---\nmarkmap:\n ...\n---) —theme,direction,initialExpandLevelmap 1:1.
5.5 Visual Conventions
- Mindmap tab fills the editor content completely (no second vertical scrolling — markmap takes 100% height).
- Pan/Zoom hint subtly in the bottom right (“Mouse wheel zooms, Drag pans”) as a small help tooltip.
- Default theme aligns with the DaisyUI theme via CSS variables — markmap allows CSS override, so Light/Dark mode follows.
6. Future (not v1)
6.1 In-Place Mindmap Editing
mind-elixir (https://github.com/ssshooter/mind-elixir-core, MIT, ~70 KB minified) replaces markmap in the Mindmap tab. This enables:
- Double-click on node → inline topic edit.
- Drag & drop of nodes between parents (true 2D re-parenting).
- Context menu per node: Color picker, Icon picker, Link editor, Tag editor.
- Keyboard shortcuts like in the Tree editor (Tab/Shift+Tab/Enter).
mind-elixir has its own data model ({ topic, id, style, tags, icons, hyperLink, expanded, children }, plus optional image which we don’t use); the adapter between our TreeItem form and mind-elixir form is 1:1 — all fields defined in §2 map directly.
Migration path: codec remains the same, only <MindmapView> is replaced. Tree tab and Raw tab unchanged.
6.2 Active Mindmap Fields in Tree Editor
Per-node Color/Icon/Link/etc. will also be displayed and editable in the Tree-View (inline picker or side panel). This means Mindmap metadata will not only live in the Mindmap tab. This is useful only when real users need it — until then, the Mindmap View is sufficient.
6.3 Mindmap Linker / Cross-Document Linking
Nodes could refer to other Documents in the same Project (link: doc:<documentId> or link: vance:document/<id>). The renderer resolves this to an app-internal tab open. Requires a convention for vance: URLs — a separate spec point.
6.4 Persistent Expand/Collapse
As with tree (§6.3 there): per-user setting or per-item field. Not now.
7. Open Points
- Single-Root Requirement: Should we restrict
kind: mindmapto exactly one top-level item? markmap also renders forests, but UX-wise, a Mindmap user expects a single radial center. Suggestion: allow it, but warn in the editor if more than one top-level item is present. - markmap vs. mind-elixir Default: If the first real Mindmap creation shows that viewing without editing is insufficient, the default will switch directly to mind-elixir. Until then, Markmap, because of the leaner adapter.
- Tags Rendering: markmap has no tag display. Either append as inline code spans (
`tag`) to the topic or natively with mind-elixir migration. Decision pending until the first use case.