ToDiagram

ToDiagram Format

Build architecture and system diagrams in the ToDiagram format

Build architecture diagrams, system designs, and process flows with full control over nodes and edges using the ToDiagram format (.todiagram). The format is JSON-based and saved as .todiagram files.

JSON Schema

The canonical JSON Schema for this format is available at:

https://todiagram.com/schemas/todiagram.json

Example

{
  "nodes": [
    {
      "id": "client",
      "label": "Mobile App",
      "imageUrl": "https://cdn-icons-png.flaticon.com/512/149/149071.png"
    },
    {
      "id": "api-gateway",
      "label": "API Gateway",
      "fields": {
        "port": 443,
        "protocol": "HTTPS",
        "requests_per_sec": 1500
      }
    },
    {
      "id": "backend",
      "label": "Backend Services",
      "nodes": [
        {
          "id": "auth-service",
          "label": "Auth Service",
          "fields": {
            "status": "healthy",
            "uptime": 99.9
          }
        },
        {
          "id": "data-service",
          "label": "Data Service",
          "fields": {
            "instances": 3,
            "load_balanced": true
          }
        }
      ]
    },
    {
      "id": "database",
      "label": "PostgreSQL",
      "imageUrl": "https://cdn-icons-png.flaticon.com/512/5968/5968342.png"
    }
  ],
  "edges": [
    { "from": "client", "to": "api-gateway", "label": "HTTPS Request" },
    { "from": "api-gateway", "to": "auth-service", "label": "Authenticate" },
    { "from": "api-gateway", "to": "data-service", "label": "Fetch Data" },
    { "from": "auth-service", "to": "database", "label": "Verify User" },
    { "from": "data-service", "to": "database", "label": "Query" }
  ]
}

Custom Theming

You can add a custom_theme field to any node to fully customize its appearance using a custom theme. This allows you to override default styles, colors, and more for individual nodes or groups. See the Custom Theme Guide for details and examples.

Example:

{
  "id": "api-gateway",
  "label": "API Gateway",
  "custom_theme": {
    "NODE": {
      "NODE": "#1e293b",
    },
    "EDGE": {
      "EDGE": "#38bdf8",
      "LABEL": "#fff"
    },
    "TEXT": {
      "TEXT": "#fff"
    }
  }
}

Icons

You can use any of the 200,000+ icons available on iconify.design for imageUrl or iconUrl. The format is set:icon-name, for example fa:user or fa:desktop. Use valid Iconify names; invalid names will not render.

{
  "id": "server",
  "label": "Web Server",
  "imageUrl": "fa:desktop"
}

Not everything belongs on the card. Two node keys hold data that is shown on demand instead:

  • link: the node's primary destination (an http, https or mailto URL).
  • details: content for the details panel, a markdown description and a list of related links.
{
  "id": "editor_mvp",
  "label": "Editor MVP",
  "iconUrl": "fa7-solid:pen-to-square",
  "fields": { "owner": "Frontend", "status": "in progress" },
  "link": "https://example.com/projects/editor-mvp",
  "details": {
    "description": "Ships the **canvas editor**.\n\n- [x] node modal\n- [ ] inline edit",
    "links": [
      { "label": "Design doc", "url": "https://example.com/docs/editor" },
      { "label": "Figma", "url": "https://example.com/figma/editor" }
    ]
  }
}

What a click does depends on the node and on where the diagram is viewed:

Node hasViewers, embedsEditor
detailsClick opens the details panelClick selects the node and opens the details panel
link onlyClick opens the linkCmd/Ctrl+click or the toolbar's "Open link" button opens it
bothDetails panel, with "Open link" as its primary actionSame as details

Notes:

  • Only http, https and mailto URLs are opened; anything else is ignored.
  • The description is rendered as Markdown (GitHub flavored: lists, tables, task lists). Raw HTML is not rendered.
  • Unknown keys inside details are preserved by the editor and ignored by the renderer, so you can keep your own data there.
  • The node editor has a Details tab for these values.
  • Edges accept the same link and details keys. They are reserved today and validated by the schema; the edge panel is coming.

Structure

Nodes

Every node must have an id field. Use the fields object to add key-value pairs that are displayed as rows on the node card.

Prop

Type

Fields Example:

{
  "id": "server",
  "label": "API Server",
  "iconUrl": "fa:server",
  "fields": {
    "port": 3000,
    "status": "active",
    "uptime": 99.9,
    "ssl": true
  }
}

Deprecated: top-level extra properties

Top-level extra properties on a node are deprecated and may be removed in a future version. Always use the fields object for key-value display data.

Shapes

Set the shape field on any node to render it with a non-default silhouette. The default is a rounded rectangle.

Non-rectangular shapes don't render fields (no room inside the silhouette), but they compose with the visual fields:

  • iconUrl — small icon stacks above the label, both centered inside the silhouette.
  • imageUrl — image fills the silhouette as a contain-fit background, label moves below the node (same layout as a rectangular image node).
ValueDescription
rectangleSharp-cornered rectangle
roundedRounded rectangle (default for nodes without shape)
stadiumPill / capsule
subroutineRectangle with two inner vertical bars
cylinderDatabase / storage symbol
circleCircle
double-circleCircle with an inner ring (terminal / accept state)
diamondDecision / branch
hexagonHexagon
parallelogramRight-leaning parallelogram
parallelogram-altLeft-leaning parallelogram
trapezoidWide-top trapezoid
trapezoid-altWide-bottom trapezoid
asymmetricRectangle with a left-edge notch

Example:

{
  "nodes": [
    { "id": "start",   "label": "Start",       "shape": "stadium" },
    { "id": "decide",  "label": "Approved?",   "shape": "diamond" },
    { "id": "store",   "label": "PostgreSQL",  "shape": "cylinder" },
    { "id": "end",     "label": "Done",        "shape": "double-circle" }
  ],
  "edges": [
    { "from": "start",  "to": "decide" },
    { "from": "decide", "to": "store",  "label": "yes" },
    { "from": "store",  "to": "end" }
  ]
}

Edges

Edges define connections between nodes.

Prop

Type


Configuration

You can include an optional configuration object at the root level to customize field mappings. This is useful when your data has field names that conflict with the defaults (e.g., a column named id or label).

Schema Field Mappings

The configuration.schema object lets you override which fields are used for node IDs, labels, edges, etc.

{
  "configuration": {
    "schema": {
      "keys": {
        "nodes": "nodes",
        "edges": "edges",
        "direction": "direction"
      },
      "node": {
        "id": "id",
        "label": "label",
        "imageUrl": "imageUrl",
        "iconUrl": "iconUrl",
        "shape": "shape",
        "customTheme": "custom_theme",
        "link": "link",
        "details": "details"
      },
      "edge": {
        "from": "from",
        "to": "to",
        "label": "label"
      }
    }
  },
  "nodes": [...],
  "edges": [...]
}

Example: Custom ID Field

If your data uses name as the unique identifier instead of id:

{
  "configuration": {
    "schema": {
      "node": { "id": "name" }
    }
  },
  "nodes": [
    { "name": "server-1", "fields": { "status": "running" } },
    { "name": "server-2", "fields": { "status": "stopped" } }
  ],
  "edges": [
    { "from": "server-1", "to": "server-2" }
  ]
}

Example: Database Schema Diagram

Column names like id or label can be used freely inside the fields object without conflicting with reserved node keys:

{
  "nodes": [
    {
      "id": "users",
      "label": "users",
      "iconUrl": "logos:postgresql",
      "fields": {
        "id": "🔑 uuid",
        "email": "varchar *",
        "name": "varchar"
      }
    },
    {
      "id": "posts",
      "label": "posts",
      "iconUrl": "logos:postgresql",
      "fields": {
        "id": "🔑 uuid",
        "user_id": "🔗 uuid",
        "title": "varchar *"
      }
    }
  ],
  "edges": [
    { "from": "posts", "to": "users", "label": "user_id" }
  ]
}

On this page