How Stories Work in the Archify Viewer: Declarative Walkthroughs for Diagrams

Archify stories are guided, interactive walkthroughs defined by data-story-beat and data-story-step attributes in SVG markup that the viewer's runtime parses into an ordered timeline, managing state transitions to drive CSS animations and caption updates automatically.

The Archify viewer (from the tt-a1i/archify repository) transforms static architecture diagrams into interactive experiences using a declarative story system. By embedding specific data attributes directly into your HTML or SVG elements, you create story beats and steps that the runtime automatically sequences into animated guided tours without requiring custom JavaScript. This article examines the source code implementation to show exactly how the viewer discovers, parses, and plays these stories.

What Are Story Beats and Steps?

The Archify story system uses a two-level hierarchy to structure guided experiences.

Story beats act as containers that group related visualization states into a single narrative unit. A beat is defined by the data-story-beat attribute on an SVG or HTML element.

Story steps are individual elements within a beat that become active in sequence. Marked with data-story-step, these elements represent the specific diagram components (nodes, edges, or groups) that receive visual emphasis as the story progresses.

As the story advances, the runtime toggles the data-story-beat-state attribute on each step between three values: "past" for completed steps, "active" for the current step, and "next" for upcoming steps. CSS selectors target these states to trigger highlight animations, opacity changes, or focus effects.

Declarative Markup in SVG

You define a story directly in your diagram markup by adding data attributes to the elements you want to highlight. The viewer requires no additional configuration files because the metadata lives with the visual elements.

<svg data-story-beat id="authentication-flow">
  <!-- Step 1: Highlight the Client node -->
  <g data-story-step data-story-beat-state="next" class="client-node">
    <rect width="100" height="40" x="50" y="50" />
    <text x="100" y="75">Client</text>
  </g>

  <!-- Step 2: Highlight the authentication edge -->
  <path data-story-step 
        data-story-beat-state="next" 
        d="M150 70 L250 70" 
        class="connection-line"/>

  <!-- Step 3: Highlight the Auth Service -->
  <g data-story-step data-story-beat-state="next">
    <rect width="120" height="40" x="250" y="50" />
    <text x="310" y="75">Auth Service</text>
  </g>
</svg>

The data-story-beat attribute on the root SVG signals to the runtime that this element contains a sequence to be indexed. Each child with data-story-step is ordered according to its DOM position, creating the playback sequence.

Runtime Discovery and State Management

When the viewer initializes, it scans the document to build an internal timeline of all available stories.

In scripts/start-template.html around line 3370, the discovery logic executes querySelectorAll('[data-story-beat]') to locate every story container. For each beat found, the script queries for [data-story-step] children and stores them in an ordered array that functions as the story's timeline.

The state machine tracks the current step index and updates the data-story-beat-state attributes on the DOM elements as the user navigates. When next() is called—either by user interaction or the auto-play timer—the runtime:

  1. Sets the current step's state to "past"
  2. Advances the pointer to the next element
  3. Sets that element's state to "active"
  4. Updates any subsequent elements to "next"

This attribute-based approach decouples the timing logic from the visual presentation, allowing designers to modify animations purely through CSS without touching JavaScript.

UI Components and Caption System

The viewer provides a standardized interface for story navigation that works automatically once markup is detected.

The caption bar structure appears in scripts/start-template.html between lines 4500 and 4530:

<div class="guided-story-caption" id="guided-story-caption" hidden>
  <span class="guided-story-caption-index" id="guided-story-caption-index">1</span>
  <strong id="guided-story-caption-route">Step Title</strong>
  <small id="guided-story-caption-detail">Description of what is happening.</small>
</div>

Navigation controls include:

  • Play/Pause: The button with class guided-view-play (ID guided-view-play) toggles automatic advancement using setInterval
  • Step Navigation: Buttons with data-story-link="forward" or data-story-link="backward" trigger the state machine's next() and prev() methods
  • Stop: The guided-view-stop button halts playback and resets the story to the initial state

The runtime updates the caption text content dynamically based on the active step's context, though you can customize the caption content by modifying the markup or overriding the update handlers.

CSS Animations and Visual Feedback

Visual feedback relies entirely on CSS selectors targeting the state attributes. The keyframe definitions reside in the template's stylesheet section around line 4298 of scripts/start-template.html.

[data-story-beat-state="active"] {
  animation: archify-story-flow 1.5s ease-in-out infinite alternate;
  stroke-width: 3px;
  filter: drop-shadow(0 0 8px rgba(59, 130, 246, 0.8));
}

[data-story-beat-state="past"] {
  opacity: 0.5;
  filter: grayscale(0.6);
}

[data-story-beat-state="next"] {
  opacity: 0.8;
}

@keyframes archify-story-flow {
  from { stroke: #3b82f6; }
  to { stroke: #60a5fa; }
}

Because the runtime only manipulates data attributes, designers have complete control over the visual language of stories. You can replace the default pulse animation with fades, slides, or 3D transforms by modifying the CSS without changing the core viewer logic.

Programmatic Story Control

While the viewer creates story objects automatically, you can access them via the DOM to build custom controls or integrate with external UI frameworks.

// Access the story object attached to the SVG element
const storyElement = document.querySelector('[data-story-beat]');
const story = storyElement.story; // Attached by the runtime

// Manual control
story.play();      // Start auto-advancement
story.pause();     // Pause auto-advancement
story.next();      // Advance one step
story.prev();      // Go back one step
story.stop();      // Reset to beginning and clear active states

// Check current state
console.log(story.currentIndex); // Current step number
console.log(story.totalSteps);   // Total number of steps

This API allows integration with routing libraries or presentation frameworks, letting you synchronize the diagram story with documentation scroll position or tutorial checklists.

Summary

  • Stories in Archify are created using declarative data-story-beat and data-story-step attributes embedded directly in SVG or HTML markup.
  • The runtime discovers stories using querySelectorAll and builds an ordered timeline from DOM elements, storing the logic in scripts/start-template.html around line 3370.
  • A state machine manages progression by cycling data-story-beat-state attributes through "past", "active", and "next" values.
  • Visual effects are handled entirely by CSS keyframes (defined near line 4298) that respond to state attribute changes, enabling custom animations without JavaScript modifications.
  • UI controls including play buttons, navigation arrows, and caption bars are pre-defined in the template (lines 4500-4530) and wire automatically to the story state machine.
  • The system supports programmatic control through story objects exposed on DOM elements, enabling integration with external applications or custom interaction patterns.

Frequently Asked Questions

How do I create a basic story in an Archify diagram?

Add the data-story-beat attribute to your root SVG element, then place data-story-step on each element you want to highlight in sequence. The viewer automatically detects these attributes and initializes the story timeline when the page loads. No JavaScript initialization is required for basic playback.

What triggers the visual animations during story playback?

The runtime modifies the data-story-beat-state attribute on active elements to "active", which triggers CSS rules defined in the viewer template. The default stylesheet includes pulse animations and glow effects, but you can customize these by targeting [data-story-beat-state="active"] in your own CSS.

Can I control story playback programmatically?

Yes. Once initialized, the viewer attaches a story object to the DOM element bearing data-story-beat. Access it via element.story to call methods like play(), pause(), next(), and stop(). This allows you to synchronize diagram walkthroughs with external documentation or user interactions outside the diagram itself.

Where is the story logic implemented in the Archify source code?

The core story parsing and state management logic resides in scripts/start-template.html around line 3370. The caption UI markup appears between lines 4500-4530, and the associated CSS animations are defined near line 4298. Additional examples demonstrating gallery and guide implementations appear in scripts/gallery-template.html and scripts/guide-template.html.

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 →