How Guided Views Work in the Archify Viewer: Architecture and Implementation

Guided views in the Archify viewer are implemented as a client-side state machine that renders a toolbar from JSON-defined camera shots, enabling step-by-step navigation through architectural stories without requiring server calls.

The tt-a1i/archify repository provides a lightweight 3D document viewer where guided views serve as the primary mechanism for authors to create interactive, cinematic walkthroughs. Understanding how guided views work reveals a purely client-side architecture that leverages HTML data attributes and minimal JavaScript to manage complex playback states across four key source files.

Architecture Overview

The implementation follows a three-layer architecture spanning markup, presentation, and behavior.

HTML Markup Layer

In scripts/mco-runtime.html, the system renders a container with the class guided-views that holds the entire interface. Each individual view is represented as a <div class="guided-view-copy"> containing visible labels and notes, paired with a hidden <button class="guided-view-stop"> that stores the view's serialized state and camera position.

CSS Styling Layer

The stylesheet in scripts/mco-runtime.html defines the .guided-views class and its child selectors (.guided-view-play, .guided-view-stop, .guided-view-copy). These rules render the toolbar interface when the document runs standalone, but apply display:none !important when data-embed="true" or data-motion="still" attributes are present on the container.

JavaScript Logic Layer

File scripts/build-gallery.mjs coordinates the runtime behavior. The script sets a boolean flag guidedPlayback to true whenever a document contains a non-zero viewCount, triggering the initialization of navigation controls. The logic maintains a state machine where each view button carries a data-story-beat-state attribute cycling through pending, next, past, and active values to drive UI updates and camera transitions.

The Build Pipeline and Data Generation

The process begins with a JSON description of camera states and compiles into interactive HTML.

  1. Authoring: Creators define view objects with properties like label, note, and cameraState.
  2. Compilation: scripts/build-gallery.mjs parses this JSON and emits the <div class="guided-views"> block, injecting hidden buttons for each view and calculating the guidedPlayback flag.
  3. Attribute Injection: The build step adds data attributes including data-preset, data-present, data-document-hidden, and data-story-beat to control visibility and initial state.

User interaction is handled through a declarative state system rather than imperative DOM manipulation.

The viewer tracks playback position using the data-story-beat-state attribute on each .guided-view-stop button. When users click the Prev or Next buttons, the JavaScript advances the cursor, updates the container's data-story-beat attribute, and triggers camera transitions through the Archify API. The Play button toggles data-playing="true" on the container, initiating automatic stepping through views at fixed intervals while updating button opacity and icons based on the current state.

Embedding and Contextual Visibility

The toolbar automatically adapts to its presentation context. When the containing element specifies data-embed="true", CSS rules hide the entire .guided-views interface, allowing the viewer to integrate seamlessly into external pages while preserving the underlying navigation logic for programmatic control.

Exporting and Deep Linking

Each guided view supports one-click sharing through the copy functionality. The event handler in scripts/build-gallery.mjs constructs a deep link by appending the current view ID to location.href, then writes the result to the system clipboard using navigator.clipboard.writeText().

Implementation Examples

Basic Toolbar Markup

<div class="guided-views" data-preset="blueprint">
  <button id="guided-view-prev" disabled>←</button>
  <button id="guided-view-play" aria-pressed="false">▶︎</button>
  <button id="guided-view-next">→</button>

  <div class="guided-view-copy">
    <strong id="guided-view-label">Intro</strong>
    <small id="guided-view-note">Overview of the architecture</small>
  </div>

  <button class="guided-view-stop" data-story-beat-state="pending"></button>
</div>

Playback Initialization

// From scripts/build-gallery.mjs
if (entry.viewCount > 0) {
  guidedPlayback = true;  // Enables toolbar rendering
}

// Navigation handler
document.getElementById('guided-view-next')
  .addEventListener('click', () => advanceView());

function advanceView() {
  const container = document.querySelector('.guided-views');
  const next = container.querySelector('[data-story-beat-state="next"]');
  if (!next) return;
  
  setCameraFromView(next.dataset.viewId);
  next.dataset.storyBeatState = 'active';
}

Copy to Clipboard

document.querySelector('.guided-view-copy button')
  .addEventListener('click', async () => {
    const link = location.href + `#view=${currentViewId}`;
    await navigator.clipboard.writeText(link);
  });

Key Source Files

  • scripts/build-gallery.mjs: Generates markup, manages guidedPlayback state, and wires navigation handlers.
  • scripts/mco-runtime.html: Demonstrates the live toolbar implementation and contains the CSS styling block.
  • scripts/guide-template.html: Template used during builds to produce pages with guided-view support.
  • scripts/start-template.html: Base viewer template including responsive CSS rules for toolbar visibility.

Summary

  • Guided views are defined in JSON and compiled into HTML by scripts/build-gallery.mjs.
  • The guidedPlayback flag activates the feature only when views exist.
  • State management relies on data-story-beat-state attributes cycling through pending, next, past, and active.
  • The toolbar hides automatically via CSS when data-embed="true" is set.
  • All functionality executes client-side with no server dependencies after the initial page load.

Frequently Asked Questions

What triggers the guided views toolbar to appear?

The toolbar renders when scripts/build-gallery.mjs detects a non-zero viewCount in the document configuration and sets guidedPlayback to true. This flag initializes the DOM listeners and unhides the .guided-views container.

How does the state machine track which view is active?

Each view button stores its status in the data-story-beat-state attribute, which can hold values of pending, next, past, or active. The JavaScript updates these values and the container's data-story-beat attribute to synchronize the camera position with the UI highlight.

Can I use guided views when embedding the Archify viewer in another site?

Yes, but the toolbar hides automatically. When the root element carries data-embed="true", CSS rules apply display:none !important to the .guided-views class. The underlying navigation logic remains available for programmatic control via the Archify API.

Which source files should I modify to customize the guided views styling?

Edit scripts/mco-runtime.html to change the CSS rules for .guided-views and its children. For structural changes to how views are generated, modify scripts/build-gallery.mjs, which controls the HTML emission and state initialization.

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 →