# How archify Renderers Convert JSON to HTML and SVG

> Discover how Archify renderers convert JSON to HTML and SVG. Learn about layout computation, validation, and SVG injection for creating standalone diagrams.

- Repository: [tt-a1i/archify](https://github.com/tt-a1i/archify)
- Tags: internals
- Published: 2026-08-07

---

**archify renderers convert JSON diagram descriptions into standalone HTML files with embedded SVG by loading and validating the input, computing diagram-specific layouts, and injecting the resulting SVG into a static HTML template.**

The archify project provides typed renderers for **architecture**, **workflow**, **sequence**, **dataflow**, and **lifecycle** diagrams. Each renderer follows a consistent three-stage pipeline implemented in `archify/renderers/shared/cli.mjs` and specialized per diagram type in dedicated renderer modules.

## The Three-Stage Conversion Pipeline

### Stage 1: Load and Validate with `loadDiagram()`

Every renderer begins by invoking `loadDiagram()` from `archify/renderers/shared/cli.mjs`. This utility function:

- Resolves the input JSON file path from command-line arguments
- Parses and validates the JSON against the diagram-type-specific schema
- Validates **guided views** and **relationship identifiers** for cross-collection consistency
- Retrieves the HTML template from [`archify/assets/template.html`](https://github.com/tt-a1i/archify/blob/main/archify/assets/template.html)
- Constructs the output path object

The validation ensures that architectural components, sequence participants, workflow nodes, or lifecycle states conform to expected structures before rendering begins.

### Stage 2: Compute Layout and Generate SVG

Each typed renderer imports shared utilities from `archify/renderers/shared/` and implements diagram-specific layout logic:

| Renderer | Source File | Layout Focus |
|----------|-------------|--------------|
| **Architecture** | `archify/renderers/architecture/render-architecture.mjs` | Grid-based component positioning, boundary containment, connection routing |
| **Sequence** | `archify/renderers/sequence/render-sequence.mjs` | Fixed-column participant layout, lifeline coordinates, message arc positioning |
| **Workflow** | `archify/renderers/workflow/render-workflow.mjs` | DAG node placement, edge routing through waypoints |
| **Dataflow** | `archify/renderers/dataflow/render-dataflow.mjs` | Port-based node positioning, flow path computation |
| **Lifecycle** | `archify/renderers/lifecycle/render-lifecycle.mjs` | State arrangement, transition curve routing |

The `renderSvg()` function in each module assembles the SVG markup with:

- Accessibility attributes via `svgRootAttrs` and `svgAccessibleText`
- SVG `<defs>` from `renderDefinitions()`
- Background grid, boundaries, connections, components, and labels
- A complete legend block

Layout validation helpers like `cleanFlowProblems()` and `cleanCrossingProblems()` ensure visual correctness before SVG generation.

### Stage 3: Template Injection with `writeDiagram()`

The final stage occurs in `writeDiagram()`, also from `cli.mjs`:

```javascript
writeDiagram({
  outPath,
  template,
  diagramType: 'architecture',
  meta: arch.meta,
  footerLabel: 'Architecture diagram',
  svg,           // Generated SVG string
  cards,         // Optional evidence cards
});

```

This function calls `applyTemplate()` to substitute placeholders in [`archify/assets/template.html`](https://github.com/tt-a1i/archify/blob/main/archify/assets/template.html) with:

- Page `<title>` and `<meta>` tags from `meta.title` and `meta.subtitle`
- The complete SVG markup
- Footer UI controls and guided-view navigation
- Visual preset data attributes

The result is a **self-contained HTML file** that requires no external dependencies.

## Command-Line Usage

Invoke any renderer directly with Node.js:

```bash

# Architecture diagram

node archify/renderers/architecture/render-architecture.mjs \
  examples/web-app.architecture.json \
  output/web-app.html

# Sequence diagram

node archify/renderers/sequence/render-sequence.mjs \
  examples/cache-miss-request.sequence.json \
  output/cache-miss.html

# Workflow diagram

node archify/renderers/workflow/render-workflow.mjs \
  examples/release-delivery.workflow.json \
  output/release.html

# Dataflow diagram

node archify/renderers/dataflow/render-dataflow.mjs \
  examples/api-gateway.dataflow.json \
  output/gateway.html

# Lifecycle diagram

node archify/renderers/lifecycle/render-lifecycle.mjs \
  examples/deployment.lifecycle.json \
  output/deploy.html

```

## Programmatic Integration

Embed rendering in Node.js scripts using `child_process`:

```javascript
import { spawnSync } from 'node:child_process';

function renderDiagram(type, inputJson, outputHtml) {
  const result = spawnSync('node', [
    `archify/renderers/${type}/render-${type}.mjs`,
    inputJson,
    outputHtml
  ], { encoding: 'utf-8' });
  
  if (result.error) throw result.error;
  console.log(`Rendered: ${outputHtml}`);
}

// Example usage
renderDiagram(
  'architecture',
  'diagrams/system.architecture.json',
  'dist/system.html'
);

```

## Renderer Internals: Architecture Example

The `render-architecture.mjs` module demonstrates the full pattern:

```javascript
// From archify/renderers/architecture/render-architecture.mjs

// 1. Load and validate
const { diagram: arch, template, outPath } = loadDiagram({
  rendererDir: new URL('.', import.meta.url).pathname,
  diagramType: 'architecture',
  defaultExample: 'web-app.architecture.json',
  argv: process.argv.slice(2)
});

// 2. Compute layout
const grid = gridLayout(arch.components, arch.layout || {});
const viewBox = computeViewBox(grid.extents);

// 3. Generate SVG with components, boundaries, connections
const svg = renderSvg({
  viewBox,
  definitions: renderDefinitions(),
  background: renderGrid(grid),
  content: [
    ...renderBoundaries(arch.boundaries),
    ...renderConnections(arch.connections),
    ...renderComponents(arch.components),
    renderLegend(arch.legend)
  ].join('\n')
});

// 4. Write final HTML
writeDiagram({
  outPath,
  template,
  diagramType: 'architecture',
  meta: arch.meta,
  footerLabel: `${arch.meta?.title || 'Architecture'} diagram`,
  svg,
  cards: arch.cards
});

```

The sequence renderer follows an analogous structure but replaces grid layout with column-based participant positioning and adds lifeline rendering for message flows.

## Key Source Files

- **`archify/renderers/shared/cli.mjs`** — CLI infrastructure: `loadDiagram()`, `writeDiagram()`, validation orchestration
- **`archify/renderers/shared/utils.mjs`** — Shared helpers: `esc()`, `renderDefinitions()`, template utilities
- **`archify/renderers/architecture/render-architecture.mjs`** — Architecture-specific layout and SVG generation
- **`archify/renderers/sequence/render-sequence.mjs`** — Sequence diagram lifelines and message rendering
- **`archify/renderers/workflow/render-workflow.mjs`** — Workflow DAG visualization
- **`archify/renderers/dataflow/render-dataflow.mjs`** — Dataflow port and flow rendering
- **`archify/renderers/lifecycle/render-lifecycle.mjs`** — State machine visualization
- **[`archify/assets/template.html`](https://github.com/tt-a1i/archify/blob/main/archify/assets/template.html)** — HTML scaffold with substitution placeholders

## Summary

- **archify renderers** convert JSON to HTML/SVG through a validated, three-stage pipeline
- **`loadDiagram()`** handles parsing, schema validation, and guided-view verification in `archify/renderers/shared/cli.mjs`
- **Typed renderer modules** (`render-architecture.mjs`, `render-sequence.mjs`, etc.) implement diagram-specific layouts and SVG generation via `renderSvg()`
- **`writeDiagram()`** injects the SVG and metadata into [`archify/assets/template.html`](https://github.com/tt-a1i/archify/blob/main/archify/assets/template.html) to produce standalone output files
- The architecture supports **five diagram types** with consistent patterns but specialized geometry for each visual domain

## Frequently Asked Questions

### What JSON schema do archify renderers validate against?

Each renderer validates input against a diagram-type-specific JSON Schema defined in the renderer's directory. The `loadDiagram()` function in `cli.mjs` selects the appropriate schema based on the `diagram_type` field and enforces structural requirements before layout computation begins.

### Can I customize the HTML template used for output?

Yes. The [`template.html`](https://github.com/tt-a1i/archify/blob/main/template.html) file in `archify/assets/` contains substitution placeholders that `applyTemplate()` replaces at runtime. Modify this file to change the page structure, CSS styling, or JavaScript behavior. Pass a custom template path via renderer configuration if supported by the specific implementation.

### How do archify renderers handle large diagrams?

Renderers compute view boxes automatically from layout extents and include zoom/pan controls in the generated HTML. The SVG output is static and self-contained, so browser-native zooming works without server dependencies. For very large diagrams, consider enabling guided views to present focused subsets sequentially.

### Are the generated SVGs accessible?

Yes. Every renderer injects accessibility features via `svgAccessibleText()` and `svgRootAttrs`, including `<title>` elements, `aria-label` attributes, and semantic `data-*` attributes for screen reader compatibility. The legend block provides textual alternatives to visual encoding.