# Mermaid Diagram API Architecture: How diagram-orchestration.ts Orchestrates Diagram Loaders

> Explore the Mermaid diagram API architecture in diagram-orchestration.ts. Learn how it directs diagram types to specialized loaders for efficient parsing and rendering.

- Repository: [mermaid-js/mermaid](https://github.com/mermaid-js/mermaid)
- Tags: architecture
- Published: 2026-02-23

---

**The Mermaid diagram API architecture is centered on [`diagram-orchestration.ts`](https://github.com/mermaid-js/mermaid/blob/main/diagram-orchestration.ts), which acts as a traffic controller that detects diagram types and delegates parsing and rendering to specialized diagram loaders implementing the `DiagramLoader` interface.**

The mermaid-js/mermaid repository uses a modular architecture to support dozens of diagram types without bloating the core bundle. At the heart of this system lies [`packages/mermaid/src/diagram-orchestration.ts`](https://github.com/mermaid-js/mermaid/blob/main/packages/mermaid/src/diagram-orchestration.ts), which coordinates how raw text definitions transform into rendered SVG output. Understanding this architecture reveals how Mermaid maintains extensibility while keeping diagram-specific logic isolated.

## The Role of diagram-orchestration.ts as the Central Orchestrator

[`diagram-orchestration.ts`](https://github.com/mermaid-js/mermaid/blob/main/diagram-orchestration.ts) functions as the single entry point for all diagram rendering operations. When a user calls `mermaid.render()`, the orchestration layer receives the raw diagram definition and executes a four-phase workflow: type detection, loader selection, pipeline delegation, and error handling.

### Diagram Type Detection and Routing

The orchestrator extracts the first keyword from the diagram definition (e.g., `flowchart`, `sequenceDiagram`, `classDiagram`) and consults an internal registration map. This map, defined as `loaders: Record<string, DiagramLoader>`, associates each keyword with its corresponding loader instance.

```typescript
// Simplified conceptual flow from diagram-orchestration.ts
function getDiagram(type: string): DiagramLoader {
  const loader = loaders[type];
  if (!loader) {
    throw new Error(`No diagram loader registered for type: ${type}`);
  }
  return loader;
}

```

### Error Handling and Fallback Mechanisms

If the orchestrator encounters an unsupported diagram keyword or if a loader throws during execution, [`diagram-orchestration.ts`](https://github.com/mermaid-js/mermaid/blob/main/diagram-orchestration.ts) surfaces descriptive error messages rather than failing silently. In certain configurations, it can fall back to a no-op loader that returns a placeholder diagram structure, preventing total rendering failure when one diagram type malfunctions.

## How Diagram Loaders Implement the Rendering Pipeline

Diagram loaders encapsulate the syntax-specific logic for individual diagram types. Located in files like [`flowchart-loader.ts`](https://github.com/mermaid-js/mermaid/blob/main/flowchart-loader.ts), [`sequence-loader.ts`](https://github.com/mermaid-js/mermaid/blob/main/sequence-loader.ts), and [`class-loader.ts`](https://github.com/mermaid-js/mermaid/blob/main/class-loader.ts), these modules implement the `DiagramLoader` interface defined in [`diagram-loader-base.ts`](https://github.com/mermaid-js/mermaid/blob/main/diagram-loader-base.ts).

### The DiagramLoader Interface Contract

The abstract base class `DiagramLoader` in [`packages/mermaid/src/diagram-loader-base.ts`](https://github.com/mermaid-js/mermaid/blob/main/packages/mermaid/src/diagram-loader-base.ts) enforces a three-method contract that every loader must implement:

```typescript
export abstract class DiagramLoader {
  /** Turn the raw text into an abstract syntax tree (AST) */
  abstract parse(text: string): DiagramAST;

  /** Validate the AST – throw if something is illegal */
  abstract validate(ast: DiagramAST): void;

  /** Convert the AST into a renderable structure */
  abstract draw(ast: DiagramAST, id: string): DiagramModel;
}

```

This contract ensures that [`diagram-orchestration.ts`](https://github.com/mermaid-js/mermaid/blob/main/diagram-orchestration.ts) can treat all diagram types uniformly, regardless of their internal complexity.

### From Parse to Draw: The Three-Stage Pipeline

When the orchestrator invokes a loader, it triggers a standardized three-stage pipeline:

1. **Parse**: The loader's `parse()` method executes grammar-specific parsing (often using generated parsers from Jison or similar tools) to produce a `DiagramAST`.
2. **Validate**: The `validate()` method checks semantic constraints—ensuring that node references exist, that class inheritance cycles are absent, or that sequence diagram participants are declared before use.
3. **Draw**: The `draw()` method transforms the validated AST into a `DiagramModel`, a language-agnostic structure containing nodes, edges, and layout constraints that the generic [`renderer.ts`](https://github.com/mermaid-js/mermaid/blob/main/renderer.ts) consumes to produce SVG output.

## Extending the Architecture with Custom Loaders

The orchestration architecture enables runtime extensibility without modifying core Mermaid source code. Developers can register custom diagram types by implementing the `DiagramLoader` interface and calling the registration API.

```typescript
import mermaidAPI from 'mermaid';
import { DiagramLoader, DiagramAST, DiagramModel } from 'mermaid/src/diagram-loader-base';

// Custom loader implementation
class EchoLoader extends DiagramLoader {
  parse(text: string): DiagramAST {
    return { type: 'echo', raw: text.trim() };
  }
  
  validate(ast: DiagramAST): void {
    if (!ast.raw) throw new Error('Empty echo diagram');
  }
  
  draw(ast: DiagramAST, id: string): DiagramModel {
    return {
      id,
      nodes: [{ id: 'node1', label: ast.raw, type: 'text' }],
      edges: []
    };
  }
}

// Register with the orchestration layer
mermaidAPI.registerDiagram('echoDiagram', new EchoLoader());

// Usage
const definition = `
echoDiagram
    This text appears as a single node.
`;

mermaidAPI.render('echoId', definition, (svg) => {
  console.log('Custom diagram rendered:', svg);
});

```

This extensibility pattern demonstrates how [`diagram-orchestration.ts`](https://github.com/mermaid-js/mermaid/blob/main/diagram-orchestration.ts) serves as the single source of truth for loader management while remaining agnostic to the specific implementation details of each diagram type.

## Summary

- **[`diagram-orchestration.ts`](https://github.com/mermaid-js/mermaid/blob/main/diagram-orchestration.ts)** functions as the central traffic controller for Mermaid's rendering pipeline, detecting diagram types and delegating to specialized loaders.
- **Diagram loaders** implement the `DiagramLoader` interface defined in [`diagram-loader-base.ts`](https://github.com/mermaid-js/mermaid/blob/main/diagram-loader-base.ts), providing `parse()`, `validate()`, and `draw()` methods that transform text into renderable models.
- The architecture enforces a **clean separation of concerns**: the orchestration layer handles routing and error management while loaders encapsulate syntax-specific logic.
- **Runtime extensibility** is supported through the `registerDiagram()` API, allowing custom diagram types without modifying core source code.
- The generic **[`renderer.ts`](https://github.com/mermaid-js/mermaid/blob/main/renderer.ts)** consumes the `DiagramModel` produced by loaders to generate final SVG/HTML output, completing the decoupled pipeline.

## Frequently Asked Questions

### What is the primary responsibility of diagram-orchestration.ts?

The primary responsibility of [`diagram-orchestration.ts`](https://github.com/mermaid-js/mermaid/blob/main/diagram-orchestration.ts) is to act as the central routing layer that detects diagram types from raw text definitions and delegates rendering operations to the appropriate diagram loader. It maintains a registry of loaders, handles error boundaries when loaders fail, and coordinates the handoff between parsing, validation, and the generic rendering subsystem.

### How does a diagram loader differ from the generic renderer?

A **diagram loader** is syntax-specific and implements the `DiagramLoader` interface to handle parsing, AST validation, and model construction for one diagram type (e.g., flowcharts or sequence diagrams). The **generic renderer** ([`renderer.ts`](https://github.com/mermaid-js/mermaid/blob/main/renderer.ts)) is diagram-agnostic; it consumes the standardized `DiagramModel` produced by any loader and handles the actual SVG generation, layout calculations, and DOM insertion. This separation allows Mermaid to support new diagram types by only implementing a new loader, without touching the rendering engine.

### Can I register a custom diagram type without modifying Mermaid's core?

Yes, Mermaid's architecture supports runtime registration of custom diagram types through the `mermaidAPI.registerDiagram()` method. By implementing the `DiagramLoader` abstract class from [`diagram-loader-base.ts`](https://github.com/mermaid-js/mermaid/blob/main/diagram-loader-base.ts) and providing concrete implementations for `parse()`, `validate()`, and `draw()`, you can inject new diagram syntax into the orchestration layer. The custom loader is then stored in the same internal map that [`diagram-orchestration.ts`](https://github.com/mermaid-js/mermaid/blob/main/diagram-orchestration.ts) consults, making it a first-class citizen alongside built-in diagram types.

### What happens when diagram-orchestration.ts encounters an unsupported diagram keyword?

When [`diagram-orchestration.ts`](https://github.com/mermaid-js/mermaid/blob/main/diagram-orchestration.ts) encounters a diagram keyword that does not exist in its loader registry, it throws a descriptive error indicating that no loader is registered for that type. In certain edge cases or configurations, the orchestration layer may fall back to a no-op loader that returns a placeholder diagram structure, preventing a total application crash while signaling that the specific diagram type is unavailable. This error handling ensures that invalid or unsupported syntax fails gracefully with clear feedback to the developer.