# Archify Visual Presets Rendering and Styling: Complete Implementation Guide

> Implement Archify visual presets rendering and styling using data attributes for instant, CSS-driven theme switching between Signal-Flow, Blueprint, and Editorial modes. No JavaScript needed.

- Repository: [tt-a1i/archify](https://github.com/tt-a1i/archify)
- Tags: deep-dive
- Published: 2026-09-13

---

**Archify visual presets rendering and styling** relies on HTML data attributes (`data-preset` and `data-theme`) applied to the root `<html>` element, enabling instant CSS-driven switching between Signal-Flow, Blueprint, and Editorial modes without JavaScript style manipulation.

The tt-a1i/archify repository implements a declarative theming system that separates visual intent from color scheme through cascade-scoped CSS. By using attribute selectors rather than class-based styling, the viewer layer achieves immediate aesthetic changes without re-rendering the underlying diagram canvas.

## How the Preset Architecture Works

### Root-Level Data Attributes

Every Archify viewer instance begins with a root `<html>` tag seeded with `data-preset` and `data-theme` attributes. According to the template in [`viewer/template.source.html`](https://github.com/tt-a1i/archify/blob/main/viewer/template.source.html), the markup structure uses placeholders that resolve at runtime:

```html
<html lang="en" data-theme="dark" data-preset="[VISUAL PRESET]">

```

The placeholder `[VISUAL PRESET]` resolves to one of three identifiers: `signal-flow`, `blueprint`, or `editorial`. This attribute cascade allows all child elements to inherit styling context without inline style manipulation.

### MutationObserver for Dynamic Updates

The [`viewer-chrome-layout.js`](https://github.com/tt-a1i/archify/blob/main/viewer-chrome-layout.js) file establishes a `MutationObserver` that watches for attribute mutations on `data-embed`, `data-present`, `data-preset`, and `data-theme` [L297-L300]. When the preset changes, the observer triggers immediate re-styling without reloading the diagram canvas or executing heavy JavaScript computations.

## CSS Scoping and Theme Interaction

The system supports both dark and light themes through parallel CSS rule sets. Each preset defines scoped blocks using the attribute selector pattern `[data-preset="..."]`, enabling clean separation between visual layout and color scheme.

**Signal-Flow** dark mode styles target specific viewer components:

```css
[data-preset="signal-flow"][data-theme="dark"] .header { … }
[data-preset="signal-flow"] .diagram-container { … }
[data-preset="signal-flow"] .header-row::after { 
  content: attr(data-preset-badge-signal-flow); 
}

```

**Blueprint** and **Editorial** presets follow identical structural patterns, customizing borders, radii, card layouts, and badge content through the same selector architecture (see the complete selector list in [`viewer/template.source.html`](https://github.com/tt-a1i/archify/blob/main/viewer/template.source.html) [L257-L340]).

Theme toggling works independently by updating the `data-theme` attribute:

```css
[data-preset="signal-flow"][data-theme="light"] .diagram-container { … }
[data-preset="blueprint"][data-theme="dark"] .card { background: #fff; }

```

## Implementing Preset Controls

### Toolbar Interface

The viewer includes a toolbar button (`#btn-preset`) that embeds options via `data-preset-option` attributes. When users select a preset, the script updates the root element's `data-preset` attribute, causing scoped CSS selectors to activate instantly without reflow penalties.

### Programmatic Preset Switching

Developers can switch presets without user interaction by manipulating the DOM attributes directly:

```javascript
// Switch to the Editorial preset (light theme)
const root = document.documentElement;
root.setAttribute('data-preset', 'editorial');
root.setAttribute('data-theme', 'light');

```

The mutation observer in [`viewer-chrome-layout.js`](https://github.com/tt-a1i/archify/blob/main/viewer-chrome-layout.js) automatically detects these changes and synchronizes the UI chrome state.

## Extending the Preset System

To add a custom preset, modify both the CSS definitions and the initialization script. First, add scoped rules to [`viewer/template.source.html`](https://github.com/tt-a1i/archify/blob/main/viewer/template.source.html):

```css
/* Add a new preset called "research" */
[data-preset="research"][data-theme="dark"] .header { 
  background: #1a1a2e; 
}
[data-preset="research"][data-theme="light"] .header { 
  background: #f0f0f0; 
}

```

Then extend the UI menu in [`viewer-chrome-layout.js`](https://github.com/tt-a1i/archify/blob/main/viewer-chrome-layout.js):

```javascript
const btn = document.createElement('button');
btn.dataset.presetOption = 'research';
btn.textContent = 'Research';
document.querySelector('.preset-menu').appendChild(btn);

```

The new preset follows the same attribute-driven pattern, guaranteeing immediate styling once the attribute is toggled.

## Summary

- Archify uses **HTML data attributes** (`data-preset`, `data-theme`) to control visual rendering through CSS scoping rather than JavaScript style injection.
- The **MutationObserver** in [`viewer/viewer-chrome-layout.js`](https://github.com/tt-a1i/archify/blob/main/viewer/viewer-chrome-layout.js) watches for attribute changes at lines 297-300 and applies styles without re-rendering diagrams.
- Three built-in presets exist: **Signal-Flow**, **Blueprint**, and **Editorial**, each with dark and light variants defined in [`viewer/template.source.html`](https://github.com/tt-a1i/archify/blob/main/viewer/template.source.html).
- **Declarative styling** eliminates runtime style calculations, ensuring smooth performance during preset transitions.
- New presets require only CSS selector blocks and toolbar menu extensions following the established `[data-preset="name"]` pattern.

## Frequently Asked Questions

### How do I set the default preset when embedding Archify?

Set the `data-preset` attribute on the container element before calling `initViewer()` from [`viewer/viewer-chrome-layout.js`](https://github.com/tt-a1i/archify/blob/main/viewer/viewer-chrome-layout.js). The initialization script reads this attribute and applies it to the root `<html>` element, triggering the corresponding CSS rules from [`viewer/template.source.html`](https://github.com/tt-a1i/archify/blob/main/viewer/template.source.html) immediately upon load.

### Can I use custom presets beyond the three built-in options?

Yes. Define new CSS blocks using the `[data-preset="your-name"]` selector pattern in [`viewer/template.source.html`](https://github.com/tt-a1i/archify/blob/main/viewer/template.source.html), then extend the toolbar UI in [`viewer-chrome-layout.js`](https://github.com/tt-a1i/archify/blob/main/viewer-chrome-layout.js) by adding buttons with `data-preset-option` attributes. The existing MutationObserver automatically handles custom presets without additional JavaScript observers.

### What happens when a user toggles between dark and light themes?

The system updates the `data-theme` attribute on the root element, causing CSS selectors that include `[data-theme="dark"]` or `[data-theme="light"]` to activate. This works independently from the preset system, allowing any combination of preset and theme (e.g., Blueprint dark mode or Signal-Flow light mode) without conflicts.

### Does switching presets require re-rendering the diagram?

No. Because styling relies entirely on CSS attribute selectors, preset changes apply instantly through the browser's render pipeline. The MutationObserver detects the attribute change and ensures the UI chrome updates, but the underlying diagram canvas remains intact, preserving performance and state.