How Archify's Layout Algorithm Handles Automatic Routing: A Deep Dive into the Auto-Route Engine

Archify's automatic routing engine activates when a relationship's route field is omitted or set to "auto" and no explicit path constraints (via points, sides, or channels) are provided by the author.

The automatic routing system in tt-a1i/archify is implemented across multiple modules in the renderer pipeline. When drawing architecture diagrams, clean connection routing is essential—Archify balances flexibility (allowing manual override) with intelligence (inferring optimal paths automatically).


When "Auto" Routing Kicks In

In /archify/renderers/architecture/render-architecture.mjs (lines 79–86), the renderer checks whether to engage automatic routing:

  • The route field is missing or explicitly "auto"
  • No via points are specified
  • No channelX/Y, fromSide, toSide, or label-position constraints exist

If all these conditions hold, Archify delegates to its automatic routing engine rather than using explicit or forced routing modes.


Inferring Endpoint Sides Automatically

Before calculating paths, Archify must determine which side of each component to connect from and to.

Default Side Selection (defaultFromSide / defaultToSide)

In /archify/renderers/shared/geometry.mjs (lines 1554–1567), the system examines the relative center positions of the two connected components. It selects the "natural" side based on geometric relationships:

// Pseudocode based on geometry.mjs implementation
function defaultFromSide(fromCenter, toCenter) {
  const dx = toCenter[0] - fromCenter[0];
  const dy = toCenter[1] - fromCenter[1];
  // Choose side based on dominant axis and direction
  if (Math.abs(dx) > Math.abs(dy)) {
    return dx > 0 ? 'right' : 'left';
  } else {
    return dy > 0 ? 'bottom' : 'top';
  }
}

Explicit Override Support (chosenSide)

Lines 1170–1172 in the same file implement chosenSide, which allows author-specified sides to override these defaults:

function chosenSide(explicit, fallback) {
  return explicit !== undefined ? explicit : fallback;
}

Port Spreading for Clean Fan-Out/Fan-In

When multiple connections share the same component side, collapsing lines create visual clutter. The automaticPortSpread function (lines 1102–1154 in /archify/renderers/shared/geometry.mjs) distributes anchor points with a small pixel offset:

  • Prevents overlapping connections
  • Maintains visual separation without excessive gap
  • Applies to both outgoing (fan-out) and incoming (fan-in) edges

The Core Routing Routine: routeVia

The automatic routing engine centers on routeVia, which handles all routing modes including "auto". Here's the implementation structure from geometry.mjs:

function routeVia(conn, from, to, start, end, fromSide, toSide) {
  if (conn.via) return conn.via;                // explicit control points
  
  switch (conn.route || 'auto') {
    case 'straight':
      return [];                                // direct straight line
    
    case 'orthogonal-h':
      // forced horizontal dogleg routing
      // ...
    
    case 'orthogonal-v':
      // forced vertical dogleg routing
      // ...
    
    case 'auto':
    default: {
      // 4-a. Check if direct line respects chosen sides
      const deltaX = Math.abs(start[0] - end[0]);
      const deltaY = Math.abs(start[1] - end[1]);
      
      if ((deltaX /* condition for side-respecting direct line */)) {
        // Use direct connection
      }
      // 4-b. Otherwise, compute minimal orthogonal path
      // with appropriate doglegs to respect fromSide/toSide
    }
  }
}

Automatic Path Selection Logic

The "auto" case follows a decision hierarchy:

  1. Direct line test: If a straight connection from the calculated start and end points respects the chosen sides (doesn't require entering/exiting from wrong faces), use it
  2. Minimal orthogonal path: Otherwise, compute the shortest orthogonal route with one or two doglegs that properly respects fromSide and toSide
  3. Dogleg preference: The algorithm biases toward solutions that minimize total wire length and number of bends

Summary

  • Automatic routing triggers when route: "auto" (or omitted) and no explicit constraints exist—checked in render-architecture.mjs
  • Side inference uses relative component positions via defaultFromSide/defaultToSide in geometry.mjs, with chosenSide allowing override
  • Port spreading via automaticPortSpread prevents overlapping lines on busy component sides
  • Path calculation in routeVia prefers direct connections when valid, falling back to minimal orthogonal doglegs that respect inferred or specified side constraints

Frequently Asked Questions

What determines whether Archify uses automatic routing or manual routing?

Archify checks route field value and presence of explicit constraints in render-architecture.mjs lines 79–86. If route is "auto" or missing and no via, channelX/Y, or side specifications exist, automatic routing activates. Any explicit control point or side override disables the auto-engine for that connection.

How does Archify prevent lines from overlapping when multiple connections share a side?

The automaticPortSpread function in geometry.mjs (lines 1102–1154) automatically distributes anchor points along the shared side with small pixel offsets. This creates visual separation without requiring manual port positioning from diagram authors.

Can I override the automatically chosen side for a connection?

Yes. The chosenSide helper (lines 1170–1172) checks for explicit fromSide or toSide values before falling back to defaultFromSide/defaultToSide. Providing either side in your relationship definition overrides the geometric inference while still allowing automatic path calculation between those fixed endpoints.

What path does routeVia generate in "auto" mode?

routeVia first tests whether a direct line respects the chosen entry/exit sides (checking deltaX/deltaY in the auto case). If valid, it returns an empty via array for straight-line rendering. Otherwise, it computes a minimal orthogonal path with doglegs that properly enters from fromSide and exits to toSide.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →