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.
- Authoring: Creators define view objects with properties like
label,note, andcameraState. - Compilation:
scripts/build-gallery.mjsparses this JSON and emits the<div class="guided-views">block, injecting hidden buttons for each view and calculating theguidedPlaybackflag. - Attribute Injection: The build step adds data attributes including
data-preset,data-present,data-document-hidden, anddata-story-beatto control visibility and initial state.
Navigation and State Machine
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, managesguidedPlaybackstate, 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
guidedPlaybackflag activates the feature only when views exist. - State management relies on
data-story-beat-stateattributes cycling throughpending,next,past, andactive. - 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →