Reference Manual v6.0

Branching Course Editor

Reference Manual — v6.0

What is it? The Branching Course Editor is a visual, node-based authoring tool for creating interactive, non-linear learning experiences. Authors design courses as directed graphs where each node represents a content screen, a decision point, a quiz, or a flow-control mechanism. Connections between nodes define the paths learners can take, enabling deterministic, probabilistic, conditional, and gated branching.

The editor runs entirely in the browser as a single-page application. Courses are exported as portable JSON or YAML files and can be played back in the companion Course Player.

Key Concepts

ConceptDescription
NodeA single screen or logic point in the course. Each node has a type (content, decision, assessment, etc.), a title, optional body content, and a position on the canvas.
ConnectionA directed edge from one node to another. Connections have a type (default, conditional, weighted, random), an optional label, and may carry conditions or weights.
AttributeA named numeric variable that tracks learner progress (e.g., knowledge, confidence). Attributes are defined at the course level and modified by attribute effects on individual nodes.
PageA self-contained sub-graph within a course. Multi-page courses group related nodes together and use page_link nodes to navigate between pages.
LayoutEach node can have a custom visual layout made of content blocks (headings, text, images, callouts, quizzes). The layout editor controls how nodes appear to learners at runtime.
Start NodeThe designated entry point of the course. Exactly one node per page should be marked as the start node.

System Requirements

2. Interface Reference

2.1 Canvas

The canvas is the central work area where nodes are placed and connections are drawn. It is an infinite, pannable, zoomable surface with a dot-grid background.

FeatureInteraction
Grid40px dot grid (configurable). Provides visual alignment reference. Can be hidden via settings.
PanMiddle-click drag, Alt+click drag, Space+drag, or two-finger trackpad scroll.
ZoomCtrl/Cmd+scroll wheel or pinch gesture. Zoom range configurable (default 10% to 500%). Zoom percentage displayed in the menu bar.
Fit AllClick the fit button in the zoom controls, or use View > Fit all nodes. Automatically adjusts pan and zoom to show all nodes.
SelectClick a node to select it. Click empty canvas to deselect. Ctrl/Cmd+click to add/remove nodes from multi-selection.
Rectangle SelectClick and drag on empty canvas to draw a selection rectangle. All nodes within the rectangle are selected.
Empty Canvas HintWhen no nodes exist, a centered hint with instructions is displayed.
CONTENT Introduction DECISION Which path? ASSESSMENT Quiz END Complete Pass Fail
A simple branching flow: Content → Decision → Assessment or End

2.2 Toolbar & Menu Bar

The desktop interface uses a macOS-style menu bar across the top of the editor. Below the menu bar is a pages tab bar and a floating quick-add toolbar on the canvas.

Menu Bar

MenuItems
FileCourse Database, Load from server, Save to server, New page, Import file, Export YAML, Export JSON, Print diagram, Clear canvas
Add NodeContent, Decision, Assessment, End, Random, Weighted, Condition, Gate, Page Link. All items are draggable to the canvas.
ViewFit all nodes, Auto-arrange nodes, Read/Storyboard view, Horizontal layout, Vertical layout
ThemesDomain theme configuration
SettingsDark mode, System themes (Default, Midnight, Ocean, Warm, Slate, Forest, Rose, Violet), All settings...

Quick-Add Toolbar

A floating pill-shaped toolbar centered at the top of the canvas. Contains the most common node types as colored buttons. Each button can be clicked to add at the center of the viewport, or dragged directly to a position on the canvas. The toolbar can be collapsed to a small "Add" stub.

Quick-add buttons: Content Decision Quiz Condition Page Link End

Additionally, the toolbar includes toggle buttons for Link Drag and Downstream Drag physics modes, and a Node Repulsion toggle.

Zoom Controls

Located at the right end of the menu bar: zoom out (), zoom percentage display, zoom in (+), and fit-all () buttons.

2.3 Properties Panel

The right sidebar (default 288px wide) shows contextual property editors. It is organized into tabs:

TabContents
PropertiesWhen a node is selected: node ID (read-only), type selector, title, content (Markdown), options (for decision), questions (for assessment), condition/default_target (for condition/gate), target_page/target_node (for page_link), passing score (for assessment), success/failure targets (for assessment), attribute effects, media attachments, "Set as Start" button. When a connection is selected: from/to node IDs, type, label, condition, weight. When nothing is selected: course title, description, version, tags, metadata.
CodeRaw JSON/YAML view of the selected node, connection, or entire course data. Syntax-highlighted and read-only preview with copy button.
AttributesCourse-level attribute definitions. Each attribute has: name, description, default value, min, max. Below definitions: a Progression Map showing which nodes affect each attribute with visual bar charts.
SettingsAll editor configuration options organized into categories. See Section 9: Editor Settings.

2.4 Mobile Interface

On screens narrower than 768px, the interface adapts:

2.5 Keyboard Shortcuts

ShortcutAction
EscapeCancel current connection, deselect all nodes and connections
Delete / BackspaceDelete selected node(s) or connection (with confirmation if enabled)
Space (hold)Enter pan mode — click and drag to pan the canvas
Ctrl+click / Cmd+clickToggle node in multi-selection
Ctrl+scroll / Cmd+scrollZoom in/out at cursor position
Ctrl+SSave to server
Ctrl+EExport YAML
Ctrl+KFocus search (in this manual)
Alt+click dragPan the canvas
Middle-click dragPan the canvas
Tip
Keyboard shortcuts for Delete and Space only activate when focus is not in a text input or textarea field.

3. Node Types Reference

The editor supports 11 node types. Each type serves a distinct purpose in branching course design.

Content Decision Assessment Example Practice Random Weighted Condition Gate Page Link End
All 11 node types with their signature colors

Content Content Node

Purpose: Displays information to the learner. The most basic and commonly used node type. Content is displayed as Markdown with support for LaTeX math, tables, and images.

Properties
PropertyTypeDefaultDescription
idstringauto-generatedUnique identifier
typestring"content"Fixed type identifier
titlestring"New Content"Display title
contentstring""Markdown body text
positionobject{x:0, y:0}Canvas position {x, y}
isStartbooleanfalseWhether this is the start node
attribute_effectsarray[]Attribute modifications applied when visited
attachmentsarray[]Media file attachments
Connection Rules
Validation
Player Behavior

Renders the Markdown content with a "Next" or "Continue" button that follows the single outgoing default connection. Attribute effects are applied on node entry. If a layout is defined, it renders the layout blocks instead of raw Markdown.

Example JSON
JSON
{
  "id": "intro",
  "type": "content",
  "title": "Introduction",
  "content": "Welcome to the course! This is **Markdown** content.\n\nYou can use:\n- Lists\n- `code`\n- Math: $E = mc^2$",
  "position": { "x": 100, "y": 100 },
  "attribute_effects": [
    { "attr_id": "knowledge", "delta": 5, "when": "always" }
  ]
}
Common Pattern
Use content nodes for introductions, explanations, narrative passages, summaries, and transitions between sections. Chain them in sequence for linear progressions.

Decision Decision Node

Purpose: Presents the learner with explicit choices. Each option maps to an outgoing connection. The learner's selection determines which path is taken.

Properties
PropertyTypeDefaultDescription
idstringauto-generatedUnique identifier
typestring"decision"Fixed type identifier
titlestring"New Decision"Display title / question
contentstring""Markdown body text above the options
optionsarray[{id:"opt-a", label:"Option A"}, {id:"opt-b", label:"Option B"}]Choice options. Each has id, label, and optional description.
positionobject{x:0, y:0}Canvas position
attribute_effectsarray[]Attribute modifications
Connection Rules
Player Behavior

Renders content followed by a list of clickable choice buttons (labeled A, B, C...). When the learner selects an option, the player finds the outgoing connection whose label matches the option label and navigates to that node. If no match is found, the first connection is used as a fallback.

Example JSON
JSON
{
  "id": "fork-1",
  "type": "decision",
  "title": "Which path?",
  "content": "Choose your direction:",
  "options": [
    { "id": "opt-a", "label": "Beginner Path", "description": "Start from basics" },
    { "id": "opt-b", "label": "Advanced Path", "description": "Jump to the deep end" }
  ],
  "position": { "x": 300, "y": 100 }
}

Assessment Assessment Node

Purpose: Tests learner knowledge with one or more questions. Routes to different paths based on whether the learner passes or fails (score vs. passing threshold).

Properties
PropertyTypeDefaultDescription
idstringauto-generatedUnique identifier
typestring"assessment"Fixed type identifier
titlestring"New Assessment"Display title
contentstring""Instructions shown before questions
questionsarray[]Array of question objects
passing_scorenumber80Percentage required to pass (0-100)
success_targetstring""Node ID to navigate to on pass
failure_targetstring""Node ID to navigate to on fail
attribute_effectsarray[]Effects with when: "always", "pass", or "fail"
Question Types
TypeProperties
multiple-choiceprompt, options (array of {id, label, correct:bool}), points
true-falseprompt, correct_answer (boolean), points
short-answerprompt, correct_answer (string), points
numericprompt, correct_answer (number), tolerance, points
Connection Rules
Player Behavior

All questions are presented at once. The learner answers each, then clicks "Submit". The player calculates the percentage score, compares to passing_score, shows a pass/fail result with score breakdown, then navigates to success_target or failure_target. Attribute effects with when: "pass" or when: "fail" only apply for the corresponding outcome.

Example JSON
JSON
{
  "id": "quiz-1",
  "type": "assessment",
  "title": "Knowledge Check",
  "passing_score": 80,
  "questions": [
    {
      "id": "q1",
      "type": "multiple-choice",
      "prompt": "What is 2+2?",
      "options": [
        { "id": "a", "label": "3" },
        { "id": "b", "label": "4", "correct": true },
        { "id": "c", "label": "5" }
      ],
      "points": 10
    }
  ],
  "success_target": "module-2",
  "failure_target": "review-1",
  "position": { "x": 600, "y": 100 }
}

Example Example Node

Purpose: Displays a worked example, demonstration, or case study. Functionally similar to a content node but visually distinct to indicate its pedagogical role. Domain themes can automatically flavor example content.

Properties

Same as Content node with type: "example".

Connection Rules
Player Behavior

Renders identically to content with a green "Example" badge. In the player, a distinct badge style (green background) distinguishes it from standard content. When a domain theme is set, the layout editor can auto-generate domain-specific example content.

Example JSON
JSON
{
  "id": "ex-1",
  "type": "example",
  "title": "Worked Example: Quadratic Formula",
  "content": "Solve $x^2 + 5x + 6 = 0$...",
  "position": { "x": 200, "y": 300 }
}
Tip
If the editor encounters an unknown node type during import (such as "lesson" or "slide"), it maps them to content nodes automatically.

Practice Practice Node

Purpose: Provides an interactive practice exercise or hands-on activity. Like example, this is functionally a content node with distinct visual identity for instructional design clarity.

Properties

Same as Content node with type: "practice".

Connection Rules
Player Behavior

Renders with an orange "Practice" badge. Content is displayed as Markdown with a "Continue" button.

Example JSON
JSON
{
  "id": "practice-1",
  "type": "practice",
  "title": "Try It Yourself",
  "content": "Using the formula above, solve the following problems...",
  "position": { "x": 400, "y": 300 }
}

Random Random Node

Purpose: Introduces controlled randomness. The runtime picks one of the outgoing connections completely at random (uniform probability). Useful for randomized practice sets, unpredictable narrative branches, or A/B testing scenarios.

Properties
PropertyTypeDefaultDescription
idstringauto-generatedUnique identifier
typestring"random"Fixed type identifier
titlestring"New Random"Display title
contentstring""Optional text shown before branching
positionobject{x:0, y:0}Canvas position
Connection Rules
Player Behavior

Briefly displays the node content (if any), then automatically picks one outgoing connection uniformly at random and navigates to its target. The learner does not make a choice — the system decides.

Example JSON
JSON
{
  "id": "random-event",
  "type": "random",
  "title": "Random Encounter",
  "content": "Something unexpected happens...",
  "position": { "x": 400, "y": 200 }
}

Weighted Weighted Node

Purpose: Similar to random, but each outgoing connection carries a probability weight (0-100). The runtime samples proportionally. Useful for scenarios where some outcomes are more likely than others.

Properties

Same base properties as Random. Weights are stored on the connections, not the node itself.

Connection Rules
Validation
Player Behavior

Displays content briefly, then samples one outgoing connection proportionally to its weight. Probability chips are shown on the node in the editor to visualize the distribution.

Example JSON
JSON
{
  "id": "weighted-fork",
  "type": "weighted",
  "title": "Scenario Draw",
  "content": "The outcome depends on probability.",
  "position": { "x": 500, "y": 200 }
}
// Connections from this node:
// { from: "weighted-fork", to: "easy-path", type: "weighted", label: "Easy", weight: 70 }
// { from: "weighted-fork", to: "hard-path", type: "weighted", label: "Hard", weight: 30 }

Condition Condition Node

Purpose: Evaluates a runtime expression and routes the learner to the matching outgoing connection. Works like a programmatic switch/case statement. Used for adaptive routing based on scores, attributes, or custom variables.

Properties
PropertyTypeDefaultDescription
idstringauto-generatedUnique identifier
typestring"condition"Fixed type identifier
titlestring"New Condition"Display title
conditionstring""The variable or expression to evaluate
default_targetstring""Fallback node ID if no condition matches
positionobject{x:0, y:0}Canvas position
Connection Rules
Player Behavior

Evaluates each outgoing connection's condition expression against the current state (score, attributes, variables). Navigates to the first matching connection. If none match, navigates to default_target. See Expression Language Reference for syntax.

Example JSON
JSON
{
  "id": "score-router",
  "type": "condition",
  "title": "Score Router",
  "condition": "score",
  "default_target": "review-1",
  "position": { "x": 700, "y": 150 }
}

Gate Gate Node

Purpose: Blocks the learner at this point until a condition becomes true. Acts as a prerequisite check or conditional barrier. Once the condition is satisfied, the learner proceeds.

Properties
PropertyTypeDefaultDescription
idstringauto-generatedUnique identifier
typestring"gate"Fixed type identifier
titlestring"New Gate"Display title
contentstring""Message shown while gate is locked
conditionstring""Expression that must be true to pass. Empty string = always pass.
default_targetstring""Node ID to proceed to when gate opens
positionobject{x:0, y:0}Canvas position
Connection Rules
Player Behavior

When a learner arrives at a gate node, the condition is evaluated. If true, the learner passes through immediately. If false, the gate displays the content/message and a locked state. The runtime periodically re-evaluates the condition. A gate with an empty condition always passes immediately.

Example JSON
JSON
{
  "id": "prereq-gate",
  "type": "gate",
  "title": "Prerequisite Check",
  "content": "Complete Module 1 before continuing.",
  "condition": "completed_modules >= 1",
  "default_target": "module-2-intro",
  "position": { "x": 800, "y": 150 }
}

Purpose: Navigates to another page in a multi-page course. Acts as a portal between sub-graphs. The target can be a specific page and optionally a specific node within that page.

Properties
PropertyTypeDefaultDescription
idstringauto-generatedUnique identifier
typestring"page_link"Fixed type identifier
titlestring"New Page Link"Display title
target_pagestring""ID of the target page
target_nodestring""Optional: specific node ID within the target page
positionobject{x:0, y:0}Canvas position
Connection Rules
Player Behavior

When reached, the player switches to the target page and navigates to either the target_node or the start node of that page. Learner state (attributes, variables, score) is preserved across page transitions.

Example JSON
JSON
{
  "id": "go-to-page-2",
  "type": "page_link",
  "title": "Continue to Module 2",
  "target_page": "page-2",
  "target_node": "module-2-intro",
  "position": { "x": 1000, "y": 200 }
}

End End Node

Purpose: Marks the terminal point of a course path. No outgoing connections. Displays a completion screen with final statistics.

Properties
PropertyTypeDefaultDescription
idstringauto-generatedUnique identifier
typestring"end"Fixed type identifier
titlestring"New End"Display title
contentstring""Optional completion message
attribute_effectsarray[]Final attribute modifications
positionobject{x:0, y:0}Canvas position
Connection Rules
Player Behavior

Displays a completion screen with a trophy icon, the node title, optional content, and a statistics grid showing: final score, nodes visited, questions answered, and final attribute values. A "Restart" button allows the learner to begin the course again.

Example JSON
JSON
{
  "id": "finish",
  "type": "end",
  "title": "Course Complete",
  "content": "Congratulations! You have completed the course.",
  "position": { "x": 1200, "y": 150 }
}

Node Type Summary

TypeColorIconMax OutConn TypeHas OptionsHas Condition
contentBlue📄1defaultNoNo
decisionAmber🔀UnlimitedconditionalYesNo
assessmentEmerald📝2*defaultNoNo
exampleLime📚1defaultNoNo
practiceOrange🔧1defaultNoNo
randomViolet🎲UnlimitedrandomNoNo
weightedOrange⚖️UnlimitedweightedNoNo
conditionCyanUnlimitedconditionalNoYes
gateRose🚧1defaultNoYes
page_linkPurple📑1defaultNoNo
endGray🏁0N/ANoNo

* Assessment routing uses success_target / failure_target properties rather than standard connections.

4. Connection Reference

Connection Properties

PropertyTypeRequiredDescription
idstringAutoUnique connection identifier (auto-generated: conn-{timestamp})
fromstringYesSource node ID
tostringYesTarget node ID
typestringYesConnection type: default, conditional, weighted, or random
labelstringNoDisplay label on the edge. For decision nodes, matches option labels. For condition nodes, carries the condition expression.
conditionstringNoCondition expression (for conditional type)
weightnumberNo*Probability weight 0-100 (required for weighted type)

Connection Types

TypeUsed WithBehaviorExtra Fields
defaultcontent, gate, page_link, end, assessmentTaken automatically when the source node completes. Unconditional.None
conditionaldecision, conditionTaken only when the label/condition evaluates to true. For decision nodes, the label matches the selected option. For condition nodes, the label is an expression.label, condition
weightedweightedSampled by probability. The runtime generates a random number and selects a connection proportional to its weight.weight (0-100), label
randomrandomOne connection is selected uniformly at random. All connections have equal probability.label

Creating Connections

  1. Hover over a node to reveal connection points — small circles on the left (input) and right (output) sides of the node.
  2. Click and drag from an output point (blue circle, right side).
  3. A temporary line follows your cursor. Release on another node's input point (left side) to complete the connection.
  4. Press Escape to cancel an in-progress connection.

Editing: Click a connection line to select it (turns red). Edit its properties in the Properties panel. Click elsewhere to deselect.

Deleting: Select a connection and press Delete/Backspace, or use the delete button in the properties panel.

Connection Validation Rules

5. Attribute System Reference

Attributes are named numeric variables that represent learner characteristics (knowledge, confidence, skill level, etc.). They are defined at the course level, modified by node effects, displayed in the player's HUD, and can be used in condition/gate expressions.

Attribute Definitions

Defined in the Attributes tab of the properties panel. Each attribute has:

FieldTypeDescription
idstringUnique identifier (auto-generated: attr-{timestamp})
namestringDisplay name (e.g., "Courage", "Knowledge")
descriptionstringOptional description of what this attribute represents
defaultnumberStarting value (default: 0)
minnumber|nullMinimum value (null = no minimum)
maxnumber|nullMaximum value (null = no maximum)

Attribute Effects

Individual nodes can modify attributes when the learner visits them. Effects are configured in the Properties tab when a node is selected.

FieldTypeDescription
attr_idstringID of the attribute to modify
deltanumberAmount to add (positive) or subtract (negative)
whenstring"always", "pass", or "fail". For assessment nodes, "pass"/"fail" triggers only apply for the corresponding outcome.
Progression Map

The Attributes tab displays a visual Progression Map showing which nodes affect each attribute, with bar charts indicating the magnitude and direction of each effect. Click a node in the map to select it and jump to its properties.

Using Attributes in Expressions

Attributes are available as variables in condition and gate expressions. Reference them by their name (lowercase, underscores for spaces):

Expression
// In a condition node's outgoing connection:
knowledge >= 50

// In a gate node's condition:
confidence > 30 && skill_level >= 2

// Compound conditions:
(knowledge >= 80 || experience >= 5) && attempts < 3
Player HUD Display

When a course has attributes defined, the player shows an Attribute Bar below the header. Each attribute appears as a pill with an icon, name, and current value. When an attribute changes, a delta indicator (+N / -N) flashes with a green (increase) or red (decrease) animation.

Built-in icon mappings:

Attribute NameIcon
knowledge📚
confidence💪
experience
skill_level🎯
creativity🎨
critical_thinking🧠
intuition🔮
wisdom🦉
speed
accuracy🎯
research🔬
practical🔧
communication💬
leadership👑
teamwork🤝
default📊

6. Layout Editor Reference

Each node can have a custom visual layout that controls how it appears to learners at runtime. The layout editor is a full-screen modal with a block-based WYSIWYG canvas.

Opening the Layout Editor

Select a node, then click the "Edit Layout" button in the Properties panel. The editor opens as a full-screen overlay with three areas:

  1. Block Palette (left sidebar, 192px) — lists all available block types. Click or drag to add.
  2. Page Canvas (center, 900px default) — a positioned canvas with a dot-grid background where blocks are placed.
  3. Header Bar (top) — shows node name, canvas width presets, template menu, and close/save buttons.

Block Types

BlockIconDefault SizeProperties
heading 🔤 660 x 90 level (1-6), text (string), align (left/center/right)
text 📝 640 x 200 content (Markdown string), align (left/center/right)
callout 💡 640 x 140 style (info/warning/success), content (Markdown string)
image 🖼️ 500 x 320 url (image URL), alt (alt text), caption (optional). Supports upload via media endpoint.
video 🎬 640 x 160 url (embed URL or direct video URL), caption (optional). YouTube/Vimeo embeds auto-detected.
code 💻 660 x 240 language (string, e.g. "python", "javascript"), content (code string). Syntax highlighting via marked.js code blocks.
columns 780 x 240 columns (array of 2 column objects). Each column can contain text content. Renders as a side-by-side grid.
divider ── 640 x 48 No properties. Renders as a horizontal line separator.
quiz_question 660 x 340 question (string), choices (array of strings), answer_idx (number, 0-based correct choice index), explanation (optional string shown after answer)
nav_button 260 x 80 label (button text, e.g. "Next"), style (primary/secondary), _optId (optional: binds to a decision option for routing)
Positioning and Sizing

Each block has absolute positioning on the canvas with properties x, y, w (width), and h (height). Blocks can be:

Canvas Width Presets

The header bar provides width presets for the page canvas: common options include 640px (mobile), 900px (default), and wider options for desktop-first designs.

Templates

The layout editor includes pre-built templates accessible from the header menu:

TemplateContents
Lesson IntroHeading (H1), info callout (learning objectives), text block, primary nav button
Content SectionHeading (H2), text block, image, divider
Quiz SectionHeading (H2), quiz_question block, primary nav button ("Submit")
Two-ColumnHeading (H2), columns block with side-by-side content
Auto-Generated Layouts

When opening the layout editor for a node that has no layout, the editor auto-generates one based on the node type:

Tip
Hover over a node on the main canvas to see a miniature preview tooltip of its layout, showing a scaled-down rendering of all layout blocks.

7. Course File Format Specification

Courses are stored as JSON or YAML files. The format supports both single-page and multi-page structures.

Top-Level Structure

FieldTypeRequiredDescription
courseobjectYesCourse metadata
nodesarrayYes*Node list (single-page format)
connectionsarrayYes*Connection list (single-page format)
pagesarrayYes*Page list (multi-page format)

* Either nodes+connections (single-page) or pages (multi-page) must be present.

Course Metadata Object

FieldTypeDefaultDescription
idstringautoUnique course identifier
titlestring"Untitled Course"Course title
descriptionstring""Course description
versionstring"1.0.0"Semantic version string
tagsarray[]String tags for categorization
metadataobject{}Free-form metadata: author, created, estimated_time, etc.
attributesarray[]Attribute definitions (see Section 5)
themesarray[]Visual theme definitions
default_theme_idstring"theme-scholar"Active theme identifier

Single-Page Format

JSON
{
  "course": {
    "id": "my-course",
    "title": "My Course",
    "version": "1.0.0",
    "attributes": []
  },
  "nodes": [
    { "id": "start", "type": "content", "title": "Start", "content": "...", "position": {"x":100,"y":100} },
    { "id": "end", "type": "end", "title": "Done", "position": {"x":400,"y":100} }
  ],
  "connections": [
    { "from": "start", "to": "end", "type": "default" }
  ]
}

Multi-Page Format

JSON
{
  "course": {
    "id": "multi-page-course",
    "title": "Multi-Page Course",
    "version": "1.0.0"
  },
  "pages": [
    {
      "id": "page-1",
      "title": "Module 1",
      "nodes": [ /* ... */ ],
      "connections": [ /* ... */ ]
    },
    {
      "id": "page-2",
      "title": "Module 2",
      "nodes": [ /* ... */ ],
      "connections": [ /* ... */ ]
    }
  ]
}

Complete Example: Mixed Branching Course

YAML
course:
  id: "adventure-1"
  title: "The Forest Adventure"
  version: "1.0.0"
  attributes:
    - id: courage
      name: Courage
      default: 0
      min: 0
      max: 100

nodes:
  - id: "start"
    type: "content"
    title: "Forest Edge"
    content: "You stand at the forest edge."
    position: {x: 80, y: 200}
  - id: "fork"
    type: "decision"
    title: "Which way?"
    options:
      - {id: left, label: "Go left"}
      - {id: right, label: "Go right"}
    position: {x: 320, y: 200}
  - id: "encounter"
    type: "weighted"
    title: "Random Encounter"
    position: {x: 800, y: 200}
  - id: "quiz"
    type: "assessment"
    title: "Quick Check"
    passing_score: 70
    success_target: "win"
    failure_target: "retry"
    position: {x: 1280, y: 200}
  - id: "retry"
    type: "gate"
    title: "Retry Gate"
    condition: "attempts < 3"
    default_target: "quiz"
    position: {x: 1280, y: 380}
  - id: "win"
    type: "end"
    title: "Victory"
    position: {x: 1520, y: 200}

connections:
  - {from: "start", to: "fork", type: "default"}
  - {from: "fork", to: "encounter", type: "conditional", label: "Go left"}
  - {from: "encounter", to: "quiz", type: "weighted", label: "Friendly", weight: 70}
  - {from: "retry", to: "quiz", type: "default"}

8. Import & Export

Exporting

FormatHowDetails
YAMLFile > Export YAMLProduces a .yaml file using js-yaml. Human-readable, ideal for version control.
JSONFile > Export JSONProduces a .json file. Indentation controlled by the prettyJson setting (default: 2-space indent). Set to false for compact output.
Export Options (controlled by settings)
Export Behavior

Importing

How: File > Import file, or the mobile More sheet "Import" button. Accepts .json, .yaml, and .yml files.

Format Detection
Import Handling
Legacy Format Support

Unknown node types encountered during import (e.g., "lesson", "slide", "info") are automatically mapped to the content type.

Print

File > Print diagram opens the browser's print dialog. The canvas is rendered without the grid, toolbar, sidebar, and status bar. Nodes retain their visual styling. Uses landscape orientation by default.

9. Editor Settings Reference

All settings are persisted to localStorage. Access via Settings menu > All settings, or the Settings tab in the properties panel.

Appearance

SettingTypeDefaultDescription
showGridbooleantrueShow the dot-grid background on the canvas
gridSizenumber40Grid spacing in pixels
nodeShadowsbooleantrueShow box shadows on nodes
animationsbooleantrueEnable CSS transitions and animations
fontSizenumber13Base font size in pixels
sidebarWidthnumber288Properties panel width in pixels

Canvas

SettingTypeDefaultDescription
snapToGridbooleanfalseSnap node positions to grid
zoomSpeednumber0.10Zoom step per scroll increment
zoomMinnumber0.10Minimum zoom level (10%)
zoomMaxnumber5Maximum zoom level (500%)
autoFitbooleantrueAuto-fit view after import/load

Nodes

SettingTypeDefaultDescription
defaultNodeTypestring"content"Default type for new nodes
nodeWidthnumber220Node width in pixels
showTypeLabelsbooleantrueShow type label badge on nodes
showContentPreviewbooleantrueShow content preview text on nodes
showOptionChipsbooleantrueShow option chips on decision nodes
showNodeIdsbooleanfalseDisplay node IDs on the canvas
nodeRadiusnumber8Node border radius in pixels
compactNodesbooleanfalseUse compact node rendering

Connections

SettingTypeDefaultDescription
connStylestring"curve"Connection line style (curve or straight)
arrowStylestring"arrow"Arrow head style
connColorstring"default"Connection color scheme
connHoverbooleantrueHighlight connections on hover
showConnLabelsbooleantrueShow labels on connection edges
edgeThicknessnumber2Connection line thickness in pixels

Behavior

SettingTypeDefaultDescription
selectOnAddbooleantrueAutomatically select newly added nodes
confirmDeletebooleantrueShow confirmation dialog before deleting nodes/connections
confirmClearbooleantrueShow confirmation before clearing the canvas
propsOnSelectbooleantrueAuto-switch to Properties tab when a node is selected
layoutDirstring"horizontal"Auto-arrange layout direction (horizontal or vertical)

Physics

SettingTypeDefaultDescription
nodeRepulsionbooleantrueEnable node repulsion physics (nodes push away from each other to avoid overlap)
linkedDragbooleantrueWhen dragging a node, connected nodes are pulled along as if connected by elastic ropes
downstreamDragbooleanfalseWhen dragging a node, all downstream (connected-forward) nodes move rigidly with it

Export

SettingTypeDefaultDescription
exportFormatstring"yaml"Default export format
prettyJsonbooleantruePretty-print JSON exports with 2-space indentation
exportMetabooleantrueInclude metadata in exports

API / Server

SettingTypeDefaultDescription
apiBaseUrlstring"http://localhost:8001"Base URL for the course API server
autoLoadbooleanfalseAuto-load last course from localStorage on startup
showServerErrorsbooleantrueDisplay server error messages
autoSavebooleantrueAuto-save to server periodically
autoSaveIntervalnumber30Auto-save interval in seconds
saveIndicatorbooleantrueShow save toast notifications

Rich Content

SettingTypeDefaultDescription
renderMarkdownbooleantrueRender Markdown in node content previews
renderLatexbooleantrueRender LaTeX math expressions
renderTablesbooleantrueRender Markdown tables
allowImagesbooleantrueAllow inline images in content

Accessibility

SettingTypeDefaultDescription
highContrastbooleanfalseEnable high-contrast mode
focusRingbooleanfalseShow visible focus rings on interactive elements
reduceMotionbooleanfalseDisable animations for motion sensitivity

10. Player Reference

The Course Player renders branching courses for learners. It supports file upload, URL loading, and a built-in course catalog with server integration.

State Variables

The player maintains these state variables throughout a session:

VariableTypeDescription
nodeIdstringCurrent node ID
scorenumberAccumulated score (from assessments)
historyarrayOrdered list of visited nodes: [{id, title}]
varsobjectCustom variables set by set_variables blocks on nodes
attrsobjectCurrent attribute values (from attribute_effects)
visitedSetSet of all node IDs that have been visited
quizAnswersobjectMap of node ID to quiz response data
Built-in Variables Available in Expressions
VariableTypeDescription
scorenumberCurrent accumulated score
completed_modulesnumberCount of visited content-type nodes
attemptsnumberTotal number of unique nodes visited
questions_answerednumberNumber of quiz questions answered
All custom varsvariesAny variable set via set_variables
All attrsnumberCurrent value of each defined attribute

Runtime Behavior by Node Type

Node TypePlayer RenderingNavigation
contentMarkdown content with "Next" buttonFollows single default connection
exampleSame as content, green badgeFollows single default connection
practiceSame as content, orange badgeFollows single default connection
decisionContent + choice buttonsFollows connection matching selected option
assessmentQuiz questions + submit buttonRoutes to success_target or failure_target based on score
randomBrief content display (auto-advance)Randomly selects one outgoing connection
weightedBrief content display (auto-advance)Weighted random selection of outgoing connection
conditionTransparent (auto-advance)First matching condition expression, or default_target
gateShows locked message if condition is falseProceeds when condition becomes true
page_linkTransparent (auto-advance)Switches to target page
endCompletion screen with statsNone (terminal). Restart button available.

Attribute HUD

When a course defines attributes, the player displays an attribute bar below the header. Each attribute shows as a pill with icon, name, and current value. Changes animate with flash effects (green pulse for increases, red pulse for decreases) and show delta indicators.

History / Breadcrumb Trail

A breadcrumb trail at the top of the content area shows the path taken: each visited node's title is listed, separated by arrows. The current node is highlighted. A floating history FAB opens a slide-out panel listing all visited nodes.

Restart Behavior

Clicking the restart FAB (or the restart button on the end screen) resets all state: score, history, vars, attrs, visited, and quizAnswers return to their initial values. The player navigates back to the start node.

11. Validation Rules

The editor continuously validates the course and shows issue counts in the status bar. Nodes with issues display a warning badge.

Node-Type Specific Rules

RuleSeverityDescription
Single-output overflowWarningContent, gate, and page_link nodes can only have 1 outgoing connection. Additional connections trigger this warning.
End node has outgoingErrorEnd nodes must be terminal. Any outgoing connections are invalid.
No start nodeWarningIf the course has nodes but none are marked as the start node, a course-level warning appears.

Connection Rules

RuleBehavior
Self-connectionSilently rejected (connection is not created)
Duplicate connectionSilently rejected
Connection to end nodeRejected with hint message
Excess connection on single-outputAllowed but warning displayed

Course-Level Rules

Status Bar

The bottom status bar displays: node count, connection count, and issue count. Clicking the issue indicator can reveal details about each validation problem with the option to navigate to the affected node.

12. Common Patterns & Recipes

Linear Progression

The simplest pattern. Chain content nodes in sequence.

Content A → Content B → Content C → End

Use: Tutorials, presentations, guided walkthroughs.

Binary Choice

A decision node with exactly two options leading to different paths.

Content → Decision (A / B) → Path A → End
                                → Path B → End

Use: Choose-your-own-adventure, A/B scenarios, beginner vs. advanced tracks.

Multi-Path Scenario

A decision with 3+ options, each leading to unique content, eventually converging back to a common node.

Decision (A/B/C) → Path A →
                   → Path B → Merge Point → Continue
                   → Path C →

Use: Role-play scenarios, case studies with multiple approaches.

Assessment with Remediation Loop

Assessment routes failures back through review content, then re-tests. A gate limits retry attempts.

Content → Assessment -(pass)→ Next Module
                       -(fail)→ Review Content → Gate (attempts < 3) → Assessment

Use: Certification courses, mastery learning, skill verification.

Probabilistic Outcomes

A weighted node distributes learners across paths by probability.

Content → Weighted (70%/30%) → Easy Scenario (70%)
                                → Hard Scenario (30%)

Use: Simulated real-world variance, randomized case studies, gamification.

Attribute-Gated Progression

Use attributes and gate/condition nodes to create adaptive paths based on accumulated learner traits.

Content (+5 knowledge) → Content (+5 knowledge) → Gate (knowledge ≥ 10) → Advanced Topic

Use: Adaptive learning paths, RPG-style skill trees, prerequisite enforcement.

Multi-Page Course

Organize a large course into pages (chapters/modules). Use page_link nodes to navigate between them.

Page 1: Intro → Content → Page Link (to Page 2)
Page 2: Content → Assessment → Page Link (to Page 3)
Page 3: Content → End

Use: Large courses, multi-chapter textbooks, modular curricula.

Adaptive Difficulty

Combine assessments with condition nodes to route learners based on their performance.

Assessment → Condition (score) -(score ≥ 90)→ Advanced Track
                                  -(score ≥ 60)→ Standard Track
                                  -(score < 60)→ Remediation Track

Use: Differentiated instruction, placement testing, scaffolded difficulty.

Assessment Condition Advanced Standard Remediation End ≥90 ≥60 <60
Adaptive difficulty pattern: Assessment → Condition → three tracks

13. Expression Language Reference

Expressions are used in condition nodes (outgoing connection labels) and gate nodes (condition field). They are evaluated at runtime using JavaScript semantics.

Operators

OperatorMeaningExample
==Equality (loose)path == "scenic"
===Strict equalityscore === 100
!=Inequalityattempts != 0
<Less thanscore < 50
<=Less than or equalknowledge <= 30
>Greater thanconfidence > 80
>=Greater than or equalscore >= 90
&&Logical ANDscore >= 70 && attempts < 3
||Logical ORknowledge > 50 || experience > 5
!Logical NOT!visited_scenic
+ - * /Arithmeticscore + bonus >= 100
%Moduloattempts % 2 == 0
()Grouping(a || b) && c

Available Variables

SourceVariables
Built-inscore, completed_modules, attempts, questions_answered
Custom varsAny key set via set_variables on nodes (e.g., path, visited_scenic)
AttributesAll defined attributes by name (e.g., knowledge, confidence, courage)

Example Expressions

Expressions
// Simple threshold
score >= 80

// Attribute check
knowledge >= 50 && confidence > 20

// Custom variable check
path == "scenic" && visited_scenic

// Compound with grouping
(score >= 90 || (knowledge >= 80 && experience > 3)) && attempts < 5

// Arithmetic in condition
score + bonus >= 100

// Negation
!completed_intro

Evaluation Order

  1. All current state variables are collected: vars + attrs + built-in variables.
  2. The expression string is evaluated as a JavaScript expression with variables injected as function parameters.
  3. The result is coerced to a boolean.
  4. If evaluation throws an error (e.g., undefined variable), the result defaults to false.
Warning
Expressions are evaluated using new Function(). Avoid injecting user-controlled strings into expressions in production environments. For authored courses, this is safe as the course author controls all expression content.

14. Troubleshooting & FAQ

"My connections are not showing"

  • Ensure you are dragging from the output port (right side, blue circle) to the input port (left side) of another node.
  • Self-connections (same source and target) are silently rejected.
  • Duplicate connections (same from/to pair already exists) are silently rejected.
  • Connections into end nodes are blocked.
  • Check the zoom level — at very low zoom, thin connection lines may be hard to see.
  • Verify the showConnLabels and edgeThickness settings.

"Assessment is not routing correctly"

  • Verify that success_target and failure_target contain valid node IDs that exist in the course.
  • Check passing_score — it is a percentage (0-100). A score of 80 means the learner needs 80% correct.
  • Ensure your questions have correct: true marked on the right option, or correct_answer set for true-false questions.
  • If using attribute effects with when: "pass"/"fail", make sure the when field is set correctly.

"Gate node is stuck / learner cannot proceed"

  • Check the gate's condition expression. Use the expression reference to ensure syntax is correct.
  • Verify that the variables referenced in the condition are actually being set by earlier nodes (via set_variables or attribute_effects).
  • An empty condition always passes immediately. If the gate should be open, clear the condition field.
  • Ensure default_target points to a valid node ID.
  • Check that the gate has an outgoing connection or a default_target.

"Attributes not updating in the player"

  • Attributes must be defined at the course level (Attributes tab) before they can be referenced in effects.
  • Attribute effects on nodes must reference the correct attr_id matching a defined attribute.
  • Check the delta value — a delta of 0 has no effect.
  • For assessment nodes, check the when field — effects with when: "pass" only apply when the learner passes.
  • Verify that the learner actually visits the node (check history in the player).

"Import failed"

  • Ensure the file is valid JSON or YAML. Use a validator tool to check syntax.
  • The file must contain either a nodes array (single-page) or a pages array (multi-page) at the top level.
  • The course object is optional but recommended. If missing, defaults are applied.
  • Check for trailing commas (invalid in JSON) or incorrect YAML indentation.
  • If the file was exported from an older version, unknown node types are mapped to content automatically.

"Nodes overlap / cluttered layout"

  • Use View > Auto-arrange nodes to apply the tree layout algorithm.
  • Enable Node Repulsion in settings or the quick toolbar to have nodes push apart automatically.
  • Use View > Fit all nodes to adjust zoom and pan to see all nodes.
  • Try switching between horizontal and vertical layout directions.

"Weighted node probabilities seem wrong"

  • Verify that all outgoing connections from the weighted node have a weight value set.
  • Weights should ideally sum to 100. If they do not, the runtime normalizes them proportionally.
  • Remember: probability does not guarantee specific outcomes in small sample sizes. A 70/30 split may not produce exactly 7 and 3 results in 10 runs.

"Condition node always takes the default path"

  • Check that each outgoing connection's label contains a valid expression.
  • Connections are evaluated in order; ensure the most specific conditions come first.
  • Undefined variables evaluate to undefined, causing comparisons to fail. Make sure variables are set before the condition node is reached.
  • Use the Code tab to inspect the raw condition expressions.

"Auto-save is not working"

  • Auto-save requires a running API server at the configured apiBaseUrl.
  • Check that autoSave is enabled in settings.
  • Verify the server is accessible (check browser DevTools console for CORS or network errors).
  • The course must have been saved to the server at least once (via File > Save to server) before auto-save activates.

Branching Course Editor Reference Manual — Version 6.0
Last updated: March 2026
Tutorial · Open Editor · Course Player · Course Database