# miniMindMap — JSON Format Reference for AI Models

This document describes the JSON format used by the miniMindMap application. Use it to generate mind map files that users can import directly via the homepage upload form.

---

## Top-level structure

```json
{
  "title": "My Mind Map",
  "nodes": [ ...node objects... ],
  "edges": [ ...edge objects... ]
}
```

| Field | Type | Required | Notes |
|-------|------|----------|-------|
| `title` | string | yes | Map name, max 100 characters |
| `nodes` | array | yes | At least one node required |
| `edges` | array | yes | Can be empty `[]` |

---

## Node object

```json
{
  "data": {
    "id": "node1",
    "label": "Main topic",
    "note": "Optional secondary text shown below label",
    "color": "#00d4aa"
  },
  "position": {
    "x": 80,
    "y": 0
  }
}
```

### Node `data` fields

| Field | Type | Required | Limits | Notes |
|-------|------|----------|--------|-------|
| `id` | string | yes | unique within file | Identifier used to reference the node in edges. No spaces. Use `root` for the root node. |
| `label` | string | yes | max 200 chars | Main text displayed in the bubble. Supports line wrapping. |
| `note` | string | no | max 500 chars | Secondary text shown below the label in smaller font, separated by `· · ·`. Leave as `""` or omit if unused. |
| `color` | string | no | `#rrggbb` hex only | Border color of the bubble. Background is derived automatically as a darkened variant. Defaults to `#00d4aa` (teal). |

### Node `position` fields

| Field | Type | Notes |
|-------|------|-------|
| `x` | number | Horizontal position in canvas units. Left = smaller values. |
| `y` | number | Vertical position in canvas units. Top = smaller (or negative) values. |

Positions are optional — if omitted or set to `0,0`, the user can use the **Auto layout** button in the app to arrange the map automatically. When providing positions manually, use the layout grid below.

---

## Edge object

```json
{
  "data": {
    "id": "e1",
    "source": "node1",
    "target": "node2",
    "note": "Optional label along the arrow",
    "dashed": false
  }
}
```

### Edge `data` fields

| Field | Type | Required | Limits | Notes |
|-------|------|----------|--------|-------|
| `id` | string | yes | unique within file | Any unique string, e.g. `"e1"`, `"e_topic_sub"`. |
| `source` | string | yes | must match a node `id` | The node the arrow starts from. |
| `target` | string | yes | must match a node `id` | The node the arrow points to. |
| `note` | string | no | max 100 chars | Text label rendered along the edge. Leave as `""` or omit if unused. |
| `dashed` | boolean | no | `true` / `false` | When `true`, the edge is drawn as a dashed line. Use for weaker or secondary relationships. Defaults to `false`. |

Edges are **directional** (source → target) but the graph supports **any topology** — not just trees. You can connect any node to any other node, create cycles, or have a node with multiple parents.

---

## Recommended layout coordinates

When generating positions manually, use this grid to produce a clean horizontal left-to-right layout:

| Level | x value | Description |
|-------|---------|-------------|
| 0 (root) | `80` | Single root node |
| 1 | `260` | Direct children of root |
| 2 | `440` | Grandchildren |
| 3 | `620` | Third level |
| n | `80 + n × 180` | General formula |

For vertical spacing between siblings at the same level, use **54 units** between nodes. Center the group vertically around `y = 0`.

**Example for 3 siblings at level 1:**
```
y = -54   (first sibling)
y =   0   (second sibling)
y =  54   (third sibling)
```

**Example for 4 siblings at level 1:**
```
y = -81   (first)
y = -27   (second)
y =  27   (third)
y =  81   (fourth)
```

General formula for `n` siblings, sibling index `i` (0-based):
```
y = i × 54 − (n − 1) × 27
```

---

## Color palette suggestions

Use hex colors only (`#rrggbb`). The app automatically darkens the color for the node background so the label remains readable. Recommended colors:

| Purpose | Color | Hex |
|---------|-------|-----|
| Root / primary | Teal | `#00d4aa` |
| Category A | Blue | `#0087ff` |
| Category B | Purple | `#7c5cbf` |
| Category C | Orange | `#e07b39` |
| Warning / risk | Red | `#ff4d6a` |
| Neutral | Grey-blue | `#4a5568` |
| Positive | Green | `#38a169` |

---

## Validation rules (enforced on import)

- `id` values must be non-empty strings, unique across all nodes.
- `source` and `target` in edges must reference existing node `id` values.
- `color` must match `#rrggbb` exactly (6-digit lowercase or uppercase hex). Invalid values are silently replaced with `#00d4aa`.
- `label` is truncated to 200 characters, `note` to 500, edge `note` to 100.
- `title` is truncated to 100 characters.
- The import is subject to the same rate limit as creating a new map (10 maps per hour per IP).

---

## Minimal valid example

```json
{
  "title": "Project Overview",
  "nodes": [
    {
      "data": { "id": "root", "label": "Project Overview", "color": "#00d4aa" },
      "position": { "x": 80, "y": 0 }
    }
  ],
  "edges": []
}
```

---

## Full example — 3-level mind map

```json
{
  "title": "Learning Plan",
  "nodes": [
    {
      "data": { "id": "root", "label": "Learning Plan", "color": "#00d4aa" },
      "position": { "x": 80, "y": 0 }
    },
    {
      "data": { "id": "theory", "label": "Theory", "color": "#0087ff" },
      "position": { "x": 260, "y": -54 }
    },
    {
      "data": { "id": "practice", "label": "Practice", "color": "#0087ff" },
      "position": { "x": 260, "y": 54 }
    },
    {
      "data": { "id": "books", "label": "Books", "note": "Read at least 2 per month", "color": "#4a5568" },
      "position": { "x": 440, "y": -108 }
    },
    {
      "data": { "id": "videos", "label": "Video courses", "color": "#4a5568" },
      "position": { "x": 440, "y": -54 }
    },
    {
      "data": { "id": "projects", "label": "Side projects", "note": "1 project per topic", "color": "#4a5568" },
      "position": { "x": 440, "y": 54 }
    },
    {
      "data": { "id": "review", "label": "Weekly review", "color": "#4a5568" },
      "position": { "x": 440, "y": 108 }
    }
  ],
  "edges": [
    { "data": { "id": "e1", "source": "root",     "target": "theory"   } },
    { "data": { "id": "e2", "source": "root",     "target": "practice" } },
    { "data": { "id": "e3", "source": "theory",   "target": "books"    } },
    { "data": { "id": "e4", "source": "theory",   "target": "videos"   } },
    { "data": { "id": "e5", "source": "practice", "target": "projects" } },
    { "data": { "id": "e6", "source": "practice", "target": "review"   } },
    {
      "data": {
        "id": "e7",
        "source": "books",
        "target": "projects",
        "note": "apply theory",
        "dashed": true
      }
    }
  ]
}
```

---

## Instructions for AI models generating mind maps

1. **Always include a root node** with `"id": "root"`. This is the central topic.
2. **Use descriptive, concise labels** — bubbles have limited width; prefer 1–5 words per label.
3. **Use `note` for elaboration**, not for longer labels. Notes appear smaller below the label.
4. **Assign colors by category** — give all nodes of the same branch/theme the same color to make the map visually scannable.
5. **Use `dashed: true` for cross-links** between branches (non-tree connections) to visually distinguish them from the primary hierarchy.
6. **Place the root at `x: 80, y: 0`** and expand to the right using `x += 180` per level.
7. **If unsure about positions**, set all positions to `{ "x": 0, "y": 0 }` — the user can click Auto layout in the app.
8. **Keep the graph connected** — every node should be reachable from root via edges.
9. **Edge `id` values** must be unique. A simple convention: `"e1"`, `"e2"`, ... or `"e_<source>_<target>"`.
10. **Do not include extra fields** — any field outside `data` and `position` is ignored.
