Skip to content

Diagram as Code in ConnectSoft Microservice Template

Purpose & Overview

Diagram as Code is a practice of defining diagrams programmatically using code or markup languages, enabling version control, automated generation, and consistency across documentation. In the ConnectSoft Microservice Template, diagram-as-code is implemented using two complementary approaches:

  • Python Diagrams Library: Programmatic diagram generation using the diagrams Python library
  • Mermaid: Text-based diagram markup for embedding in Markdown documentation

Why Diagram as Code?

Diagram as Code offers several key benefits:

  • Version Control: Diagrams are stored as code, enabling version tracking and change history
  • Automation: Diagrams can be generated automatically in CI/CD pipelines
  • Consistency: Same diagrams across all documentation and environments
  • Maintainability: Update diagrams by editing code, not manual image editing
  • Collaboration: Multiple developers can work on diagrams without conflicts
  • Reproducibility: Generate diagrams on-demand with consistent results
  • Integration: Diagrams can be embedded in documentation and generated during builds
  • Reusability: Diagram components can be shared and reused across projects

Diagram as Code Philosophy

Diagrams should be treated as code—versioned, tested, and generated automatically. This ensures documentation stays in sync with the actual system architecture and provides a single source of truth for visual representations of the system.

Architecture Overview

Diagram Types

The template supports multiple diagram types:

Diagram as Code
├── Python Diagrams (diagrams library)
│   ├── C4 Diagrams (System Context, Container, Component, Deployment, Dynamic, System Landscape)
│   ├── Infrastructure Diagrams (AWS, Azure, Kubernetes, Docker Compose)
│   ├── Observability Diagrams
│   └── CI/CD Diagrams
└── Mermaid Diagrams
    ├── Flowcharts
    ├── Sequence Diagrams
    ├── Class Diagrams
    └── State Diagrams

Project Structure

ConnectSoft.MicroserviceTemplate.DiagramAsCodeModel/
├── ConnectSoft.MicroserviceTemplate.DiagramAsCodeModel.pyproj
├── requirements.txt
├── ConnectSoft.MicroserviceTemplate.C4-SystemContextDiagram.py
├── ConnectSoft.MicroserviceTemplate.C4-ContainerDiagram.py
├── ConnectSoft.MicroserviceTemplate.C4-ComponentDiagram.py
├── ConnectSoft.MicroserviceTemplate.C4-DeploymentDiagram.py
├── ConnectSoft.MicroserviceTemplate.C4-DynamicDiagram.py
├── ConnectSoft.MicroserviceTemplate.C4-SystemLandscapeDiagram.py
├── ConnectSoft.MicroserviceTemplate.Azure.py
├── ConnectSoft.MicroserviceTemplate.AWS.py
├── ConnectSoft.MicroserviceTemplate.Kubernetes.py
├── ConnectSoft.MicroserviceTemplate.DockerCompose.py
├── ConnectSoft.MicroserviceTemplate.Observability.py
├── ConnectSoft.MicroserviceTemplate.CICD.py
├── ConnectSoft.MicroserviceTemplate.OnPrem.py
└── images/
    ├── hangfire.png
    ├── health.png
    ├── orleans.png
    ├── otel-collector.png
    ├── seq.png
    └── swagger.png

Docs/Diagrams/
├── Solution Structure Graph.mmd
└── Use Cases.mmd

ConnectSoft.MicroserviceTemplate.DiagramAsCodeModel Project

Project Overview

The ConnectSoft.MicroserviceTemplate.DiagramAsCodeModel is a Python project that provides programmatic diagram generation for the microservice template. It uses the diagrams Python library to generate architecture diagrams programmatically, ensuring consistency and maintainability.

Key Features: - Visual Studio Integration: Python project file (.pyproj) for Visual Studio support - C4 Model Diagrams: Complete C4 model implementation (System Context, Container, Component, Deployment, Dynamic, System Landscape) - Infrastructure Diagrams: Azure, AWS, Kubernetes, Docker Compose, On-Premises - Observability Diagrams: Telemetry and monitoring architecture - CI/CD Diagrams: Build and deployment pipeline visualization - Custom Icons: Custom images for template-specific components (Hangfire, Orleans, Swagger, etc.)

Project File Structure

ConnectSoft.MicroserviceTemplate.DiagramAsCodeModel.pyproj: Visual Studio Python project file that: - Defines project structure and dependencies - Configures build settings - Sets startup file (ConnectSoft.MicroserviceTemplate.OnPrem.py) - Includes all Python diagram scripts - References custom images

requirements.txt:

pip==24.2
diagrams==0.24.1

Dependencies: - diagrams: Python library for generating architecture diagrams - pip: Package installer (version pinned for consistency)

Diagram Scripts

Each diagram script is a standalone Python file that generates a specific type of diagram. All scripts follow a consistent pattern:

Common Pattern

All diagram scripts follow this pattern:

import os
from diagrams import Diagram, Cluster, Edge

# Configure output path
script_dir = os.path.dirname(os.path.abspath(__file__))
output_path = os.path.join(script_dir, "..", "Images", "DiagramName")
images_path = os.path.join(script_dir, "Images")

# Graph styling attributes
graph_attr = {
    "center": "true",
    "splines": "spline",  # Rounded arrows
    "fontsize": "16",
    "fontname": "Arial",
    "fontcolor": "black",
    "style": "rounded"
}

cluster_attr = {
    "fontsize": "16",
    "fontname": "Arial",
    "fontcolor": "black",
    "style": "rounded"
}

# Generate diagram
with Diagram('DiagramName',
             show=True,
             direction="TB",
             filename=output_path,
             outformat="png",
             graph_attr=graph_attr):
    # Diagram content

C4 System Context Diagram

File: ConnectSoft.MicroserviceTemplate.C4-SystemContextDiagram.py

Purpose: Shows the microservice in the context of its users and external systems.

Components: - User/Developer - Application container - Dashboards (Hangfire, Swagger, Health Check, Orleans Dashboard) - Dependencies (Redis, RabbitMQ, MongoDB, SQL Server) - Security (Azure Key Vault) - Observability Collectors (Elasticsearch, Jaeger, Prometheus, OTel Collector, Seq) - Observability Visualizations (Kibana, Grafana)

Output: Images/ConnectSoft.MicroserviceTemplate.C4SystemContext.png

C4 Container Diagram

File: ConnectSoft.MicroserviceTemplate.C4-ContainerDiagram.py

Purpose: Shows the containers (applications, databases, etc.) that make up the microservice.

Components: - API container (Dotnet Core) - Worker container (Background Worker) - OTel Collector - Seq (Logs) - Dashboards (Hangfire, Swagger UI, Health Check, Orleans Dashboard) - Dependencies (Redis, RabbitMQ, MongoDB, SQL Server) - Security (Azure Key Vault) - Observability stack (Elasticsearch, Jaeger, Prometheus, Kibana, Grafana)

Output: Images/ConnectSoft.MicroserviceTemplate.C4Container.png

Key Features: - Uses C4 model Container and Database types - Shows relationships between containers - Groups related components using SystemBoundary

C4 Component Diagram

File: ConnectSoft.MicroserviceTemplate.C4-ComponentDiagram.py

Purpose: Shows the internal components of the API container.

Output: Images/ConnectSoft.MicroserviceTemplate.C4Component.png

C4 Deployment Diagram

File: ConnectSoft.MicroserviceTemplate.C4-DeploymentDiagram.py

Purpose: Shows how containers are deployed to infrastructure.

Output: Images/ConnectSoft.MicroserviceTemplate.C4Deployment.png

C4 Dynamic Diagram

File: ConnectSoft.MicroserviceTemplate.C4-DynamicDiagram.py

Purpose: Shows dynamic interactions and flows between components.

Output: Images/ConnectSoft.MicroserviceTemplate.C4Dynamic.png

C4 System Landscape Diagram

File: ConnectSoft.MicroserviceTemplate.C4-SystemLandscapeDiagram.py

Purpose: Shows multiple systems and their relationships.

Output: Images/ConnectSoft.MicroserviceTemplate.C4SystemLandscape.png

Azure Infrastructure Diagram

File: ConnectSoft.MicroserviceTemplate.Azure.py

Purpose: Shows Azure-specific infrastructure components.

Components: - Azure App Services - Azure SQL Database - Azure Storage - Azure Key Vault - Azure Service Bus - Azure Application Insights

Output: Images/ConnectSoft.MicroserviceTemplate.Azure.png

AWS Infrastructure Diagram

File: ConnectSoft.MicroserviceTemplate.AWS.py

Purpose: Shows AWS-specific infrastructure components.

Components: - EC2 instances - RDS databases - S3 buckets - AWS Lambda - AWS CloudWatch

Output: Images/ConnectSoft.MicroserviceTemplate.AWS.png

Kubernetes Diagram

File: ConnectSoft.MicroserviceTemplate.Kubernetes.py

Purpose: Shows Kubernetes deployment architecture.

Components: - Kubernetes cluster - Pods - Services - Deployments - ConfigMaps - Secrets

Output: Images/ConnectSoft.MicroserviceTemplate.Kubernetes.png

Docker Compose Diagram

File: ConnectSoft.MicroserviceTemplate.DockerCompose.py

Purpose: Shows Docker Compose stack architecture.

Components: - Application container - Database containers (SQL Server, MongoDB, Redis) - Message queue (RabbitMQ) - Monitoring stack (Prometheus, Grafana) - CI/CD integration (Azure DevOps)

Output: Images/ConnectSoft.MicroserviceTemplate.DockerCompose.png

Example Code:

from diagrams import Diagram, Cluster, Edge
from diagrams.onprem.compute import Server
from diagrams.onprem.database import Mssql
from diagrams.onprem.inmemory import Redis
from diagrams.onprem.queue import Rabbitmq

def main():
    with Diagram('ConnectSoft.MicroserviceTemplate Diagram', show=True, direction="TB"):
        with Cluster("ConnectSoft.MicroserviceTemplate.Application"):
            app_server = Server("Server")
            db = Mssql("Database")
            cache = Redis("Cache")
            message_queue = Rabbitmq("Message Queue")

            app_server >> Edge(label="SQL") >> db
            app_server >> Edge(label="Cache") >> cache
            app_server >> Edge(label="Queues") >> message_queue

if __name__ == "__main__":
    main()

Observability Diagram

File: ConnectSoft.MicroserviceTemplate.Observability.py

Purpose: Shows the observability stack and telemetry flow.

Components: - Instrumented Application - Collection (OTel Collector) - Processing and Storage (Jaeger, Prometheus, Elasticsearch) - Visualization and Alerting (Kibana, Grafana, Notification Systems)

Output: Images/ConnectSoft.MicroserviceTemplate.Observability.png

Key Features: - Shows complete telemetry pipeline - Demonstrates trace, metric, and log flows - Includes alerting and notification systems

Example Code:

from diagrams import Diagram, Cluster, Edge
from diagrams.onprem.container import Docker
from diagrams.custom import Custom
from diagrams.onprem.tracing import Jaeger
from diagrams.onprem.monitoring import Prometheus, Grafana

with Diagram('ConnectSoft.MicroserviceTemplate.Observability',
             show=True,
             direction="TB",
             filename=output_path,
             outformat="png",
             graph_attr=graph_attr):
    app = Docker("Instrumented Application")

    with Cluster("Collection", graph_attr=cluster_attr):
        otel_collector = Custom("OTel Collector", os.path.join(images_path, "otel-collector.png"))

    with Cluster("Processing and Storage", graph_attr=cluster_attr):
        jaeger = Jaeger("Jaeger")
        prometheus = Prometheus("Prometheus")
        elasticsearch = Elasticsearch("Elasticsearch")

    with Cluster("Visualization and Alerting", graph_attr=cluster_attr):
        kibana = Kibana("Kibana")
        grafana = Grafana("Grafana")

    app >> Edge(label="sends\ntelemetry") >> otel_collector
    otel_collector >> Edge(label="traces") >> jaeger
    otel_collector >> Edge(label="metrics") >> prometheus
    otel_collector >> Edge(label="logs") >> elasticsearch
    prometheus >> Edge(label="connects") >> grafana
    elasticsearch >> Edge(label="connects") >> kibana

CI/CD Diagram

File: ConnectSoft.MicroserviceTemplate.CICD.py

Purpose: Shows CI/CD pipeline and deployment process.

Components: - Azure DevOps - Application server - Database - Cache - Message Queue - Monitoring and dashboards

Output: Images/ConnectSoft.MicroserviceTemplate.CICD.png

On-Premises Diagram

File: ConnectSoft.MicroserviceTemplate.OnPrem.py

Purpose: Shows on-premises deployment architecture.

Components: - On-premises servers - Local databases - Local infrastructure components

Output: Images/ConnectSoft.MicroserviceTemplate.OnPrem.png

Note: This is the startup file for the Visual Studio Python project.

Custom Icons

The project includes custom icons for template-specific components:

Location: images/ directory

Custom Icons: - hangfire.png - Hangfire background job scheduler - health.png - Health check dashboard - orleans.png - Orleans dashboard - otel-collector.png - OpenTelemetry Collector - seq.png - Seq log viewer - swagger.png - Swagger UI

Usage:

from diagrams.custom import Custom
import os

images_path = os.path.join(os.path.dirname(__file__), "Images")

# Use custom icon
hangfire = Custom("Hangfire", os.path.join(images_path, "hangfire.png"))
swagger = Custom("Swagger UI", os.path.join(images_path, "swagger.png"))

Benefits: - Consistent branding across diagrams - Template-specific components clearly identified - Professional appearance

Output Configuration

Output Path: All diagrams are generated in the Images/ directory at the solution root:

script_dir = os.path.dirname(os.path.abspath(__file__))
output_path = os.path.join(script_dir, "..", "Images", "DiagramName")

Output Format: - Default: PNG (outformat="png") - Can be changed to: SVG, PDF, JPG

File Naming: - Files are named based on the diagram title - Example: ConnectSoft.MicroserviceTemplate.C4SystemContext.png

Visual Studio Integration

Python Project File: The .pyproj file enables Visual Studio integration:

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <StartupFile>ConnectSoft.MicroserviceTemplate.OnPrem.py</StartupFile>
    <Name>ConnectSoft.MicroserviceTemplate.DiagramAsCodeModel</Name>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="ConnectSoft.MicroserviceTemplate.C4-SystemContextDiagram.py" />
    <!-- ... other diagram scripts ... -->
  </ItemGroup>
</Project>

Features: - F5 Launch: Run diagram scripts directly from Visual Studio - Debugging: Set breakpoints and debug diagram generation - IntelliSense: Code completion and syntax highlighting - Project Management: Organize diagram scripts as a project

Running Diagrams: 1. Right-click on any .py file → "Set as Startup File" 2. Press F5 to run and generate the diagram 3. Diagram opens automatically (if show=True)

Running Diagram Scripts

Individual Script:

# Navigate to diagram project
cd ConnectSoft.MicroserviceTemplate.DiagramAsCodeModel

# Run specific diagram
python ConnectSoft.MicroserviceTemplate.C4-SystemContextDiagram.py

All Scripts:

# Run all C4 diagrams
python ConnectSoft.MicroserviceTemplate.C4-SystemContextDiagram.py
python ConnectSoft.MicroserviceTemplate.C4-ContainerDiagram.py
python ConnectSoft.MicroserviceTemplate.C4-ComponentDiagram.py
python ConnectSoft.MicroserviceTemplate.C4-DeploymentDiagram.py
python ConnectSoft.MicroserviceTemplate.C4-DynamicDiagram.py
python ConnectSoft.MicroserviceTemplate.C4-SystemLandscapeDiagram.py

# Run infrastructure diagrams
python ConnectSoft.MicroserviceTemplate.Azure.py
python ConnectSoft.MicroserviceTemplate.AWS.py
python ConnectSoft.MicroserviceTemplate.Kubernetes.py
python ConnectSoft.MicroserviceTemplate.DockerCompose.py

# Run specialized diagrams
python ConnectSoft.MicroserviceTemplate.Observability.py
python ConnectSoft.MicroserviceTemplate.CICD.py
python ConnectSoft.MicroserviceTemplate.OnPrem.py

Automated Generation Script: Create a script to generate all diagrams:

# generate_all_diagrams.py
import os
import subprocess

script_dir = os.path.dirname(os.path.abspath(__file__))
diagram_scripts = [
    "ConnectSoft.MicroserviceTemplate.C4-SystemContextDiagram.py",
    "ConnectSoft.MicroserviceTemplate.C4-ContainerDiagram.py",
    "ConnectSoft.MicroserviceTemplate.C4-ComponentDiagram.py",
    "ConnectSoft.MicroserviceTemplate.C4-DeploymentDiagram.py",
    "ConnectSoft.MicroserviceTemplate.C4-DynamicDiagram.py",
    "ConnectSoft.MicroserviceTemplate.C4-SystemLandscapeDiagram.py",
    "ConnectSoft.MicroserviceTemplate.Azure.py",
    "ConnectSoft.MicroserviceTemplate.AWS.py",
    "ConnectSoft.MicroserviceTemplate.Kubernetes.py",
    "ConnectSoft.MicroserviceTemplate.DockerCompose.py",
    "ConnectSoft.MicroserviceTemplate.Observability.py",
    "ConnectSoft.MicroserviceTemplate.CICD.py",
    "ConnectSoft.MicroserviceTemplate.OnPrem.py",
]

for script in diagram_scripts:
    script_path = os.path.join(script_dir, script)
    print(f"Generating {script}...")
    try:
        subprocess.run(["python", script_path], check=True, cwd=script_dir)
        print(f"✓ Generated {script}")
    except subprocess.CalledProcessError as e:
        print(f"✗ Failed to generate {script}: {e}")

print("All diagrams generated!")

Diagram Styling

Consistent Styling: All diagram scripts use consistent styling:

graph_attr = {
    "center": "true",
    "splines": "spline",  # Rounded arrows
    "fontsize": "16",
    "fontname": "Arial",
    "fontcolor": "black",
    "style": "rounded"
}

cluster_attr = {
    "fontsize": "16",
    "fontname": "Arial",
    "fontcolor": "black",
    "style": "rounded"
}

Benefits: - Consistent appearance across all diagrams - Professional look and feel - Easy to read and understand - Brand consistency

Customization

Adding New Diagrams: 1. Create new Python file: ConnectSoft.MicroserviceTemplate.NewDiagram.py 2. Follow the common pattern 3. Add to .pyproj file 4. Update generation scripts

Modifying Existing Diagrams: 1. Edit the corresponding Python file 2. Run the script to regenerate 3. Commit changes to version control

Adding Custom Icons: 1. Add PNG/SVG file to images/ directory 2. Reference in diagram script:

custom_icon = Custom("Label", os.path.join(images_path, "icon.png"))
3. Commit icon file to version control

Python Diagrams Library

Overview

The Python Diagrams library is a Python package that generates cloud system architecture diagrams using code. It uses Graphviz under the hood to render diagrams as images (PNG, SVG, etc.).

Installation

Prerequisites: - Python 3.7+ - Graphviz (must be installed on the system)

Install Graphviz:

# Windows (using Chocolatey)
choco install graphviz

# macOS (using Homebrew)
brew install graphviz

# Linux (Ubuntu/Debian)
sudo apt-get install graphviz

Install Python Dependencies:

cd ConnectSoft.MicroserviceTemplate.DiagramAsCodeModel
pip install -r requirements.txt

requirements.txt:

pip==24.2
diagrams==0.24.1

Basic Usage

Simple Diagram:

from diagrams import Diagram, Cluster, Edge
from diagrams.onprem.compute import Server
from diagrams.onprem.database import Mssql

with Diagram('Simple Microservice', show=True, direction="TB"):
    server = Server("Application")
    database = Mssql("Database")

    server >> Edge(label="connects to") >> database

Output: Generates a PNG image showing a server connected to a database.

Diagram Structure

Basic Elements:

from diagrams import Diagram, Cluster, Edge

# Create diagram
with Diagram('My Diagram', show=True, direction="TB"):
    # Add nodes
    node1 = Server("Node 1")
    node2 = Server("Node 2")

    # Add connections
    node1 >> Edge(label="label") >> node2

Parameters: - show=True: Open the diagram after generation - direction: "TB" (top-bottom), "LR" (left-right), "BT" (bottom-top), "RL" (right-left) - filename: Output file path (without extension) - outformat: Output format ("png", "svg", "pdf", "jpg")

Clusters

Grouping Components:

from diagrams import Diagram, Cluster
from diagrams.onprem.compute import Server
from diagrams.onprem.database import Mssql

with Diagram('Clustered Architecture', show=True):
    with Cluster("Application Layer"):
        app1 = Server("App 1")
        app2 = Server("App 2")

    with Cluster("Database Layer"):
        db1 = Mssql("Database 1")
        db2 = Mssql("Database 2")

C4 Diagrams

C4 Model Support:

The template includes C4 diagram scripts for different levels of abstraction:

System Context Diagram:

from diagrams.c4 import Person, System, SystemBoundary, Relationship

with Diagram('System Context', show=True):
    user = Person(name="User", description="System user", external=True)

    with SystemBoundary("ConnectSoft.MicroserviceTemplate"):
        system = System(
            name="Microservice",
            description="Main microservice application",
            external=False)

    user >> Relationship("Uses") >> system

Container Diagram:

from diagrams.c4 import Container, SystemBoundary, Person, Database, Relationship

with Diagram('Container Diagram', show=True):
    user = Person(name="User", external=True)

    with SystemBoundary("Microservice"):
        api = Container(
            name="API",
            technology=".NET Core",
            description="REST API")
        database = Database(
            name="Database",
            technology="SQL Server",
            description="Main database")

    user >> Relationship("Uses") >> api
    api >> Relationship("Reads/Writes") >> database

Available C4 Diagrams in Template: - C4-SystemContextDiagram.py: System context view - C4-ContainerDiagram.py: Container view - C4-ComponentDiagram.py: Component view - C4-DeploymentDiagram.py: Deployment view - C4-DynamicDiagram.py: Dynamic/interaction view - C4-SystemLandscapeDiagram.py: System landscape view

Custom Icons

Using Custom Images:

from diagrams import Diagram
from diagrams.custom import Custom
import os

images_path = os.path.join(os.path.dirname(__file__), "images")

with Diagram('Custom Icons', show=True):
    hangfire = Custom("Hangfire", os.path.join(images_path, "hangfire.png"))
    swagger = Custom("Swagger", os.path.join(images_path, "swagger.png"))

Provider-Specific Diagrams

Azure Diagrams:

from diagrams.azure.compute import AppServices
from diagrams.azure.database import SQLDatabases
from diagrams.azure.storage import StorageAccounts

with Diagram('Azure Architecture', show=True):
    app = AppServices("Web App")
    db = SQLDatabases("SQL Database")
    storage = StorageAccounts("Storage")

    app >> db
    app >> storage

AWS Diagrams:

from diagrams.aws.compute import EC2
from diagrams.aws.database import RDS
from diagrams.aws.storage import S3

with Diagram('AWS Architecture', show=True):
    ec2 = EC2("EC2 Instance")
    rds = RDS("RDS Database")
    s3 = S3("S3 Bucket")

    ec2 >> rds
    ec2 >> s3

Advanced Configuration

Graph Attributes:

graph_attr = {
    "center": "true",
    "splines": "spline",  # Rounded arrows
    "fontsize": "16",
    "fontname": "Arial",
    "fontcolor": "black",
    "style": "rounded"
}

cluster_attr = {
    "fontsize": "16",
    "fontname": "Arial",
    "fontcolor": "black",
    "style": "rounded"
}

with Diagram('Styled Diagram', 
             show=True,
             graph_attr=graph_attr):
    # Diagram content

Output Configuration:

script_dir = os.path.dirname(os.path.abspath(__file__))
output_path = os.path.join(script_dir, "..", "Images", "MyDiagram")

with Diagram('My Diagram',
             show=True,
             filename=output_path,
             outformat="png",
             graph_attr=graph_attr):
    # Diagram content

Running Diagram Scripts

Individual Scripts:

# Navigate to diagram project
cd ConnectSoft.MicroserviceTemplate.DiagramAsCodeModel

# Run a specific diagram script
python ConnectSoft.MicroserviceTemplate.C4-SystemContextDiagram.py
python ConnectSoft.MicroserviceTemplate.Azure.py

All Scripts:

# Run all diagram scripts
python ConnectSoft.MicroserviceTemplate.C4-SystemContextDiagram.py
python ConnectSoft.MicroserviceTemplate.C4-ContainerDiagram.py
python ConnectSoft.MicroserviceTemplate.C4-ComponentDiagram.py
# ... etc

Mermaid Diagrams

Overview

Mermaid is a text-based diagram markup language that can be embedded directly in Markdown files. It's supported by many documentation platforms (GitHub, GitLab, MkDocs, etc.) and renders diagrams client-side.

Flowcharts

Basic Flowchart:

flowchart TD
    Start([Start]) --> Process[Process]
    Process --> Decision{Decision?}
    Decision -->|Yes| End1([End 1])
    Decision -->|No| End2([End 2])
Hold "Alt" / "Option" to enable pan & zoom

Code:

```mermaid
flowchart TD
    Start([Start]) --> Process[Process]
    Process --> Decision{Decision?}
    Decision -->|Yes| End1([End 1])
    Decision -->|No| End2([End 2])
**Complex Flowchart with Subgraphs**:

```mermaid
flowchart TB
    subgraph "Application Layer"
        API[API]
        Service[Service]
    end
    subgraph "Database Layer"
        DB[(Database)]
    end
    API --> Service
    Service --> DB

Sequence Diagrams

Sequence Diagram:

sequenceDiagram
    participant Client
    participant API
    participant Service
    participant Database

    Client->>API: Request
    API->>Service: Process
    Service->>Database: Query
    Database-->>Service: Result
    Service-->>API: Response
    API-->>Client: Response
Hold "Alt" / "Option" to enable pan & zoom

Class Diagrams

Class Diagram:

classDiagram
    class Processor {
        +Process(input) IOutput
    }
    class Retriever {
        +Retrieve(input) IOutput
    }
    class Repository {
        +Insert(entity)
        +Update(entity)
        +Delete(entity)
    }
    Processor --> Repository
    Retriever --> Repository
Hold "Alt" / "Option" to enable pan & zoom

State Diagrams

State Diagram:

stateDiagram-v2
    [*] --> Draft
    Draft --> Review
    Review --> Approved
    Review --> Rejected
    Approved --> Published
    Rejected --> Draft
    Published --> [*]
Hold "Alt" / "Option" to enable pan & zoom

Solution Structure Diagram

Example from Template:

graph TB
  subgraph "ConnectSoft.MicroserviceTemplate [Microservice]"
    subgraph TestLibraries [Test Libraries]
      UnitTests["ConnectSoft.MicroserviceTemplate.UnitTests"]
      ArchitectureTests["ConnectSoft.MicroserviceTemplate.ArchitectureTests"]
    end
    subgraph DomainLayer [Domain Layer]
      DomainModel["ConnectSoft.MicroserviceTemplate.DomainModel"]
    end
  end
Hold "Alt" / "Option" to enable pan & zoom

File: Docs/Diagrams/Solution Structure Graph.mmd

Use Case Diagrams

Example from Template:

flowchart LR
    subgraph 'ConnectSoft.MicroserviceTemplate microservice'
    uc1((Retrieve MicroserviceAggregateRoots use case))
    uc2((Process MicroserviceAggregateRoots use cases))
    uc3((Create MicroserviceAggregateRoot use case))
    uc4((Delete MicroserviceAggregateRoot use case))
    end
    consumer[Microservice Consumer]
    consumer-->uc1
    consumer-->uc2
    uc2 -. include .-> uc3
    uc2 -. include .-> uc4
Hold "Alt" / "Option" to enable pan & zoom

File: Docs/Diagrams/Use Cases.mmd

Embedding in Documentation

MkDocs Integration:

Mermaid diagrams are automatically rendered in MkDocs when using the mkdocs-mermaid2-plugin:

# mkdocs.yml
plugins:
  - mermaid2:
      arguments:
        theme: default

Markdown Usage:

# Architecture Overview

Here's the system architecture:

```mermaid
flowchart TD
    A[Client] --> B[API]
    B --> C[Service]
## CI/CD Integration

### Pipeline Configuration

**Azure DevOps Pipeline**:

```yaml
# azure-pipelines.yml
variables:
  isRemovePythonDiagramsEnabled: true
  pythonDiagramsProjectName: 'ConnectSoft.MicroserviceTemplate.DiagramAsCodeModel/ConnectSoft.MicroserviceTemplate.DiagramAsCodeModel.pyproj'

stages:
  - stage: GenerateDiagrams
    jobs:
      - job: GeneratePythonDiagrams
        steps:
          - task: UsePythonVersion@0
            inputs:
              versionSpec: '3.9'
          - script: |
              cd ConnectSoft.MicroserviceTemplate.DiagramAsCodeModel
              pip install -r requirements.txt
              python ConnectSoft.MicroserviceTemplate.C4-SystemContextDiagram.py
              python ConnectSoft.MicroserviceTemplate.C4-ContainerDiagram.py
              # ... other diagram scripts
            displayName: 'Generate Python Diagrams'
          - task: PublishPipelineArtifact@1
            inputs:
              targetPath: 'Images'
              artifactName: 'diagrams'

Pre-commit Hooks

Generate Diagrams Before Commit:

#!/bin/bash
# .git/hooks/pre-commit

cd ConnectSoft.MicroserviceTemplate.DiagramAsCodeModel
pip install -r requirements.txt
python ConnectSoft.MicroserviceTemplate.C4-SystemContextDiagram.py
# ... other scripts

Build Integration

MSBuild Target:

<Target Name="GenerateDiagrams" BeforeTargets="Build">
  <Exec Command="python ConnectSoft.MicroserviceTemplate.DiagramAsCodeModel/ConnectSoft.MicroserviceTemplate.C4-SystemContextDiagram.py" />
</Target>

Best Practices

Do's

  1. Version Control All Diagram Code

    # ✅ GOOD - Diagram code in version control
    git add ConnectSoft.MicroserviceTemplate.DiagramAsCodeModel/*.py
    git add Docs/Diagrams/*.mmd
    

  2. Use Descriptive Names

    # ✅ GOOD - Clear naming
    ConnectSoft.MicroserviceTemplate.C4-SystemContextDiagram.py
    
    # ❌ BAD - Unclear naming
    diagram1.py
    

  3. Organize by Purpose

    # ✅ GOOD - Organized structure
    DiagramAsCodeModel/
    ├── C4-SystemContextDiagram.py
    ├── C4-ContainerDiagram.py
    ├── Azure.py
    └── Kubernetes.py
    

  4. Use Consistent Styling

    # ✅ GOOD - Consistent graph attributes
    graph_attr = {
        "fontsize": "16",
        "fontname": "Arial",
        "splines": "spline"
    }
    

  5. Document Diagram Purpose

    """
    System Context Diagram
    Shows the microservice in the context of its users and external systems.
    """
    

  6. Generate Images Automatically

    # ✅ GOOD - Generate in CI/CD
    - script: python generate-diagrams.py
      displayName: 'Generate Diagrams'
    

  7. Keep Diagrams Up to Date

    # ✅ GOOD - Update diagrams when architecture changes
    # Update diagram code when adding new components
    

Don'ts

  1. Don't Commit Generated Images

    # ❌ BAD - Generated images in version control
    git add Images/*.png
    
    # ✅ GOOD - Generate images in CI/CD
    # Images are generated artifacts, not source
    

  2. Don't Hardcode Paths

    # ❌ BAD - Hardcoded paths
    output_path = "C:/Users/Dev/Images/diagram.png"
    
    # ✅ GOOD - Relative paths
    output_path = os.path.join(script_dir, "..", "Images", "diagram")
    

  3. Don't Mix Diagram Types

    # ❌ BAD - Mixing providers
    from diagrams.aws.compute import EC2
    from diagrams.azure.database import SQLDatabases
    
    # ✅ GOOD - Consistent provider
    from diagrams.azure.compute import AppServices
    from diagrams.azure.database import SQLDatabases
    

  4. Don't Create Overly Complex Diagrams

    # ❌ BAD - Too many components
    # 50+ nodes in a single diagram
    
    # ✅ GOOD - Split into multiple diagrams
    # System Context → Container → Component
    

  5. Don't Ignore Diagram Updates

    # ❌ BAD - Outdated diagrams
    # Diagram shows old architecture
    
    # ✅ GOOD - Update diagrams with architecture changes
    

Diagram Types Guide

C4 Model Diagrams

When to Use Each Level:

Level Purpose When to Use
System Context High-level system overview Initial documentation, stakeholder communication
Container Application containers and interactions Architecture documentation, deployment planning
Component Internal components and relationships Developer documentation, code organization
Deployment Physical infrastructure Infrastructure planning, deployment documentation
Dynamic Interaction flows Understanding system behavior
System Landscape Multiple systems overview System portfolio view, enterprise architecture

Infrastructure Diagrams

When to Use:

  • Azure Diagrams: For Azure-hosted deployments
  • AWS Diagrams: For AWS-hosted deployments
  • Kubernetes Diagrams: For container orchestration
  • Docker Compose Diagrams: For local development setup
  • On-Prem Diagrams: For on-premises deployments

Observability Diagrams

When to Use:

  • Show monitoring and logging architecture
  • Document telemetry flow
  • Explain observability stack

CI/CD Diagrams

When to Use:

  • Document build and deployment pipelines
  • Show automated workflows
  • Explain deployment process

Troubleshooting

Issue: Python Diagrams Not Generating

Symptoms: Diagram script runs but no image is created.

Solutions: 1. Verify Graphviz is installed: dot -V 2. Check Python dependencies: pip list | grep diagrams 3. Verify output path is writable 4. Check for errors in script execution 5. Verify show=True parameter (if testing interactively)

Issue: Mermaid Diagrams Not Rendering

Symptoms: Mermaid code blocks show as code instead of diagrams.

Solutions: 1. Verify MkDocs plugin is installed: pip install mkdocs-mermaid2-plugin 2. Check plugin configuration in mkdocs.yml 3. Verify syntax is correct (proper indentation) 4. Check browser console for JavaScript errors 5. Verify Mermaid version compatibility

Issue: Custom Icons Not Showing

Symptoms: Custom icon placeholders appear instead of images.

Solutions: 1. Verify image path is correct (relative to script) 2. Check image file exists and is readable 3. Verify image format is supported (PNG, SVG) 4. Check file permissions 5. Use absolute paths if relative paths fail

Issue: Diagrams Too Large

Symptoms: Generated diagrams are too large or complex.

Solutions: 1. Split into multiple diagrams (C4 model levels) 2. Reduce number of nodes 3. Use clusters to group related components 4. Increase output resolution settings 5. Use vector formats (SVG) for scalability

Advanced Patterns

Diagram Generation Script

Automated Generation:

# generate_all_diagrams.py
import os
import subprocess

diagram_scripts = [
    "ConnectSoft.MicroserviceTemplate.C4-SystemContextDiagram.py",
    "ConnectSoft.MicroserviceTemplate.C4-ContainerDiagram.py",
    "ConnectSoft.MicroserviceTemplate.C4-ComponentDiagram.py",
    "ConnectSoft.MicroserviceTemplate.Azure.py",
    "ConnectSoft.MicroserviceTemplate.Kubernetes.py",
]

script_dir = os.path.dirname(os.path.abspath(__file__))

for script in diagram_scripts:
    script_path = os.path.join(script_dir, script)
    print(f"Generating {script}...")
    subprocess.run(["python", script_path], check=True)
    print(f"✓ Generated {script}")

print("All diagrams generated successfully!")

Template-Based Diagrams

Reusable Components:

# diagram_components.py
from diagrams import Cluster, Edge
from diagrams.onprem.compute import Server
from diagrams.onprem.database import Mssql

def create_application_cluster(name):
    with Cluster(name):
        app = Server("Application")
        db = Mssql("Database")
        app >> db
        return app, db

# Usage
from diagram_components import create_application_cluster

with Diagram('Multi-Service Architecture', show=True):
    app1, db1 = create_application_cluster("Service 1")
    app2, db2 = create_application_cluster("Service 2")

Conditional Diagram Generation

Environment-Based Diagrams:

import os

environment = os.getenv("DEPLOYMENT_ENVIRONMENT", "development")

if environment == "production":
    # Generate production diagram
    from diagrams.azure.compute import AppServices
elif environment == "development":
    # Generate development diagram
    from diagrams.onprem.compute import Server

Summary

Diagram as Code in the ConnectSoft Microservice Template provides:

  • Version Control: Diagrams stored as code in version control
  • Automation: Automatic diagram generation in CI/CD
  • Consistency: Same diagrams across all environments
  • Maintainability: Update diagrams by editing code
  • Multiple Formats: Python diagrams (PNG/SVG) and Mermaid (text-based)
  • C4 Model Support: Full C4 model implementation
  • Provider Support: Azure, AWS, Kubernetes, Docker Compose
  • Documentation Integration: Mermaid diagrams embedded in Markdown

By following these patterns, teams can:

  • Maintain Up-to-Date Documentation: Diagrams stay in sync with architecture
  • Collaborate Effectively: Multiple developers can work on diagrams
  • Automate Generation: Diagrams generated automatically in CI/CD
  • Ensure Consistency: Same diagrams across all environments
  • Reduce Maintenance: Update code, not images
  • Improve Communication: Visual representations of system architecture

Diagram as Code transforms diagrams from static images into living documentation that evolves with the system, ensuring architecture documentation remains accurate and up-to-date.