Manifest ReferenceGraph & Edges

Graph

The chapter flow graph — entry panels, directed edges with transitions, JSON Logic conditions, priorities, and variable mutations.

Every chapter has a required graph: panels are nodes, and directed edges define how the reader moves between them. Edges can carry a transition, a JSON Logic condition for branching, and variable mutations that run when the edge is taken. This is what turns a linear comic into an interactive one.

Graph

PropertyTypeRequiredDescription
entryIdentifier | Identifier[] (min 1, unique)YesThe panel where the chapter starts. An array declares multiple possible entry points
edgesEdge[]YesDirected connections between panels. May be empty since 1.7 (it was min 1 before)
nodesobject (ID → { label: LocalizedString })—Optional per-node metadata (display labels, e.g. for a chapter map)

The panel references entry and from are keys of the chapter's panels map. An edge's to is usually one too, but may name a panel of any other chapter of the work — a chapter transition, or a jump into an endings chapter. The reader then continues in the target's chapter. This is part of the format since 1.7.0 (earlier wording required to to be in the same chapter) (see Moving between chapters). Since format 1.7 edges may be empty ("edges": []): a chapter without edges — for example a single-panel chapter — follows its panels' reading order. The property itself stays required.

Edge

PropertyTypeRequiredDescription
fromIdentifierYesSource panel ID — a panel of this chapter
toIdentifierYesTarget panel ID — usually of this chapter, but any panel of the work is allowed
conditionJsonLogic—The edge is only eligible when this evaluates truthy against the current variable state
priorityinteger ≥ 0—Ordering hint when multiple edges from the same panel are eligible
transitionTransition—Animation when traversing this edge; overrides the format preset's defaultTransition
cameraMoveCameraMove—Camera travel when this edge is taken in canvas view (1.4+); inherits the format preset's defaultCameraMove. Coexists with transition (which still applies in panel view)
actionMutation[]—Variable mutations executed when the edge is taken
labelLocalizedString—Reader-facing choice text of this path (1.7+). Players show it on the branch chooser's buttons when several paths leave a panel; without it they fall back to the target panel's title, then to a numbered "Option N"
mutationsobject[]—Editor metadata — free-form edge descriptors written by the CMS (e.g. hotspot/edge-type markers). Not variable mutations

Naming gotcha: on an Edge, variable writes go in action (an array of typed Mutation objects). The mutations property on an edge is unvalidated editor metadata. Hotspot actions, by contrast, do use a property named mutations for variable writes — see Hotspots.

Branching

A panel with several outgoing edges branches on their conditions. Typically a choice panel sets a variable via hotspots, and downstream edges route on it:

{
  "graph": {
    "entry": "p1-1",
    "edges": [
      {
        "from": "p1-1",
        "to": "p1-2",
        "transition": { "type": "slide", "dir": "left", "durationMs": 350 }
      },
      {
        "from": "p1-2",
        "to": "p1-3-left",
        "condition": { "==": [ { "var": "path.choice" }, "left" ] },
        "priority": 1
      },
      {
        "from": "p1-2",
        "to": "p1-3-right",
        "condition": { "==": [ { "var": "path.choice" }, "right" ] },
        "priority": 1
      },
      {
        "from": "p1-2",
        "to": "p1-3-default",
        "priority": 0
      }
    ]
  }
}

An unconditional edge acts as the fallback when no conditional edge matches. How the player evaluates eligibility and order at runtime is described in Graph Navigation and State & Conditions.

Mutation

A typed write to a variable, used in Edge.action and in hotspot goTo/setVariables actions:

PropertyTypeRequiredDescription
opstringYesset | increment | toggle | append | remove
varstringYesTarget variable ID, e.g. "path.choice"
valueJsonValue—Operand — the value to set / increment by / append / remove
{
  "from": "p2-4",
  "to": "p2-5",
  "action": [
    { "op": "set", "var": "story.metCourier", "value": true },
    { "op": "increment", "var": "story.visits", "value": 1 }
  ]
}
opEffect
setAssign value to the variable
incrementAdd value to a numeric variable
toggleFlip a boolean variable
appendAdd value to a list-valued variable
removeRemove value from a list-valued variable

Mutations on readOnly variables are invalid at runtime (the schema cannot cross-check this). Keep decision state in session or chapter scope and preferences in persistent scope — see Variables.

Node labels

nodes attaches display labels to panels without touching the panel definitions — useful for authoring tools and reader-facing chapter maps:

{
  "graph": {
    "entry": "p1",
    "nodes": {
      "p1": { "label": { "en-US": "Opening", "de-DE": "Auftakt" } },
      "p9": { "label": { "en-US": "Good ending" } }
    },
    "edges": [ { "from": "p1", "to": "p9" } ]
  }
}

Validation notes

  • The schema does not verify that entry, from, and to reference existing panels, or that every panel is reachable — run graph checks in your pipeline (the CMS does this in Validation).
  • condition accepts any JSON shape; malformed JSON Logic only fails at runtime.
  • Cycles are legal (loops, hubs, replayable scenes).