# Claude Code's GCP Architecture Diagram Skills Improvement — Automating Coordinate Validation and Discovering Design Patterns

# Claude Code's GCP Architecture Diagram Skills Improvement — Automating Coordinate Validation and Discovering Design Patterns

We will introduce a practical improvement cycle that feeds back into SKILL.md, adding improvements such as coordinate validation automation (Python), avoiding Draw.io z-order issues, inline edge labels, and logical grouping of layouts to Claude Code's GCP architecture diagram generation skills.
2026.07.24

This page has been translated by machine translation. View original

Introduction

In the previous article, I created a skill that automatically generates Draw.io files just by telling Claude Code "draw a GCP architecture diagram."

Icon display and container nesting worked correctly, but when I actually used it on a real project, several problems emerged. Arrows were passing over labels making text unreadable, element placement was linear with no logical grouping, and flow diagram step numbers were meaningless without consulting the legend.

This article introduces how I solved these problems. Specifically:

  1. Coordinate validation script — A Python tool that automatically detects element overlaps
  2. Draw.io z-order problem — The root cause of arrows being drawn on top of labels, and how to handle it
  3. Inline edge labels — Making step numbers self-documenting by adding descriptions
  4. Layout improvements — Logical grouping of related services

Problem: Finding coordinate overlaps manually is tedious

When I instruct the skill to "draw an architecture diagram for a RAG chatbot," it generates a Draw.io file like the following.

Google Chat → Chatbot → Knowledge Search → AI Answer Generation

                                              Conversation History

Looking at the generated XML, each element's coordinates are defined as relative positions from the parent container:

<!-- svc-cf-bot coordinates are (80, 130) inside grp-project (x=280, y=130) -->
<!-- → absolute coordinates: (360, 260) -->
<mxCell id="svc-cf-bot" parent="grp-project" vertex="1">
  <mxGeometry x="80" y="130" width="34" height="42" as="geometry" />
</mxCell>

The problem is that as elements increase, it becomes difficult to mentally calculate absolute positions from relative coordinates. Is one icon's label overlapping another icon? Are an arrow's waypoints avoiding the label area? Manual verification is impractical.

Solution 1: Coordinate validation script

I created a Python script that parses Draw.io XML and automatically detects overlaps between elements.

How it works

@dataclass
class BBox:
    """Axis-aligned bounding box"""
    x: float
    y: float
    width: float
    height: float

    @property
    def right(self) -> float:
        return self.x + self.width

    @property
    def bottom(self) -> float:
        return self.y + self.height

    def overlaps(self, other: BBox) -> bool:
        """AABB overlap test"""
        if self.x >= other.right or other.x >= self.right:
            return False
        if self.y >= other.bottom or other.y >= self.bottom:
            return False
        return True

The script's processing flow is as follows:

1. XML parsing — Extract all mxCell elements from the .drawio file and retrieve coordinates, styles, and parent-child relationships

2. Recursive absolute coordinate resolution — Convert relative coordinates from parent containers to absolute coordinates

def _resolve(elem_id: str) -> tuple[float, float]:
    elem = elements[elem_id]
    if elem.resolved:
        return (elem.abs_x, elem.abs_y)
    parent_abs = _resolve(elem.parent_id)
    elem.abs_x = parent_abs[0] + elem.rel_x
    elem.abs_y = parent_abs[1] + elem.rel_y
    elem.resolved = True
    return (elem.abs_x, elem.abs_y)

3. Label bounding box estimation — GCP icons use verticalLabelPosition=bottom to display labels below the icon. The label area is estimated from font size and character count

# CJK characters are approximately 9px each, Latin characters approximately 7px (at 11px font)
avg_char_w = 9.0 if any(ord(c) > 0x2E80 for c in text) else 7.0
text_width = len(text) * avg_char_w * (font_size / 11.0)

4. Edge routing approximation — Edges with explicit waypoints calculate segments precisely, while auto-routed edges are approximated as Z-shaped orthogonal paths

5. Four types of overlap detection:

  • Edge–label intersections
  • Container overlaps
  • Icon proximity (minimum gap of 10px)
  • Label–label overlaps

How to use

uv run python scripts/validate_drawio.py docs/gcp-rag-chatbot.drawio \
  --export-coords docs/gcp-rag-chatbot-coords.json \
  --ignore grp-project:lane-b-header

Example output:

Elements: 33 (11 edges)

[EDGE-LABEL] edge-4 overlaps svc-cf-bot label (gap: -3.5px)
[EDGE-LABEL] edge-5 overlaps svc-cf-bot label (gap: -8.2px)
[EDGE-LABEL] edge-rag-link overlaps svc-logging label (gap: -5.1px) [approx]

The [approx] mark indicates detections from auto-routing approximation, which may be false positives and require visual confirmation. --ignore ID1:ID2 can exclude intentional overlaps (such as swim lane headers spanning containers).

The JSON file output by --export-coords records the relative coordinates, absolute coordinates, and bounding boxes of all elements. It is useful for checking coordinates one by one during debugging.

Problem: Arrows are drawn on top of labels

After detecting overlaps with the validation script, I thought "if I add a white background to labels, they'll be readable even over arrows," and added labelBackgroundColor=#FFFFFF to the style of all icons.

fontColor=#999999;labelBackgroundColor=#FFFFFF;shape=image;...

However, this had no effect. When I actually exported to PNG in Draw.io, arrows were still being drawn on top of labels.

Cause: mxGraph edge drawing order

After creating several test files and investigating, I discovered a specification of mxGraph, the underlying library of Draw.io:

Edges (arrows) are always drawn on top of vertices (icons/labels), regardless of XML order or layer

This is a design decision in mxGraph and there is no workaround. Even if you set labelBackgroundColor, change the XML order, or separate into different layers, edges are always drawn at the front.

Workaround: Avoid label areas with waypoints

The only solution is to route the arrow around label areas.

<!-- Before: Arrow crosses the chatbot's label -->
<mxCell id="edge-4" source="svc-cf-bot" target="svc-firestore" edge="1">
  <mxGeometry relative="1" as="geometry">
    <Array as="points">
      <mxPoint x="377" y="401" />  <!-- Passes through label area -->
    </Array>
  </mxGeometry>
</mxCell>

<!-- After: Route through x=420 to avoid label right edge (x=409) -->
<mxCell id="edge-4" source="svc-cf-bot" target="svc-firestore" edge="1">
  <mxGeometry relative="1" as="geometry">
    <Array as="points">
      <mxPoint x="420" y="401" />  <!-- Outside label area -->
    </Array>
  </mxGeometry>
</mxCell>

I added this finding to the skill's SKILL.md as a label avoidance rule:

Edges must not pass through icon label text. When an edge would cross a label area, add explicit waypoints to route above the icon or below the label. Target the icon center y for vertical centering when pointing at an icon from the side.

labelBackgroundColor is ineffective as an arrow countermeasure, but since it still helps make labels readable on top of container backgrounds, I continue to use it.

Improvement: Inline edge labels

In the previous skill, I designed step-numbered edges for non-technical user mode:

Flow A: ① ② ③ ④ (white circled numbers)
Flow B: ❶ ❷ ❸ ❹ (black circled numbers)

The intent was to record step number-to-description mappings in the legend, but when actually looking at the diagram, numbers alone don't convey what operation is being performed, requiring a look at the legend each time.

After improvement: Number + description inline

Before: ① → ② → ③
After:  ①Send question → ②Knowledge search → ③AI answer generation

Since each arrow directly carries a description, the diagram becomes self-documenting. The legend only needs to indicate the type of flow (e.g., "①–⑤ Chat response flow").

This change in Draw.io XML only requires changing the value attribute of edge elements:

<!-- Before -->
<mxCell id="edge-1" value="①" ... />
<!-- After -->
<mxCell id="edge-1" value="①Send question" ... />

Improvement: Logical grouping in layout

In the layout initially generated by the skill, all services were arranged in a single horizontal line:

Chatbot → Knowledge Search → AI Answer Generation → ... → Log Management

This layout had two problems:

1. Log management was misplaced — It was placed at the end of the flow, making it look like the final step, but it is actually a side effect of bot processing

2. Knowledge search and AI answer generation were discrete — They were arranged in a horizontal line, but these two are actually two steps of a single concept called RAG processing and have a logically close relationship

Improved layout

Chatbot → Log Management    Knowledge Search

                            AI Answer Generation → Conversation History
  • Log management moved next to the chatbot — visually clear that it's a side effect
  • Knowledge search and AI answer generation stacked vertically — expresses logical cohesion as RAG processing

Reflecting improvements in SKILL.md

I reflected these improvements in the skill's SKILL.md so that the same quality can be achieved in future diagram generation. Main additions:

Visual QA workflow (Step 5)

#### 5a. Automated coordinate validation
uv run python scripts/validate_drawio.py docs/<slug>.drawio \
  --export-coords docs/<slug>-coords.json

#### 5b. Visual inspection
/opt/homebrew/bin/drawio -x -f png -s 2 -o docs/<slug>.png docs/<slug>.drawio

#### 5c. Fix and iterate

Three new rules

  • Z-order rule: In Draw.io, edges are always drawn on top of vertices. The only solution is to route around label areas using waypoints
  • Edge separation rule: Edges sharing the same path should be routed with at least 40px spacing
  • Label avoidance rule: Edges must not pass through icon label text areas

Adoption of inline edge labels

### Inline step-numbered edges
- Flow A: ①Send question ②Knowledge search ③AI answer generation(white circled + description)
- **Always include the description inline** — makes edges self-documenting

What I learned

You can't leave "visual quality" entirely to the LLM

LLMs can generate correct XML structure, but they cannot "see" and judge the coordinate relationships between elements. By supplementing with tools like coordinate validation scripts, you can run a generate→validate→fix loop.

Draw.io's rendering order is counterintuitive

The idea that "changing XML order changes z-order" is correct for vertices, but the specification that it has absolutely no effect on edges was not something I understood until I confirmed it with actual test files. It's not documented explicitly either — the kind of knowledge you discover through trial and error.

Skill improvement is a "use it and fix it" cycle

The SKILL.md I initially created covered references to 163 icons and layout rules, but using it on an actual project revealed design insights such as "inline labels are more readable" and "log management should be placed as a side effect, not at the end of the flow." By feeding these back into SKILL.md, the skill gets smarter the more you use it.

Summary

I added automated coordinate validation and design pattern improvements to the Claude Code GCP architecture diagram skill.

  • validate_drawio.py (536 lines): Recursive coordinate resolution, label BBox estimation, edge routing approximation, 4 types of overlap detection
  • Z-order discovery: Draw.io edges are always drawn on top of vertices → route around label areas using waypoints
  • Inline edge labels: Pairing numbers with descriptions like ①Send question makes diagrams self-documenting
  • Logical layout grouping: Place related services nearby, and keep side-effect services off the main flow line

In the previous article I made it possible to produce accurate icons just by "copy-pasting style strings," but with this round of improvements, "layout and routing can also be quality-checked automatically." Skills aren't finished once created — by using them in practice and feeding back what you learn, they gradually approach a truly practical level.


Claudeならクラスメソッドにお任せください

クラスメソッドは、Anthropic社とリセラー契約を締結しています。各種製品ガイドから、業種別の活用法、フェーズごとのお悩み解決などサービス支援ページにまとめております。まずはご覧いただき、お気軽にご相談ください。

サービス詳細を見る

Share this article

AI白書