How Archify's Preview Mode Works: A Deep Dive into the Attribute-Driven Overlay System

Archify's preview mode uses data attributes on SVG elements coordinated by a token-based MotionGovernor to render temporary highlights for chapters, legends, and relationships without permanent navigation.

Archify implements a sophisticated preview system that allows users to temporarily visualize architectural relationships and chapters through CSS-driven overlays. According to the tt-a1i/archify source code, this system relies on modular JavaScript handlers that manipulate data attributes on the main SVG canvas, all coordinated by a central MotionGovernor to prevent conflicting interactions.

The Three Pillars of Archify Preview Mode

The preview architecture rests on three distinct technical concepts that work together to create smooth, non-destructive visual feedback.

Data-Attribute Driven Rendering

Rather than modifying DOM structures directly, Archify's preview mode expresses state entirely through data attributes on SVG elements. When a preview activates, the system sets attributes such as data-chapter-preview, data-legend-preview-active, or data-relationship-preview-active on the root SVG element. Individual nodes receive specific markers like data-legend-preview-match, data-legend-preview-selected, or data-relationship-preview-source. CSS rules target these attributes to render colored overlays, connection lines, and opacity changes without JavaScript manipulating styles directly.

Modular Preview Handlers

Three specialized modules handle distinct preview types, each encapsulating its own attribute logic:

  • Legend previews (viewer/semantic-lens.js): Handle PREVIEW_KINDS constants including MATCH, SELECTED, and PEER, applying recursive highlighting through previewLegend() and cleaning up via clearLegendPreview().
  • Chapter previews (viewer/guided-views.js): Manage document-section highlighting through previewChapter() and clearChapterPreview(), setting data-chapter-preview attributes.
  • Relationship previews (viewer/focus.js): Highlight specific edges and nodes using previewRelationship(), which reads data-relationship-key and data-edge-key attributes to draw connections between source and target elements.

MotionGovernor Exclusivity

To prevent overlapping previews from conflicting, Archify employs a token-based governor exposed globally as Archify.motionGovernor. This lightweight coordinator guarantees only one preview type owns the interaction slot at any moment. When previewChapter() activates, it claims the governor token, temporarily blocking legend and relationship previews until the token releases.

Implementation Details by Preview Type

Each preview type follows a consistent pattern: claim the governor, set data attributes, and register cleanup callbacks.

Legend Previews in Semantic Lens

The viewer/semantic-lens.js module manages legend-driven highlights through three distinct visual tiers defined in PREVIEW_KINDS:

const PREVIEW_KINDS = {
  MATCH: 'match',
  SELECTED: 'selected', 
  PEER: 'peer',
};

When previewLegend(entry) executes, it first validates the entry exists, then determines the preview kind via previewLegendKind(). The function marks the SVG with data-legend-preview-active, highlights the primary node with data-legend-preview-match, and applies kind-specific attributes (data-legend-preview-selected or data-legend-preview-peer) based on the entry type. If the entry contains edge members, it iterates through entry.edge.members to highlight connected elements.

To clear legend previews, clearLegendPreview() removes the global attribute and queries for all elements bearing data-legend-preview-match, data-legend-preview-selected, or data-legend-preview-peer attributes, stripping each to restore the default view.

Chapter Previews in Guided Views

Chapter previews operate through viewer/guided-views.js using defensive programming principles. The previewChapter(index) function first checks if the requested view is already active by comparing activePreviewIndex and verifying svg.getAttribute('data-chapter-preview') matches views[index].id.

Upon activation, the function sets data-chapter-preview to the view's identifier and marks the corresponding chapter button with data-preview-active="true". Crucially, it claims the MotionGovernor token through Archify.motionGovernor.claim('chapter-preview', callback), which auto-releases after 5000ms or when explicitly cleared. The cleanup callback resets previewOwnerToken to zero and invokes clearChapterPreview().

Relationship Previews in Focus

The viewer/focus.js module handles relationship visualization through previewRelationship(button, options). This function extracts relationship keys from data-relationship-key attributes, then marks matching edges via data-edge-key comparisons. It highlights source and target nodes by ID, setting data-relationship-preview-source and data-relationship-preview-target attributes respectively.

When options.direct is not true, the function also activates a visual indicator by setting data-relationship-previewing="true" on the appropriate chip element, providing users with feedback that an indirect relationship is being examined.

The MotionGovernor Coordination Layer

Located in viewer/motion-governor.js, the MotionGovernor prevents race conditions between rapid user interactions. The implementation uses a simple object with claim() and release() methods:

const governor = {
  current: null,
  claim(kind, onRelease) {
    if (this.current) return null;
    this.current = {kind, onRelease};
    setTimeout(() => {
      this.release(this.current);
    }, 5000);
    return this.current;
  },
  release(token) {
    if (this.current !== token) return;
    const {onRelease} = this.current;
    this.current = null;
    if (typeof onRelease === 'function') onRelease();
  }
};

The governor integrates into the global namespace through viewer/viewer-chrome-layout.js, which exposes window.Archify.motionGovernor for cross-module access. This centralization ensures that chapter previews automatically suppress legend highlights, and relationship previews cannot interfere with active chapter navigation.

Practical Code Examples

Initializing a Legend Preview

import {previewLegend, clearLegendPreview, LegendPreviewKinds} from './viewer/semantic-lens.js';

// Construct a legend entry highlighting a specific node as "selected"
const legendEntry = {
  id: 'arch-component-42',
  kind: LegendPreviewKinds.SELECTED,
  edge: {
    members: [] // Array of DOM elements to highlight
  }
};

// Activate the preview
previewLegend(legendEntry);

// Clear when done
clearLegendPreview();

Starting a Chapter Preview

import {previewChapter, clearChapterPreview} from './viewer/guided-views.js';

// Preview the chapter at index 3
const success = previewChapter(3);
if (success) {
  console.log('Chapter preview active for 5 seconds');
}

// Manual cleanup (optional - governor auto-releases)
clearChapterPreview();

Triggering Relationship Highlights

import {previewRelationship} from './viewer/focus.js';

// Select a button element containing relationship metadata
const relButton = document.querySelector('[data-relationship-key="user-auth-flow"]');

// Show indirect preview with UI chip
previewRelationship(relButton, {direct: false});

// The preview automatically clears via MotionGovernor timeout

Summary

Archify's preview mode represents a clean separation of concerns between state management and visual rendering:

  • Attribute-based state allows CSS to handle all visual changes while JavaScript manages data attributes on the SVG and its child elements.
  • Three specialized modules handle distinct preview contexts: viewer/semantic-lens.js for legends, viewer/guided-views.js for chapters, and viewer/focus.js for relationships.
  • MotionGovernor coordination prevents UI conflicts through a 5000ms token-based locking mechanism exposed globally via Archify.motionGovernor.
  • Recursive highlighting supports complex legend hierarchies through chainable previewLegend() calls that traverse entry.next pointers.
  • Defensive cleanup ensures transient UI states never persist through comprehensive attribute removal functions like clearLegendPreview() and clearChapterPreview().

Frequently Asked Questions

How does Archify prevent multiple previews from overlapping?

Archify uses the MotionGovernor in viewer/motion-governor.js to enforce exclusive access. When any preview activates—whether chapter, legend, or relationship—it calls Archify.motionGovernor.claim(), which returns a token only if no other preview currently holds the slot. If the governor is occupied, subsequent preview requests are ignored until the current token releases via timeout (5000ms) or explicit release() call.

What are the different legend preview kinds available?

The viewer/semantic-lens.js module defines three preview kinds in the PREVIEW_KINDS constant: MATCH (standard highlighting), SELECTED (primary selection emphasis via data-legend-preview-selected), and PEER (related elements styling via data-legend-preview-peer). The previewLegendKind() function normalizes entry kinds to these constants, defaulting to MATCH for unknown values.

How long does a preview remain active before auto-clearing?

All previews governed by the MotionGovernor automatically release after 5000 milliseconds (5 seconds). This timeout is hardcoded in the claim() method within viewer/motion-governor.js using setTimeout(). Developers can also clear previews immediately using the exported cleanup functions: clearLegendPreview(), clearChapterPreview(), or manual governor.release(token) calls.

Can I extend the preview system for custom visualization types?

Yes. The modular architecture in viewer/guided-views.js demonstrates the extension pattern through its preview() dispatcher function. To add custom previews, create a new handler module that manages specific data attributes, then integrate it into the dispatcher. Ensure your implementation claims the MotionGovernor token via Archify.motionGovernor.claim() to maintain compatibility with existing preview modes and prevent visual conflicts.

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 →