Building a browser-based workflow simulator is one of the most useful features for modern enterprise applications. Sectors like manufacturing, aviation, finance, insurance, and IT operations commonly need custom workflows. Users want to visually create steps, connect nodes, define rules, run simulations, and see how the workflow behaves before pushing it to the live environment.

This article explains how to build a production-ready Workflow Simulator using Angular.
The system supports:

The goal is to build an Angular-based workflow editor that functions like lightweight versions of Camunda Modeler, Node-RED, or n8n, but fully customisable for your product.

Why Build a Workflow Simulator

Typical enterprise systems contain long-running or multi-step business processes. Before executing workflows in production, developers and business users need a safe sandbox to test logic.

A browser-based simulator allows:

Most importantly, it reduces rework and production issues.

High-Level Features Required

A workflow simulator must include:

  1. Node palette (Start, Task, Decision, API Call, Script, End).

  2. Drag-and-drop canvas.

  3. Connectors between nodes.

  4. Node configuration (name, rules, conditions, inputs).

  5. JSON export/import of the workflow.

  6. Execution engine to simulate the workflow step-by-step.

  7. Visual highlight of execution path.

  8. Validation engine.

  9. Undo/redo support.

  10. Event logs and breakpoints.

This article focuses on the Angular implementation, core architecture, and execution simulation.

High-Level Architecture

The system is divided into:

Architecture Workflow Diagram

           +------------------------------+
           |         Workflow UI          |
           +------------------------------+
             |          |            |
             |          |            |
             v          v            v
     +------------+  +-------+  +------------+
     | Node       |  | Edge  |  | Config     |
     | Palette    |  | Layer |  | Panel      |
     +------------+  +-------+  +------------+
             |          |
             |  Drag    | Connections
             v          v
        +---------------------+
        | Workflow Canvas     |
        +----------+----------+
                   |
                   v
        +------------------------+
        | Workflow Engine (Core) |
        +----------+-------------+
                   |
        Validate   |    Simulate
                   v
        +-------------------------+
        | Execution Simulator     |
        +-------------------------+
                   |
                   v
           +---------------+
           | Event Logs    |
           +---------------+

Flowchart: Workflow Execution Simulation

          +--------------------------+
          | Load Workflow Definition |
          +-------------+------------+
                        |
                        v
            +-----------+-----------+
            | Identify Start Node   |
            +-----------+-----------+
                        |
                        v
            +-----------+-----------+
            | Execute Current Node  |
            +-----------+-----------+
                        |
            +-----------+------------+
            | Node has outgoing path?|
            +------+-----------------+
                   | Yes
                   v
          +--------+--------+
          | Evaluate Rules  |
          +--------+--------+
                   |
         +---------+--------+
         | Select Next Node |
         +---------+--------+
                   |
                   v
         +---------+--------+
         | Move to Next Node|
         +---------+--------+
                   |
                   v
        Repeat until End node reached

Designing the Workflow Data Model

A workflow is a directed graph. Each node represents a step, and each edge represents the flow.

Node Structure

export interface WorkflowNode {
  id: string;
  type: 'start' | 'task' | 'decision' | 'api' | 'script' | 'end';
  name: string;
  position: { x: number; y: number };
  config?: any;
}

Edge Structure

export interface WorkflowEdge {
  id: string;
  from: string;
  to: string;
  condition?: string; // expression or rule
}

Workflow Definition

export interface WorkflowDefinition {
  nodes: WorkflowNode[];
  edges: WorkflowEdge[];
}

Building the Canvas in Angular

You will use these libraries/tools:

Basic Canvas Component

@Component({
  selector: 'app-workflow-canvas',
  templateUrl: './workflow-canvas.component.html',
  styleUrls: ['./workflow-canvas.component.css']
})
export class WorkflowCanvasComponent {
  @Input() workflow!: WorkflowDefinition;

  onNodeDrag(event: CdkDragMove, node: WorkflowNode) {
    node.position.x = event.pointerPosition.x;
    node.position.y = event.pointerPosition.y;
  }
}

Canvas Template

<div class="canvas-area">
  <div *ngFor="let node of workflow.nodes"
       class="node"
       cdkDrag
       [style.left.px]="node.position.x"
       [style.top.px]="node.position.y">
       {{ node.name }}
  </div>

  <svg class="edge-layer">
    <ng-container *ngFor="let edge of workflow.edges">
      <line
        [attr.x1]="getNode(edge.from).position.x + 50"
        [attr.y1]="getNode(edge.from).position.y + 20"
        [attr.x2]="getNode(edge.to).position.x"
        [attr.y2]="getNode(edge.to).position.y"
        stroke="black"
        stroke-width="2" />
    </ng-container>
  </svg>
</div>

Implementing Drag-and-Drop Node Palette

A simple palette:

<div class="palette">
  <button (click)="addNode('task')">Add Task</button>
  <button (click)="addNode('decision')">Add Decision</button>
  <button (click)="addNode('api')">Add API Call</button>
</div>

Add Node Logic

addNode(type: string) {
  const newNode: WorkflowNode = {
    id: crypto.randomUUID(),
    type,
    name: `${type} node`,
    position: { x: 100, y: 100 }
  };

  this.workflow.nodes.push(newNode);
}

Adding Connectors Between Nodes

Common approach:

  1. Click first node.

  2. Click second node.

  3. Create edge.

Add Edge Logic

addEdge(fromId: string, toId: string) {
  this.workflow.edges.push({
    id: crypto.randomUUID(),
    from: fromId,
    to: toId
  });
}

Adding Node Configuration Panel

This allows editing:

Sample Configuration Panel

<div class="config-panel" *ngIf="selectedNode">
  <h3>Node Configuration</h3>
  <label>Name:
    <input [(ngModel)]="selectedNode.name" />
  </label>

  <label *ngIf="selectedNode.type === 'decision'">
    Condition:
    <input [(ngModel)]="selectedNode.config.condition" />
  </label>
</div>

The Workflow Execution Engine

The Workflow Engine runs the workflow.
This includes:

Engine Structure

export class WorkflowEngine {
  constructor(private workflow: WorkflowDefinition) {}

  private logs: string[] = [];

  execute() {
    let currentNode = this.findStartNode();

    while (currentNode && currentNode.type !== 'end') {
      this.logs.push(`Executing: ${currentNode.name}`);
      currentNode = this.getNextNode(currentNode);
    }

    this.logs.push('Reached end node');
    return this.logs;
  }
}

Rule Evaluation for Decision Nodes

Rules may be:

Example Rule Evaluation

evaluateCondition(condition: string, context: any): boolean {
  const fn = new Function("context", `return ${condition}`);
  return fn(context);
}

For large enterprise systems, use a safe rule engine instead of dynamic functions.

Simulating Execution Step-by-Step

Support:

Step Mode Example

step() {
  if (!this.currentNode) {
    this.currentNode = this.findStartNode();
    return this.currentNode;
  }

  this.currentNode = this.getNextNode(this.currentNode);
  return this.currentNode;
}

Visualising Execution Path

When the simulator runs:

Canvas Highlighting Example

.node.active {
  border: 2px solid blue;
}

.edge.active {
  stroke: blue;
}

You will toggle CSS classes based on execution logs.

Validations Before Simulation

Essential validations:

  1. Workflow must contain exactly one start node.

  2. All nodes must be reachable from start.

  3. No cycles unless allowed.

  4. Decision nodes must contain valid conditions.

  5. All edges must reference valid node IDs.

Example Validation Function

validateWorkflow(workflow: WorkflowDefinition): string[] {
  const errors: string[] = [];

  const startNodes = workflow.nodes.filter(n => n.type === 'start');
  if (startNodes.length !== 1) {
    errors.push('Workflow must contain exactly one start node.');
  }

  // Additional validations…

  return errors;
}

JSON Export and Import

The workflow editor must support saving and loading.

Export

downloadJSON() {
  const json = JSON.stringify(this.workflow);
  // download logic
}

Import

uploadWorkflow(json: string) {
  this.workflow = JSON.parse(json);
}

Undo / Redo Support

Use an RxJS BehaviorSubject to push state snapshots.

Example

history: WorkflowDefinition[] = [];
historyIndex = -1;

pushState() {
  this.history.push(JSON.parse(JSON.stringify(this.workflow)));
  this.historyIndex++;
}

Undo

undo() {
  if (this.historyIndex > 0) {
    this.historyIndex--;
    this.workflow = JSON.parse(JSON.stringify(this.history[this.historyIndex]));
  }
}

Real-World Challenges and Best Practices

  1. Performance drops when rendering more than 200 nodes.
    Use canvas or WebGL for large workflows.

  2. Users need zooming and panning.
    Implement with CSS transforms.

  3. Complex connectors require bezier curves.
    Use SVG path elements.

  4. Decision rules get messy.
    Integrate a rules engine (Nools, JSON-rules-engine).

  5. Autosaving is essential.
    Persist state in localStorage every few seconds.

  6. Multi-user collaboration.
    Use WebSockets and operational transforms.

  7. Prevent invalid node drops.
    Add guards and context checks.

Production-Level Recommendations

Conclusion

A browser-based workflow simulator is a powerful and reusable tool for any enterprise Angular application. By combining a graph-based canvas, configurable nodes, a robust execution engine, and a validation system, you can build a complete workflow modelling and testing system inside the browser.

What makes this solution truly valuable is its flexibility. It doesn’t depend on any external engine and can be adapted for HR approvals, manufacturing processes, IT automation, financial rules, document processing, and more.