Graphviz Diagrams
by mindmorass
Create complex graph visualizations using Graphviz DOT language, with both source code and pre-rendered images.
Skill Details
Repository Files
1 file in this skill directory
name: graphviz-diagrams description: Create complex graph visualizations using Graphviz DOT language, with both source code and pre-rendered images.
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
```dot
digraph G {
A -> B
}
```
### Rendered

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
{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)
Related Skills
Mermaid Diagrams
Comprehensive guide for creating software diagrams using Mermaid syntax. Use when users need to create, visualize, or document software through diagrams including class diagrams (domain modeling, object-oriented design), sequence diagrams (application flows, API interactions, code execution), flowcharts (processes, algorithms, user journeys), entity relationship diagrams (database schemas), C4 architecture diagrams (system context, containers, components), state diagrams, git graphs, pie charts,
Matlab
MATLAB and GNU Octave numerical computing for matrix operations, data analysis, visualization, and scientific computing. Use when writing MATLAB/Octave scripts for linear algebra, signal processing, image processing, differential equations, optimization, statistics, or creating scientific visualizations. Also use when the user needs help with MATLAB syntax, functions, or wants to convert between MATLAB and Python code. Scripts can be executed with MATLAB or the open-source GNU Octave interpreter
Dask
Distributed computing for larger-than-RAM pandas/NumPy workflows. Use when you need to scale existing pandas/NumPy code beyond memory or across clusters. Best for parallel file processing, distributed ML, integration with existing pandas code. For out-of-core analytics on single machine use vaex; for in-memory speed use polars.
Consult Zai
Compare z.ai GLM 4.7 and code-searcher responses for comprehensive dual-AI code analysis. Use when you need multiple AI perspectives on code questions.
Writing Effective Prompts
Structure Claude prompts for clarity and better results using roles, explicit instructions, context, positive framing, and strategic organization. Use when crafting prompts for complex tasks, long documents, tool workflows, or code generation.
Analyze Performance
Establish performance baselines and detect regressions using flamegraph analysis. Use when optimizing performance-critical code, investigating performance issues, or before creating commits with performance-sensitive changes.
Flowchart Creator
Create HTML flowcharts and process diagrams with decision trees, color-coded stages, arrows, and swimlanes. Use when users request flowcharts, process diagrams, workflow visualizations, or decision trees.
Bio Reporting Rmarkdown Reports
Create reproducible bioinformatics analysis reports with R Markdown including code, results, and visualizations in HTML, PDF, or Word format. Use when generating analysis reports with RMarkdown.
Desmos Graphing
Create interactive Desmos graphs in Obsidian using desmos-graph code blocks. Use when visualizing functions, parametric curves, inequalities, or mathematical relationships with customizable styling and settings.
Performance
Rendimiento & Optimización - Atoll Tourisme. Use when optimizing performance or profiling code.
