How the Archify Workflow Renderer Manages Lanes, Phases, Groups, and Exception Paths

The Archify workflow renderer constructs SVG diagrams by mapping lane IDs to geometric coordinates, rendering phases as horizontal spans across columns, grouping nodes with variant-aware styling, and visually distinguishing exception paths through conditional CSS class application.

The tt-a1i/archify repository provides a workflow visualization engine that transforms JSON workflow definitions into publication-ready SVG diagrams. The core workflow renderer implemented in archify/renderers/workflow/render-workflow.mjs orchestrates the spatial layout and semantic styling of diagram elements including lanes, phases, groups, and exception paths. This module calculates precise geometric coordinates while applying variant-specific styling rules to generate consistent, accessible workflow visualizations.

Layout Configuration and Geometry

Static Layout Constants

The renderer relies on a static layout object declared at the top of the file to establish the canvas geometry. This configuration defines lane geometry through properties including laneX, laneY, laneW, laneH, laneGap, and laneTitleH, which collectively determine the position and size of each lane rectangle. The colXs array stores the X‑coordinates for columns inside lanes, while nodeW and nodeH provide fallback dimensions for workflow nodes. These constants ensure consistent spacing across the entire diagram as implemented on lines 31‑40.

Lane Management and Positioning

Lane Index Construction

Before rendering, the workflow renderer builds a lookup structure to map logical lane IDs to numeric indices. It constructs a Map named laneIndex from the workflow.lanes array, enabling O(1) retrieval of any lane’s vertical position. This index is created on line 50 and is essential for calculating coordinates when rendering nodes, groups, and edges that reference specific lanes.

Coordinate Calculation

The helper function laneTop(id) computes the exact Y‑coordinate for a lane’s top edge by combining the base layout.laneY with the lane’s index multiplied by the total lane height plus gap. As implemented on lines 52‑54, this function ensures that adding or reordering lanes automatically adjusts the vertical layout without manual coordinate recalculation.

Exception Lane Rendering

Visual Distinction for Exception Paths

An exception lane is a standard lane flagged with variant: 'exception'. The renderer treats these specially within the renderLane(lane, index) function on lines 70‑78. When lane.variant === 'exception', the code injects an additional inner rectangle using the class c-security-group to create a highlighted background effect. Simultaneously, the label class switches from the default t-dim to t-security, and the prefix changes from a zero-padded numeric index to the string "EX", providing immediate visual indication of security-sensitive pathways.

function renderLane(lane, index) {
  const y = layout.laneY + index * (layout.laneH + layout.laneGap);
  const exception = lane.variant === 'exception'
    ? `\n        <rect x="${layout.laneX + 6}" y="${y + 6}" width="${layout.laneW - 12}" height="${layout.laneH - 12}" rx="8" class="c-security-group" stroke-width="1"/>`
    : '';
  const labelClass = lane.variant === 'exception' ? 't-security' : 't-dim';
  const prefix = lane.variant === 'exception' ? 'EX' : String(index + 1).padStart(2, '0');
  return `        <rect x="${layout.laneX}" y="${y}" width="${layout.laneW}" height="${layout.laneH}" rx="10" class="c-lane" stroke-width="1"/>${exception}
    <text x="${layout.laneX + 14}" y="${y + 22}" class="${labelClass}" font-size="10" font-weight="600">${prefix} / ${esc(lane.label)}</text>`;
}

Phase Definitions and Rendering

Phase Validation

Phases represent optional horizontal bands spanning one or more columns. The renderer validates each phase definition on lines 76‑84 to ensure that fromCol and toCol are integers and fall within the defined column range. This validation prevents rendering errors and ensures that phase headers align correctly with the underlying grid structure.

Phase SVG Generation

The renderPhase(phase) function generates a horizontal line and background rectangle covering the specified column span. It calculates the geometry using spanForCols(fromCol, toCol, 46) with 46 pixels of padding, then applies variant-specific accent colors using the variantAccent() utility. Phases are inserted into the SVG immediately after the lane definitions, as shown on lines 81‑88 and line 54.

function renderPhase(phase) {
  const span = spanForCols(phase.fromCol, phase.toCol, 46);
  const accent = variantAccent(phase.variant);
  const [lineClass] = arrowClassMap[phase.variant || 'default'] || arrowClassMap.default;
  return `        <line x1="${span.x}" y1="35" x2="${span.x + span.width}" y2="35" class="${lineClass}" stroke-width="1.1"/>
    <rect x="${span.x}" y="27" width="${span.width}" height="16" rx="4" class="c-mask"/>
    <text x="${span.cx}" y="39" class="${accent}" font-size="8" font-weight="600" text-anchor="middle">${esc(phase.label)}</text>`;
}

Group Containers and Node Clustering

Group Validation Logic

Groups visually cluster nodes within a single lane. The renderer enforces strict constraints on lines 91‑106: it verifies the specified lane exists, confirms the column range is valid, and ensures at least one node falls within the group’s boundaries. These checks guarantee that groups render as coherent visual units without overlapping invalid regions.

Security Variant Styling

The renderGroup(group) function on lines 90‑98 draws a rounded rectangle spanning the group’s columns using spanForCols(group.fromCol, group.toCol, 50) with 50 pixels of padding. The rectangle is positioned below the lane title using laneTop(group.lane) + layout.laneTitleH + 8. When group.variant === 'security', the class changes from c-lane to c-security-group, creating a consistent visual language with exception lanes.

function renderGroup(group) {
  const span = spanForCols(group.fromCol, group.toCol, 50);
  const y = laneTop(group.lane) + layout.laneTitleH + 8;
  const height = layout.laneH - layout.laneTitleH - 16;
  const cls = group.variant === 'security' ? 'c-security-group' : 'c-lane';
  const textClass = variantAccent(group.variant);
  return `        <rect x="${span.x}" y="${y}" width="${span.width}" height="${height}" rx="9" class="${cls}" stroke-width="1"/>
    <text x="${span.x + 10}" y="${y + 14}" class="${textClass}" font-size="7" font-weight="600">${esc(group.label)}</text>`;
}

Final SVG Assembly

The renderSvg function orchestrates the complete rendering pipeline by concatenating components in a specific z‑order. It first draws the background grid, followed by lanes (renderLane), phases (renderPhase), and groups (renderGroup). Edge paths and labels are rendered next, followed by workflow nodes, and finally a legend. This deliberate ordering ensures that group and phase backgrounds appear behind nodes while labels remain legible against the lane rectangles.

Summary

  • The static layout object defines fixed geometry for lanes, gaps, and column positions to ensure consistent spacing.
  • The laneIndex Map and laneTop() function provide O(1) coordinate lookups for vertical lane positioning.
  • Exception lanes reuse standard lane logic but inject conditional styling via c-security-group and t-security classes when variant === 'exception'.
  • Phases and groups utilize spanForCols() with specific padding values (46px for phases, 50px for groups) to calculate horizontal spans.
  • Security variants for both lanes and groups trigger distinct CSS classes, creating a unified visual language for sensitive workflow elements.

Frequently Asked Questions

How does the Archify workflow renderer distinguish exception lanes from standard lanes?

The renderer checks the variant property of each lane definition. When variant === 'exception', the renderLane function adds an inner rectangle with the class c-security-group and changes the label class from t-dim to t-security, while prepending the label with "EX" instead of a numeric index.

What validation does the workflow renderer perform on phases and groups?

For phases, the renderer validates that fromCol and toCol are integers within the valid column range. For groups, it verifies that the specified lane exists, the column range is valid, and at least one node falls within the defined span, ensuring geometric integrity before SVG generation.

How are column spans calculated for phases and groups?

The renderer uses the spanForCols(startCol, endCol, padding) utility to calculate pixel coordinates. Phases use 46 pixels of padding, while groups use 50 pixels, allowing precise horizontal positioning that aligns with the lane's internal grid.

Can a workflow group span multiple lanes?

No, groups are constrained to a single lane. The renderGroup function accepts a single lane identifier and uses laneTop() to calculate the vertical position, validating that the lane exists before rendering the group rectangle within those specific boundaries.

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 →