# How Route Probing Traces Paths in the Archify Viewer

> Discover how route probing traces paths in the Archify viewer using BFS to find shortest routes. Visualize and animate network journeys with interactive SVG overlays.

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

---

**Route probing in the Archify viewer uses a breadth-first search (BFS) algorithm to discover and highlight the shortest directed path between two user-selected nodes, rendering the result as an interactive SVG overlay with animated journey controls.**

The Archify viewer provides an interactive route probing feature that enables users to trace dependencies and connections within rendered diagrams. This functionality is implemented in [`viewer/route-probe.js`](https://github.com/tt-a1i/archify/blob/main/viewer/route-probe.js) and combines graph traversal logic with DOM manipulation to provide visual path analysis.

## Initialization and Source Selection

When a user initiates route tracing, the process begins with `Archify.routeProbe.begin()` at lines 7-14 of [`viewer/route-probe.js`](https://github.com/tt-a1i/archify/blob/main/viewer/route-probe.js). This method clears existing UI states, resets the internal mode to **source**, and prepares the SVG container for node selection.

To select a starting node, users click or activate a node via keyboard, triggering `chooseStart(id)`. According to the source code at lines 90-99, this function:
- Assigns `data-route-start` and `data-route-match` attributes to the selected node
- Computes the set of reachable nodes using `reachableFrom(id)`
- Transitions the UI to **target** mode, displaying the source label and a destination selection hint

Only nodes reachable from the source remain interactive in this mode, guiding users toward valid destinations.

## Path Discovery Algorithm (BFS Implementation)

The core pathfinding logic relies on breadth-first search (BFS) operations performed on the SVG's graph structure. When a destination node is selected via `choose(id)`, the system invokes `shortestDirectedPath(startId, id)` at lines 107-124.

### Building the Graph from SVG Elements

Before traversal begins, `outgoingByNode()` (lines 66-74) constructs an adjacency map by parsing the SVG edge elements. This function examines the diagram's current state to build a directed graph representation in memory, mapping each node ID to its outgoing connections.

### Computing Reachability

The `reachableFrom(source)` method (lines 78-88) executes an initial BFS to identify all nodes accessible from the selected source. This step both validates potential destinations and filters the interactive elements in the UI, ensuring users cannot select unreachable targets.

### Shortest Path Calculation

Once a destination is confirmed, `shortestDirectedPath` performs a second BFS to trace the optimal route. As implemented at lines 108-133, this method:
- Records predecessor relationships (`previous`) for each visited node
- Terminates when reaching the target node
- Back-tracks through the predecessor chain to assemble an ordered list of node IDs and corresponding edge elements

This approach guarantees the shortest path in terms of hop count for directed graphs.

## Rendering the Route Overlay

With the path calculated, `showResult(result)` handles visualization at lines 127-138. This function receives arrays of nodes and edges, then:
- Applies `data-route-match` and `data-route-step` attributes for CSS styling
- Calls `renderOverlay(result.edges)` (lines 59-72) to generate a dedicated SVG layer highlighting the path geometry
- Invokes `renderPath` (lines 98-124) to construct an interactive textual representation where each hop appears as a focusable button

The separation of concerns between geometry rendering (`renderOverlay`) and textual navigation (`renderPath`) allows for multiple visualization modes of the same underlying path data.

## Journey Navigation and Visual Feedback

The route probe provides interactive traversal controls including previous, next, play, and overview modes. These update the journey state via `applyJourneyState(index)` at lines 95-106, which:
- Updates node and edge attributes (`data-route-journey-state`) to distinguish past, current, and future steps
- Triggers `renderJourneyPulse` (lines 60-68) to create an animated pulse effect along the current edge when auto-play is active

This state management enables users to step through complex paths incrementally while maintaining visual context of their position within the overall route.

## URL Synchronization for Deep Linking

Archify persists route states in the URL fragment identifier using the format `#route=start~end`. The `replaceRouteHash` function updates the URL whenever a result displays, while `syncFromHash` can restore a route from a bookmarked or shared URL (lines 86-95).

This synchronization enables:
- Sharing specific paths via copied URLs
- Browser back/forward navigation through route history
- Deep linking to predefined routes in documentation or bug reports

## Programmatic Route Control

Developers can interact with the route probing system programmatically through the public API exposed on the `Archify.routeProbe` object:

```javascript
// Initiate route probing mode
Archify.routeProbe.begin();

// Select source and destination programmatically
Archify.routeProbe.choose('node-42');  // Sets source (when in source mode)
Archify.routeProbe.choose('node-87');  // Sets target and renders path

// Access current route data for analytics or export
const routeInfo = Archify.routeProbe.result();
// Returns: { source, target, nodes, hops, ... }

// Animate automatic traversal
Archify.routeProbe.playJourney();  // Starts auto-advance with pulse effects

```

## Related Implementation Files

While [`viewer/route-probe.js`](https://github.com/tt-a1i/archify/blob/main/viewer/route-probe.js) contains the core logic, several adjacent modules integrate with the probing system:

- [`viewer/template.source.html`](https://github.com/tt-a1i/archify/blob/main/viewer/template.source.html) — Defines the HTML panel structure and button containers manipulated by the route probe UI
- [`viewer/semantic-lens.js`](https://github.com/tt-a1i/archify/blob/main/viewer/semantic-lens.js) — Clears conflicting visual previews when route probing activates
- [`viewer/viewer-camera.js`](https://github.com/tt-a1i/archify/blob/main/viewer/viewer-camera.js) — Adjusts camera focus and reveals nodes during `showResult` and `showJourneyOverview` operations
- [`viewer/intent-trace.js`](https://github.com/tt-a1i/archify/blob/main/viewer/intent-trace.js) — Disables intent tracing displays to prevent UI conflicts during route selection

## Summary

- **Route probing** in Archify traces shortest directed paths using BFS traversal of SVG-derived graph data in [`viewer/route-probe.js`](https://github.com/tt-a1i/archify/blob/main/viewer/route-probe.js)
- The **two-phase selection** process (source → target) filters unreachable nodes using `reachableFrom()` to guide valid choices
- **Path calculation** occurs in `shortestDirectedPath()` which records predecessors and back-tracks to reconstruct the optimal route
- **Visual rendering** separates concerns between SVG geometry overlays (`renderOverlay`) and interactive textual buttons (`renderPath`)
- **Journey controls** provide step-by-step navigation with state-based styling and optional pulse animations via `applyJourneyState()`
- **URL persistence** enables deep linking through fragment hash synchronization (`replaceRouteHash` and `syncFromHash`)
- A **public API** exposes methods like `begin()`, `choose()`, and `result()` for toolbar integration and programmatic control

## Frequently Asked Questions

### How does Archify determine the shortest path between nodes?

Archify uses a breadth-first search (BFS) algorithm implemented in `shortestDirectedPath()` within [`viewer/route-probe.js`](https://github.com/tt-a1i/archify/blob/main/viewer/route-probe.js) (lines 108-133). The algorithm builds an adjacency map from SVG edge elements using `outgoingByNode()`, then traverses the graph while recording predecessor relationships. When the target node is reached, it back-tracks through the predecessor chain to assemble the ordered path, guaranteeing the shortest route in terms of connection count for directed graphs.

### What file contains the core route probing implementation?

The primary implementation resides in [`viewer/route-probe.js`](https://github.com/tt-a1i/archify/blob/main/viewer/route-probe.js), which contains the `Archify.routeProbe` module. This file includes graph traversal logic (`shortestDirectedPath`, `reachableFrom`), UI state management (`applyJourneyState`), rendering functions (`renderOverlay`, `renderPath`), and URL synchronization handlers (`replaceRouteHash`, `syncFromHash`).

### Can route states be shared via URLs?

Yes. Archify encodes active routes in the URL fragment using the format `#route=start~end`. The `replaceRouteHash` function updates the URL when a route displays, and `syncFromHash` can restore the route when loading a bookmarked or shared link. This enables deep linking to specific paths within complex diagrams.

### How does the journey animation work?

The journey animation utilizes `applyJourneyState(index)` (lines 95-106) to update `data-route-journey-state` attributes on nodes and edges, distinguishing past, present, and future steps. When playing, `renderJourneyPulse` (lines 60-68) creates a visual pulse effect along the current edge. Users can control playback through previous/next buttons or auto-play functionality via `playJourney()`.