Hotspots
Reference for Hotspot and HotspotAction — interactive shapes on panels, the five action types, mutations, and visibility conditions.
Hotspots are interactive regions on a panel. Readers click or tap them to navigate the story graph, set variables, open bonus content, show a modal, or trigger a plugin event. Hotspots are the primary building block for choice-driven branching (see Graph Navigation).
Hotspot
Defined as $defs/Hotspot. Lives in chapters[].panels.<panelId>.hotspots[] (and in variant overrides).
| Property | Type | Required | Description |
|---|---|---|---|
id | Identifier | Yes | Unique hotspot ID within the panel. |
shape | Shape | Yes | Clickable region in normalized panel coordinates (0–1). |
label | LocalizedString | Yes | Visible/announced label for the hotspot. |
action | HotspotAction | Yes | What happens on activation — one of five action types. |
ariaLabel | LocalizedString | No | Screen-reader label, if it should differ from label. |
visibleIf | JsonLogic | No | Condition controlling hotspot availability, evaluated against variables. |
display | "auto" | "button" | "area" | No | How readers see the hotspot (1.7+, default auto). area: an invisible click area over the artwork — the label is only its accessible name. button: the label is shown as a button. auto: a button when the panel's goTo hotspots lead to two or more panels (a choice), otherwise an area. Use area when the artwork or a caption already shows the option. |
Shape
A discriminated union ($defs/Shape) — the type property selects one of four geometries. All coordinates are normalized (0–1) relative to the panel.
Required: type, x, y, w, h.
{ "type": "rect", "x": 0.05, "y": 0.4, "w": 0.4, "h": 0.4 }
Required: type, cx, cy, r (center point and radius).
{ "type": "circle", "cx": 0.5, "cy": 0.5, "r": 0.15 }
Required: type, x, y, w, h (bounding box of the ellipse).
{ "type": "ellipse", "x": 0.6, "y": 0.15, "w": 0.3, "h": 0.18 }
Required: type, points — an array of at least 3 [x, y] points.
{ "type": "polygon", "points": [[0.1, 0.1], [0.4, 0.1], [0.25, 0.35]] }
HotspotAction
A oneOf union ($defs/HotspotAction) discriminated by type. Exactly these five action types exist:
goTo — navigate to a panel
| Property | Type | Required | Description |
|---|---|---|---|
type | "goTo" | Yes | Action discriminator. |
to | Identifier | Yes | Target panel ID — any panel of the work, including one in another chapter; the reader then continues in that chapter (Moving between chapters). |
mutations | Mutation[] | No | Variable mutations applied when the hotspot fires (e.g. record the choice). |
transition | Transition | No | Visual transition for this navigation — see Animations & Transitions. |
setVariables — mutate variables without navigating
| Property | Type | Required | Description |
|---|---|---|---|
type | "setVariables" | Yes | Action discriminator. |
mutations | Mutation[] (min 1) | Yes | One or more variable mutations. |
openExtras — open a bonus-content block
| Property | Type | Required | Description |
|---|---|---|---|
type | "openExtras" | Yes | Action discriminator. |
extrasId | Identifier | Yes | ID of an extras block to open. |
openModal — show an inline modal
| Property | Type | Required | Description |
|---|---|---|---|
type | "openModal" | Yes | Action discriminator. |
title | LocalizedString | Yes | Modal title. |
content | LocalizedString | Yes | Modal body text. |
pluginEvent — dispatch an event to a plugin
| Property | Type | Required | Description |
|---|---|---|---|
type | "pluginEvent" | Yes | Action discriminator. |
pluginId | Identifier | Yes | Target plugin — see Extensions & Plugins. |
event | string | Yes | Event name. |
payload | JsonValue | No | Arbitrary JSON payload. |
Mutation
Variable mutations ($defs/Mutation) used by goTo and setVariables (and on graph edges):
| Property | Type | Required | Description |
|---|---|---|---|
op | "set" | "increment" | "toggle" | "append" | "remove" | Yes | Operation. |
var | string | Yes | Variable ID (e.g. "path.choice"). |
value | JsonValue | No | Operand where the operation needs one. |
Conditions
Two mechanisms make hotspots conditional:
visibleIfon the hotspot hides or shows the hotspot itself based on a JSON Logic expression over current variable values.- Mutations + conditional edges: a common branching pattern is a
goTohotspot that both navigates and sets a variable, with downstream graph edges or panel variants conditioned on that variable.
Example
A decision panel with two choices (from the branching sample):
{
"hotspots": [
{
"id": "hs-forest",
"label": { "en-US": "Enter the Forest", "de-DE": "Betrete den Wald" },
"shape": { "type": "rect", "x": 0.05, "y": 0.3, "w": 0.4, "h": 0.6 },
"action": {
"type": "goTo",
"to": "panel-forest-path",
"mutations": [
{ "op": "set", "var": "choices.first", "value": "forest" }
],
"transition": { "type": "slide", "dir": "left", "durationMs": 350 }
}
},
{
"id": "hs-mountain",
"label": { "en-US": "Climb the Mountain", "de-DE": "Besteige den Berg" },
"shape": { "type": "rect", "x": 0.55, "y": 0.3, "w": 0.4, "h": 0.6 },
"action": {
"type": "goTo",
"to": "panel-mountain-path",
"mutations": [
{ "op": "set", "var": "choices.first", "value": "mountain" }
],
"transition": { "type": "slide", "dir": "right", "durationMs": 350 }
}
}
]
}