Compile VN
Where a visual novel stops being nodes and becomes a bundle
- graph
- state
- workflow_id
- entry_scene_id
- selected_choice_id
- ui_widget
- bundle
- preview
- validation
- derived_state
- canonical_bundle
LF_VNCompile is the terminal node of the pack's visual-novel suite - the moment your authored narrative stops being a pile of nodes and becomes one deterministic, validated bundle. It takes the complete declaration chain you've built with LF_SceneSpec, LF_VNSwitch, and LF_VNState, checks the structure, compiles it into a target-neutral LF_VN_BUNDLE, and previews the story once against a fixture state. If the suite's job is "narrative as data," this node is the moment the data gets a stamp of approval.
"Target-neutral" is the key phrase, and it's worth understanding before you wire anything: the bundle describes the story - scenes, choices, switches, effects - with zero assumptions about who consumes it. No renderer, no engine, no live application state. A game engine, a web app, or a Workflow Runner consumer takes the bundle and does the actual presentation. That's why the compile step exists at all: it's the guarantee that the narrative contract is structurally sound before someone downstream depends on it.
How it works
You hand it the complete graph (every declaration chained in order), a state fixture for preview, a workflow_id (an LF_ID, persistent, generated once by the authoring UI), and an entry_scene_id pointing at the bundle's starting scene. Compilation validates the whole chain; if validation isn't complete, the node raises a contract error rather than emitting a half-baked bundle - it would rather fail loudly than hand you something that won't run. The optional selected_choice_id replays one choice against the fixture to show the branch it leads to.
Outputs are the payoff:
- bundle - the deterministic target-neutral VN bundle (
lf.vn.bundle.v1). - preview - fixture preview before and after the optional selected choice.
- validation - machine-readable structural validation report.
- derived_state - immutable state after replaying the supported core effects once.
- canonical_bundle - the bundle as canonical JSON string, meant for byte-identity checks (hash two runs; if the hashes match, the narrative is reproducible).
Because compilation is deterministic and CPU-only, you can run it headless - the node deliberately works without a UI attached.
The three inputs that gate everything
- graph - the complete declaration chain; missing scenes or unlinked branches will fail validation.
- state - fixture state used for preview only. The author is explicit that it is not embedded in the authored bundle - preview state and shipped story stay separate, which is the right call.
- workflow_id / entry_scene_id - the bundle's identity and its starting point.
Installing and gotchas
It's in the LF Nodes pack, installed like the rest:
cd ComfyUI/custom_nodes
git clone https://github.com/lucafoscili/lf-nodes.git
restart (ComfyUI Manager → "LF Nodes"). The whole VN suite is pure Python - no models, no GPU. Pack notes: Pillow pinned at 12.2.0, and the repo was rewritten/archived in 2025, so clone lucafoscili/lf-nodes.
Where people stumble: skipping the earlier authoring nodes (it needs the actual chain, not a hand-built JSON you think matches), and expecting state to travel inside the bundle - it doesn't, by design. If you're building a reproducible story pipeline - version-controllable narrative JSON that a game or app can consume - this is the clean ending point. The canonical_bundle output alone is worth it: byte-identical narrative artifacts are a rare and genuinely useful property in a tool that usually produces images.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| graph | LF_VN_GRAPH | Complete authored declaration chain. | |
| state | LF_VN_STATE | Fixture state used for preview only; it is not embedded in the authored bundle. | |
| workflow_id | LF_ID | LF-owned persistent workflow declaration identity. Generated once by the authoring UI. | |
| entry_scene_id | LF_REF | Bundle-local entry scene reference. Choose by friendly label or connect a scene_ref output. | |
| selected_choice_id | LF_REF | Optional choice reference from the active scene to replay once against the fixture. | |
| ui_widgetopt | LF_CODE | — |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| bundle | LF_VN_BUNDLE | Deterministic target-neutral VN bundle. |
| preview | JSON | Fixture preview before and after the optional selected choice. |
| validation | JSON | Machine-readable structural validation report. |
| derived_state | LF_VN_STATE | Derived immutable state after replaying supported core effects once. |
| canonical_bundle | STRING | Canonical bundle JSON used for byte-identity checks. |