Graph Navigation
How PanelWave models reading flow as a directed graph — entry panels, edges, JSON Logic conditions, transitions, and variable mutations.
In PanelWave, a chapter's reading flow is not a page order — it is a directed graph. Panels are the nodes; edges define which panel can follow which, under what condition, and with what visual transition. The player's flow engine evaluates the graph at every step to decide where the reader can go next.
Why a graph instead of linear pages?
- Branching is native. A choice is just two or more outgoing edges with different conditions — no special "decision page" construct.
- Non-linearity stays consistent. Loops, detours, optional scenes, and re-converging paths are all ordinary graph shapes; history and back-navigation still work.
- Linear stories cost nothing. A conventional comic is simply a chain of unconditional edges. You only pay for complexity where you use it.
- State and flow compose. Because edges can test variables and mutate them, the same graph can route differently on a second read-through.
Anatomy of a graph
Each chapter has a graph with a required entry (the starting panel ID — or an array of candidate entry IDs) and a required list of edges:
{
"graph": {
"entry": "panel-01",
"edges": [
{ "from": "panel-01", "to": "panel-02" },
{
"from": "panel-02",
"to": "panel-03-left",
"condition": { "==": [{ "var": "story.choice" }, "left"] }
},
{
"from": "panel-02",
"to": "panel-03-right",
"condition": { "==": [{ "var": "story.choice" }, "right"] }
}
]
}
}
That graph looks like this:
An edge supports these properties (full reference: Graph):
| Property | Purpose |
|---|---|
from, to | Panel IDs (required). |
condition | JSON Logic expression; the edge is only available when it evaluates truthy. |
action | List of variable mutations applied when the edge is traversed. |
transition | Visual transition for the panel change. |
priority | Orders competing edges when several conditions match. |
Conditions: a JSON Logic primer
Conditions are JSON Logic expressions — small JSON trees where the key is an operator and the value holds its arguments. Variables are read with { "var": "name" }:
{ "==": [{ "var": "story.choice" }, "left"] }
reads as "story.choice equals the string left". Operators compose:
{
"and": [
{ ">=": [{ "var": "user.age" }, 16] },
{ "==": [{ "var": "prefs.explicit" }, true] }
]
}
Common operators: ==, !=, >, >=, <, <=, and, or, !, in, if. The same condition language is used everywhere in the format — edges, panel variants, and conditional content — and is evaluated by the player against the current variable state. See State & conditions in the player.
An edge with no condition is always available. When multiple edges leave the same panel, the player evaluates their conditions and uses priority to break ties.
Transitions
An edge can describe how the panel change looks:
{ "type": "slide", "dir": "left", "durationMs": 500, "easing": "ease-in-out" }
type:none,cut,fade,slide,zoom,push, orcoverdir:left,right,up,down(for directional types)durationMs: 0–60000easing:linear,ease,ease-in,ease-out,ease-in-out
Mutations
Traversing an edge (via action) or clicking a hotspot can mutate variables:
{ "op": "set", "var": "story.choice", "value": "left" }
Operations: set, increment, toggle, append, remove. In practice, choices usually work like this: a hotspot on the panel sets a variable (goTo actions can carry mutations too), and outgoing edges test that variable to route the reader. See Variables for scopes and lifetime.
How the player walks the graph
- The chapter opens at
entry. - When the reader advances (tap, key, autoplay, or hotspot
goTo), the flow engine collects the current panel's outgoing edges, evaluates eachcondition, and picks the winner (usingpriorityif needed). - Edge
actionmutations are applied, thetransitionplays, and the target panel renders. - The step is pushed onto history, so back-navigation restores both position and state.
Moving between chapters
- A panel without an outgoing edge ends its chapter; the reader continues with the next chapter's
entry. - An edge's
to(or a hotspot'sgoTo) may name a panel of another chapter — a chapter transition, or a jump from the last chapter into a separate endings chapter. The reader continues in that chapter: from the player release after 1.2.0 the flow engine switches to the target's chapter, so further steps follow that chapter's graph. entryand every edge'sfrombelong to the chapter that holds the graph.
The CMS keeps such edges in exported and published manifests, and its Graph Editor shows the whole work with the links between chapters.
Related pages
- Graph schema reference — every property, with constraints
- Hotspots — interactive regions and the
goTo/setVariablesactions - Editing the graph in the CMS — the visual graph editor
- Variables — the state that conditions read