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

> Discover how the Archify workflow renderer maps lanes, renders phases, groups nodes, and styles exception paths for clear SVG diagram generation. Learn about its efficient process.

- Repository: [tt-a1i/archify](https://github.com/tt-a1i/archify)
- Tags: internals
- Published: 2026-07-14

---

**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.

```javascript
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.

```javascript
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.

```javascript
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.