How to Create a Custom Visual Preset or Theme in Archify: A Complete Guide
To create a custom visual preset in Archify, extend the JSON schema with a new enum value, add scoped CSS rules under the [data-preset] attribute selector, and expose the option in the preset picker UI.
Archify's visual preset system lets you rebrand diagrams without touching geometry or logic. The preset flows from the meta.visual_preset field in your diagram JSON through to CSS variables that style the entire rendered output. Because the renderer keeps layout and appearance strictly separated, you can invent entirely new aesthetics without risking diagram integrity.
This guide walks through the three-step process based on the actual Archify source code in tt-a1i/archify.
Step 1: Extend the Schema to Accept Your Custom Preset
Before any renderer will load your theme, the JSON validator must recognize its name. In archify/schemas/architecture.schema.json, line 20 defines the allowed enum values for visual_preset [source].
Modify the schema to include your custom preset:
{
"visual_preset": {
"enum": [
"classic",
"signal-flow",
"blueprint",
"editorial",
"my-preset"
]
}
}
Without this change, diagrams using your custom preset will fail validation at load time.
Step 2: Define CSS Rules Scoped to Your Preset
Archify applies presets client-side only, using the data-preset attribute on the root <html> element. All styling hangs off this selector, as demonstrated in experiments/visual-evolution/prototype.html lines 129-170 [source].
Create a CSS block that targets html[data-preset="your-name"]:
/* Dark mode support via data-theme attribute */
html[data-preset="my-preset"][data-theme="dark"] {
--bg-body: #1a1a2e;
--fg-primary: #e0e0ff;
--accent: #ff6f61;
}
/* Light mode fallback */
html[data-preset="my-preset"][data-theme="light"] {
--bg-body: #fafafa;
--fg-primary: #1a1a2e;
--accent: #ff6f61;
}
/* Component-level styling */
html[data-preset="my-preset"] .header {
padding-right: 2rem;
}
html[data-preset="my-preset"] .card {
background: var(--bg-body);
color: var(--fg-primary);
border: 1px solid var(--accent);
}
/* Decorative overlay */
html[data-preset="my-preset"] .diagram-container::before {
content: "";
position: absolute;
inset: 0;
background: radial-gradient(
circle at 20% 20%,
var(--accent) 0%,
transparent 70%
);
pointer-events: none;
}
The renderer never recomputes layout based on these styles—geometry remains stable regardless of which preset is active [source].
Step 3: Expose the Preset in the UI Picker
The preset picker is a menu-pattern button that appears in every rendered page. The test suite in archify/test/preset-tryon.test.mjs validates that all four built-in presets appear as options and that selecting one synchronizes both <html> and <svg> elements [source].
To add your preset to the picker, extend the runtime preset list and generate the corresponding menu item. The shared UI utilities in archify/renderers/shared/utils.mjs (or equivalent) handle this:
// Extend the supported preset values
const PRESET_VALUES = [
'classic',
'signal-flow',
'blueprint',
'editorial',
'my-preset'
];
// Assign to global Archify config
Archify.preset = PRESET_VALUES;
function buildPresetMenu() {
const menu = document.getElementById('preset-menu');
PRESET_VALUES.forEach(value => {
const item = document.createElement('button');
item.dataset.presetValue = value;
item.setAttribute('role', 'menuitemradio');
item.textContent = value
.split('-')
.map(w => w.charAt(0).toUpperCase() + w.slice(1))
.join(' ');
item.addEventListener('click', () => applyPreset(value));
menu.appendChild(item);
});
}
function applyPreset(presetName) {
const html = document.documentElement;
const svg = document.querySelector('svg.archify-root');
// Both elements must carry the attribute for full styling coverage
html.setAttribute('data-preset', presetName);
svg?.setAttribute('data-preset', presetName);
// Update ARIA states
menu.querySelectorAll('[role="menuitemradio"]')
.forEach(btn => btn.setAttribute('aria-checked',
btn.dataset.presetValue === presetName));
}
This synchronization logic—setting data-preset on both <html> and <svg>—mirrors the test assertions at lines 58-61 of the preset try-on suite [source].
Using Your Custom Preset in a Diagram
Once the three steps above are complete, reference your preset in any diagram JSON:
{
"schema_version": 1,
"diagram_type": "architecture",
"meta": {
"title": "Production API Gateway",
"visual_preset": "my-preset",
"animation": "none"
},
"components": [
{
"id": "gateway",
"type": "service",
"label": "API Gateway"
}
],
"connections": []
}
The renderer will validate against your extended schema, apply the data-preset attribute, and your CSS will take effect immediately.
Preset Architecture and Performance Guarantees
Understanding how presets operate helps you build efficiently:
- Geometry preservation: The architecture renderer in
render-architecture.mjsnever inspectsvisual_presetwhen computing node positions or edge routes. Your preset cannot accidentally corrupt layout. - Zero server-side processing: The preset string passes straight from JSON to HTML attribute without transformation.
- CSS-only activation: All visual effects—colors, spacing, decorative elements—flow through standard CSS custom properties and selectors.
Summary
- Extend the schema at
archify/schemas/architecture.schema.jsonto whitelist your preset name. - Scope all styles under
html[data-preset="your-name"]following the pattern inexperiments/visual-evolution/prototype.html. - Register in the UI by adding to
PRESET_VALUESand ensuring the picker synchronizesdata-preseton both<html>and<svg>elements. - Reference in diagrams via
meta.visual_presetwithout any other changes to structure or semantics.
Frequently Asked Questions
What happens if I use a preset not in the schema?
Diagrams with unrecognized visual_preset values fail JSON validation at load time. The renderer never reaches the CSS stage—extend the schema first.
Can a preset affect layout or node positioning?
No. The renderer separates geometry computation from styling. Presets only control CSS custom properties and decorative elements; they cannot modify edge routing, node sizes, or relative positioning.
How do I support both light and dark modes in my custom preset?
Use the data-theme attribute alongside data-preset. Define parallel blocks: html[data-preset="my-preset"][data-theme="light"] and [data-theme="dark"]. Archify toggles data-theme independently of preset selection.
Where should I store custom preset CSS?
Add it to the same file that hosts built-in preset styles, or load it as a separate stylesheet after the core Archify CSS. The experiments/visual-evolution/prototype.html file demonstrates inline <style> blocks for prototyping; production deployments typically externalize these rules.
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 →