Sketch
SketchDocs
by FileKit Studio
Diagram SDK

Anchors & Ports

Step-by-step guide to connection face anchors, multi-port contact distribution, and collision-free feedback return cycles.

Anchors determine the exact physical attachment coordinates where connectors meet node boundaries. @filekit-studio/diagram automatically assigns the optimal connection face based on flow direction, but gives you granular control to force specific sides or handle complex feedback loops.


1. Automatic Multi-Port Fan-Out

When a single service has multiple outgoing connections to parallel downstream workers, connecting all arrows to a single point creates an unreadable cluster.

The layout engine automatically activates Multi-Port Contact Fan-Out: it spaces the connection points evenly along the source node's edge so every arrow leaves from its own distinct port.

fanout.ts
import type { DiagramData } from "@filekit-studio/diagram";

export const fanoutDiagram: DiagramData = {
  title: "Multi-Port Contact Fan-Out",
  direction: "LR",
  nodes: [
    { id: "load_balancer", label: "Cloudflare Anycast LB\n(Multi-Port Ingress)", shape: "diamond", color: "indigo", badge: "INGRESS" },
    { id: "pod_a", label: "Worker Pod A\n(Zone 1)", shape: "rounded", color: "emerald" },
    { id: "pod_b", label: "Worker Pod B\n(Zone 2)", shape: "rounded", color: "purple" },
    { id: "pod_c", label: "Worker Pod C\n(Zone 3)", shape: "rounded", color: "amber" }
  ],
  edges: [
    { from: "load_balancer", to: "pod_a", label: "Lane 1 (Port A)", color: "#10b981" },
    { from: "load_balancer", to: "pod_b", label: "Lane 2 (Port B)", color: "#8b5cf6" },
    { from: "load_balancer", to: "pod_c", label: "Lane 3 (Port C)", color: "#f59e0b" }
  ],
  layout: { direction: "LR", edgeRouting: "elbow", rankSpacing: 220, nodeSpacing: 60 }
};
Multi-Port Contact Fan-Out Live Preview
Loading diagram canvas...

2. Cardinal Face Overrides (startAnchor & endAnchor)

You can override the automatic layout engine by explicitly declaring which face an arrow must leave or enter.

Supported anchor values:

  • "left": Left edge.
  • "right": Right edge.
  • "top": Top edge.
  • "bottom": Bottom edge.

In the example below, we connect the primary pipeline from left-to-right, but route an auxiliary telemetry stream vertically out of the bottom face into an analytics collector:

cardinal-overrides.ts
export const cardinalDiagram: DiagramData = {
  title: "Vertical & Horizontal Port Overrides",
  direction: "LR",
  nodes: [
    { id: "web_app", label: "Web Client", shape: "rounded", color: "sky" },
    { id: "core_api", label: "Core API Server", shape: "rounded", color: "purple" },
    { id: "db_cluster", label: "PostgreSQL DB", shape: "cylinder", color: "emerald" },
    { id: "telemetry", label: "Telemetry Collector\n(OpenTelemetry Agent)", shape: "rounded", color: "amber", badge: "AUDIT" }
  ],
  edges: [
    { from: "web_app", to: "core_api", label: "HTTP Request" },
    { from: "core_api", to: "db_cluster", label: "SQL Query" },
    {
      from: "core_api",
      to: "telemetry",
      startAnchor: "bottom",
      endAnchor: "top",
      label: "Metrics Stream (Bottom -> Top)",
      color: "#f59e0b",
      style: "dashed"
    }
  ],
  layout: { direction: "LR", edgeRouting: "elbow", rankSpacing: 220, nodeSpacing: 90 }
};
Cardinal Face Overrides Live Preview
Loading diagram canvas...

3. Backward Feedback & Retry Cycles

In distributed systems, consumers often send acknowledgement (ACK) signals, failure retries, or rollback triggers back to upstream services.

When an edge connects from a downstream node back to an upstream node:

  1. The engine automatically detects that the edge travels backwards against the flow.
  2. It assigns top or bottom departure anchors.
  3. It arches the connector gracefully above or below the intermediate nodes, preventing edge crossings.
feedback-loop.ts
export const feedbackDiagram: DiagramData = {
  title: "Async Job Dispatch & Retry Feedback Cycle",
  direction: "LR",
  nodes: [
    { id: "producer", label: "Job Producer\n(Scheduler)", shape: "rounded", color: "indigo" },
    { id: "queue", label: "SQS Buffer Queue", shape: "cylinder", color: "amber", badge: "FIFO" },
    { id: "worker", label: "Heavy Compute Worker\n(GPU Instance)", shape: "rounded", color: "purple" }
  ],
  edges: [
    { from: "producer", to: "queue", label: "Enqueue Task", color: "#6366f1" },
    { from: "queue", to: "worker", label: "Pull Batch", color: "#f59e0b" },
    {
      from: "worker",
      to: "producer",
      label: "Failure Alert & Retry (Feedback Loop)",
      routing: "curved",
      color: "#ef4444",
      style: "dashed"
    }
  ],
  layout: { direction: "LR", rankSpacing: 220, nodeSpacing: 80 }
};
Backward Feedback & Retry Live Preview
Loading diagram canvas...

4. Anchor Options Reference

JSON
{
  "from": "node_a",
  "to": "node_b",
  "startAnchor": "right" | "left" | "top" | "bottom",
  "endAnchor": "left" | "right" | "top" | "bottom"
}
  • Leave startAnchor and endAnchor undefined to let the router compute optimal multi-port coordinates automatically.
  • Specify startAnchor and endAnchor when you want strict, deterministic attachment points.

On this page