Files
diagrams-drawio/references/rules-style.md
T
oleg-lukasonokandClaude Code 6584df0666 Fix review findings: importer DoS, sync data loss, views/profile rendering, docs
Source importers: lstat before open so FIFOs no longer hang the directory
walk; replace the quadratic Rust macro regex with a linear scan.
Three-way sync: report page add/add and delete-vs-modify as conflicts
instead of silently overwriting or resurrecting; canonical comparison so
key order is not a change; the sync action withholds output and fails on
conflicts unless --force. Story publishing escapes <, >, & and U+2028/9
inside the embedded JSON.
Views: drop parentId of unselected containers, re-layout instead of
manual geometry, validate before serialising; flatten() merges identical
nodes repeated across pages so C4 output works with every analysis
action. Dark theme edge labels get a background; tube-map corridors sit
above the stations; C4 containers keep the swimlane style and orphan
relationships land on the matching page; router keeps container header
bands as obstacles; sequence self-messages loop on one side.
Docs: SKILL.md lists all 23 CLI actions and how each capability family
is invoked, task wrappers for query/test/what-if/doctor, capability
tables and --page scope corrected, maintenance snippet uses the real
synchronous action signature, duplicated rule bullets moved to the rule
references, coverage matrix wording made verifiable.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-06 17:01:50 +03:00

6.4 KiB
Raw Blame History

diagrams-drawio — Style Rules

Visual appearance and sizing rules for draw.io diagrams generated by this skill.
These rules are MANDATORY — apply them when generating any diagram.


General style rules — MANDATORY

  • All child shapes within the same swimlane must have the same height — never mix different heights within one swimlane layer/row
  • Rectangles must never use rounding — always set rounded=0 on rectangle shapes
  • Prefer dimensions divisible by 40; wrap non-divisible vendor icons in a grid-aligned container
  • The space between sibling shapes of the same level (same swimlane, same row) must be divisible by 40px — use 40px as the minimum gap. If a swimlane row has shapes of width W and gap G, the step between shape origins = W + G where G ≥ 40 and G mod 40 = 0.
  • Swimlane startSize (header height) must be divisible by 40 — use startSize=40
  • Swimlane body height (total − startSize) must be divisible by 40 — so total height = 40 + N×40 = a multiple of 40
  • Example: startSize=40, body=80 → total=120 ✓; body=160 → total=200 ✓
  • Use ≤ 3 primary color families; create hierarchy with shades
  • Keep connector colors simple and consistent; use dashed connectors only for semantically distinct flows (async, backup, admin, private)
  • Avoid borders on shapes unless needed for visual separation or canonical styling
  • Shape size is driven by content, not routing — typically 80–160px tall per label line

Text fit and cards

  • Avoid long text inside narrow shapes; use wider cards or wrap the label in a dedicated text area inside the card
  • Service names must fit within the visual card width and never extend beyond card boundaries
  • For service-card diagrams use one consistent card pattern: icon on the left, service label on the right, enough padding around both
  • When using canonical vendor icons, preserve the original icon styling; adjust the surrounding card/container layout instead of modifying the icon style

Connector routing rules — MANDATORY

  • All outgoing connectors from the same shape must share a single exit point — never let multiple connectors leave a shape at different X/Y coordinates. Pick one exit side (top/bottom/left/right) and one coordinate on that side; all outgoing connectors use it as their first waypoint.
  • All incoming connectors to the same shape must share a single entry point — never let multiple connectors enter a shape at different X/Y coordinates. Pick one entry side and one coordinate; all incoming connectors use it as their last waypoint before the shape.
  • Connectors must never attach at a shape corner — the exit/entry point must lie on the middle of a side: top-center, bottom-center, left-center, or right-center. A point that is simultaneously on both an X-edge (left or right) AND a Y-edge (top or bottom) of the shape bounding box is a corner and is forbidden. Use the midpoint of the chosen side: x_mid = (x1+x2)/2 for top/bottom sides, y_mid = (y1+y2)/2 for left/right sides.
  • These rules ensure a clean "bus-bar" fan-out/fan-in pattern and prevent connectors from diverging at their source or converging at their target at different positions, which creates visual clutter and increases crossing risk.
  • Exception: shapes with only a single outgoing or single incoming connector — the single-port rule trivially holds. The corner rule still applies.
  • Arrowheads stay outside shape interiors — connectors touch the shape/card edge and never pass through the body.
  • When computing waypoints: use page-negative-space-summary to find free X corridors per row, then pick an exit/entry coordinate that lies within a free corridor at the next traversed level. This minimises connector-shape overlaps and connector crossings.
  • Waypoints must never be closer than 20px to any shape — the first waypoint after a shape exit must be at least 20px away from the shape's edge in the direction of travel (e.g., if exiting bottom at y=520, first waypoint y ≥ 540; if exiting right at x=1040, first waypoint x ≥ 1060). The last waypoint before a shape entry must likewise be at least 20px away from the shape's edge. This 20px clearance also applies to any waypoint relative to same-level sibling shapes the connector passes by — the waypoint must not come within 20px of any sibling shape's bounding box side it is adjacent to.

Text-width estimation — negative space calculation

When computing negative space manually (e.g. for a negative-space diagram), shape bounding boxes alone overestimate occupied space. Text labels only occupy a sub-region within the shape bbox. Use the following formula to estimate the text rendering width:

charWidth  = fontSize × 0.6           // avg glyph width for proportional fonts
rawWidth   = longestLineChrCount × charWidth
padding    = fontSize × 1.0           // horizontal padding (~0.5em each side)
textWidth  = rawWidth + padding

fontStyle modifiers (draw.io flags):
  bit 0 (value 1) = bold   → charWidth × 1.10
  bit 1 (value 2) = italic → charWidth × 1.05

textXMin = clamp(shapeCenterX − textWidth/2, shape.xMin, shape.xMax)
textXMax = clamp(shapeCenterX + textWidth/2, shape.xMin, shape.xMax)

When to apply:

  • Swimlane headers (startSize=40 band): the header text is centered in the full zone width. Use text region for occupied X, flanks are free negative space.
  • Large container shapes whose children don't fill the full width.
  • Any shape where textWidth < shapeWidth — the flanks inside the bbox are free.

Example — zone headers at fontSize=12 bold (fontStyle=1), center x=660, zone x=80..1240:

Label chars charWidth rawWidth padding textWidth textXMin textXMax flank each side
"Client Layer" 12 7.9 95 12 107 607 713 ~527pt
"API Gateway / Edge Layer" 24 7.9 190 12 202 559 761 ~479pt
"Core Microservices" 18 7.9 143 12 155 583 737 ~503pt
"Messaging / Event Bus" 21 7.9 166 12 178 571 749 ~491pt
"Data Layer" 10 7.9 79 12 91 615 705 ~535pt

The page-negative-space-summary action now outputs these fields per shape:

  • textXMin, textXMax, textWidth — estimated text rendering region
  • textFlankLeft, textFlankRight — free space flanking text inside bbox
  • rows[].textAwareFreeCorridors — free corridors computed using text regions (wider than bbox-based corridors)