Make a relationship chart with ChatGPT or Claude

Any AI chat can draft a RelationMap chart. Ask it for the chart as JSON in RelationMap’s format, then open that JSON in the editor. From there you can move people around, fix relationships and add pictures, then save, share, embed or export the chart.

Drafting with your own AI and opening the result is free. RelationMap Pro has an AI assistant inside the editor, but you don’t need it for this.

1. Copy this prompt

Replace [STORY] with the book, show, game or group of people you want, then send it to ChatGPT, Claude, Gemini or any other AI chat.

Make a character relationship chart of [STORY] for RelationMap (relationmap.io).
Answer with one JSON code block in exactly this format:

{
  "meta": { "title": "[STORY] characters", "version": "1.2" },
  "nodes": [
    { "id": "n1", "name": "Full name", "subtitle": "Role in a few words", "groups": ["g1"] },
    { "id": "n2", "name": "Full name", "subtitle": "Role in a few words", "groups": ["g1"] }
  ],
  "edges": [
    { "id": "e1", "source": "n1", "target": "n2", "label": "mentor" }
  ],
  "groups": [
    { "id": "g1", "name": "Family or faction", "color": "#42A5F5" }
  ]
}

Rules:
- Pick the 10 to 40 most important characters. Every node needs a unique "id" and a "name".
- "source" and "target" are node ids, never names. An edge reads "source is target's label".
- Keep labels short. Use these words where they fit, so the lines get colored:
  love, lover, crush, wife, husband (romance); enemy, hates, betrays, kills, nemesis (hostility);
  father, mother, son, daughter, brother, sister, sibling, parent (family);
  friend, best friend, buddy, comrade (friendship);
  master, servant, mentor, student, follower (hierarchy);
  ally, alliance, partner (alliance); rival (rivalry).
- Add "bidirectional": true only when the label reads both ways, like "sisters" or "friends".
  For a married couple, draw one edge from husband to wife labeled "husband".
- Draw at most one edge between two characters. If two relationships apply, put both in one label, like "husband and cousin".
- Keep each "subtitle" to 30 characters or fewer. Put longer notes in "description".
- Groups are optional. Give every group a color like "#42A5F5".
- No pictures and no avatars. No positions either, unless I ask for a family tree.
- Before answering, check that the JSON is valid and that every source and target is a node id.

A good answer looks like this (a short one, for Pride and Prejudice):

{
  "meta": { "title": "Pride and Prejudice characters", "subtitle": "Jane Austen, 1813", "version": "1.2" },
  "nodes": [
    { "id": "elizabeth", "name": "Elizabeth Bennet", "subtitle": "Second Bennet daughter", "groups": ["bennets"] },
    { "id": "jane", "name": "Jane Bennet", "subtitle": "Eldest Bennet daughter", "groups": ["bennets"] },
    { "id": "lydia", "name": "Lydia Bennet", "subtitle": "Youngest Bennet daughter", "groups": ["bennets"] },
    { "id": "mr-bennet", "name": "Mr. Bennet", "subtitle": "Father of five daughters", "groups": ["bennets"] },
    { "id": "mrs-bennet", "name": "Mrs. Bennet", "subtitle": "Eager matchmaker", "groups": ["bennets"] },
    { "id": "darcy", "name": "Fitzwilliam Darcy", "subtitle": "Master of Pemberley", "groups": ["darcys"] },
    { "id": "georgiana", "name": "Georgiana Darcy", "subtitle": "Darcy's younger sister", "groups": ["darcys"] },
    { "id": "bingley", "name": "Charles Bingley", "subtitle": "Rents Netherfield" },
    { "id": "wickham", "name": "George Wickham", "subtitle": "Militia officer" },
    { "id": "collins", "name": "Mr. Collins", "subtitle": "Clergyman, the Bennets' cousin" },
    { "id": "charlotte", "name": "Charlotte Lucas", "subtitle": "Elizabeth's best friend" }
  ],
  "edges": [
    { "id": "e1", "source": "mr-bennet", "target": "elizabeth", "label": "father" },
    { "id": "e2", "source": "mrs-bennet", "target": "jane", "label": "mother" },
    { "id": "e3", "source": "jane", "target": "elizabeth", "label": "sisters", "bidirectional": true },
    { "id": "e4", "source": "lydia", "target": "elizabeth", "label": "sisters", "bidirectional": true },
    { "id": "e5", "source": "darcy", "target": "elizabeth", "label": "in love with" },
    { "id": "e6", "source": "bingley", "target": "jane", "label": "in love with" },
    { "id": "e7", "source": "darcy", "target": "bingley", "label": "friends", "bidirectional": true },
    { "id": "e8", "source": "darcy", "target": "georgiana", "label": "brother" },
    { "id": "e9", "source": "wickham", "target": "darcy", "label": "rival" },
    { "id": "e10", "source": "wickham", "target": "georgiana", "label": "betrays" },
    { "id": "e11", "source": "wickham", "target": "lydia", "label": "husband" },
    { "id": "e12", "source": "collins", "target": "charlotte", "label": "husband" },
    { "id": "e13", "source": "charlotte", "target": "elizabeth", "label": "best friends", "bidirectional": true }
  ],
  "groups": [
    { "id": "bennets", "name": "The Bennets", "color": "#00B894" },
    { "id": "darcys", "name": "The Darcys", "color": "#0984E3" }
  ]
}

2. Open it in RelationMap

Paste it (any AI chat)

  1. Copy the JSON. Most chats put a copy button on the code block. Copying the whole answer works too: RelationMap finds the JSON inside it.
  2. Open relationmap.io/edit/?paste=1. A box for pasting opens.
  3. Paste into the box. If the box already shows a map as text, select all of it first and paste over it.
  4. The line under the box should now say something like “Chart data: 11 characters, 13 relationships”. Tap Apply.

If you already have a map in this browser, RelationMap asks before replacing it.

An AI that can run code, such as ChatGPT running Python or Claude Code, can turn the JSON into a link. Opening the link loads the chart in the editor:

https://relationmap.io/edit/#data=eNqtlVFP2zAQx7-KlT3wwhAF...

To ask for one, add this to the prompt: “Then run code to turn the JSON into a RelationMap link, as described at https://relationmap.io/docs/ai.md, and give me the link.”

Using Claude Code? Install the RelationMap chart skill once, then ask for a chart in plain words. It writes the JSON, checks it and gives you the link:

git clone https://github.com/Unibrighter/relationmap-skill.git ~/.claude/skills/relationmap-chart

Another way that always works: ask the AI to save the JSON as a .json file, download it, and choose Open in the editor (or drag the file onto the canvas).

Python:

import base64, json, zlib

def relationmap_link(chart):
    data = json.dumps(chart, ensure_ascii=False).encode("utf-8")
    packed = base64.urlsafe_b64encode(zlib.compress(data, 9)).decode("ascii").rstrip("=")
    return "https://relationmap.io/edit/#data=" + packed

JavaScript (Node.js 16 or newer):

const zlib = require("zlib");

function relationmapLink(chart) {
  const packed = zlib.deflateSync(Buffer.from(JSON.stringify(chart), "utf8")).toString("base64url");
  return "https://relationmap.io/edit/#data=" + packed;
}

How the link works:

  • Everything after #data= is the chart JSON (UTF-8), base64url-encoded. Standard base64 and missing = padding are accepted too.
  • Compressing the JSON with zlib (as above) or gzip first is optional. The editor tells them apart by their first bytes. Compressed links are much shorter. With the Python code above, the Pride and Prejudice example makes a link of 930 characters, against 3,258 without compression; a 40-person chart with no pictures, about 3,000 to 4,000 against 11,000 to 15,000.
  • Compressed links need Chrome 80, Firefox 113, Safari 16.4 or newer. Links without compression work in any browser.
  • A link can carry up to 1 MB of chart data, counted after unpacking. For bigger charts, use a .json file and Open.
  • The part after #data= is not sent to our server. The editor removes it from the address bar before our analytics scripts start, so the link itself is never recorded. Reloading doesn’t open the chart twice.
  • Use the address https://relationmap.io/edit/#data=... as it is. The editor ignores #data= on a saved chart’s page (/edit/<slug>) and together with ?demo= or ?fork=.

Family trees

For a family tree, add this to the end of the prompt:

This is a family tree. Also follow these rules:
- One edge from each parent to each child, labeled "father" or "mother".
- One edge per marriage, from husband to wife, labeled "husband", without "bidirectional".
- No edges between siblings: shared parents already show them.
- Give every node a "position": {"x": ..., "y": ...}. One generation per row, oldest at the top,
  rows 200 apart (y grows downward), people in a row at least 150 apart, spouses side by side.

A good answer, for the Bennets at the end of Pride and Prejudice (two of the five daughters, to keep it short):

{
  "meta": { "title": "The Bennet family", "subtitle": "Pride and Prejudice, by the last chapter", "version": "1.2" },
  "nodes": [
    { "id": "mr-bennet", "name": "Mr. Bennet", "subtitle": "Owner of Longbourn", "position": { "x": -100, "y": 0 } },
    { "id": "mrs-bennet", "name": "Mrs. Bennet", "subtitle": "Eager matchmaker", "position": { "x": 100, "y": 0 } },
    { "id": "bingley", "name": "Charles Bingley", "subtitle": "Of Netherfield", "position": { "x": -300, "y": 200 } },
    { "id": "jane", "name": "Jane Bennet", "subtitle": "Eldest daughter", "position": { "x": -150, "y": 200 } },
    { "id": "elizabeth", "name": "Elizabeth Bennet", "subtitle": "Second daughter", "position": { "x": 150, "y": 200 } },
    { "id": "darcy", "name": "Fitzwilliam Darcy", "subtitle": "Of Pemberley", "position": { "x": 300, "y": 200 } }
  ],
  "edges": [
    { "id": "e1", "source": "mr-bennet", "target": "mrs-bennet", "label": "husband" },
    { "id": "e2", "source": "mr-bennet", "target": "jane", "label": "father" },
    { "id": "e3", "source": "mrs-bennet", "target": "jane", "label": "mother" },
    { "id": "e4", "source": "mr-bennet", "target": "elizabeth", "label": "father" },
    { "id": "e5", "source": "mrs-bennet", "target": "elizabeth", "label": "mother" },
    { "id": "e6", "source": "bingley", "target": "jane", "label": "husband" },
    { "id": "e7", "source": "darcy", "target": "elizabeth", "label": "husband" }
  ]
}

It reads “Mr. Bennet is Jane’s father” and “Bingley is Jane’s husband”. The “father” and “mother” lines come out green and the “husband” lines pink. Each child brings two lines, one from each parent, so family trees grow fast: split a big family into branches. More in the data format: Positions, Family trees and Words for family trees, which also shows how to color “uncle” or “cousin”.

Tips

  • How many characters. 10 to 40 works best. The editor opens a chart zoomed out to show all of it: on a laptop screen, 20 characters with 40 relationships open at about half size and 40 with 80 at about a third, so you zoom in to read the names. On a phone, the smallest zoom (20%) runs out of room at around 50 to 60 characters. Keep a chart to about 40 characters and 80 relationships, and split a bigger cast into one chart per family, faction or season.
  • Relationship words and colors. The editor colors each line by words in its label. Some common words get no color: “married”, “spouse”, “uncle”, “cousin”, “teacher”, “boss” and plurals like “enemies” and “allies” stay gray, and “girlfriend” comes out blue like “friend”. The words in the prompt above all get a color. The full table, and how to add your own words, is in the data format.
  • Leave pictures out for now. Image links written by an AI often don’t load, and pictures inside the JSON make it very large. Add pictures in the editor afterwards.
  • Positions. Leave them out and the editor lays the chart out and zooms to show all of it. Give every character a position only when the layout matters, as in a family tree.
  • Short subtitles. A subtitle is drawn on one line under the name and is never wrapped, so a long one runs into its neighbors. Keep it to about 30 characters or fewer and put longer notes in “description”, which shows when you click the character in the editor.
  • Faces instead of initials. Characters without a picture show their initials. Add "settings": { "avatarStyle": "notionists" } to meta (or lorelei, open-peeps, pixel-art, thumbs) to give each one a drawn face, or pick a style later under Project → Default avatar in the editor.
  • Long answers get cut off. If the chat stops in the middle of the JSON, ask it to continue or to use fewer characters. The paste box tells you when JSON is cut off, before anything changes.
  • What’s free. Opening, editing and exporting (PNG, JPG, PDF, JSON) are free. Charts saved to the cloud on the free plan are public under CC BY-NC 4.0. Pro adds private charts, a license of your choice and the AI assistant inside the editor.

If something goes wrong

What you seeWhat to do
No “Chart data” line under the paste box, it lists names insteadThe text wasn’t JSON, so the box read it as a cast list. Ask the AI again for one JSON code block.
”This looks like chart data, but it is cut off or broken”Part of the JSON is missing, or it has something JSON doesn’t allow, such as a comma after the last item or a // comment. Copy the whole code block again, or ask the AI to send it again as plain JSON.
”This is JSON, but not a RelationMap chart”The AI used its own format. Send the prompt above again.
”Opened, but skipped 2 relationship(s) pointing to missing characters”Some source or target values are not node ids (often names were used instead).
Two lines between the same two characters lie on top of each otherBoth are kept, but they are drawn in nearly the same place. Use one edge whose label says both, like “husband and cousin”.
Subtitles run into each otherShorten them to about 30 characters or fewer, or move the characters further apart.
”This link could not be opened: the chart data in it is damaged or cut off”The link was cut short when it was copied. Copy all of it, or paste the JSON instead.
”This link holds 1.3 MB of chart data, and a link can open at most 1 MB”Save the chart as a .json file and use Open.

Updated November 15, 2026. Markdown version of this page. Open the editor.