InViNode v1.13.1

A node-graph editor for building Ren'Py visual novel scripts visually. Connect nodes to define dialogue flow, choices, scene changes, and logic — then export the result directly as a .rpy file.

Before you start: This tool generates Ren'Py script code. You still need a working Ren'Py project on your computer. Export the .rpy file into your project's game/ folder.

Quick Start

  1. Open the app. An empty canvas appears.
  2. Add a node via the + Add Node button or right-click on the canvas. The first non-label node automatically creates a start label above it.
  3. Edit the node by clicking it (opens the right-side inspector) or double-clicking it (opens the full-screen modal editor).
  4. Connect nodes by dragging from the bottom handle of one node to the top handle of another.
  5. Export with the Export .rpy button in the toolbar.
Tip: Set your Ren'Py Project Folder in Settings → the game/ directory of your project. Scan buttons will then find your images, audio, and transitions automatically.

Interface Tour

Toolbar (top bar)

ElementWhat it does
Project nameClick and type to rename your project. Used as the default filename when saving.
+ Add NodeOpens a categorised dropdown menu listing all available node types.
/ Undo / Redo the last graph change.
🆕 New FlowAdds a flow. On an empty canvas it opens a new blank flow slot immediately; on a canvas with content, it asks whether to save the current canvas as a named flow (then open a fresh blank one) or overwrite it. Registries and project folder are always preserved. See Multi-Flow Projects.
SaveSaves the whole project — every flow plus all registries — to its .ivn.json file. Writes silently once a project folder is known; only shows a save dialog if it isn't. See Save & Open.
OpenOpens a previously saved .ivn.json (or legacy .json) project file via a file picker, replacing the current graph. See Save & Open.
Import ▾Imports an external script into the canvas. Choose from: Ren'Py script (.rpy), Mermaid diagram (.mmd / .md), or Twine 2 story (.html). See Import formats.
👥 CharactersManage character definitions (identifier, display name, colour).
📋 VariablesManage project variables and their default values.
🖼 ImagesManage the image registry (name → file path mappings).
🎵 AudioManage the audio registry (display name → file path).
🔍 SearchOpens the node search panel. Also triggered by Ctrl+F.
📁 ProjectsOpens the Project Switcher — browse, inspect, open, or scaffold Ren'Py projects. Requires a Projects Root set in Settings. See Project Switcher.
📖 HelpOpens this manual in a separate window.
Opens Settings: project folder, keyboard shortcuts, startup options, and canvas display settings.
Export .rpy ▾Exports the graph as a Ren'Py script. Click to choose Single File or Multiple Files. See Export .rpy.

Canvas (centre)

The main working area. Drag nodes around, zoom with the scroll wheel, and pan by dragging an empty area. The minimap (bottom-right) gives an overview of large graphs.

Inspector panel (right side)

Appears when a node is selected. Shows all editable fields for that node in a compact form. Changes apply immediately to the graph.

Modal editor

Double-click any node to open a full-screen modal editor with more space — especially useful for long dialogue text and Python code blocks. Press Esc or click outside to close.


Adding Nodes

There are three ways to add a node:

  • Toolbar dropdown: Click + Add Node and choose from the categorised list.
  • Right-click context menu: Right-click anywhere on the empty canvas to open the same menu at that position.
  • Keyboard shortcut: Press Ctrl + the assigned letter to spawn a node at the centre of the viewport. Shortcuts are configurable in Settings.
Auto-label: Every Ren'Py script needs at least one label. If you add a node to an empty canvas, a start label is created automatically above it and connected. You don't need to add a Label node manually for the first scene.

Connecting Nodes

Each node has a bottom handle (output) and a top handle (input). Drag from the bottom handle of one node and drop onto the top handle of another to create a connection. The connection defines the execution order.

Menu nodes have one handle per choice. Connect each choice handle to the first node of that branch.

Jump edges

When you connect a node to a Label node (or a named Menu), the edge is automatically marked as a jump edge — it renders with a badge and exports a jump statement rather than inline flow.

Dragging from a handle to empty canvas

If you drag a handle and release on empty canvas (not on another node), the context menu opens pre-loaded with the source connection, so the new node you pick is automatically wired in.

Editing Nodes

Inspector panel (single-click)

Click any node once to select it. The right-side inspector shows all its fields. Every change applies immediately — there is no separate Save button for individual node edits.

Modal editor (double-click)

Double-click any node to open the full-screen modal editor. It shows the exact same fields as the inspector, but with:

  • Much taller text areas for dialogue and narration text
  • A larger code editor for Python blocks
  • More comfortable spacing overall

Press Esc, click the ✕ button, or click the dark backdrop to close the modal. Changes still apply immediately.

Image preview

On imagepath fields (Scene, Show, Side Image), a small thumbnail preview of the selected image appears below the field in both the inspector and the modal editor — provided the image is registered and the Project Folder is set. The preview hides itself silently if the file cannot be found.

Deleting & Moving

Deleting a node

  • Select a node and press Delete.
  • Or click the Delete button in the inspector or modal editor.

Smart reconnect: If the deleted node had exactly one incoming and one outgoing connection, those two are automatically bridged so you don't have to rewire.

Multi-select and bulk delete

Hold Shift and drag on an empty area of the canvas to draw a selection rectangle. All nodes inside the rectangle are selected. Press Delete to remove all selected nodes at once (no smart reconnect for bulk deletes).

Deleting an edge

Click an edge to select it (it highlights), then press Delete.

Moving nodes

Drag any node to reposition it. The canvas snaps to a 16 px grid. Hold nothing — just drag.


Story Nodes

🏷 Label Structure
Defines a Ren'Py label — an entry point for flow control and jump targets. Every script needs at least one. The first label is always named start.
label start:
📖 Narrative Story
Narrator text with no character — shown at the bottom of the screen in quotes. Supports optional if/elif/else conditions to show the line conditionally.
"It was a dark and stormy night."
💬 Dialog Story
A line of dialogue spoken by a character. The Character field accepts a Ren'Py identifier (e.g. mc). Typing a new identifier auto-registers it. Use the Speech type field to set how the text renders: Talk (normal), Whisper (italic {i}…{/i}), Thought (parenthesised), or Yell (bold {b}…{/b}). A badge on the canvas card shows when a non-default type is active.
mc "Hello, world!"
📋 Menu Story
A choice menu. Add choices with labels and optional conditions. Each choice gets its own output handle. Connect choice handles to the first node of each branch.
menu:
  "Yes":
  "No":
Menu branching tip: Nodes connected directly to a choice handle execute inside that branch. To continue the story once after the menu ends, connect each choice to a shared Label node — the exporter emits jump statements automatically.

Scene & Media Nodes

🎬 Scene Media
Clears the screen and shows a background image. Select the image from the registry (🔍 to scan, 📁 to pick a file) and optionally set a transition.
scene bg forest with dissolve
🖼 Show Media
Shows a sprite (character or prop) at a position on screen. Accepts an image name from the registry and an optional position tag and transition.
show eileen happy at left with dissolve
👁️ Hide Media
Hides a displayed sprite. Enter the image tag to hide and an optional transition.
hide eileen with dissolve
Pause Media
Pauses execution. Leave the duration blank for an indefinite pause (waits for player click). Enter a number (in seconds) for a timed pause.
pause 2.0
📌 Side Image Media
Defines and shows a persistent side image (prop, HUD element, or secondary sprite). First registers the image name, then positions it at a screen anchor. Fields: name, file path, position (left/right/center/topleft/topright/offscreenleft/offscreenright), optional transition.
image side gun = "images/prop_gun.png"
show side gun at right

Using the image registry

Scene, Show, and Hide nodes use image names (Ren'Py identifiers like bg forest), not file paths. Register names in the Images panel (🖼 in the toolbar) or use the 🔍 / 📁 buttons on the node field itself.

Canvas thumbnails

Scene and Show nodes can display a small image thumbnail directly on the canvas card, so you can see which image is attached at a glance. Toggle this in Settings → Canvas → Show node thumbnails. Thumbnails require the Project Folder to be set and the image to be registered.

Audio Nodes

🎵 Play Music Audio
Plays background music. Supports a playlist (multiple tracks) with optional fadeout and fadein durations. Uses play music statement.
play music "audio/theme.ogg" fadein 1.0
🔊 Play Sound Audio
Plays a one-shot sound effect. Uses play sound statement.
play sound "audio/click.ogg"
🔇 Stop Music Audio
Stops the currently playing music with an optional fadeout duration.
stop music fadeout 2.0

Audio paths are relative to the game/ folder, e.g. audio/main_theme.ogg. Register paths in the Audio panel (🎵) or use the scan buttons on the node fields.

Logic & Flow Nodes

📌 Variable Update Logic
Sets a variable to a value. The variable name is auto-registered on blur. Choose the operator (=, +=, -=) and enter the value.
$ kind = True
🔀 Condition Logic
An if/elif/else branch. Chain multiple Condition nodes together — the first is if, middle ones are elif, last can be else.
if kind:
Jump Flow
Emits a jump statement to transfer execution to another label. Hidden from the add-node menu — created automatically when you connect a node to a Label.
jump outro
📞 Call Flow
Calls another label and returns after it finishes. Hidden from the add-node menu — add manually if needed.
call intro
🔔 Notify Logic
Shows a small toast notification to the player at runtime. Enter the message text in the single Message field. The canvas card previews the message text with a 🔔 icon.
$ renpy.notify("Checkpoint reached!")

Condition chains

To build an if / elif / else chain, add multiple Narrative or Dialog nodes and set their Condition type field:

  • if — independent check (always evaluated)
  • elif — chained else-if (only checked if the previous was false)
  • else — catch-all (no condition needed, field is hidden)

Code Node

Python Code
A block of Python code. Use the modal editor (double-click) for the full code editing experience — the modal gives a much larger code area than the side panel.
python:
  kind = True
  renpy.notify("Done")
Indentation: Ren'Py uses Python-style indentation. Code inside a python: block should be indented with spaces. The editor preserves your indentation exactly as typed.

Characters Panel

Open with 👥 Characters in the toolbar. Each entry has:

  • Identifier — the Ren'Py variable name used in Dialog nodes (e.g. mc). This is also what you type in the "Character" field on a Dialog node.
  • Display name — the name shown in-game above the dialogue box (e.g. Main Character).
  • Colour — used in the game's name card. Click the swatch to change it.

Characters are auto-created when you type a new identifier in a Dialog node and leave the field. You can then rename or recolour them in this panel.

Characters are exported at the top of the .rpy file as define mc = Character("Main Character", color="#f87171").

Variables Panel

Open with 📋 Variables in the toolbar. Each variable has a name and a default value.

Variables are auto-created when you type a new name in a Variable Update node. Set the default value here — it controls the starting state of that variable at game launch.

Exported at the top of the .rpy file as default kind = False. Ren'Py's default statement only sets the value if the variable hasn't been set before, so save games work correctly.

Images Panel

Open with 🖼 Images in the toolbar. Each entry maps an image name to a file path.

  • Name — the Ren'Py image identifier (e.g. bg forest, eileen happy). Used in Scene/Show/Hide node fields.
  • Path — file path relative to game/ (e.g. images/bg_forest.png).

Use 🔍 Scan project (or Scan folder) to bulk-import all image files from your images folder. Images with standard names are auto-converted to Ren'Py identifiers.

Exported as image bg forest = "images/bg_forest.png" definitions at the top of the .rpy file.

Audio Panel

Open with 🎵 Audio in the toolbar. Each entry maps a display name to a file path.

Registered paths appear as autocomplete suggestions in Play Music and Play Sound node fields. Audio is not exported as define statements — paths are used directly in play music / play sound statements.

Use 🔍 Scan project to find all audio files in your audio/ folder, or + Add to register a track manually.


Importing Scripts

The Import ▾ toolbar button lets you bring an existing script into the canvas as a node graph. Three formats are supported:

Ren'Py script (.rpy)

Parses a .rpy file and converts labels, dialogue, narration, menus, scene/show/hide commands, and variable statements into nodes. An import log is shown after the import listing what was recognised, what was skipped, and any unresolved identifiers (characters or variables not yet in the registry).

Partial import: Not all Ren'Py syntax is supported. Comments, init blocks, Python functions, and advanced control flow are skipped. The importer is best used as a starting point for migration, not a full round-trip.

Mermaid diagram (.mmd / .md)

Parses a Mermaid flowchart or graph definition and converts nodes and edges into the canvas. Node labels become Narrative nodes; edge labels become Dialog nodes. A start label is placed at the entry node automatically.

Twine 2 story (.html)

Parses a Twine 2 HTML export (any story format) and converts passages into Label + Narrative nodes. Links between passages become edges. Variables referenced in the story are added to the variable registry as stubs.

Import replaces the canvas. Importing clears all existing nodes and edges. Save your project first if you want to keep the current graph.

Project Folder Setting

Open Settings (⚙) → Settings tab and set the Ren'Py Project Folder to the game/ directory of your Ren'Py project (e.g. D:\MyGame\game).

When configured:

  • Image scan buttons automatically target game/images/
  • Audio scan buttons automatically target game/audio/
  • Transition scan buttons automatically target game/ (scans .rpy files for custom transition names)
  • Canvas image thumbnails and image preview in the inspector both resolve from this folder

Without a project folder, each scan button opens a folder-picker dialog instead.

The project folder is saved per project — stored in the .ivn.json save file. If you open a project on a different machine and the stored path no longer exists, an amber warning banner appears in the toolbar reminding you to update the setting.

Ren'Py Projects Root

Set a Projects Root folder (e.g. D:\RenPy Projects\) in the Settings tab. InViNode scans that folder for valid Ren'Py projects (any subfolder containing a game/ directory) and makes them available in the Project Switcher.

Multi-Flow Projects

A project isn't limited to a single canvas. Split a long story into named, tabbed flows — one per chapter, route, or character arc — using the flow tabs bar that appears below the toolbar once a project has at least one named flow.

ActionWhat it does
Click an inactive tabSwitches the canvas to that flow. The flow you're leaving keeps its current state.
Click the active tabEnters inline rename mode for that tab.
Double-click any tabAlso enters inline rename mode.
Enter / click awayCommits the new name. Esc cancels.
on a tabDeletes that flow. Hidden when only one flow remains — a project always needs at least one.
+Adds a new, empty flow at the end of the tab bar.

The toolbar's 🆕 New Flow button is the other way to add a flow — see the Interface Tour for how it behaves on an empty vs. non-empty canvas. Characters, variables, images, and audio registries are shared across every flow in a project; they're never cleared when you switch tabs.

Linking flows: Jump and Call nodes target a label by typed name, not by a canvas connection — so they can reference a label defined in any flow in the project, not just the active one. Every flow exports into the same Ren'Py label namespace, exactly like separate .rpy files would.

Saving and exporting always act on the whole project — every flow, not just the active tab. See Save & Open and Exporting to Ren'Py.

Project Switcher

Click 📁 Projects in the toolbar to open the Project Switcher (requires a Projects Root to be set in Settings). It's a master-detail view: a searchable project list on the left, a detail pane on the right.

Browsing and opening a project

Clicking a project in the list doesn't open it — it populates the detail pane with the project's path and, if it's been opened in InViNode before, its created/last-modified dates and flow, label, and node counts. Click the Open button in the detail pane to actually switch to it.

On Open, InViNode first silently saves the current project (if a project folder is set), then looks for the target project's own .ivn.json:

  1. Found — loads it immediately, no further steps.
  2. Not found — falls back to a picker listing any legacy .json save files, plus a Start fresh option that clears the canvas, auto-scans the project's images/audio/registry files, reads the project name from options.rpy, and imports script.rpy as the first flow if one exists.

If the canvas has unsaved changes, a confirmation dialog appears before switching either way.

Creating a new project

The + New Project button (top of the switcher, requires a Projects Root) scaffolds a brand-new Ren'Py project — the default GUI, options.rpy, gui.rpy, screens.rpy, a starter script.rpy, and empty images//audio/ folders — from a bundled template. Just give it a name; no Ren'Py SDK or renpy.exe install is required. The new project is selected automatically once it's created, ready to open.

Tip: For a project with no save file yet, Start fresh auto-scans images, audio, and registry files, and imports script.rpy as a starting flow — you shouldn't need to hit the scan buttons manually right after creating or first-opening a project. For older projects that already have a save file, registries load from that save automatically.

Keyboard Shortcuts

Canvas shortcuts

KeyAction
DeleteDelete the selected node or edge
Shift + dragDraw a selection rectangle to select multiple nodes
Delete (multi-select)Delete all selected nodes at once
Ctrl+ZUndo
Ctrl+Shift+Z / Ctrl+YRedo
Ctrl+FOpen node search
Scroll wheelZoom in / out
Click empty canvasDeselect everything
Right-click canvasOpen the node context menu
Right-click Label nodeOpen the label context menu (Export this label…)
Double-click nodeOpen the full-screen modal editor
EscClose the modal editor or search panel

Node spawn shortcuts

Hold Ctrl + the assigned letter to spawn a node at the viewport centre. Default bindings:

ShortcutNode type
Ctrl+LLabel
Ctrl+NNarrative
Ctrl+DDialog
Ctrl+MMenu
Ctrl+VVariable Update
Ctrl+SScene

All shortcuts are reassignable in Settings → Shortcuts tab. Click a badge to reassign it, then press any letter key.

Startup & Canvas Settings

These options are in the Settings tab of the Settings panel and are stored globally (not per project).

Load last project on startup

When enabled, InViNode automatically re-opens the last saved or opened .json file on launch. If the file has been moved or deleted, the startup silently starts with an empty canvas instead.

Show node thumbnails

When enabled, Scene and Show nodes display a small image preview on the canvas card. Requires the Project Folder to be set and the image to be registered. Toggle this if you prefer a cleaner canvas without the previews.


Save & Open Projects

The editor uses its own .ivn.json project format that stores every flow, all registries, and settings. This is not a Ren'Py file — it's the editor's working file.

  • Save — with a project folder set, writes straight to <projectFolder>/<ProjectName>.ivn.json with no dialog, since the location is fully determined by the project folder. Without a project folder yet, it falls back to a save-as dialog.
  • Open — opens a previously saved .ivn.json (or legacy single-flow .json) file via a file picker, replacing the current graph.
Why Save is silent: Once InViNode knows your project folder, prompting for a save location every time would just be friction — the file's destination is already fixed. The Project Switcher's Open button is kept as a deliberate, explicit confirmation step instead, since switching projects can discard unsaved canvas changes.
Save often. The editor has no background auto-save timer — Save only writes when you click it. Save your project before closing the app.

Exporting to Ren'Py

Click Export .rpy ▾ and choose an export mode. The exporter performs a pre-flight check first:

  • Every Label node must have a valid name (letters, numbers, underscores; starts with a letter).
  • No two Label nodes may share the same name.

If either check fails, the export is blocked, the offending label is selected, and an error banner appears below the toolbar.

Export modes

ModeOutput
Single File (.rpy)Everything in one <project-name>.rpy file — character defines, variable defaults, image statements, and the full script.
Multiple FilesSeparate files written into a folder: characters.rpy, variables.rpy, images.rpy, and script.rpy. Only files with content are created. If a project folder is set, files are written there directly; otherwise a folder-picker opens.

The active mode is indicated by a highlight in the dropdown and is remembered between exports.

What gets exported

  • Character define statements
  • Variable default statements
  • Image image statements
  • One label block per Label node, containing the nodes connected after it (in graph order)
  • jump statements at Label-node connections
  • menu blocks with nested branches

Placing the exported file(s)

Copy the .rpy file(s) into your project's game/ folder. Ren'Py loads all .rpy files in that folder automatically.

Export from Label

Right-click any Label node on the canvas and choose 📤 Export this label… to export just that label's connected flow as a standalone .rpy file — without the registry preamble (character defines, variable defaults, image statements).

Before exporting, a validation walk checks that every branch reachable from the label ends in a Jump or Call node. If any branch has a dangling exit, the export is blocked and the offending nodes are reported in an error banner.

No registry preamble: The exported file contains only the label block and its content. A comment at the top of the file reminds you to use Split Files export for characters, variables, and image defines — or to add them manually to your characters.rpy / variables.rpy / images.rpy.

This is useful for exporting individual scenes or chapters to separate .rpy files without re-exporting the whole project.

Tips & Best Practices

Organise with labels

Use Label nodes as chapter or scene dividers. Each label becomes a named jump target in Ren'Py, making your script easier to navigate and allowing other scripts to jump into your scene by name.

Use the modal for long text

The side inspector shows a small text area. For long dialogue or narration, double-click the node to open the modal editor where the text area is much taller and easier to write in.

Keep menu choices short

Ren'Py choice labels should be concise — they appear as clickable buttons in-game. Put the detailed dialogue in the Dialog nodes inside each branch.

Register assets before exporting

Image and character definitions are emitted at the top of the exported file. Scan your images and audio folders (or add entries manually) before exporting so all references resolve correctly in Ren'Py.

Back up your project files

Keep both the .ivn.json project and the exported .rpy file. The .ivn.json lets you re-edit the graph; the .rpy is what Ren'Py runs.


InViNode v1.13.1 · open with 📖 Help in the toolbar