# Graph Apps With LivePanels

Use this track when the canvas is primarily a graph editor, workflow builder,
schema diagram, dependency map, or node-and-connector application.

The shorter `Add Graph Connections` guide shows how graph support fits into a
canvas. This track goes deeper: node modeling, port declarations, connector
layers, connection gestures, reconnect UX, routing, labels, hit targets, layout,
navigation, persistence, shared canvases, and recipes.

## What LivePanels Gives A Graph App

LivePanels gives graph apps a server-authoritative canvas model:

- graph nodes are canvas items;
- ports are declared item capabilities;
- connectors live in canvas state;
- connection gestures become commands;
- connector projection derives SVG paths from item placement and port geometry;
- selection, history, clipboard, persistence, and shared mode keep working
  because graph state stays inside the canvas model.

Your application still owns the product:

- what a node means;
- what a port means;
- how nodes and ports look;
- how connectors are styled;
- whether a connection creates a domain record;
- how users browse, filter, inspect, and edit the graph.

## The Graph App Loop

A graph app usually follows this loop:

```text
author node items
  -> declare ports on those item attrs
  -> render application node markup
  -> render application port controls with graph attrs
  -> let canvas_runtime render connector items in the world SVG projection
  -> style runtime connector classes and data attrs
  -> send graph commands from browser attrs or server code
```

The important part is that the graph does not become a separate client-side
store. The graph is a capability on the canvas.

## Minimum Graph Canvas

Start with the graph toolkit:

```elixir
defmodule MyAppWeb.FlowLive do
  use MyAppWeb, :live_view

  use LivePanels.Canvas,
    pubsub: MyApp.PubSub

  use LivePanels.Toolkit.Graph

  def render(assigns) do
    ~H"""
    <.canvas_runtime {canvas_runtime_attrs(assigns)}>
      <:item
        id="step-1"
        type="step"
        at={{120, 80}}
        size={{520, 360}}
        ports={[
          %{name: "in", direction: :input, type: :task},
          %{name: "out", direction: :output, type: :task}
        ]}
      >
        <.step_card />
      </:item>
    </.canvas_runtime>
    """
  end
end
```

Render the canvas and node ports. Connector items render through the runtime
world SVG item projection:

```heex
<.canvas_runtime {canvas_runtime_attrs(assigns)}>
  <:item :let={context}>
    <article class="node">
      <header {drag_handle_attrs()}>{context.item.label}</header>

      <button
        :for={port <- context.ports}
        {graph_port_anchor_attrs(port)}
        {if port.direction == :output,
          do: begin_connector_attrs(context.item, port),
          else: complete_connector_attrs(context.item, port)}
      >
        {port.label}
      </button>

      {context.content}
    </article>
  </:item>
</.canvas_runtime>
```

That is the foundation. The rest of this track shows how to turn it into a real
graph application.

## Track Map

Read the guides in this order when building a graph app:

- `Model Nodes, Ports, And Connectors` for the runtime data model.
- `Render Nodes And Ports` for item shells, port placement, and application UI.
- `Render Connector Items` for runtime SVG connector rendering and styling.
- `Connect, Reconnect, And Disconnect` for graph commands and gestures.
- `Select, Edit, Route, Label, And Hit-Test Connectors` for graph editor behavior.
- `Layout, Fit, And Navigate Graphs` for graph layout and viewport movement.
- `Persist And Share Graph Canvases` for recovery and collaboration.
- `Graph App Recipes` for common application patterns.

## What To Keep Out Of The Core Runtime

Do not put product meaning into LivePanels.

A connection might mean "foreign key", "workflow transition", "message route",
"dependency", "lineage", or "related idea". LivePanels only needs to know that
a connector connects endpoint A to endpoint B and that the command is valid.

Keep domain records in your app. Use LivePanels to make the canvas behavior
consistent.
