Vibecode MindNode
track this build4 phases, 12 steps, beginner friendly0%The visible mind mapping loop is buildable, but a credible replacement needs more than the first screen. MindNode earns its keep through interaction polish, collaboration, so expect a weekend or multi-day build and a narrower personal scope.
You are building a lean indie version of MindNode. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # MindNode · indie build A mind mapping tool where the value is thinking speed rather than diagramming: nodes are created and rearranged from the keyboard without pauses, the layout resolves itself without overlaps, and the same structure is editable as an outline when a tree is the wrong view. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Model | A tree with optional cross-links, kept separate | a mind map is a tree that occasionally is not, and conflating them ruins the layout | | Layout | Automatic radial or lateral placement with collision resolution | manual positioning at fifty nodes is the thing people give up on | | Input | Keyboard-first with every action bound, no modal dialogs | the tool competes with a sheet of paper on speed | | Duality | The same document editable as a map or an outline | an outline is faster for entering and a map is better for seeing | | Runtime | A local application with file-based documents | a mind map is a document and should behave like one | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the local application. - Get it: nodejs.org, or nvm install 22. - Verify: node --version prints v22 or higher - [ ] **A tree layout algorithm you understand** · free - Why: Collision resolution and subtree balancing are the difference between a usable map at a hundred nodes and an unusable one, and it is a solved problem worth reading rather than inventing. - Get it: Read a published tree drawing algorithm and implement it, or use a maintained library. - Verify: A hundred node tree lays out without overlaps - [ ] **A real map of at least a hundred nodes** · free - Why: Layout quality, reflow smoothness and export size are all uninteresting below fifty nodes and become the whole problem above a hundred. - Get it: Build one from real thinking rather than generating a balanced tree, since real maps are lopsided. - Verify: A hundred node lopsided map exists with several cross-links - [ ] **Your keyboard scheme, decided before building** · free - Why: Everything is keyboard bound and retrofitting a scheme after building the interface means rebuilding the interface. - Get it: Decide the bindings for creation, navigation, collapsing and view switching before writing phase one. - Verify: A written scheme covers every planned action ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Real-time collaboration. - Presentation and walkthrough modes. - Task management with dates and dependencies. - Automatic map generation from a document. - high-fidelity import and export - presentation and enterprise controls - multiplayer cursors and comments - large template libraries If one of those is essential to you, that is the reason to keep paying for MindNode, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · MindNode The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a mind map you build entirely from the keyboard, that lays itself out to replace MindNode. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Model: A tree with optional cross-links, kept separate · a mind map is a tree that occasionally is not, and conflating them ruins the layout - Layout: Automatic radial or lateral placement with collision resolution · manual positioning at fifty nodes is the thing people give up on - Input: Keyboard-first with every action bound, no modal dialogs · the tool competes with a sheet of paper on speed - Duality: The same document editable as a map or an outline · an outline is faster for entering and a map is better for seeing - Runtime: A local application with file-based documents · a mind map is a document and should behave like one ### Data model (create this before Phase 1) - documents(id, title, layout_kind, theme, updated_at) - nodes(id, document_id, parent_id, ordinal, text, note, collapsed, style_json, manual_position) - links(from_node_id, to_node_id, label) · cross-links outside the tree, drawn differently - layout_cache(document_id, computed_at, positions_json) · derived, discarded when the tree changes - focus_state(document_id, node_id, at) · so reopening returns you where you were thinking - attachments(node_id, kind, ref) · images and file references, bounded - A node records whether its position was set manually, so automatic layout never discards a placement someone made deliberately. ### Phase 1 · Typing a map without pausing Build: Keyboard creation of siblings and children, navigation between nodes, and editing in place with no modal dialogs. Measure how long fifty nodes take. Undo covering the last many actions. Trap: Any modal dialog or mouse reach in the creation loop breaks the rhythm, and a mind map is used precisely when someone is thinking quickly, so a pause costs the idea rather than a second. Bind everything, edit in place, and time a realistic session rather than assuming. Done when: Fifty nodes are entered in a couple of minutes without touching a mouse, timed by hand. Creating a sibling, a child and a parent are all single keystrokes. Editing happens in place with no dialog. Undo covers at least the last twenty actions including structural changes. Do not build yet: No layout, outline view, links or export. ### Phase 2 · A layout that resolves itself Build: Automatic placement with collision resolution and balanced subtree distribution. Reflow smoothly when a node is added rather than jumping. Respect a node whose position was set manually. Trap: Reflowing the whole map on every keystroke makes the canvas jump around while someone is typing, which is disorienting enough that they stop using automatic layout entirely. Animate the reflow, keep the focused node stationary, and move everything else around it. Done when: A hundred nodes lay out without overlaps and with readable connector paths. Adding a node keeps the focused node stationary and moves the rest around it. A manually positioned node is not moved by automatic layout. Layout completes fast enough to be imperceptible while typing. Do not build yet: No outline view, links or export yet. ### Phase 3 · The same document as an outline Build: An outline view over the same tree with the same keyboard model, where edits in either view are the same edits. Handle collapsing consistently across views and a cross-link that has no place in an outline. Trap: Implementing the outline as a separate representation that syncs to the map produces two structures that drift, and the drift is discovered when one view is missing a branch. Render both from one tree, so there is nothing to synchronise. Done when: Both views render from one tree and an edit in either is immediately correct in the other, verified by editing in each. Collapsed state is shared and consistent. A cross-link is represented in the outline by a stated convention rather than dropped. Switching views keeps the focused node. Do not build yet: No links, tasks or export yet. ### Phase 4 · Links that are not the tree Build: Cross-links between arbitrary nodes, drawn distinctly from tree edges and excluded from layout balancing. Detect a cross-link that duplicates a tree relationship. Handle a link whose endpoint is deleted. Trap: Treating a cross-link as another parent edge makes the layout algorithm try to satisfy an impossible tree and produces a tangle, which is why many mind mappers refuse cross-links entirely. Keep them out of the layout computation and draw them as an overlay. Done when: Cross-links draw distinctly and do not participate in layout balancing. A hundred node map with twenty cross-links remains readable. Deleting a node removes or orphans its links by a stated rule rather than leaving dangling references. A cross-link duplicating a tree edge is flagged. Do not build yet: No tasks or export yet. ### Phase 5 · Getting the thinking out Build: Export to an indented text outline, a vector image with text preserved, and an open interchange format. Verify the outline round trips back into the same tree. Handle a very large map without exhausting memory. Trap: Exporting only as an image loses the structure entirely, and a mind map's value is usually that it becomes a document, an outline or a plan afterwards. Export the text structure first and treat the image as secondary. Done when: An indented text export round trips back into an identical tree, asserted in the suite. Vector export preserves text as text rather than outlines. An open interchange format export opens in another mind mapping tool. A map of a thousand nodes exports without exhausting memory. Do not build yet: Nothing after this. ### Out of scope (and why) - Real-time collaboration, which is a synchronisation problem and changes how quickly a single person can think. - Presentation modes and animated walkthroughs, which is a different product wearing the same interface. - Task management with dates and dependencies, which turns a thinking tool into a planning one. - Automatic map generation from a document, which produces a structure nobody recognises as their own thinking. ### README must contain - That everything is keyboard bound and there are no modal dialogs, because a pause costs the thought - That the focused node stays stationary during reflow, since a jumping canvas is disorienting - That both the map and the outline render from one tree rather than syncing two - That cross-links are excluded from layout, because treating them as tree edges produces a tangle - That the text outline export round trips, since a map usually becomes a document ===== AGENTS.md ===== # Agent instructions · MindNode indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A tree with optional cross-links, kept separate, Automatic radial or lateral placement with collision resolution, Keyboard-first with every action bound, no modal dialogs, The same document editable as a map or an outline, A local application with file-based documents. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - Any modal dialog or mouse reach in the creation loop breaks the rhythm, and a mind map is used precisely when someone is thinking quickly, so a pause costs the idea rather than a second. Bind everything, edit in place, and time a realistic session rather than assuming. - Reflowing the whole map on every keystroke makes the canvas jump around while someone is typing, which is disorienting enough that they stop using automatic layout entirely. Animate the reflow, keep the focused node stationary, and move everything else around it. - Implementing the outline as a separate representation that syncs to the map produces two structures that drift, and the drift is discovered when one view is missing a branch. Render both from one tree, so there is nothing to synchronise. - Treating a cross-link as another parent edge makes the layout algorithm try to satisfy an impossible tree and produces a tangle, which is why many mind mappers refuse cross-links entirely. Keep them out of the layout computation and draw them as an overlay. ===== BUILD_PLAN.md ===== # Build plan · MindNode A mind mapping tool where the value is thinking speed rather than diagramming: nodes are created and rearranged from the keyboard without pauses, the layout resolves itself without overlaps, and the same structure is editable as an outline when a tree is the wrong view. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · Typing a map without pausing Fifty nodes can be entered in a couple of minutes without a mouse. ### Steps 1. Bind creation and navigation to keys Sibling, child, parent, move. All single keystrokes. Files: `src/keys.ts` 2. Edit in place, never in a dialog A dialog is a pause and a pause costs the thought. Files: `src/editing.ts` 3. Make undo deep and structural Fast entry produces mistakes and they must be cheap. Files: `src/undo.ts` ### Done when - [ ] Fifty nodes are entered in a couple of minutes - [ ] Sibling, child and parent are single keystrokes - [ ] Editing is in place with no dialog - [ ] Undo covers twenty structural actions ### Watch out - Any modal dialog or mouse reach in the creation loop breaks the rhythm, and a mind map is used precisely when someone is thinking quickly, so a pause costs the idea rather than a second. Bind everything, edit in place, and time a realistic session rather than assuming. ## Phase 2 · A layout that resolves itself A hundred nodes arrange without overlapping or crossing badly. ### Steps 1. Resolve collisions and balance subtrees Overlapping nodes at a hundred is where people abandon the layout. Files: `src/layout.ts`, `src/layout.test.ts` 2. Keep the focused node stationary A canvas jumping while you type is disorienting. Files: `src/reflow.ts` 3. Respect manual positions A deliberate placement should survive the next node. Files: `src/layout.ts` ### Done when - [ ] A hundred nodes lay out without overlaps - [ ] The focused node stays stationary on reflow - [ ] Manual positions are respected - [ ] Layout is imperceptible while typing ### Watch out - Reflowing the whole map on every keystroke makes the canvas jump around while someone is typing, which is disorienting enough that they stop using automatic layout entirely. Animate the reflow, keep the focused node stationary, and move everything else around it. ## Phase 3 · The same document as an outline Switching between map and outline edits one structure, not two. ### Steps 1. Render both views from one tree Two representations drift and the drift loses a branch. Files: `src/outline.ts` 2. Share collapsed state A branch collapsed in one view should not reappear in the other. Files: `src/tree.ts` 3. Represent cross-links by convention They have no natural place in an outline and dropping them loses information. Files: `src/outline.ts` ### Done when - [ ] Edits in either view are immediately correct in both - [ ] Collapsed state is shared - [ ] Cross-links appear by a stated convention - [ ] Switching views keeps focus ### Watch out - Implementing the outline as a separate representation that syncs to the map produces two structures that drift, and the drift is discovered when one view is missing a branch. Render both from one tree, so there is nothing to synchronise. ## Phase 4 · Links that are not the tree A connection between distant branches exists without breaking the layout. ### Steps 1. Exclude cross-links from layout Trying to satisfy them as tree edges produces a tangle. Files: `src/links.ts` 2. Draw them distinctly A reader must be able to tell structure from association. Files: `src/render.ts` 3. Handle endpoint deletion explicitly A stated rule rather than a dangling reference. Files: `src/links.ts` ### Done when - [ ] Cross-links do not affect layout - [ ] Twenty cross-links stay readable at a hundred nodes - [ ] Endpoint deletion follows a stated rule - [ ] Duplicate cross-links are flagged ### Watch out - Treating a cross-link as another parent edge makes the layout algorithm try to satisfy an impossible tree and produces a tangle, which is why many mind mappers refuse cross-links entirely. Keep them out of the layout computation and draw them as an overlay. ## Not in this build - Real-time collaboration. - Presentation and walkthrough modes. - Task management with dates and dependencies. - Automatic map generation from a document. ## After v1, if you want it - Focus mode showing one subtree, which is how large maps stay usable - Node styling driven by depth or tag rather than set by hand - Merging two maps, which is harder than it sounds once cross-links exist ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Map files. A mind map is a document and should behave like one. DOCUMENTS_DIR=~/Documents/maps # Required. Radial or lateral. Both need collision resolution. LAYOUT_KIND=radial # Required. Long enough to follow, short enough not to feel slow while typing. REFLOW_ANIMATION_MS=180 # Required. Layout runs while typing. Beyond this it must degrade rather than stutter. LAYOUT_BUDGET_MS=16 # Required. Fast entry produces mistakes and they should all be cheap. UNDO_DEPTH=50 # Required. Where layout quality starts to degrade, made explicit rather than discovered. MAX_NODES_WARNING=1000
You are building a lean indie version of MindNode. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # MindNode · indie build A mind mapping tool where the value is thinking speed rather than diagramming: nodes are created and rearranged from the keyboard without pauses, the layout resolves itself without overlaps, and the same structure is editable as an outline when a tree is the wrong view. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Model | A tree with optional cross-links, kept separate | a mind map is a tree that occasionally is not, and conflating them ruins the layout | | Layout | Automatic radial or lateral placement with collision resolution | manual positioning at fifty nodes is the thing people give up on | | Input | Keyboard-first with every action bound, no modal dialogs | the tool competes with a sheet of paper on speed | | Duality | The same document editable as a map or an outline | an outline is faster for entering and a map is better for seeing | | Runtime | A local application with file-based documents | a mind map is a document and should behave like one | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the local application. - Get it: nodejs.org, or nvm install 22. - Verify: node --version prints v22 or higher - [ ] **A tree layout algorithm you understand** · free - Why: Collision resolution and subtree balancing are the difference between a usable map at a hundred nodes and an unusable one, and it is a solved problem worth reading rather than inventing. - Get it: Read a published tree drawing algorithm and implement it, or use a maintained library. - Verify: A hundred node tree lays out without overlaps - [ ] **A real map of at least a hundred nodes** · free - Why: Layout quality, reflow smoothness and export size are all uninteresting below fifty nodes and become the whole problem above a hundred. - Get it: Build one from real thinking rather than generating a balanced tree, since real maps are lopsided. - Verify: A hundred node lopsided map exists with several cross-links - [ ] **Your keyboard scheme, decided before building** · free - Why: Everything is keyboard bound and retrofitting a scheme after building the interface means rebuilding the interface. - Get it: Decide the bindings for creation, navigation, collapsing and view switching before writing phase one. - Verify: A written scheme covers every planned action ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Real-time collaboration. - Presentation and walkthrough modes. - Task management with dates and dependencies. - Automatic map generation from a document. - high-fidelity import and export - presentation and enterprise controls - multiplayer cursors and comments - large template libraries If one of those is essential to you, that is the reason to keep paying for MindNode, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · MindNode The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a mind map you build entirely from the keyboard, that lays itself out to replace MindNode. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Model: A tree with optional cross-links, kept separate · a mind map is a tree that occasionally is not, and conflating them ruins the layout - Layout: Automatic radial or lateral placement with collision resolution · manual positioning at fifty nodes is the thing people give up on - Input: Keyboard-first with every action bound, no modal dialogs · the tool competes with a sheet of paper on speed - Duality: The same document editable as a map or an outline · an outline is faster for entering and a map is better for seeing - Runtime: A local application with file-based documents · a mind map is a document and should behave like one ### Data model (create this before Phase 1) - documents(id, title, layout_kind, theme, updated_at) - nodes(id, document_id, parent_id, ordinal, text, note, collapsed, style_json, manual_position) - links(from_node_id, to_node_id, label) · cross-links outside the tree, drawn differently - layout_cache(document_id, computed_at, positions_json) · derived, discarded when the tree changes - focus_state(document_id, node_id, at) · so reopening returns you where you were thinking - attachments(node_id, kind, ref) · images and file references, bounded - A node records whether its position was set manually, so automatic layout never discards a placement someone made deliberately. ### Phase 1 · Typing a map without pausing Build: Keyboard creation of siblings and children, navigation between nodes, and editing in place with no modal dialogs. Measure how long fifty nodes take. Undo covering the last many actions. Trap: Any modal dialog or mouse reach in the creation loop breaks the rhythm, and a mind map is used precisely when someone is thinking quickly, so a pause costs the idea rather than a second. Bind everything, edit in place, and time a realistic session rather than assuming. Done when: Fifty nodes are entered in a couple of minutes without touching a mouse, timed by hand. Creating a sibling, a child and a parent are all single keystrokes. Editing happens in place with no dialog. Undo covers at least the last twenty actions including structural changes. Do not build yet: No layout, outline view, links or export. ### Phase 2 · A layout that resolves itself Build: Automatic placement with collision resolution and balanced subtree distribution. Reflow smoothly when a node is added rather than jumping. Respect a node whose position was set manually. Trap: Reflowing the whole map on every keystroke makes the canvas jump around while someone is typing, which is disorienting enough that they stop using automatic layout entirely. Animate the reflow, keep the focused node stationary, and move everything else around it. Done when: A hundred nodes lay out without overlaps and with readable connector paths. Adding a node keeps the focused node stationary and moves the rest around it. A manually positioned node is not moved by automatic layout. Layout completes fast enough to be imperceptible while typing. Do not build yet: No outline view, links or export yet. ### Phase 3 · The same document as an outline Build: An outline view over the same tree with the same keyboard model, where edits in either view are the same edits. Handle collapsing consistently across views and a cross-link that has no place in an outline. Trap: Implementing the outline as a separate representation that syncs to the map produces two structures that drift, and the drift is discovered when one view is missing a branch. Render both from one tree, so there is nothing to synchronise. Done when: Both views render from one tree and an edit in either is immediately correct in the other, verified by editing in each. Collapsed state is shared and consistent. A cross-link is represented in the outline by a stated convention rather than dropped. Switching views keeps the focused node. Do not build yet: No links, tasks or export yet. ### Phase 4 · Links that are not the tree Build: Cross-links between arbitrary nodes, drawn distinctly from tree edges and excluded from layout balancing. Detect a cross-link that duplicates a tree relationship. Handle a link whose endpoint is deleted. Trap: Treating a cross-link as another parent edge makes the layout algorithm try to satisfy an impossible tree and produces a tangle, which is why many mind mappers refuse cross-links entirely. Keep them out of the layout computation and draw them as an overlay. Done when: Cross-links draw distinctly and do not participate in layout balancing. A hundred node map with twenty cross-links remains readable. Deleting a node removes or orphans its links by a stated rule rather than leaving dangling references. A cross-link duplicating a tree edge is flagged. Do not build yet: No tasks or export yet. ### Phase 5 · Getting the thinking out Build: Export to an indented text outline, a vector image with text preserved, and an open interchange format. Verify the outline round trips back into the same tree. Handle a very large map without exhausting memory. Trap: Exporting only as an image loses the structure entirely, and a mind map's value is usually that it becomes a document, an outline or a plan afterwards. Export the text structure first and treat the image as secondary. Done when: An indented text export round trips back into an identical tree, asserted in the suite. Vector export preserves text as text rather than outlines. An open interchange format export opens in another mind mapping tool. A map of a thousand nodes exports without exhausting memory. Do not build yet: Nothing after this. ### Out of scope (and why) - Real-time collaboration, which is a synchronisation problem and changes how quickly a single person can think. - Presentation modes and animated walkthroughs, which is a different product wearing the same interface. - Task management with dates and dependencies, which turns a thinking tool into a planning one. - Automatic map generation from a document, which produces a structure nobody recognises as their own thinking. ### README must contain - That everything is keyboard bound and there are no modal dialogs, because a pause costs the thought - That the focused node stays stationary during reflow, since a jumping canvas is disorienting - That both the map and the outline render from one tree rather than syncing two - That cross-links are excluded from layout, because treating them as tree edges produces a tangle - That the text outline export round trips, since a map usually becomes a document ===== AGENTS.md ===== # Agent instructions · MindNode indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A tree with optional cross-links, kept separate, Automatic radial or lateral placement with collision resolution, Keyboard-first with every action bound, no modal dialogs, The same document editable as a map or an outline, A local application with file-based documents. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - Any modal dialog or mouse reach in the creation loop breaks the rhythm, and a mind map is used precisely when someone is thinking quickly, so a pause costs the idea rather than a second. Bind everything, edit in place, and time a realistic session rather than assuming. - Reflowing the whole map on every keystroke makes the canvas jump around while someone is typing, which is disorienting enough that they stop using automatic layout entirely. Animate the reflow, keep the focused node stationary, and move everything else around it. - Implementing the outline as a separate representation that syncs to the map produces two structures that drift, and the drift is discovered when one view is missing a branch. Render both from one tree, so there is nothing to synchronise. - Treating a cross-link as another parent edge makes the layout algorithm try to satisfy an impossible tree and produces a tangle, which is why many mind mappers refuse cross-links entirely. Keep them out of the layout computation and draw them as an overlay. ===== BUILD_PLAN.md ===== # Build plan · MindNode A mind mapping tool where the value is thinking speed rather than diagramming: nodes are created and rearranged from the keyboard without pauses, the layout resolves itself without overlaps, and the same structure is editable as an outline when a tree is the wrong view. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · Typing a map without pausing Fifty nodes can be entered in a couple of minutes without a mouse. ### Steps 1. Bind creation and navigation to keys Sibling, child, parent, move. All single keystrokes. Files: `src/keys.ts` 2. Edit in place, never in a dialog A dialog is a pause and a pause costs the thought. Files: `src/editing.ts` 3. Make undo deep and structural Fast entry produces mistakes and they must be cheap. Files: `src/undo.ts` ### Done when - [ ] Fifty nodes are entered in a couple of minutes - [ ] Sibling, child and parent are single keystrokes - [ ] Editing is in place with no dialog - [ ] Undo covers twenty structural actions ### Watch out - Any modal dialog or mouse reach in the creation loop breaks the rhythm, and a mind map is used precisely when someone is thinking quickly, so a pause costs the idea rather than a second. Bind everything, edit in place, and time a realistic session rather than assuming. ## Phase 2 · A layout that resolves itself A hundred nodes arrange without overlapping or crossing badly. ### Steps 1. Resolve collisions and balance subtrees Overlapping nodes at a hundred is where people abandon the layout. Files: `src/layout.ts`, `src/layout.test.ts` 2. Keep the focused node stationary A canvas jumping while you type is disorienting. Files: `src/reflow.ts` 3. Respect manual positions A deliberate placement should survive the next node. Files: `src/layout.ts` ### Done when - [ ] A hundred nodes lay out without overlaps - [ ] The focused node stays stationary on reflow - [ ] Manual positions are respected - [ ] Layout is imperceptible while typing ### Watch out - Reflowing the whole map on every keystroke makes the canvas jump around while someone is typing, which is disorienting enough that they stop using automatic layout entirely. Animate the reflow, keep the focused node stationary, and move everything else around it. ## Phase 3 · The same document as an outline Switching between map and outline edits one structure, not two. ### Steps 1. Render both views from one tree Two representations drift and the drift loses a branch. Files: `src/outline.ts` 2. Share collapsed state A branch collapsed in one view should not reappear in the other. Files: `src/tree.ts` 3. Represent cross-links by convention They have no natural place in an outline and dropping them loses information. Files: `src/outline.ts` ### Done when - [ ] Edits in either view are immediately correct in both - [ ] Collapsed state is shared - [ ] Cross-links appear by a stated convention - [ ] Switching views keeps focus ### Watch out - Implementing the outline as a separate representation that syncs to the map produces two structures that drift, and the drift is discovered when one view is missing a branch. Render both from one tree, so there is nothing to synchronise. ## Phase 4 · Links that are not the tree A connection between distant branches exists without breaking the layout. ### Steps 1. Exclude cross-links from layout Trying to satisfy them as tree edges produces a tangle. Files: `src/links.ts` 2. Draw them distinctly A reader must be able to tell structure from association. Files: `src/render.ts` 3. Handle endpoint deletion explicitly A stated rule rather than a dangling reference. Files: `src/links.ts` ### Done when - [ ] Cross-links do not affect layout - [ ] Twenty cross-links stay readable at a hundred nodes - [ ] Endpoint deletion follows a stated rule - [ ] Duplicate cross-links are flagged ### Watch out - Treating a cross-link as another parent edge makes the layout algorithm try to satisfy an impossible tree and produces a tangle, which is why many mind mappers refuse cross-links entirely. Keep them out of the layout computation and draw them as an overlay. ## Not in this build - Real-time collaboration. - Presentation and walkthrough modes. - Task management with dates and dependencies. - Automatic map generation from a document. ## After v1, if you want it - Focus mode showing one subtree, which is how large maps stay usable - Node styling driven by depth or tag rather than set by hand - Merging two maps, which is harder than it sounds once cross-links exist ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Map files. A mind map is a document and should behave like one. DOCUMENTS_DIR=~/Documents/maps # Required. Radial or lateral. Both need collision resolution. LAYOUT_KIND=radial # Required. Long enough to follow, short enough not to feel slow while typing. REFLOW_ANIMATION_MS=180 # Required. Layout runs while typing. Beyond this it must degrade rather than stutter. LAYOUT_BUDGET_MS=16 # Required. Fast entry produces mistakes and they should all be cheap. UNDO_DEPTH=50 # Required. Where layout quality starts to degrade, made explicit rather than discovered. MAX_NODES_WARNING=1000
You are building a production product version of MindNode. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== PRODUCT.md ===== # MindNode · product brief ## Problem The visible mind mapping loop is buildable, but a credible replacement needs more than the first screen. MindNode earns its keep through interaction polish, collaboration, so expect a weekend or multi-day build and a narrower personal scope. ## Product outcome A mind map you can fill as fast as you think, that arranges itself without overlaps, and that leaves as an outline you can keep working in. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - Node.js 22 - modern browser - no account required ## Explicit non-goals for v1 - Real-time collaboration. - Presentation and walkthrough modes. - Task management with dates and dependencies. - Automatic map generation from a document. - high-fidelity import and export - presentation and enterprise controls - multiplayer cursors and comments - large template libraries ## Success criteria - Fifty nodes are confirmed to enter in a couple of minutes without a mouse - A hundred nodes are confirmed to lay out without overlaps - Both views are confirmed to render from one tree - Cross-links are confirmed excluded from layout - The text outline export is confirmed to round trip ===== BRIEF.md ===== # Build brief · MindNode The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a mind map you build entirely from the keyboard, that lays itself out to replace MindNode. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Model: A tree with optional cross-links, kept separate · a mind map is a tree that occasionally is not, and conflating them ruins the layout - Layout: Automatic radial or lateral placement with collision resolution · manual positioning at fifty nodes is the thing people give up on - Input: Keyboard-first with every action bound, no modal dialogs · the tool competes with a sheet of paper on speed - Duality: The same document editable as a map or an outline · an outline is faster for entering and a map is better for seeing - Runtime: A local application with file-based documents · a mind map is a document and should behave like one ### Data model (create this before Phase 1) - documents(id, title, layout_kind, theme, updated_at) - nodes(id, document_id, parent_id, ordinal, text, note, collapsed, style_json, manual_position) - links(from_node_id, to_node_id, label) · cross-links outside the tree, drawn differently - layout_cache(document_id, computed_at, positions_json) · derived, discarded when the tree changes - focus_state(document_id, node_id, at) · so reopening returns you where you were thinking - attachments(node_id, kind, ref) · images and file references, bounded - A node records whether its position was set manually, so automatic layout never discards a placement someone made deliberately. ### Phase 1 · Typing a map without pausing Build: Keyboard creation of siblings and children, navigation between nodes, and editing in place with no modal dialogs. Measure how long fifty nodes take. Undo covering the last many actions. Trap: Any modal dialog or mouse reach in the creation loop breaks the rhythm, and a mind map is used precisely when someone is thinking quickly, so a pause costs the idea rather than a second. Bind everything, edit in place, and time a realistic session rather than assuming. Done when: Fifty nodes are entered in a couple of minutes without touching a mouse, timed by hand. Creating a sibling, a child and a parent are all single keystrokes. Editing happens in place with no dialog. Undo covers at least the last twenty actions including structural changes. Do not build yet: No layout, outline view, links or export. ### Phase 2 · A layout that resolves itself Build: Automatic placement with collision resolution and balanced subtree distribution. Reflow smoothly when a node is added rather than jumping. Respect a node whose position was set manually. Trap: Reflowing the whole map on every keystroke makes the canvas jump around while someone is typing, which is disorienting enough that they stop using automatic layout entirely. Animate the reflow, keep the focused node stationary, and move everything else around it. Done when: A hundred nodes lay out without overlaps and with readable connector paths. Adding a node keeps the focused node stationary and moves the rest around it. A manually positioned node is not moved by automatic layout. Layout completes fast enough to be imperceptible while typing. Do not build yet: No outline view, links or export yet. ### Phase 3 · The same document as an outline Build: An outline view over the same tree with the same keyboard model, where edits in either view are the same edits. Handle collapsing consistently across views and a cross-link that has no place in an outline. Trap: Implementing the outline as a separate representation that syncs to the map produces two structures that drift, and the drift is discovered when one view is missing a branch. Render both from one tree, so there is nothing to synchronise. Done when: Both views render from one tree and an edit in either is immediately correct in the other, verified by editing in each. Collapsed state is shared and consistent. A cross-link is represented in the outline by a stated convention rather than dropped. Switching views keeps the focused node. Do not build yet: No links, tasks or export yet. ### Phase 4 · Links that are not the tree Build: Cross-links between arbitrary nodes, drawn distinctly from tree edges and excluded from layout balancing. Detect a cross-link that duplicates a tree relationship. Handle a link whose endpoint is deleted. Trap: Treating a cross-link as another parent edge makes the layout algorithm try to satisfy an impossible tree and produces a tangle, which is why many mind mappers refuse cross-links entirely. Keep them out of the layout computation and draw them as an overlay. Done when: Cross-links draw distinctly and do not participate in layout balancing. A hundred node map with twenty cross-links remains readable. Deleting a node removes or orphans its links by a stated rule rather than leaving dangling references. A cross-link duplicating a tree edge is flagged. Do not build yet: No tasks or export yet. ### Phase 5 · Getting the thinking out Build: Export to an indented text outline, a vector image with text preserved, and an open interchange format. Verify the outline round trips back into the same tree. Handle a very large map without exhausting memory. Trap: Exporting only as an image loses the structure entirely, and a mind map's value is usually that it becomes a document, an outline or a plan afterwards. Export the text structure first and treat the image as secondary. Done when: An indented text export round trips back into an identical tree, asserted in the suite. Vector export preserves text as text rather than outlines. An open interchange format export opens in another mind mapping tool. A map of a thousand nodes exports without exhausting memory. Do not build yet: Nothing after this. ### Out of scope (and why) - Real-time collaboration, which is a synchronisation problem and changes how quickly a single person can think. - Presentation modes and animated walkthroughs, which is a different product wearing the same interface. - Task management with dates and dependencies, which turns a thinking tool into a planning one. - Automatic map generation from a document, which produces a structure nobody recognises as their own thinking. ### README must contain - That everything is keyboard bound and there are no modal dialogs, because a pause costs the thought - That the focused node stays stationary during reflow, since a jumping canvas is disorienting - That both the map and the outline render from one tree rather than syncing two - That cross-links are excluded from layout, because treating them as tree edges produces a tangle - That the text outline export round trips, since a map usually becomes a document ===== ARCHITECTURE.md ===== # Architecture · MindNode ## Stack | Part | Choice | Why | | --- | --- | --- | | Model | A tree with optional cross-links, kept separate | a mind map is a tree that occasionally is not, and conflating them ruins the layout | | Layout | Automatic radial or lateral placement with collision resolution | manual positioning at fifty nodes is the thing people give up on | | Input | Keyboard-first with every action bound, no modal dialogs | the tool competes with a sheet of paper on speed | | Duality | The same document editable as a map or an outline | an outline is faster for entering and a map is better for seeing | | Runtime | A local application with file-based documents | a mind map is a document and should behave like one | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Input | Keyboard-bound creation and navigation. | Any interface, provided nothing in the creation loop requires a mouse. | | Layout | Automatic placement with collision resolution. | Any algorithm, provided the focused node stays stationary. | | Duality | Map and outline from one tree. | Not swappable for two representations, which drift and lose branches. | | Links | Cross-links outside the layout. | Any implementation, provided they never participate in layout balancing. | | Export | Text structure with a tested round trip. | Any format, provided text export precedes image export. | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `DOCUMENTS_DIR` · required · Map files. A mind map is a document and should behave like one. - `LAYOUT_KIND` · required · Radial or lateral. Both need collision resolution. - `REFLOW_ANIMATION_MS` · required · Long enough to follow, short enough not to feel slow while typing. - `LAYOUT_BUDGET_MS` · required · Layout runs while typing. Beyond this it must degrade rather than stutter. - `UNDO_DEPTH` · required · Fast entry produces mistakes and they should all be cheap. - `MAX_NODES_WARNING` · required · Where layout quality starts to degrade, made explicit rather than discovered. ## Production baseline - Security: least privilege, input validation at every boundary, secret redaction in logs, rate limits on abuse-prone paths, no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore procedures that have been exercised. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, timeouts. - Observability: structured logs with request or operation ids, an error-tracking hook, and health and readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, one end-to-end test of the critical path. ## Decision records For each dependency in the stack table, keep a short note: why it was chosen, its failure mode, and how it is replaced. Do not add infrastructure until a requirement in `PRODUCT.md` justifies it. ===== AGENTS.md ===== # Agent instructions · MindNode product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: A tree with optional cross-links, kept separate, Automatic radial or lateral placement with collision resolution, Keyboard-first with every action bound, no modal dialogs, The same document editable as a map or an outline, A local application with file-based documents. - Implement milestone by milestone from `MILESTONES.md`; keep each change reviewable and leave the application runnable at every commit. - Treat authentication, payments, encryption, imports, webhooks and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a check pass. - Put every external service behind an interface with a deterministic fake for tests. - Add migrations and rollback or recovery notes for every persistent data change. - Log useful operational context without credentials, tokens, passwords or personal data. - Update documentation and run every check before completing a milestone. ## Known traps - Any modal dialog or mouse reach in the creation loop breaks the rhythm, and a mind map is used precisely when someone is thinking quickly, so a pause costs the idea rather than a second. Bind everything, edit in place, and time a realistic session rather than assuming. - Reflowing the whole map on every keystroke makes the canvas jump around while someone is typing, which is disorienting enough that they stop using automatic layout entirely. Animate the reflow, keep the focused node stationary, and move everything else around it. - Implementing the outline as a separate representation that syncs to the map produces two structures that drift, and the drift is discovered when one view is missing a branch. Render both from one tree, so there is nothing to synchronise. - Treating a cross-link as another parent edge makes the layout algorithm try to satisfy an impossible tree and produces a tangle, which is why many mind mappers refuse cross-links entirely. Keep them out of the layout computation and draw them as an overlay. - Exporting only as an image loses the structure entirely, and a mind map's value is usually that it becomes a document, an outline or a plan afterwards. Export the text structure first and treat the image as secondary. ===== MILESTONES.md ===== # Delivery milestones · MindNode Estimated effort: **multi-day** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · Typing a map without pausing Fifty nodes can be entered in a couple of minutes without a mouse. ### Steps 1. Bind creation and navigation to keys Sibling, child, parent, move. All single keystrokes. Files: `src/keys.ts` 2. Edit in place, never in a dialog A dialog is a pause and a pause costs the thought. Files: `src/editing.ts` 3. Make undo deep and structural Fast entry produces mistakes and they must be cheap. Files: `src/undo.ts` ### Done when - [ ] Fifty nodes are entered in a couple of minutes - [ ] Sibling, child and parent are single keystrokes - [ ] Editing is in place with no dialog - [ ] Undo covers twenty structural actions ### Watch out - Any modal dialog or mouse reach in the creation loop breaks the rhythm, and a mind map is used precisely when someone is thinking quickly, so a pause costs the idea rather than a second. Bind everything, edit in place, and time a realistic session rather than assuming. ## M2 · A layout that resolves itself A hundred nodes arrange without overlapping or crossing badly. ### Steps 1. Resolve collisions and balance subtrees Overlapping nodes at a hundred is where people abandon the layout. Files: `src/layout.ts`, `src/layout.test.ts` 2. Keep the focused node stationary A canvas jumping while you type is disorienting. Files: `src/reflow.ts` 3. Respect manual positions A deliberate placement should survive the next node. Files: `src/layout.ts` ### Done when - [ ] A hundred nodes lay out without overlaps - [ ] The focused node stays stationary on reflow - [ ] Manual positions are respected - [ ] Layout is imperceptible while typing ### Watch out - Reflowing the whole map on every keystroke makes the canvas jump around while someone is typing, which is disorienting enough that they stop using automatic layout entirely. Animate the reflow, keep the focused node stationary, and move everything else around it. ## M3 · The same document as an outline Switching between map and outline edits one structure, not two. ### Steps 1. Render both views from one tree Two representations drift and the drift loses a branch. Files: `src/outline.ts` 2. Share collapsed state A branch collapsed in one view should not reappear in the other. Files: `src/tree.ts` 3. Represent cross-links by convention They have no natural place in an outline and dropping them loses information. Files: `src/outline.ts` ### Done when - [ ] Edits in either view are immediately correct in both - [ ] Collapsed state is shared - [ ] Cross-links appear by a stated convention - [ ] Switching views keeps focus ### Watch out - Implementing the outline as a separate representation that syncs to the map produces two structures that drift, and the drift is discovered when one view is missing a branch. Render both from one tree, so there is nothing to synchronise. ## M4 · Links that are not the tree A connection between distant branches exists without breaking the layout. ### Steps 1. Exclude cross-links from layout Trying to satisfy them as tree edges produces a tangle. Files: `src/links.ts` 2. Draw them distinctly A reader must be able to tell structure from association. Files: `src/render.ts` 3. Handle endpoint deletion explicitly A stated rule rather than a dangling reference. Files: `src/links.ts` ### Done when - [ ] Cross-links do not affect layout - [ ] Twenty cross-links stay readable at a hundred nodes - [ ] Endpoint deletion follows a stated rule - [ ] Duplicate cross-links are flagged ### Watch out - Treating a cross-link as another parent edge makes the layout algorithm try to satisfy an impossible tree and produces a tangle, which is why many mind mappers refuse cross-links entirely. Keep them out of the layout computation and draw them as an overlay. ## M5 · Getting the thinking out (production only) A map becomes text, an image or something another tool can read. ### Steps 1. Export text structure first The map usually becomes a document. An image cannot. Files: `src/export.ts` 2. Round trip the outline in the suite Export, import, compare. It is the guarantee that matters. Files: `tests/roundtrip.test.ts` 3. Keep text as text in vector export So it is searchable and readable by assistive tools. Files: `src/export-svg.ts` ### Done when - [ ] The text outline round trips identically - [ ] Vector export preserves text as text - [ ] Interchange export opens in another tool - [ ] A thousand nodes export without memory exhaustion ### Watch out - Exporting only as an image loses the structure entirely, and a mind map's value is usually that it becomes a document, an outline or a plan afterwards. Export the text structure first and treat the image as secondary. ===== OPERATIONS.md ===== # Operations · MindNode ## Backup Maps are documents and belong with your ordinary document backups. Periodic outline exports are worth keeping as a format-independent copy, since a map that only opens in this application is a map with an expiry date. ## Restore Restore and confirm manual positions and collapsed state survived, since losing them leaves a map that reflows into an arrangement the author did not choose. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring For a local tool the measurement that matters is layout time under typing, which degrades as maps grow and turns a fluid tool into a stuttering one gradually enough that nobody reports it. ## Incident checklist A map that reflows into a tangle usually means cross-links have crept into the layout computation, which is reproducible on a saved document rather than needing a live session. 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified backup when needed. 5. Document the root cause, the remediation and the regression test. ## Release gate - [ ] Fifty nodes are confirmed to enter in a couple of minutes without a mouse - [ ] A hundred nodes are confirmed to lay out without overlaps - [ ] Both views are confirmed to render from one tree - [ ] Cross-links are confirmed excluded from layout - [ ] The text outline export is confirmed to round trip ## Launch constraint Do not market omitted MindNode capabilities as implemented. The non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered. ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Map files. A mind map is a document and should behave like one. DOCUMENTS_DIR=~/Documents/maps # Required. Radial or lateral. Both need collision resolution. LAYOUT_KIND=radial # Required. Long enough to follow, short enough not to feel slow while typing. REFLOW_ANIMATION_MS=180 # Required. Layout runs while typing. Beyond this it must degrade rather than stutter. LAYOUT_BUDGET_MS=16 # Required. Fast entry produces mistakes and they should all be cheap. UNDO_DEPTH=50 # Required. Where layout quality starts to degrade, made explicit rather than discovered. MAX_NODES_WARNING=1000
# MindNode · indie build A mind mapping tool where the value is thinking speed rather than diagramming: nodes are created and rearranged from the keyboard without pauses, the layout resolves itself without overlaps, and the same structure is editable as an outline when a tree is the wrong view. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Model | A tree with optional cross-links, kept separate | a mind map is a tree that occasionally is not, and conflating them ruins the layout | | Layout | Automatic radial or lateral placement with collision resolution | manual positioning at fifty nodes is the thing people give up on | | Input | Keyboard-first with every action bound, no modal dialogs | the tool competes with a sheet of paper on speed | | Duality | The same document editable as a map or an outline | an outline is faster for entering and a map is better for seeing | | Runtime | A local application with file-based documents | a mind map is a document and should behave like one | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the local application. - Get it: nodejs.org, or nvm install 22. - Verify: node --version prints v22 or higher - [ ] **A tree layout algorithm you understand** · free - Why: Collision resolution and subtree balancing are the difference between a usable map at a hundred nodes and an unusable one, and it is a solved problem worth reading rather than inventing. - Get it: Read a published tree drawing algorithm and implement it, or use a maintained library. - Verify: A hundred node tree lays out without overlaps - [ ] **A real map of at least a hundred nodes** · free - Why: Layout quality, reflow smoothness and export size are all uninteresting below fifty nodes and become the whole problem above a hundred. - Get it: Build one from real thinking rather than generating a balanced tree, since real maps are lopsided. - Verify: A hundred node lopsided map exists with several cross-links - [ ] **Your keyboard scheme, decided before building** · free - Why: Everything is keyboard bound and retrofitting a scheme after building the interface means rebuilding the interface. - Get it: Decide the bindings for creation, navigation, collapsing and view switching before writing phase one. - Verify: A written scheme covers every planned action ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Real-time collaboration. - Presentation and walkthrough modes. - Task management with dates and dependencies. - Automatic map generation from a document. - high-fidelity import and export - presentation and enterprise controls - multiplayer cursors and comments - large template libraries If one of those is essential to you, that is the reason to keep paying for MindNode, and the README should say so rather than pretend.
# Build brief · MindNode The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a mind map you build entirely from the keyboard, that lays itself out to replace MindNode. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Model: A tree with optional cross-links, kept separate · a mind map is a tree that occasionally is not, and conflating them ruins the layout - Layout: Automatic radial or lateral placement with collision resolution · manual positioning at fifty nodes is the thing people give up on - Input: Keyboard-first with every action bound, no modal dialogs · the tool competes with a sheet of paper on speed - Duality: The same document editable as a map or an outline · an outline is faster for entering and a map is better for seeing - Runtime: A local application with file-based documents · a mind map is a document and should behave like one ### Data model (create this before Phase 1) - documents(id, title, layout_kind, theme, updated_at) - nodes(id, document_id, parent_id, ordinal, text, note, collapsed, style_json, manual_position) - links(from_node_id, to_node_id, label) · cross-links outside the tree, drawn differently - layout_cache(document_id, computed_at, positions_json) · derived, discarded when the tree changes - focus_state(document_id, node_id, at) · so reopening returns you where you were thinking - attachments(node_id, kind, ref) · images and file references, bounded - A node records whether its position was set manually, so automatic layout never discards a placement someone made deliberately. ### Phase 1 · Typing a map without pausing Build: Keyboard creation of siblings and children, navigation between nodes, and editing in place with no modal dialogs. Measure how long fifty nodes take. Undo covering the last many actions. Trap: Any modal dialog or mouse reach in the creation loop breaks the rhythm, and a mind map is used precisely when someone is thinking quickly, so a pause costs the idea rather than a second. Bind everything, edit in place, and time a realistic session rather than assuming. Done when: Fifty nodes are entered in a couple of minutes without touching a mouse, timed by hand. Creating a sibling, a child and a parent are all single keystrokes. Editing happens in place with no dialog. Undo covers at least the last twenty actions including structural changes. Do not build yet: No layout, outline view, links or export. ### Phase 2 · A layout that resolves itself Build: Automatic placement with collision resolution and balanced subtree distribution. Reflow smoothly when a node is added rather than jumping. Respect a node whose position was set manually. Trap: Reflowing the whole map on every keystroke makes the canvas jump around while someone is typing, which is disorienting enough that they stop using automatic layout entirely. Animate the reflow, keep the focused node stationary, and move everything else around it. Done when: A hundred nodes lay out without overlaps and with readable connector paths. Adding a node keeps the focused node stationary and moves the rest around it. A manually positioned node is not moved by automatic layout. Layout completes fast enough to be imperceptible while typing. Do not build yet: No outline view, links or export yet. ### Phase 3 · The same document as an outline Build: An outline view over the same tree with the same keyboard model, where edits in either view are the same edits. Handle collapsing consistently across views and a cross-link that has no place in an outline. Trap: Implementing the outline as a separate representation that syncs to the map produces two structures that drift, and the drift is discovered when one view is missing a branch. Render both from one tree, so there is nothing to synchronise. Done when: Both views render from one tree and an edit in either is immediately correct in the other, verified by editing in each. Collapsed state is shared and consistent. A cross-link is represented in the outline by a stated convention rather than dropped. Switching views keeps the focused node. Do not build yet: No links, tasks or export yet. ### Phase 4 · Links that are not the tree Build: Cross-links between arbitrary nodes, drawn distinctly from tree edges and excluded from layout balancing. Detect a cross-link that duplicates a tree relationship. Handle a link whose endpoint is deleted. Trap: Treating a cross-link as another parent edge makes the layout algorithm try to satisfy an impossible tree and produces a tangle, which is why many mind mappers refuse cross-links entirely. Keep them out of the layout computation and draw them as an overlay. Done when: Cross-links draw distinctly and do not participate in layout balancing. A hundred node map with twenty cross-links remains readable. Deleting a node removes or orphans its links by a stated rule rather than leaving dangling references. A cross-link duplicating a tree edge is flagged. Do not build yet: No tasks or export yet. ### Phase 5 · Getting the thinking out Build: Export to an indented text outline, a vector image with text preserved, and an open interchange format. Verify the outline round trips back into the same tree. Handle a very large map without exhausting memory. Trap: Exporting only as an image loses the structure entirely, and a mind map's value is usually that it becomes a document, an outline or a plan afterwards. Export the text structure first and treat the image as secondary. Done when: An indented text export round trips back into an identical tree, asserted in the suite. Vector export preserves text as text rather than outlines. An open interchange format export opens in another mind mapping tool. A map of a thousand nodes exports without exhausting memory. Do not build yet: Nothing after this. ### Out of scope (and why) - Real-time collaboration, which is a synchronisation problem and changes how quickly a single person can think. - Presentation modes and animated walkthroughs, which is a different product wearing the same interface. - Task management with dates and dependencies, which turns a thinking tool into a planning one. - Automatic map generation from a document, which produces a structure nobody recognises as their own thinking. ### README must contain - That everything is keyboard bound and there are no modal dialogs, because a pause costs the thought - That the focused node stays stationary during reflow, since a jumping canvas is disorienting - That both the map and the outline render from one tree rather than syncing two - That cross-links are excluded from layout, because treating them as tree edges produces a tangle - That the text outline export round trips, since a map usually becomes a document
# Agent instructions · MindNode indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A tree with optional cross-links, kept separate, Automatic radial or lateral placement with collision resolution, Keyboard-first with every action bound, no modal dialogs, The same document editable as a map or an outline, A local application with file-based documents. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - Any modal dialog or mouse reach in the creation loop breaks the rhythm, and a mind map is used precisely when someone is thinking quickly, so a pause costs the idea rather than a second. Bind everything, edit in place, and time a realistic session rather than assuming. - Reflowing the whole map on every keystroke makes the canvas jump around while someone is typing, which is disorienting enough that they stop using automatic layout entirely. Animate the reflow, keep the focused node stationary, and move everything else around it. - Implementing the outline as a separate representation that syncs to the map produces two structures that drift, and the drift is discovered when one view is missing a branch. Render both from one tree, so there is nothing to synchronise. - Treating a cross-link as another parent edge makes the layout algorithm try to satisfy an impossible tree and produces a tangle, which is why many mind mappers refuse cross-links entirely. Keep them out of the layout computation and draw them as an overlay.
# Build plan · MindNode A mind mapping tool where the value is thinking speed rather than diagramming: nodes are created and rearranged from the keyboard without pauses, the layout resolves itself without overlaps, and the same structure is editable as an outline when a tree is the wrong view. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · Typing a map without pausing Fifty nodes can be entered in a couple of minutes without a mouse. ### Steps 1. Bind creation and navigation to keys Sibling, child, parent, move. All single keystrokes. Files: `src/keys.ts` 2. Edit in place, never in a dialog A dialog is a pause and a pause costs the thought. Files: `src/editing.ts` 3. Make undo deep and structural Fast entry produces mistakes and they must be cheap. Files: `src/undo.ts` ### Done when - [ ] Fifty nodes are entered in a couple of minutes - [ ] Sibling, child and parent are single keystrokes - [ ] Editing is in place with no dialog - [ ] Undo covers twenty structural actions ### Watch out - Any modal dialog or mouse reach in the creation loop breaks the rhythm, and a mind map is used precisely when someone is thinking quickly, so a pause costs the idea rather than a second. Bind everything, edit in place, and time a realistic session rather than assuming. ## Phase 2 · A layout that resolves itself A hundred nodes arrange without overlapping or crossing badly. ### Steps 1. Resolve collisions and balance subtrees Overlapping nodes at a hundred is where people abandon the layout. Files: `src/layout.ts`, `src/layout.test.ts` 2. Keep the focused node stationary A canvas jumping while you type is disorienting. Files: `src/reflow.ts` 3. Respect manual positions A deliberate placement should survive the next node. Files: `src/layout.ts` ### Done when - [ ] A hundred nodes lay out without overlaps - [ ] The focused node stays stationary on reflow - [ ] Manual positions are respected - [ ] Layout is imperceptible while typing ### Watch out - Reflowing the whole map on every keystroke makes the canvas jump around while someone is typing, which is disorienting enough that they stop using automatic layout entirely. Animate the reflow, keep the focused node stationary, and move everything else around it. ## Phase 3 · The same document as an outline Switching between map and outline edits one structure, not two. ### Steps 1. Render both views from one tree Two representations drift and the drift loses a branch. Files: `src/outline.ts` 2. Share collapsed state A branch collapsed in one view should not reappear in the other. Files: `src/tree.ts` 3. Represent cross-links by convention They have no natural place in an outline and dropping them loses information. Files: `src/outline.ts` ### Done when - [ ] Edits in either view are immediately correct in both - [ ] Collapsed state is shared - [ ] Cross-links appear by a stated convention - [ ] Switching views keeps focus ### Watch out - Implementing the outline as a separate representation that syncs to the map produces two structures that drift, and the drift is discovered when one view is missing a branch. Render both from one tree, so there is nothing to synchronise. ## Phase 4 · Links that are not the tree A connection between distant branches exists without breaking the layout. ### Steps 1. Exclude cross-links from layout Trying to satisfy them as tree edges produces a tangle. Files: `src/links.ts` 2. Draw them distinctly A reader must be able to tell structure from association. Files: `src/render.ts` 3. Handle endpoint deletion explicitly A stated rule rather than a dangling reference. Files: `src/links.ts` ### Done when - [ ] Cross-links do not affect layout - [ ] Twenty cross-links stay readable at a hundred nodes - [ ] Endpoint deletion follows a stated rule - [ ] Duplicate cross-links are flagged ### Watch out - Treating a cross-link as another parent edge makes the layout algorithm try to satisfy an impossible tree and produces a tangle, which is why many mind mappers refuse cross-links entirely. Keep them out of the layout computation and draw them as an overlay. ## Not in this build - Real-time collaboration. - Presentation and walkthrough modes. - Task management with dates and dependencies. - Automatic map generation from a document. ## After v1, if you want it - Focus mode showing one subtree, which is how large maps stay usable - Node styling driven by depth or tag rather than set by hand - Merging two maps, which is harder than it sounds once cross-links exist
# Copy to .env and fill in. Never commit .env; this file documents it. # Required. Map files. A mind map is a document and should behave like one. DOCUMENTS_DIR=~/Documents/maps # Required. Radial or lateral. Both need collision resolution. LAYOUT_KIND=radial # Required. Long enough to follow, short enough not to feel slow while typing. REFLOW_ANIMATION_MS=180 # Required. Layout runs while typing. Beyond this it must degrade rather than stutter. LAYOUT_BUDGET_MS=16 # Required. Fast entry produces mistakes and they should all be cheap. UNDO_DEPTH=50 # Required. Where layout quality starts to degrade, made explicit rather than discovered. MAX_NODES_WARNING=1000
# MindNode · product brief ## Problem The visible mind mapping loop is buildable, but a credible replacement needs more than the first screen. MindNode earns its keep through interaction polish, collaboration, so expect a weekend or multi-day build and a narrower personal scope. ## Product outcome A mind map you can fill as fast as you think, that arranges itself without overlaps, and that leaves as an outline you can keep working in. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - Node.js 22 - modern browser - no account required ## Explicit non-goals for v1 - Real-time collaboration. - Presentation and walkthrough modes. - Task management with dates and dependencies. - Automatic map generation from a document. - high-fidelity import and export - presentation and enterprise controls - multiplayer cursors and comments - large template libraries ## Success criteria - Fifty nodes are confirmed to enter in a couple of minutes without a mouse - A hundred nodes are confirmed to lay out without overlaps - Both views are confirmed to render from one tree - Cross-links are confirmed excluded from layout - The text outline export is confirmed to round trip
# Build brief · MindNode The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a mind map you build entirely from the keyboard, that lays itself out to replace MindNode. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Model: A tree with optional cross-links, kept separate · a mind map is a tree that occasionally is not, and conflating them ruins the layout - Layout: Automatic radial or lateral placement with collision resolution · manual positioning at fifty nodes is the thing people give up on - Input: Keyboard-first with every action bound, no modal dialogs · the tool competes with a sheet of paper on speed - Duality: The same document editable as a map or an outline · an outline is faster for entering and a map is better for seeing - Runtime: A local application with file-based documents · a mind map is a document and should behave like one ### Data model (create this before Phase 1) - documents(id, title, layout_kind, theme, updated_at) - nodes(id, document_id, parent_id, ordinal, text, note, collapsed, style_json, manual_position) - links(from_node_id, to_node_id, label) · cross-links outside the tree, drawn differently - layout_cache(document_id, computed_at, positions_json) · derived, discarded when the tree changes - focus_state(document_id, node_id, at) · so reopening returns you where you were thinking - attachments(node_id, kind, ref) · images and file references, bounded - A node records whether its position was set manually, so automatic layout never discards a placement someone made deliberately. ### Phase 1 · Typing a map without pausing Build: Keyboard creation of siblings and children, navigation between nodes, and editing in place with no modal dialogs. Measure how long fifty nodes take. Undo covering the last many actions. Trap: Any modal dialog or mouse reach in the creation loop breaks the rhythm, and a mind map is used precisely when someone is thinking quickly, so a pause costs the idea rather than a second. Bind everything, edit in place, and time a realistic session rather than assuming. Done when: Fifty nodes are entered in a couple of minutes without touching a mouse, timed by hand. Creating a sibling, a child and a parent are all single keystrokes. Editing happens in place with no dialog. Undo covers at least the last twenty actions including structural changes. Do not build yet: No layout, outline view, links or export. ### Phase 2 · A layout that resolves itself Build: Automatic placement with collision resolution and balanced subtree distribution. Reflow smoothly when a node is added rather than jumping. Respect a node whose position was set manually. Trap: Reflowing the whole map on every keystroke makes the canvas jump around while someone is typing, which is disorienting enough that they stop using automatic layout entirely. Animate the reflow, keep the focused node stationary, and move everything else around it. Done when: A hundred nodes lay out without overlaps and with readable connector paths. Adding a node keeps the focused node stationary and moves the rest around it. A manually positioned node is not moved by automatic layout. Layout completes fast enough to be imperceptible while typing. Do not build yet: No outline view, links or export yet. ### Phase 3 · The same document as an outline Build: An outline view over the same tree with the same keyboard model, where edits in either view are the same edits. Handle collapsing consistently across views and a cross-link that has no place in an outline. Trap: Implementing the outline as a separate representation that syncs to the map produces two structures that drift, and the drift is discovered when one view is missing a branch. Render both from one tree, so there is nothing to synchronise. Done when: Both views render from one tree and an edit in either is immediately correct in the other, verified by editing in each. Collapsed state is shared and consistent. A cross-link is represented in the outline by a stated convention rather than dropped. Switching views keeps the focused node. Do not build yet: No links, tasks or export yet. ### Phase 4 · Links that are not the tree Build: Cross-links between arbitrary nodes, drawn distinctly from tree edges and excluded from layout balancing. Detect a cross-link that duplicates a tree relationship. Handle a link whose endpoint is deleted. Trap: Treating a cross-link as another parent edge makes the layout algorithm try to satisfy an impossible tree and produces a tangle, which is why many mind mappers refuse cross-links entirely. Keep them out of the layout computation and draw them as an overlay. Done when: Cross-links draw distinctly and do not participate in layout balancing. A hundred node map with twenty cross-links remains readable. Deleting a node removes or orphans its links by a stated rule rather than leaving dangling references. A cross-link duplicating a tree edge is flagged. Do not build yet: No tasks or export yet. ### Phase 5 · Getting the thinking out Build: Export to an indented text outline, a vector image with text preserved, and an open interchange format. Verify the outline round trips back into the same tree. Handle a very large map without exhausting memory. Trap: Exporting only as an image loses the structure entirely, and a mind map's value is usually that it becomes a document, an outline or a plan afterwards. Export the text structure first and treat the image as secondary. Done when: An indented text export round trips back into an identical tree, asserted in the suite. Vector export preserves text as text rather than outlines. An open interchange format export opens in another mind mapping tool. A map of a thousand nodes exports without exhausting memory. Do not build yet: Nothing after this. ### Out of scope (and why) - Real-time collaboration, which is a synchronisation problem and changes how quickly a single person can think. - Presentation modes and animated walkthroughs, which is a different product wearing the same interface. - Task management with dates and dependencies, which turns a thinking tool into a planning one. - Automatic map generation from a document, which produces a structure nobody recognises as their own thinking. ### README must contain - That everything is keyboard bound and there are no modal dialogs, because a pause costs the thought - That the focused node stays stationary during reflow, since a jumping canvas is disorienting - That both the map and the outline render from one tree rather than syncing two - That cross-links are excluded from layout, because treating them as tree edges produces a tangle - That the text outline export round trips, since a map usually becomes a document
# Architecture · MindNode ## Stack | Part | Choice | Why | | --- | --- | --- | | Model | A tree with optional cross-links, kept separate | a mind map is a tree that occasionally is not, and conflating them ruins the layout | | Layout | Automatic radial or lateral placement with collision resolution | manual positioning at fifty nodes is the thing people give up on | | Input | Keyboard-first with every action bound, no modal dialogs | the tool competes with a sheet of paper on speed | | Duality | The same document editable as a map or an outline | an outline is faster for entering and a map is better for seeing | | Runtime | A local application with file-based documents | a mind map is a document and should behave like one | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Input | Keyboard-bound creation and navigation. | Any interface, provided nothing in the creation loop requires a mouse. | | Layout | Automatic placement with collision resolution. | Any algorithm, provided the focused node stays stationary. | | Duality | Map and outline from one tree. | Not swappable for two representations, which drift and lose branches. | | Links | Cross-links outside the layout. | Any implementation, provided they never participate in layout balancing. | | Export | Text structure with a tested round trip. | Any format, provided text export precedes image export. | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `DOCUMENTS_DIR` · required · Map files. A mind map is a document and should behave like one. - `LAYOUT_KIND` · required · Radial or lateral. Both need collision resolution. - `REFLOW_ANIMATION_MS` · required · Long enough to follow, short enough not to feel slow while typing. - `LAYOUT_BUDGET_MS` · required · Layout runs while typing. Beyond this it must degrade rather than stutter. - `UNDO_DEPTH` · required · Fast entry produces mistakes and they should all be cheap. - `MAX_NODES_WARNING` · required · Where layout quality starts to degrade, made explicit rather than discovered. ## Production baseline - Security: least privilege, input validation at every boundary, secret redaction in logs, rate limits on abuse-prone paths, no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore procedures that have been exercised. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, timeouts. - Observability: structured logs with request or operation ids, an error-tracking hook, and health and readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, one end-to-end test of the critical path. ## Decision records For each dependency in the stack table, keep a short note: why it was chosen, its failure mode, and how it is replaced. Do not add infrastructure until a requirement in `PRODUCT.md` justifies it.
# Agent instructions · MindNode product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: A tree with optional cross-links, kept separate, Automatic radial or lateral placement with collision resolution, Keyboard-first with every action bound, no modal dialogs, The same document editable as a map or an outline, A local application with file-based documents. - Implement milestone by milestone from `MILESTONES.md`; keep each change reviewable and leave the application runnable at every commit. - Treat authentication, payments, encryption, imports, webhooks and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a check pass. - Put every external service behind an interface with a deterministic fake for tests. - Add migrations and rollback or recovery notes for every persistent data change. - Log useful operational context without credentials, tokens, passwords or personal data. - Update documentation and run every check before completing a milestone. ## Known traps - Any modal dialog or mouse reach in the creation loop breaks the rhythm, and a mind map is used precisely when someone is thinking quickly, so a pause costs the idea rather than a second. Bind everything, edit in place, and time a realistic session rather than assuming. - Reflowing the whole map on every keystroke makes the canvas jump around while someone is typing, which is disorienting enough that they stop using automatic layout entirely. Animate the reflow, keep the focused node stationary, and move everything else around it. - Implementing the outline as a separate representation that syncs to the map produces two structures that drift, and the drift is discovered when one view is missing a branch. Render both from one tree, so there is nothing to synchronise. - Treating a cross-link as another parent edge makes the layout algorithm try to satisfy an impossible tree and produces a tangle, which is why many mind mappers refuse cross-links entirely. Keep them out of the layout computation and draw them as an overlay. - Exporting only as an image loses the structure entirely, and a mind map's value is usually that it becomes a document, an outline or a plan afterwards. Export the text structure first and treat the image as secondary.
# Delivery milestones · MindNode Estimated effort: **multi-day** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · Typing a map without pausing Fifty nodes can be entered in a couple of minutes without a mouse. ### Steps 1. Bind creation and navigation to keys Sibling, child, parent, move. All single keystrokes. Files: `src/keys.ts` 2. Edit in place, never in a dialog A dialog is a pause and a pause costs the thought. Files: `src/editing.ts` 3. Make undo deep and structural Fast entry produces mistakes and they must be cheap. Files: `src/undo.ts` ### Done when - [ ] Fifty nodes are entered in a couple of minutes - [ ] Sibling, child and parent are single keystrokes - [ ] Editing is in place with no dialog - [ ] Undo covers twenty structural actions ### Watch out - Any modal dialog or mouse reach in the creation loop breaks the rhythm, and a mind map is used precisely when someone is thinking quickly, so a pause costs the idea rather than a second. Bind everything, edit in place, and time a realistic session rather than assuming. ## M2 · A layout that resolves itself A hundred nodes arrange without overlapping or crossing badly. ### Steps 1. Resolve collisions and balance subtrees Overlapping nodes at a hundred is where people abandon the layout. Files: `src/layout.ts`, `src/layout.test.ts` 2. Keep the focused node stationary A canvas jumping while you type is disorienting. Files: `src/reflow.ts` 3. Respect manual positions A deliberate placement should survive the next node. Files: `src/layout.ts` ### Done when - [ ] A hundred nodes lay out without overlaps - [ ] The focused node stays stationary on reflow - [ ] Manual positions are respected - [ ] Layout is imperceptible while typing ### Watch out - Reflowing the whole map on every keystroke makes the canvas jump around while someone is typing, which is disorienting enough that they stop using automatic layout entirely. Animate the reflow, keep the focused node stationary, and move everything else around it. ## M3 · The same document as an outline Switching between map and outline edits one structure, not two. ### Steps 1. Render both views from one tree Two representations drift and the drift loses a branch. Files: `src/outline.ts` 2. Share collapsed state A branch collapsed in one view should not reappear in the other. Files: `src/tree.ts` 3. Represent cross-links by convention They have no natural place in an outline and dropping them loses information. Files: `src/outline.ts` ### Done when - [ ] Edits in either view are immediately correct in both - [ ] Collapsed state is shared - [ ] Cross-links appear by a stated convention - [ ] Switching views keeps focus ### Watch out - Implementing the outline as a separate representation that syncs to the map produces two structures that drift, and the drift is discovered when one view is missing a branch. Render both from one tree, so there is nothing to synchronise. ## M4 · Links that are not the tree A connection between distant branches exists without breaking the layout. ### Steps 1. Exclude cross-links from layout Trying to satisfy them as tree edges produces a tangle. Files: `src/links.ts` 2. Draw them distinctly A reader must be able to tell structure from association. Files: `src/render.ts` 3. Handle endpoint deletion explicitly A stated rule rather than a dangling reference. Files: `src/links.ts` ### Done when - [ ] Cross-links do not affect layout - [ ] Twenty cross-links stay readable at a hundred nodes - [ ] Endpoint deletion follows a stated rule - [ ] Duplicate cross-links are flagged ### Watch out - Treating a cross-link as another parent edge makes the layout algorithm try to satisfy an impossible tree and produces a tangle, which is why many mind mappers refuse cross-links entirely. Keep them out of the layout computation and draw them as an overlay. ## M5 · Getting the thinking out (production only) A map becomes text, an image or something another tool can read. ### Steps 1. Export text structure first The map usually becomes a document. An image cannot. Files: `src/export.ts` 2. Round trip the outline in the suite Export, import, compare. It is the guarantee that matters. Files: `tests/roundtrip.test.ts` 3. Keep text as text in vector export So it is searchable and readable by assistive tools. Files: `src/export-svg.ts` ### Done when - [ ] The text outline round trips identically - [ ] Vector export preserves text as text - [ ] Interchange export opens in another tool - [ ] A thousand nodes export without memory exhaustion ### Watch out - Exporting only as an image loses the structure entirely, and a mind map's value is usually that it becomes a document, an outline or a plan afterwards. Export the text structure first and treat the image as secondary.
# Operations · MindNode ## Backup Maps are documents and belong with your ordinary document backups. Periodic outline exports are worth keeping as a format-independent copy, since a map that only opens in this application is a map with an expiry date. ## Restore Restore and confirm manual positions and collapsed state survived, since losing them leaves a map that reflows into an arrangement the author did not choose. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring For a local tool the measurement that matters is layout time under typing, which degrades as maps grow and turns a fluid tool into a stuttering one gradually enough that nobody reports it. ## Incident checklist A map that reflows into a tangle usually means cross-links have crept into the layout computation, which is reproducible on a saved document rather than needing a live session. 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified backup when needed. 5. Document the root cause, the remediation and the regression test. ## Release gate - [ ] Fifty nodes are confirmed to enter in a couple of minutes without a mouse - [ ] A hundred nodes are confirmed to lay out without overlaps - [ ] Both views are confirmed to render from one tree - [ ] Cross-links are confirmed excluded from layout - [ ] The text outline export is confirmed to round trip ## Launch constraint Do not market omitted MindNode capabilities as implemented. The non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered.
# Copy to .env and fill in. Never commit .env; this file documents it. # Required. Map files. A mind map is a document and should behave like one. DOCUMENTS_DIR=~/Documents/maps # Required. Radial or lateral. Both need collision resolution. LAYOUT_KIND=radial # Required. Long enough to follow, short enough not to feel slow while typing. REFLOW_ANIMATION_MS=180 # Required. Layout runs while typing. Beyond this it must degrade rather than stutter. LAYOUT_BUDGET_MS=16 # Required. Fast entry produces mistakes and they should all be cheap. UNDO_DEPTH=50 # Required. Where layout quality starts to degrade, made explicit rather than discovered. MAX_NODES_WARNING=1000
$ choose a build depth, inspect the files, then open the complete pack in your agent
MindNode: The shapes are easy; customers pay for low-friction editing, reliable exports, collaboration, and a canvas that never fights them.
xhigh-fidelity import and export
xpresentation and enterprise controls
xmultiplayer cursors and comments
xlarge template libraries
Don't feel like building it? These folks already made it free.
no votes, no pay-to-list · just what's real
MindNode pricing
| plan | monthly | annual (per mo) | what you get |
|---|---|---|---|
| mindnode free | $0/user | $0/user | No published document cap; create/edit documents, basic mind mapping, import/export, iCloud sync and joining shared documents |
| mindnode plus | $2.99/user | $2.08/user | No published document cap; adds outlining, AI/Apple Intelligence, notes, tasks, tags, themes, collaboration and Apple Watch |
free tierNo published document/map cap; basic mind mapping, editing, import/export, iCloud sync and shared-document participation
billingmonthly $2.99 or annual $24.99 (equivalent to $2.08/month)
hidden costsApp Store pricing/tax can vary by storefront. Setapp is a separate bundle subscription. The trial converts automatically unless canceled before it ends.
verified 2026-08-12 · source ↗
Vibecode MindNode
Kinda. The core of MindNode is buildable in a weekend with the prompt on this page, but there are real gaps: high-fidelity import and export, presentation and enterprise controls. Read the honest list above before committing.
How much does MindNode cost?
MindNode's pricing is usage-based or varies by plan · The official pricing URL is recorded, but a stable current amount was not safely recoverable in this pass. Do not publish a number until rechecked..
What do I lose by replacing MindNode?
Honestly: high-fidelity import and export; presentation and enterprise controls; multiplayer cursors and comments; large template libraries. If any of those are load-bearing for you, keep paying.
Is there an open-source alternative to MindNode?
Yes: Freeplane (Deep local mind mapping, outlining, attributes, filters, and scripting; powerful in the way software with several decades of menus tends to be.) AFFiNE (Mind maps, outlines, tasks, tags, and presentation frames in one app; less Apple-native polish, much less Apple-only lock-in.) The prompt is for when you want it exactly your way.