Nodes/lf-nodes/VN State
ComfyUI Node

VN State

The immutable 'save file' your narrative graph evaluates against

By lucafoscili·Created 2 years ago·Updated a day ago· 35
VN State
  • fixture_id
  • state_body
  • profile_ref
  • state
  • state_object
  • canonical_json

Every branching story needs a way to answer "what's true right now?" - which flag got set, which choice the player made, what the world knows. In the pack's visual-novel suite, that question is answered by LF_VNState, a small node that wraps a chunk of JSON into an immutable, versioned "fixture state" envelope. Think of it as the save file for your narrative graph, except it's deliberately not a real save file: it's a fixed test fixture you run the story against.

The distinction matters because it's the whole design. The suite is target-neutral and CPU-only - it authors and validates narrative data, not a playable game. LF_VNState creates the state object that LF_VNSwitch evaluates and LF_VNCompile previews against. The output envelope (lf.vn.state.v1) carries a fixtureId, the values you provided, an appliedEffectIds list, and an optional profileId. It's immutable once created - no mutation, no in-place edits, just a stable document.

What you actually set

  • fixture_id - an LF_ID (persistent identity, kind fixture), generated once by the authoring UI. Headless prompts must supply it.
  • state_body - the actual state, as strict JSON. The default is { "markers": [] } - a bare-bones start, and honestly a fine one for simple stories. Predicate paths in your switches and scenes are evaluated relative to this object, so this is where the flags, counters, and facts of your narrative live.
  • profile_ref (optional) - a consumer-owned profile reference, chosen from a catalogue or via a typed connection. Ignore it until you actually need per-consumer profiles.

Outputs are the same state three ways: state (the typed LF_VN_STATE), state_object (the same envelope through the generic JSON socket - useful if you're feeding downstream JSON tooling), and canonical_json (the envelope as canonical JSON text, for hashing, inspection, and API clients).

How it fits

The typical chain: define a fixture here, branch on it with LF_VNSwitch (whose cases test predicates against this state), declare scenes with LF_SceneSpec, and finally compile the whole thing with LF_VNCompile - which uses this same state purely to preview the story, and explicitly does not embed it in the shipped bundle. That separation is the author's own rule, and it's a good one: your test fixture shouldn't leak into production narrative data.

Installing and gotchas

It's part of LF Nodes:

cd ComfyUI/custom_nodes
git clone https://github.com/lucafoscili/lf-nodes.git

restart (or ComfyUI Manager → "LF Nodes"). Pure Python, no models. Pack notes as usual: Pillow pinned 12.2.0; repo rewritten and old one archived in 2025 - clone lucafoscili/lf-nodes.

The realistic pitfalls: invalid JSON in state_body (it must parse strictly - the whole suite is strict about this), and treating this node as actual game save-state machinery. It's a fixture, not runtime state - if you need a story that remembers what the player did at runtime, that's the consumer engine's job, not this node's. Keep that framing straight and LF_VNState is dead simple: state in, state out, nothing clever in between. That's precisely what makes it reliable.

Category✨ LF Nodes/Visual Novel

Inputs (3)

NameTypeDefaultDescription
fixture_idLF_IDLF-owned persistent fixture identity. Generated once by the authoring UI; headless prompts must provide it.
state_bodyLF_TEXTAREA{ "markers": [] }Opaque strict-JSON fixture values. Predicate paths are evaluated relative to this object.
profile_refoptLF_REFOptional consumer-owned profile reference. Choose it from a consumer catalogue or supply it through a typed connection.

Outputs (3)

NameTypeDescription
stateLF_VN_STATEVersioned immutable VN fixture state.
state_objectJSONThe same state envelope through the generic JSON socket.
canonical_jsonSTRINGCanonical JSON text for hashing, inspection, and API clients.