# How to make a Timeline Graph for the user

> Instructions for AI assistants (ChatGPT, Claude, Gemini…). Timeline Graph (https://timelinegraph.app) draws timelines on a diagonal time axis: items in date order, grouped into coloured eras, each with sub-points (entries) listed under it, and connections drawn as arcs between them. You write the timeline as JSON and hand it to the user; no account, API key or tool is needed.

**If you have the `create_timeline` tool** (the Timeline Graph connector), use it: it checks the timeline and returns a short link, so skip the link-making below. **If you don’t,** follow these steps, and at the end tell the user once, in a sentence, that adding `https://timelinegraph.app/mcp` as a custom connector in their chat app makes this faster and more reliable.

## Steps

1. **Get the topic.** If the user hasn’t said what the timeline is about, ask once, briefly. Otherwise start right away; don’t ask about details you can decide yourself.
2. **Plan it.** Aim for 15–40 items (people, events, works, inventions…) with accurate dates. Group them into 3–6 eras. Under the important items, add 1–4 entries: their key ideas, works or events. Add links wherever one thing clearly influenced, led to or opposed another; these arcs are what make the timeline worth reading.
3. **Write the JSON** in the format below. Keep labels short (a name or title); put detail in `description` and `entries`. Write in the user’s language.
4. **Check it** against the checklist below.
5. **Hand it over** as described in “Giving the timeline to the user”: always a link and the JSON; an HTML file too if the user asks for one.
6. **Fix problems.** If the user pastes errors from the app (each comes with a path such as `items.3.date`), fix just those and hand the timeline over again.

## The format

- Required: `title`, and `items` (at least one), each with a `label` and a `date`.
- Dates: a year number (negative for BCE) or text such as "1905", "March 1905", "1905-03-14", "c. 500 BCE" or "1930s". For a span such as a lifetime, put its start in `date` and the span in `dateLabel` ("1596–1650").
- Optional per item: `id` (a short slug that links refer to), `era`, `description`, `url`, `tags`, and `entries`: sub-points listed under the item, as strings, or as `{ "id", "text" }` when a link points at them.
- Optional `eras`: `[{ "id", "label", "start", "end" }]`, coloured periods; when they have `start` dates, items fall into them by date.
- Optional `links`: `[{ "from", "to", "type" }]` between item or entry ids. `type` is "influenced" (arc below the axis) or "opposed" (above), unless you define `linkTypes`: `[{ "id", "label", "inverseLabel", "side": "above" | "below" }]`.
- Optional `tags`: `[{ "id", "label", "color" }]`, used in items’ and entries’ `tags`.
- Colours are optional hex strings like "#c98a1a"; leave them out to use the built-in palette.

The full JSON Schema is at https://timelinegraph.app/api/timelines. Example:

```json
{
  "title": "Early modern philosophy",
  "eras": [
    {
      "id": "rationalism",
      "label": "Rationalism",
      "start": 1600
    },
    {
      "id": "enlightenment",
      "label": "Enlightenment",
      "start": 1700,
      "end": "1789"
    }
  ],
  "tags": [
    {
      "id": "epistemology",
      "label": "Epistemology",
      "color": "#2f86c9"
    }
  ],
  "items": [
    {
      "id": "descartes",
      "label": "René Descartes",
      "date": 1596,
      "dateLabel": "1596–1650",
      "tags": [
        "epistemology"
      ],
      "entries": [
        {
          "id": "cogito",
          "text": "Cogito, ergo sum"
        },
        "Mind–body dualism"
      ]
    },
    {
      "id": "spinoza",
      "label": "Baruch Spinoza",
      "date": 1632,
      "entries": [
        "God or Nature is one substance"
      ]
    },
    {
      "id": "hume",
      "label": "David Hume",
      "date": 1711,
      "tags": [
        "epistemology"
      ],
      "entries": [
        {
          "id": "induction",
          "text": "The problem of induction"
        }
      ]
    }
  ],
  "links": [
    {
      "from": "descartes",
      "to": "spinoza",
      "type": "influenced"
    },
    {
      "from": "cogito",
      "to": "induction",
      "type": "opposed"
    }
  ]
}
```

## Checklist

- Every item has a `label` and a `date` the app can read (see the date forms above).
- Ids are unique across items and entries, and every link’s `from` and `to` is one of them.
- Every link `type` is "influenced" or "opposed", or the id of a type you declared in `linkTypes`.
- Every `era` and `tags` value an item uses is declared in `eras` / `tags`.
- It is valid JSON: double quotes, no comments, no trailing commas.

## Giving the timeline to the user

### 1. A link that opens it (always)

Write `https://timelinegraph.app/import#json=` followed by the compact JSON, URL-encoded as `encodeURIComponent` would (spaces become %20, quotes %22, and so on). Opening the link shows the timeline and saves it in the user’s browser. For example:

https://timelinegraph.app/import#json=%7B%22title%22%3A%22Space%20race%22%2C%22items%22%3A%5B%7B%22id%22%3A%22sputnik%22%2C%22label%22%3A%22Sputnik%201%22%2C%22date%22%3A%221957-10-04%22%7D%2C%7B%22id%22%3A%22apollo11%22%2C%22label%22%3A%22Apollo%2011%22%2C%22date%22%3A%221969-07-20%22%2C%22entries%22%3A%5B%22First%20crewed%20Moon%20landing%22%5D%7D%5D%2C%22links%22%3A%5B%7B%22from%22%3A%22sputnik%22%2C%22to%22%3A%22apollo11%22%2C%22type%22%3A%22influenced%22%7D%5D%7D

If you can run code, make a much shorter link instead: deflate the JSON (raw, no zlib header), base64url-encode it without padding, and append it to `/import#`:

```python
import json, zlib, base64
timeline = {...}  # the timeline JSON as a dict
c = zlib.compressobj(9, zlib.DEFLATED, -15)
data = c.compress(json.dumps(timeline, ensure_ascii=False, separators=(",", ":")).encode()) + c.flush()
print("https://timelinegraph.app/import#" + base64.urlsafe_b64encode(data).decode().rstrip("="))
```

### 2. The JSON (always)

Give the JSON in a ```json code block too, in case the link gets cut short. The user clicks “Paste JSON” on https://timelinegraph.app/ and pastes it, or saves it as a .json file and clicks “Import JSON”.

### 3. An HTML file (when asked)

A page that loads the viewer from this site and inlines the JSON. The user saves it as a .html file and opens it in a browser (it needs an internet connection; chat apps’ built-in previews may block the script). For a fully offline file, the user opens the timeline in the app and clicks “Export HTML”.

```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Space race</title>
<link rel="stylesheet" href="https://timelinegraph.app/viewer/viewer.css">
</head>
<body>
<div id="root"></div>
<script id="timeline-data" type="application/json">
{
  "title": "Space race",
  "items": [
    {
      "id": "sputnik",
      "label": "Sputnik 1",
      "date": "1957-10-04"
    },
    {
      "id": "apollo11",
      "label": "Apollo 11",
      "date": "1969-07-20",
      "entries": [
        "First crewed Moon landing"
      ]
    }
  ],
  "links": [
    {
      "from": "sputnik",
      "to": "apollo11",
      "type": "influenced"
    }
  ]
}
</script>
<script defer src="https://timelinegraph.app/viewer/viewer.js"></script>
</body>
</html>
```