DYSTEN ยท Creator Documentation ยท 2026

Documentation

Learn how to build interactive stories with DYSTEN โ€” from your first node to the full JSON schema.

What is DYSTEN?

DYSTEN is a visual editor for building interactive stories โ€” branching narratives where the reader makes choices, rolls dice, manages an inventory, and shapes the outcome. You build stories as a graph of nodes (scenes) connected by edges (transitions). Conditions and effects make the graph dynamic.

๐Ÿ“–

Text Adventure

Branching prose driven by choices and dice rolls. The classic interactive fiction format.

๐Ÿ–ผ

Graphic Novel

Panel-based storytelling. Each node is an illustrated page; choices branch the art.

๐ŸŽฌ

Interactive Movie

Video clips that play per node. The viewer chooses what happens next.

โœฆ
New to interactive fiction? Start with Text Adventure and the Locked Tower template โ€” it gives you a working 6-node story to explore before building your own.

Creating a project

From the Dashboard, click + New Project. You'll configure three things before entering the editor.

1
Pick a format
Choose Text Adventure, Graphic Novel, or Interactive Movie. This affects what content fields appear on each node. You can change it later in the TopBar.
2
Name your story and pick a genre
The title appears everywhere โ€” choose something descriptive. The genre auto-populates suggested stat definitions and gear items when you open State Definitions later.
3
Choose a starting template
Blank โ€” a single placeholder node, nothing pre-wired. Best when you already know your structure.

The Locked Tower โ€” a working 6-node mystery story with stat checks, item gates, and gear. Best for learning how the system fits together.
โ„น
All projects are saved locally in your browser. Use Export JSON regularly to back up your work.

Editor layout

The editor has four zones. Understanding them makes everything faster.

Top Bar
Story title (click to edit), status badge, genre selector, Export button, Play link, and Test Mode button.
Left Sidebar
Searchable list of all nodes. Click a node to select it. Coloured dots indicate node type. Warning/error indicators appear here.
Canvas
The graph. Drag nodes to arrange. Click to select. Use โš™ Templates to insert pre-wired patterns. Use + Add Node to add bare nodes.
Right Panel
Contextual editor for the selected node. Three tabs: Content, Conditions, and State. Appears when a node is selected.

Overlay panels

Three overlay panels are accessed from the bottom bar:

โš™ State Definitions
Define every stat, flag, counter, and gear item. Source of truth for all player state.
โœ“ Validation
Live list of errors and warnings. Errors block gameplay; warnings flag potential issues.
โ–ถ Test Mode
Play through your story in a split-screen overlay without leaving the editor.

Nodes

Every moment in your story is a node. There are five node types โ€” choose based on what the moment does.

โ–ฃ
Scene node_type: "scene"
The workhorse. Contains prose (or media) and one or more actions. Most of your story will be scene nodes.
โ—Œ
Placeholder node_type: "placeholder"
An unwritten scene. Use it to map out story structure before writing content. Validation flags these as warnings.
โ—‰
Ending node_type: "ending"
Terminates the story. Mark as success, failure, or neutral. No outgoing edges. Every story needs at least one.
๐Ÿ›’
Shop node_type: "shop"
Presents items for purchase. Players spend a currency stat. Configure items and prices in the Right Panel.
โœฆ
Loot Drop node_type: "loot"
Automatically grants items on arrival. No player choice โ€” items appear in inventory immediately.

Adding & editing nodes

Click + Add Node in the canvas toolbar to open a dropdown of bare node types, or use โš™ Templates for pre-wired multi-node patterns. Click any node on the canvas to select it and open the Right Panel. To delete a node, select it and click the red trash button at the top of the Right Panel.

โš 
Deleting a node removes all edges connected to it. Actions in other nodes that targeted it will have broken transitions โ€” the Validation panel flags these as missing_target errors.

Connecting nodes

Nodes connect through outcome ports โ€” the amber dots on the right edge of each node. Each port represents one outcome of one action.

1
Add an action to a scene node
Select the node โ†’ Right Panel โ†’ Content tab โ†’ scroll to Actions โ†’ click + Add Action. Give it a label (the button text the player sees).
2
Add outcomes to the action
Expand the action โ†’ click + Add Outcome. Each outcome gets a label (e.g. "Success", "Failure"). A new amber port appears on the node's right edge.
3
Wire the outcome to a target node
In the outcome's transition settings, pick the target node from the dropdown โ€” or drag directly from the amber port to any node on the canvas.
4
Read the canvas
Each port shows its outcome label and, in amber, any condition attached to it (e.g. has torch). You can trace the full story path without opening any panel.
โœฆ
Arrange nodes left-to-right following the story timeline โ€” it makes the graph much easier to read as it grows.

Mechanic templates

Templates are pre-wired multi-node patterns. Click โš™ Templates in the canvas toolbar, pick a template, fill in a few fields, and click Insert Template.

๐Ÿ—

Item Gate

Requires the player to have a specific item. Branches to a success path (item optionally consumed) or a failure path.

Params: item key, consume toggle
๐ŸŽฒ

Stat Check

Rolls a d20 against a difficulty class. Branches to Success or Failure based on the result plus the chosen stat modifier.

Params: stat key, difficulty
โš”

Combat

A fight encounter. Victory and defeat lead to separate paths; defeat applies a health penalty.

Params: health key, difficulty, health loss
๐Ÿ›’

Shop

A pre-wired shop node with a continue action. Configure items for sale in the Right Panel after inserting.

Params: currency key
โœฆ

Loot Drop

A loot node with a continue action. Add item keys to the loot list in the Right Panel after inserting.

Params: scene name
๐Ÿ’ฌ

Dialogue Branch

A pure narrative choice with 2โ€“3 options, each routing to its own placeholder node.

Params: 2โ€“3 choice labels
โœฆ
The template picker shows clickable chips from your existing gear and state definitions. Define your stats and gear first, then insert templates.

Writing scenes

Scene content lives in the Right Panel โ†’ Content tab when a node is selected.

Content types

text
A prose field. Write the scene description, dialogue, and narration here. Displayed as formatted text in the reader.
image
Provide a URL to an image (JPG, PNG, WebP). Displayed full-width above the action buttons in the reader.
video
Provide a URL to a video file or embed. Plays before the player sees action choices.

Placeholder nodes

A Placeholder node is a reserved spot in your graph with no final content. Use them to map your full story structure before writing any prose, mark scenes you want to return to, and keep the graph connected while content is in draft. To promote a placeholder to a real scene, change its Node Type to scene in the Content tab and write your content.

Naming tips

  • โ†’Use names that describe the state of the world, not the action: "Cave (Lit)" not "Enter cave with torch"
  • โ†’Keep names short โ€” they appear on both the canvas node and the left sidebar
  • โ†’For branching outcomes from the same scene, prefix the name: "Duel โ€” Victory", "Duel โ€” Defeat"

Player state

Player state is every variable you track โ€” health, gold, flags, inventory. Define these in State Definitions (bottom bar). Every key used in a condition or effect must be declared here first.

โค

stat

A numeric value with narrative meaning. Use for health, mana, strength. Displayed as a bar or number in the player sheet.

๐Ÿšฉ

flag

A true/false toggle. Use for events that happened: door_opened, quest_complete. Invisible to the player by default.

๐Ÿช™

counter

A numeric tally used as currency or score. Use for gold, experience, kills.

๐ŸŽ’

inventory

Tracks item keys the player is carrying. Pairs with Gear Definitions for rich display in the player sheet.

Visibility & defaults

Each state key has a visibility setting: visible (shown in player sheet) or hidden (tracked internally, never shown). Enable Visual relevance on a stat to show it prominently (e.g. health bar at the top of the sheet).

Open State Definitions โ†’ Defaults to set the player's initial values. Every new session starts from these.

โš 
If you use a key in a condition or effect that isn't declared in State Definitions, the Validation panel will flag it as an undefined_state_key error and gameplay will behave unexpectedly.

Gear & items

Gear definitions describe every physical item in the world โ€” weapons, armour, consumables, key items. Open State Definitions โ†’ Gear to manage them.

Key fields

  • โ†’key โ€” machine-readable identifier used in effects (add_item: torch), conditions (has_item: torch), and loot/shop lists.
  • โ†’name โ€” the display name shown to the player.
  • โ†’item_type โ€” weapon, armor, consumable, key_item, or misc. Determines the icon in the player sheet.
  • โ†’slot โ€” equipment slot (e.g. weapon, armor). Items with the same slot replace each other when equipped.
  • โ†’stat_bonuses โ€” passive bonuses while equipped. E.g. a sword that adds +3 strength.

Genre presets

In the Gear tab, click Genre Presets to auto-populate suggested stats and gear based on your story's genre. Presets are non-destructive โ€” existing keys are never overwritten.

Actions & rules

Actions are the choices presented to the player. Each action has a rule that decides how the outcome is determined, and a list of outcomes that map results to transitions.

Simple Choice
none
No dice. Outcomes are evaluated in priority order; the first with all conditions passing wins. Use for narrative choices where player agency is the mechanic.
Skill Check
skill_check
Rolls 1d20 + stat modifier vs. a difficulty class (DC). Success if roll โ‰ฅ DC. Best for locks, persuasion, acrobatics.
Combat
fight
A fight roll vs. enemy difficulty. Defeat typically applies a health effect. Use the Combat template for a quick setup.
Luck / Dice
probability
A raw dice roll (e.g. 1d20). Each outcome has a min/max range โ€” the roll is matched to the right range. Use for random events.
โœฆ
Use the Stat Check or Combat templates instead of building these from scratch โ€” they pre-wire the rule, outcomes, and range values correctly.

Conditions & effects

Conditions and effects are attached to transitions. Conditions decide if a path is available; effects decide what changes when it's taken.

Conditions

A condition checks a player state key against a value using an operator. Outcomes with conditions are only available when those conditions pass.

has_item: torch

Player has this item in inventory or equipped.

door_opened = true

State key equals (or neq: does not equal) a value.

strength โ‰ฅ 12

Numeric key is greater than (or equal to) a value.

health < 20

Numeric key is less than (or equal to) a value.

Add multiple conditions per transition. Set logic mode to ALL (every condition must pass) or ANY (at least one).

Effects

Effects mutate player state the moment a transition is taken. You can stack multiple effects on one transition.

set door_opened = true

Set a flag or stat to an exact value.

increment gold +50

Add to a numeric value.

decrement health -20

Subtract from a numeric value.

add_item: lockpick

Put an item into inventory.

remove_item: torch

Remove an item from inventory (consumed).

equip sword โ†’ weapon

Equip an item, removing it from inventory.

Common pattern: item gate

Player must have a torch to enter the dark cave, and the torch is consumed on use:

Outcome A
has_item: torch
โ†’ Cave (Lit) + remove_item: torch
Outcome B
no condition (fallback)
โ†’ Cave (Dark)

Or use the ๐Ÿ— Item Gate template โ€” it builds this exact pattern in one click.

Shop & loot nodes

Shop nodes

A Shop node lets players buy items. To configure one:

1
Add the node
Insert a Shop node via Add Node or the Shop template. The template also wires a "Leave" action automatically.
2
Define gear items first
Shop items are drawn from your Gear Definitions. Open State Definitions โ†’ Gear and make sure your items exist.
3
Configure shop items
Select the Shop node โ†’ Right Panel โ†’ Content tab โ†’ Shop Items section. Add items: pick the gear key, set a price, and choose the currency key (any stat or counter you've defined, e.g. gold).

Loot drop nodes

A Loot node grants items automatically when the player arrives. No choice is presented โ€” items go straight to inventory. Select the node โ†’ Right Panel โ†’ Content tab โ†’ Loot Items section. Add item keys from your Gear Definitions.

โ„น
Loot and shop items are validated by the Timeline Continuity Checker. If a downstream node checks for an item that can't be obtained on any path leading to it, you'll get an item_never_acquirable warning.

Testing & validation

Test Mode

Click โ–ถ Test Mode in the TopBar to play through your story in a side panel without leaving the editor. Your node graph stays visible โ€” as you make choices, the currently active node highlights on the canvas. Test Mode is separate from the full Play view โ€” it's faster and keeps your editor context.

Validation panel

Open the Validation panel from the bottom bar to see a live list of issues:

Error
Blocks correct gameplay. Fix before publishing. Examples: missing start node, broken transition target, undefined state key.
Warning
Likely a problem but not always. Examples: placeholder nodes, unreachable nodes, timeline continuity issues.
Info
Suggestions and notices. Reserved for future checks.

Click Jump โ†’ on any issue to select the relevant node on the canvas instantly.

Timeline continuity checker

The timeline checker validates that items and flags required by conditions can actually be obtained on some path leading to that node.

๐ŸŽ’
item_never_acquirable
A condition checks for an item that cannot be obtained via loot, shop, or add_item effect on any path that reaches this node.
๐Ÿšฉ
state_never_set
A condition checks a boolean flag that is never set to the required value by any effect on any path leading to this node.
โœฆ
These warnings don't mean your story is broken โ€” the path might be intentionally unreachable. But they're worth reviewing to ensure players aren't locked out of content they should be able to access.

Import & export

DYSTEN stories are stored locally in your browser. Export your work regularly to avoid data loss and to share stories with collaborators.

Exporting

  • โ†’TopBar โ†’ โ†“ Export โ€” exports the currently open story as a .json file.
  • โ†’Dashboard โ†’ โ†“ button โ€” exports any project from the list without opening it.

Importing

On the Dashboard, click โ†‘ Import JSON and select a .json file. The story is validated, assigned a fresh ID, and opened in the editor immediately. Importing the same file twice creates two separate projects โ€” IDs are always regenerated.

Sharing with collaborators

  1. 1.Export your story as JSON from the TopBar
  2. 2.Send the file to your collaborator by any means
  3. 3.They import it via their Dashboard โ€” both have independent copies
  4. 4.Merge changes manually by re-exporting
โš 
Stories are stored in browser localStorage. Clearing your browser data will delete all stories. Always keep exported JSON backups of work you care about.

Overview

Every DYSTEN story is a single JSON object. This reference covers every field, its type, and whether it is required. Use this when hand-editing exported files or building tools that generate story JSON.

โœฆ
The easiest way to produce valid story JSON is to build your story in the editor and export it. Use this reference to understand what each field means or to make targeted edits.

Import & Export

Minimum required fields for a valid import:

FieldTypeReqDescription
titlestringโœ“Story title โ€” must be non-empty.
nodesarrayโœ“Array of node objects โ€” can be empty but must exist.
state_definitionsarrayโœ“Array of state definitions โ€” can be empty.
statusstringโœ“"draft", "published", or "archived".

All other fields are optional on import โ€” missing ones receive safe defaults. The id field is always replaced with a fresh generated ID to avoid collisions.

Story Object

FieldTypeReqDescription
idstringโœ“Unique identifier. Auto-replaced on import.
titlestringโœ“Display name of the story.
descriptionstringโ€”Short blurb shown on cards and the Discover page.
status"draft"|"published"|"archived"โœ“Publication state.
story_format"text"|"graphic_novel"|"movie"โ€”Format of the story. Defaults to text.
genreGenreTypeโ€”"heroic_fantasy"|"sci_fi"|"horror"|"mystery"|"modern"|"western"|"custom"
cover_image_urlstringโ€”URL for the cover image shown on cards.
monetization_mode"free"|"paid"|"freemium"โœ“Monetization model.
start_node_idstringโ€”ID of the start node. Must match a node in the nodes array.
nodesStoryNode[]โœ“All nodes in the story graph.
state_definitionsStateDefinition[]โœ“All player state keys.
gear_definitionsGearItem[]โœ“All items that can exist in the world.
defaultsStoryDefaultsโœ“Starting values for all player state.
created_atISO 8601โ€”Creation timestamp.
updated_atISO 8601โ€”Last modification timestamp.

Nodes

FieldTypeReqDescription
idstringโœ“Unique node identifier.
labelstringโœ“Human-readable name shown in the editor.
node_typeNodeTypeโœ“"scene"|"placeholder"|"ending"|"shop"|"loot"
content_type"text"|"image"|"video"โœ“Media type of the scene content.
content_textstringโ€”Prose text for text content type.
content_media_urlstringโ€”URL for image or video content types.
placeholder_summarystringโ€”Brief note for placeholder nodes.
is_startbooleanโœ“True for the starting node only.
is_endingbooleanโœ“True for ending nodes.
ending_type"success"|"failure"|"neutral"โ€”Required when is_ending is true.
actionsAction[]โœ“Player choices available at this node.
shop_itemsShopItem[]โ€”Items for sale. Used when node_type is "shop".
loot_itemsstring[]โ€”Item keys granted on arrival. Used when node_type is "loot".
position_xnumberโœ“X position on the canvas.
position_ynumberโœ“Y position on the canvas.

Node Types

sceneNarrative moment with content and actions.
placeholderUnwritten scene. Flagged by validation.
endingTerminates the story. No outgoing edges.
shopPurchase interface. Requires shop_items.
lootAuto-grants items on arrival. Requires loot_items.

Actions & Outcomes

Action

FieldTypeReqDescription
idstringโœ“Unique action identifier.
node_idstringโœ“Parent node ID.
labelstringโœ“Button text shown to the player.
action_template_typeActionTemplateTypeโœ“"simple_choice"|"risk_luck"|"skill_check"|"fight_challenge"|"advanced"
display_ordernumberโœ“Sort order among actions on the same node.
is_hiddenbooleanโœ“Hidden actions are never presented to the player.
ruleRuleโœ“How the outcome is selected.
outcomesOutcome[]โœ“Possible results.

Outcome

FieldTypeReqDescription
idstringโœ“Unique outcome identifier. Also the canvas port handle ID.
action_idstringโœ“Parent action ID.
labelstringโœ“Port label on canvas (e.g. "Success", "Failure").
prioritynumberโœ“Evaluation order โ€” lower is checked first.
min_valuenumberโ€”Minimum dice roll to match this outcome.
max_valuenumberโ€”Maximum dice roll to match this outcome.
transitionTransitionโ€”Target node and state changes.

Transition

FieldTypeReqDescription
idstringโœ“Unique transition identifier.
source_node_idstringโœ“Origin node.
outcome_idstringโœ“Parent outcome.
target_node_idstringโœ“Destination node.
access_type"free"|"paid"โœ“Paid transitions require a purchase.
condition_groupConditionGroupโ€”Gate conditions for this path.
effect_groupEffectGroupโ€”State mutations applied on take.

Rule Types

rule_typeExtra fieldsReqDescription
noneโ€”โ€”Simple choice. First outcome with all conditions passing wins.
probabilitydice_definitionโ€”Random roll matched to outcome min/max ranges.
skill_checkskill_key, difficulty_levelโ€”d20 + modifier vs. DC. easy=8, medium=12, hard=15, very_hard=18.
fightdifficulty_levelโ€”Combat roll vs. DC. Defeat typically applies health effects.
customcustom_expressionโ€”Reserved for future scripting.

Conditions

FieldTypeReqDescription
idstringโœ“Unique condition ID.
state_keystringโœ“Player state key or item key to check.
operatorConditionOperatorโœ“eq | neq | gt | gte | lt | lte | has_item
expected_valuestring|number|booleanโœ“Value to compare against.

Example

condition_group object"condition_group": {
  "id": "cg_001",
  "logic_mode": "all",
  "conditions": [
    { "id": "c1", "state_key": "torch", "operator": "has_item", "expected_value": true },
    { "id": "c2", "state_key": "health", "operator": "gte", "expected_value": 10 }
  ]
}

Effects

FieldTypeReqDescription
idstringโœ“Unique effect ID.
state_keystringโœ“State key or item key to modify.
operationEffectOperationโœ“set | increment | decrement | add_item | remove_item | equip | unequip
valuestring|number|booleanโœ“Value to apply.

Example

effect_group object"effect_group": {
  "id": "eg_001",
  "effects": [
    { "id": "e1", "state_key": "health", "operation": "decrement", "value": 20 },
    { "id": "e2", "state_key": "gold_key", "operation": "add_item", "value": true }
  ]
}

State Definitions

FieldTypeReqDescription
idstringโœ“Unique definition ID.
keystringโœ“Machine-readable key used in conditions and effects.
state_type"stat"|"flag"|"inventory"|"counter"โœ“Category of state.
value_type"integer"|"boolean"|"string"โœ“Data type.
default_valuestring|number|booleanโœ“Starting value for new sessions.
visibility_mode"hidden"|"visible"โœ“Whether the player sees this in the character sheet.
visual_relevancebooleanโœ“If true, shown prominently (e.g. health bar).

Gear Definitions

FieldTypeReqDescription
idstringโœ“Unique gear ID.
keystringโœ“Item key used in loot_items, shop_items, effects, and conditions.
namestringโœ“Display name shown to the player.
item_type"weapon"|"armor"|"consumable"|"key_item"|"misc"โœ“Category for character sheet icon.
slotstringโ€”Equipment slot (e.g. "weapon", "armor"). Items in the same slot replace each other.
descriptionstringโ€”Flavour text in shop and inventory panels.
stat_bonusesRecord<string, number>โ€”Passive bonuses while equipped (e.g. { "strength": 2 }).

Defaults

FieldTypeReqDescription
starting_statsRecord<string, number>โœ“Initial stat values (e.g. { "health": 100 }).
starting_flagsRecord<string, boolean>โœ“Initial flags (e.g. { "has_map": false }).
starting_inventorystring[]โœ“Item keys at start (e.g. ["torch", "ration"]).
starting_countersRecord<string, number>โœ“Initial counters (e.g. { "gold": 50 }).
starting_equippedRecord<string, string>โœ“Pre-equipped items (e.g. { "weapon": "rusty_dagger" }).

Full Example

A minimal but complete story โ€” one scene, one item gate, two outcomes.

{
  "id": "story_example",
  "title": "The Dark Cave",
  "status": "draft",
  "story_format": "text",
  "genre": "heroic_fantasy",
  "monetization_mode": "free",
  "start_node_id": "node_001",
  "state_definitions": [{
    "id": "sd_001", "key": "health",
    "state_type": "stat", "value_type": "integer",
    "default_value": 100, "visibility_mode": "visible", "visual_relevance": true
  }],
  "gear_definitions": [
    { "id": "gi_001", "key": "torch", "name": "Torch", "item_type": "consumable" }
  ],
  "defaults": {
    "starting_stats": { "health": 100 },
    "starting_flags": {},
    "starting_inventory": ["torch"],
    "starting_counters": {},
    "starting_equipped": {}
  },
  "nodes": [{
    "id": "node_001", "label": "Cave Entrance",
    "node_type": "scene", "content_type": "text",
    "content_text": "You stand at the mouth of a dark cave.",
    "is_start": true, "is_ending": false,
    "position_x": 200, "position_y": 200,
    "actions": [{
      "id": "action_001", "node_id": "node_001",
      "label": "Enter the cave",
      "action_template_type": "simple_choice",
      "display_order": 0, "is_hidden": false,
      "rule": { "id": "rule_001", "action_id": "action_001", "rule_type": "none" },
      "outcomes": [
        {
          "id": "outcome_001", "action_id": "action_001",
          "label": "With torch", "priority": 1,
          "transition": {
            "id": "trans_001", "source_node_id": "node_001",
            "outcome_id": "outcome_001", "target_node_id": "node_002",
            "access_type": "free",
            "condition_group": {
              "id": "cg_001", "logic_mode": "all",
              "conditions": [{ "id": "c1", "state_key": "torch", "operator": "has_item", "expected_value": true }]
            },
            "effect_group": {
              "id": "eg_001",
              "effects": [{ "id": "e1", "state_key": "torch", "operation": "remove_item", "value": true }]
            }
          }
        },
        {
          "id": "outcome_002", "action_id": "action_001",
          "label": "In darkness", "priority": 2,
          "transition": {
            "id": "trans_002", "source_node_id": "node_001",
            "outcome_id": "outcome_002", "target_node_id": "node_003",
            "access_type": "free"
          }
        }
      ]
    }]
  },
  {
    "id": "node_002", "label": "Cave (Lit)",
    "node_type": "placeholder", "content_type": "text",
    "placeholder_summary": "Write the lit cave scene here.",
    "is_start": false, "is_ending": false, "actions": [],
    "position_x": 500, "position_y": 80
  },
  {
    "id": "node_003", "label": "Cave (Dark)",
    "node_type": "placeholder", "content_type": "text",
    "placeholder_summary": "Write the dark cave scene here.",
    "is_start": false, "is_ending": false, "actions": [],
    "position_x": 500, "position_y": 320
  }]
}