graphviz-diagrams

Graphviz Diagrams Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "graphviz-diagrams" with this command: npx skills add mindmorass/reflex/mindmorass-reflex-graphviz-diagrams

Graphviz Diagrams Skill

Purpose

Create complex graph visualizations using Graphviz DOT language, with both source code and pre-rendered images.

When to Use

  • Complex dependency graphs

  • Call graphs and code flow

  • Network topologies

  • Hierarchical structures

  • State machines with complex transitions

  • Any graph needing precise layout control

Output Format

Every Graphviz diagram should include:

  • Inline DOT source - For reference and future editing

  • Pre-rendered image - For viewing in any markdown renderer

Document Structure

Diagram: [Name]

Source

digraph G {
    A -> B
}

Rendered

Diagram Name

Rendering Workflow

Step 1: Write DOT Source

dot_source = """ digraph G { rankdir=LR; A -> B -> C; } """

Step 2: Render to Image

import subprocess from pathlib import Path

def render_graphviz( dot_source: str, output_path: Path, format: str = "png", engine: str = "dot" ) -> Path: """ Render DOT source to image file.

Args:
    dot_source: DOT language source code
    output_path: Output file path (without extension)
    format: Output format (png, svg, pdf)
    engine: Layout engine (dot, neato, fdp, circo, twopi, sfdp)

Returns:
    Path to rendered image
"""
output_file = output_path.with_suffix(f".{format}")

result = subprocess.run(
    [engine, f"-T{format}", "-o", str(output_file)],
    input=dot_source,
    text=True,
    capture_output=True
)

if result.returncode != 0:
    raise RuntimeError(f"Graphviz error: {result.stderr}")

return output_file

Step 3: Embed in Markdown

def create_diagram_markdown( name: str, dot_source: str, image_path: str ) -> str: """Create markdown with both source and rendered image.""" return f"""## Diagram: {name}

Source

{dot_source}

Rendered

"""

## DOT Language Reference

### Basic Graph Types

#### Directed Graph (digraph)
```dot
digraph G {
    A -> B;
    B -> C;
    A -> C;
}

Undirected Graph (graph)

graph G {
    A -- B;
    B -- C;
    A -- C;
}

Graph Attributes

digraph G {
    // Graph attributes
    rankdir=LR;           // Direction: TB, BT, LR, RL
    splines=ortho;        // Edge style: line, polyline, curved, ortho, spline
    nodesep=0.5;          // Space between nodes
    ranksep=1.0;          // Space between ranks
    bgcolor="white";      // Background color
    fontname="Helvetica"; // Font for labels

    // Nodes and edges
    A -> B;
}

Node Attributes

digraph G {
    // Node defaults
    node [shape=box, style=filled, fillcolor=lightblue];

    // Individual node styling
    A [label="Start", shape=ellipse, fillcolor=green];
    B [label="Process
Data", shape=box];
    C [label="Decision", shape=diamond, fillcolor=yellow];
    D [label="End", shape=ellipse, fillcolor=red];

    A -> B -> C;
    C -> D;
}

Common Node Shapes

Shape
Use Case

box

Process, action

ellipse

Start/end, terminal

diamond

Decision

circle

State

record

Structured data

Mrecord

Rounded record

cylinder

Database

folder

Directory/collection

component

Component

note

Annotation

Edge Attributes

digraph G {
    // Edge defaults
    edge [color=gray, fontsize=10];

    A -> B [label="step 1", color=blue, penwidth=2];
    B -> C [label="step 2", style=dashed];
    C -> D [label="step 3", arrowhead=empty];
    D -> A [label="loop", style=dotted, constraint=false];
}

Arrow Styles

Arrowhead
Description

normal

Filled triangle (default)

empty

Open triangle

dot

Filled circle

odot

Open circle

diamond

Filled diamond

none

No arrowhead

vee

V-shape

box

Filled square

Subgraphs and Clusters

digraph G {
    // Cluster (named subgraph with cluster_ prefix)
    subgraph cluster_frontend {
        label="Frontend";
        style=filled;
        fillcolor=lightgray;

        UI -> Components -> State;
    }

    subgraph cluster_backend {
        label="Backend";
        style=filled;
        fillcolor=lightyellow;

        API -> Service -> Database;
    }

    // Cross-cluster edges
    State -> API [label="HTTP"];
}

Records (Structured Nodes)

digraph G {
    node [shape=record];

    user [label="User|{id: int|name: string|email: string}"];
    order [label="Order|{id: int|user_id: int|total: decimal}"];

    user -> order [label="1:N"];
}

HTML Labels

digraph G {
    node [shape=none];

    table [label=<
        <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
            <TR><TD BGCOLOR="lightblue"><B>User</B></TD></TR>
            <TR><TD ALIGN="LEFT">id: int</TD></TR>
            <TR><TD ALIGN="LEFT">name: string</TD></TR>
            <TR><TD ALIGN="LEFT">email: string</TD></TR>
        </TABLE>
    >];
}

Layout Engines

Engine
Best For
Description

dot

Hierarchies
Directed graphs, trees, DAGs

neato

Networks
Undirected graphs, spring model

fdp

Large networks
Force-directed, scalable

sfdp

Very large
Multiscale force-directed

circo

Circular
Circular layouts

twopi

Radial
Radial layouts from root

Usage

# Different engines produce different layouts
dot -Tpng graph.dot -o graph-hierarchical.png
neato -Tpng graph.dot -o graph-spring.png
circo -Tpng graph.dot -o graph-circular.png

Common Patterns

Dependency Graph

digraph Dependencies {
    rankdir=BT;
    node [shape=box, style=filled, fillcolor=lightblue];

    // Packages
    app [label="app"];
    api [label="api"];
    core [label="core"];
    utils [label="utils"];
    db [label="database"];

    // Dependencies (arrows point to dependency)
    app -> api;
    app -> core;
    api -> core;
    api -> db;
    core -> utils;
    db -> utils;
}

State Machine

digraph StateMachine {
    rankdir=LR;
    node [shape=circle];

    // Start state
    start [shape=point, width=0.2];

    // States
    idle [label="Idle"];
    loading [label="Loading"];
    success [label="Success", shape=doublecircle];
    error [label="Error"];

    // Transitions
    start -> idle;
    idle -> loading [label="fetch()"];
    loading -> success [label="200 OK"];
    loading -> error [label="error"];
    error -> idle [label="retry()"];
    success -> idle [label="reset()"];
}

Call Graph

digraph CallGraph {
    rankdir=TB;
    node [shape=box, fontname="Courier"];

    main [style=filled, fillcolor=lightgreen];
    main -> init;
    main -> process;
    main -> cleanup;

    init -> loadConfig;
    init -> connectDB;

    process -> validateInput;
    process -> transform;
    process -> save;

    transform -> normalize;
    transform -> enrich;

    save -> connectDB [style=dashed, label="reuse"];
}

Network Topology

graph Network {
    layout=neato;
    overlap=false;
    node [shape=box];

    // Nodes
    internet [shape=cloud, label="Internet"];
    firewall [shape=box3d, label="Firewall"];
    lb [label="Load
Balancer"];
    web1 [label="Web 1"];
    web2 [label="Web 2"];
    app1 [label="App 1"];
    app2 [label="App 2"];
    db [shape=cylinder, label="Database"];

    // Connections
    internet -- firewall;
    firewall -- lb;
    lb -- web1;
    lb -- web2;
    web1 -- app1;
    web1 -- app2;
    web2 -- app1;
    web2 -- app2;
    app1 -- db;
    app2 -- db;
}

Entity Relationship

digraph ERD {
    rankdir=LR;
    node [shape=record, fontname="Helvetica"];
    edge [arrowhead=none];

    user [label="<pk> User|id: PK\lname: string\lemail: string\l"];
    order [label="<pk> Order|id: PK\luser_id: FK\ltotal: decimal\l"];
    item [label="<pk> OrderItem|id: PK\lorder_id: FK\lproduct_id: FK\l"];
    product [label="<pk> Product|id: PK\lname: string\lprice: decimal\l"];

    user:pk -> order:pk [label="1:N", arrowhead=crow];
    order:pk -> item:pk [label="1:N", arrowhead=crow];
    product:pk -> item:pk [label="1:N", arrowhead=crow];
}

Flowchart

digraph Flowchart {
    rankdir=TB;
    node [fontname="Helvetica"];

    start [shape=ellipse, label="Start", style=filled, fillcolor=lightgreen];
    input [shape=parallelogram, label="Get Input"];
    validate [shape=diamond, label="Valid?"];
    process [shape=box, label="Process Data"];
    error [shape=box, label="Show Error", style=filled, fillcolor=lightyellow];
    output [shape=parallelogram, label="Output Result"];
    end [shape=ellipse, label="End", style=filled, fillcolor=lightcoral];

    start -> input;
    input -> validate;
    validate -> process [label="Yes"];
    validate -> error [label="No"];
    error -> input;
    process -> output;
    output -> end;
}

Integration with Publishers

Obsidian Integration

def publish_graphviz_to_obsidian(
    vault_path: str,
    folder: str,
    filename: str,
    diagram_name: str,
    dot_source: str
):
    """Publish Graphviz diagram to Obsidian with source and image."""
    from pathlib import Path

    vault = Path(vault_path)
    target_dir = vault / folder
    attachments_dir = vault / "attachments"

    target_dir.mkdir(parents=True, exist_ok=True)
    attachments_dir.mkdir(parents=True, exist_ok=True)

    # Render image
    image_name = f"{filename}-diagram.png"
    image_path = attachments_dir / image_name
    render_graphviz(dot_source, image_path.with_suffix(""), "png")

    # Create markdown with both source and image
    content = f"""# {diagram_name}

## Source

```dot
{dot_source}

Rendered

![[{image_name}]]
"""

note_path = target_dir / f"{filename}.md"
note_path.write_text(content)

### Joplin Integration
```python
def publish_graphviz_to_joplin(
    notebook: str,
    title: str,
    diagram_name: str,
    dot_source: str
):
    """Publish Graphviz diagram to Joplin with source and image."""
    import tempfile
    from pathlib import Path

    with tempfile.TemporaryDirectory() as tmpdir:
        tmpdir = Path(tmpdir)

        # Render image
        image_path = tmpdir / "diagram.png"
        render_graphviz(dot_source, image_path.with_suffix(""), "png")

        # Create markdown
        content = f"""# {diagram_name}

## Source

```dot
{dot_source}

Rendered

"""

    md_path = tmpdir / f"{title}.md"
    md_path.write_text(content)

    # Import to Joplin (imports markdown and referenced images)
    subprocess.run([
        "joplin", "import", str(tmpdir),
        "--notebook", notebook
    ], check=True)

## Graphviz vs Mermaid

| Feature | Graphviz | Mermaid |
|---------|----------|---------|
| **Layout control** | Precise, many engines | Automatic only |
| **Complexity** | Handles very large graphs | Better for simpler diagrams |
| **Rendering** | External tool required | Browser-native |
| **Styling** | Extensive options | Limited but sufficient |
| **Learning curve** | Steeper | Easier |
| **Use case** | Complex dependencies, call graphs | Quick diagrams, sequences |

**Use Graphviz when:**
- You need precise layout control
- Graph is large or complex
- You need specific node arrangements
- Creating dependency or call graphs

**Use Mermaid when:**
- Quick inline diagrams
- Sequence diagrams
- Simple flowcharts
- Native browser rendering preferred

## Prerequisites

### Install Graphviz
```bash
# macOS
brew install graphviz

# Ubuntu/Debian
sudo apt-get install graphviz

# Windows (chocolatey)
choco install graphviz

# Verify installation
dot -V

Checklist

Before creating Graphviz diagrams:

-  Graphviz installed (dot -V
)

-  Output directory writable

-  DOT syntax validated

-  Appropriate layout engine selected

-  Both source and image included in output

-  Image path correct for target (Obsidian/Joplin)

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

ffmpeg-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
General

site-crawler

No summary provided by upstream source.

Repository SourceNeeds Review
General

ai-video-generation

No summary provided by upstream source.

Repository SourceNeeds Review