A scene index shows records as they are stored in the file. An effective graph applies the Figma semantics that determine what an instance actually contains and displays.

Use a graph when your analysis depends on component inheritance, populated instance children, swaps, property assignments, overrides, variables, or layout-derived values.

Build a focused graph

Resolve one subtree whenever you know the root:

alias Figler.Scene

fig = File.read!("design.fig")
graph = Scene.graph(fig, root: "12:34")

root: keeps the result focused while including the component and reference data needed to resolve that subtree. focus: accepts one GUID or multiple source GUIDs for broader jobs:

graph = Scene.graph(fig, focus: ["12:34", "56:78"])

Building an unrestricted graph resolves the whole file and is intentionally more expensive:

graph = Scene.graph(fig)

Use the normal scene APIs

Most Figler.Scene helpers work with an effective graph:

Scene.node(graph, "12:34")
Scene.children(graph, "12:34")
Scene.by_type(graph, :instance)
Scene.name_contains(graph, "Button")
Scene.text_contains(graph, "Continue")

These helpers include generated instance clones and their effective values.

XPath queries on a graph still run against its reusable source index. Use helper functions, Scene.node/2, and Scene.children/2 when generated clones must be included.

Inspect a resolved tree

tree = Scene.Graph.tree(graph, root: "12:34", depth: 4)

Without root:, tree/2 returns every graph root up to the selected depth.

Explain where a value came from

explanation = Scene.Graph.explain(graph, "12:34")

The result includes:

  • the effective node;
  • its projected source node when available;
  • source and source GUID information;
  • applied resolver operations;
  • unresolved diagnostics;
  • instance metadata;
  • child GUIDs and active resolver stages.

Inspect instance-specific information directly:

instance = Scene.Graph.instance(graph, "12:34")

This includes the source component, component property assignments, symbol overrides, derived symbol data, and provenance.

Diff source and effective values

changes = Scene.Graph.diff(graph)
subtree_changes = Scene.Graph.diff(graph, root: "12:34")

Only nodes whose effective values differ from their projected source are returned.

Review anything the resolver could not apply:

unresolved = Scene.Graph.unresolved(graph)
first_ten = Scene.Graph.unresolved(graph, limit: 10)

Control variable and style resolution

graph =
  Scene.graph(fig,
    root: "12:34",
    resolve_variables: :known,
    resolve_styles: :known
  )

Variable modes are false, :known, and :preserve. Style modes are false, :refs, and :known. Defaults favor known variable values while leaving style resolution disabled.

Profile a graph build

profile = Figler.Scene.Graph.profile(fig, root: "12:34")

profile.total_ms
profile.initial_ms
profile.stages
profile.graph

Use profiling before changing stage selection. Most applications should keep the standard resolver pipeline and reduce work with root: or focus: rather than manually skipping semantic stages.