# Freeform JSON format

A freeform diagram is stored as JSON – a title and a flat list of elements. It is what **Copy as JSON** gives you, what [git sync](/git-sync) writes to `.eraserdiagram` files, and what you paste onto the canvas or send to the [API](/reference/getting-started) or [MCP server](/mcp) to create a diagram without AI.

```json
{
  "title": "Checkout",
  "elements": [
    { "tag": "Shape", "id": "web", "shape": "rectangle",
      "x": 0, "y": 72, "width": 150, "height": 60,
      "color": "purple", "icon": "monitor",
      "texts": [{ "text": "Web app" }] },
    { "tag": "Group", "id": "backend",
      "x": 220, "y": 0, "width": 400, "height": 200,
      "color": "blue",
      "title": { "text": "Backend", "icon": "server" } },
    { "tag": "Icon", "id": "api", "icon": "node", "size": "md",
      "x": 280, "y": 80, "containerId": "backend",
      "texts": [{ "text": "API" }] },
    { "tag": "Icon", "id": "db", "icon": "postgres", "size": "md",
      "x": 520, "y": 80, "containerId": "backend",
      "texts": [{ "text": "Postgres" }] },
    { "tag": "Relationship", "from": "web", "to": "api",
      "label": "HTTPS" },
    { "tag": "Relationship", "from": "api", "to": "db", "label": "SQL" }
  ]
}
```

<Figure src="/assets/freeform-minimal-example.png" alt="The diagram rendered from the JSON above: a purple Web app shape connected by HTTPS to a Node API icon inside a Backend group, which connects by SQL to a Postgres icon." width="560px" />

## Elements

Every element has a `tag`. Shapes, icons, text, groups and dividers also need an `id` and an `x` and `y` – the top-left corner, in pixels. `width` and `height` are optional. A connector joins two elements by their `id`s in `from` and `to`.

| Tag            | Draws                                                                                                                                                              |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Shape`        | A shape with text and an optional icon. `shape` is `rectangle`, `oval`, `circle`, `ellipse`, `diamond`, `hexagon`, `parallelogram`, `trapezoid`, `triangle`, `cylinder`, `document` or `star`. |
| `Icon`         | An icon with a caption. `size` is `sm`, `md`, `lg` or `xl`.                                                                                                        |
| `Textbox`      | Standalone text, in Markdown.                                                                                                                                      |
| `Group`        | A container with an optional `title`. An element joins it by setting `containerId` to the group's `id`.                                                            |
| `Divider`      | A horizontal or vertical line, with an optional label.                                                                                                             |
| `Relationship` | A connector, with an optional `label`.                                                                                                                             |

## Common properties

| Property                          | Value                                                                                                                  |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `texts`                           | The text on a shape or icon, one entry per line: `[{ "text": "API" }]`                                                 |
| `icon`                            | An icon name from [Icons](/icons)                                                                                      |
| `color`                           | `white`, `yellow`, `green`, `blue`, `purple`, `red`, `orange`, `black`, or any CSS color                                |
| `startArrowhead`, `endArrowhead`  | `arrow`, `bar`, `dot`, `triangle`, `crowFootSingle`, `crowFootMany`, or `null` for none |
| `lineStyle`                       | `solid`, `dashed` or `dotted`                                                                                           |
| `connectorStyle`                  | `elbow` (the default), `straight` or `arc`                                                                              |

The quickest way to see any other property is to style an element on the canvas and use **Copy as JSON**.

## Using the JSON

- **Canvas** – paste the JSON onto the canvas to create the diagram.
- **Git sync** – an `.eraserdiagram` file is the line `freeform-diagram`, a blank line, then the JSON.
- **API** – send the elements as `freeformElements` to [`/api/render/elements`](/reference/generate-diagram-from-eraser-dsl), with `diagramType` set to `freeform-diagram`.
- **MCP** – pass the JSON as `code` to `manually_create_diagram`, with `diagramType` set to `freeform-diagram`.
