Last active
April 22, 2026 10:13
-
-
Save nmandzyk/c14ad6b0701903996d895660056a66ee to your computer and use it in GitHub Desktop.
PlantUML macros
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ' ============================================================================ | |
| ' C4-MACROS.PUML — Self-Contained C4 Model Macro Library for Confluence | |
| ' ============================================================================ | |
| ' | |
| ' A complete, self-contained PlantUML macro library implementing the C4 model | |
| ' (https://c4model.com) by Simon Brown. Designed for Confluence PlantUML | |
| ' plugins where external !include URLs may not be available. | |
| ' | |
| ' USAGE: | |
| ' Option A — Copy-paste this entire block at the top of your diagram | |
| ' (between @startuml and your diagram content). | |
| ' Option B — Store as a Confluence page attachment and reference with: | |
| ' !include <attachment-url>/c4-macros.puml | |
| ' | |
| ' SUPPORTED DIAGRAM TYPES: | |
| ' Level 1 — System Context (Person, System, System_Ext) | |
| ' Level 2 — Container (Container, ContainerDb, ContainerQueue) | |
| ' Level 3 — Component (Component, Component_Ext) | |
| ' Level 4 — Deployment (Node, Container inside nodes) | |
| ' | |
| ' ============================================================================ | |
| ' ---------------------------------------------------------------------------- | |
| ' COLOR PALETTE (Standard C4 Model Colors) | |
| ' ---------------------------------------------------------------------------- | |
| !$PERSON_BG = "#08427B" | |
| !$PERSON_BORDER = "#073B6F" | |
| !$SYSTEM_BG = "#1168BD" | |
| !$SYSTEM_BORDER = "#0B4884" | |
| !$EXTERNAL_BG = "#999999" | |
| !$EXTERNAL_BORDER = "#8A8A8A" | |
| !$CONTAINER_BG = "#438DD5" | |
| !$CONTAINER_BORDER = "#3C7FC0" | |
| !$COMPONENT_BG = "#85BBF0" | |
| !$COMPONENT_BORDER = "#78A8D8" | |
| !$BOUNDARY_BG = "#FFFFFF" | |
| !$BOUNDARY_BORDER = "#444444" | |
| !$FONT_WHITE = "#FFFFFF" | |
| !$FONT_DARK = "#000000" | |
| !$REL_COLOR = "#707070" | |
| !$REL_LINE_COLOR = "#707070" | |
| ' ---------------------------------------------------------------------------- | |
| ' GLOBAL SKIN PARAMETERS | |
| ' ---------------------------------------------------------------------------- | |
| skinparam defaultTextAlignment center | |
| skinparam wrapWidth 200 | |
| skinparam maxMessageSize 150 | |
| skinparam shadowing false | |
| skinparam roundCorner 5 | |
| ' Arrow styling | |
| skinparam ArrowColor $REL_LINE_COLOR | |
| skinparam ArrowFontColor $REL_COLOR | |
| skinparam ArrowFontSize 11 | |
| ' Hide stereotype labels (<<system>>, <<container>>, etc.) | |
| hide stereotype | |
| ' Stereotype-based styling for boundaries | |
| skinparam rectangle<<boundary>> { | |
| BorderStyle dashed | |
| BackgroundColor $BOUNDARY_BG | |
| BorderColor $BOUNDARY_BORDER | |
| FontColor $BOUNDARY_BORDER | |
| RoundCorner 0 | |
| FontSize 14 | |
| FontStyle bold | |
| StereotypeFontSize 0 | |
| } | |
| ' Node styling for deployment diagrams | |
| skinparam node { | |
| BackgroundColor #FFFFFF | |
| BorderColor #444444 | |
| FontColor #444444 | |
| } | |
| ' ============================================================================ | |
| ' PERSON MACROS | |
| ' ============================================================================ | |
| ' Persons represent users (human or system actors) interacting with the system. | |
| !unquoted procedure Person($alias, $label, $descr="") | |
| !if ($descr != "") | |
| actor "==$label\n\n<size:11><i>$descr</i></size>" <<person>> as $alias $PERSON_BG | |
| !else | |
| actor "==$label" <<person>> as $alias $PERSON_BG | |
| !endif | |
| !endprocedure | |
| !unquoted procedure Person_Ext($alias, $label, $descr="") | |
| !if ($descr != "") | |
| actor "==$label\n\n<size:11><i>$descr</i></size>" <<person_ext>> as $alias $EXTERNAL_BG | |
| !else | |
| actor "==$label" <<person_ext>> as $alias $EXTERNAL_BG | |
| !endif | |
| !endprocedure | |
| ' ============================================================================ | |
| ' SYSTEM MACROS (Level 1 — Context Diagrams) | |
| ' ============================================================================ | |
| ' Systems are the highest level of abstraction — entire software systems. | |
| !unquoted procedure System($alias, $label, $descr="") | |
| !if ($descr != "") | |
| rectangle "==$label\n<size:11>[Software System]</size>\n\n<size:11>$descr</size>" <<system>> as $alias $SYSTEM_BG | |
| !else | |
| rectangle "==$label\n<size:11>[Software System]</size>" <<system>> as $alias $SYSTEM_BG | |
| !endif | |
| !endprocedure | |
| !unquoted procedure System_Ext($alias, $label, $descr="") | |
| !if ($descr != "") | |
| rectangle "==$label\n<size:11>[Software System]</size>\n\n<size:11>$descr</size>" <<system_ext>> as $alias $EXTERNAL_BG | |
| !else | |
| rectangle "==$label\n<size:11>[Software System]</size>" <<system_ext>> as $alias $EXTERNAL_BG | |
| !endif | |
| !endprocedure | |
| !unquoted procedure SystemDb($alias, $label, $descr="") | |
| !if ($descr != "") | |
| database "==$label\n<size:11>[Database]</size>\n\n<size:11>$descr</size>" <<system_db>> as $alias $SYSTEM_BG | |
| !else | |
| database "==$label\n<size:11>[Database]</size>" <<system_db>> as $alias $SYSTEM_BG | |
| !endif | |
| !endprocedure | |
| !unquoted procedure SystemDb_Ext($alias, $label, $descr="") | |
| !if ($descr != "") | |
| database "==$label\n<size:11>[Database]</size>\n\n<size:11>$descr</size>" <<system_db_ext>> as $alias $EXTERNAL_BG | |
| !else | |
| database "==$label\n<size:11>[Database]</size>" <<system_db_ext>> as $alias $EXTERNAL_BG | |
| !endif | |
| !endprocedure | |
| !unquoted procedure SystemQueue($alias, $label, $descr="") | |
| !if ($descr != "") | |
| queue "==$label\n<size:11>[Queue]</size>\n\n<size:11>$descr</size>" <<system_queue>> as $alias $SYSTEM_BG | |
| !else | |
| queue "==$label\n<size:11>[Queue]</size>" <<system_queue>> as $alias $SYSTEM_BG | |
| !endif | |
| !endprocedure | |
| !unquoted procedure SystemQueue_Ext($alias, $label, $descr="") | |
| !if ($descr != "") | |
| queue "==$label\n<size:11>[Queue]</size>\n\n<size:11>$descr</size>" <<system_queue_ext>> as $alias $EXTERNAL_BG | |
| !else | |
| queue "==$label\n<size:11>[Queue]</size>" <<system_queue_ext>> as $alias $EXTERNAL_BG | |
| !endif | |
| !endprocedure | |
| ' ============================================================================ | |
| ' CONTAINER MACROS (Level 2 — Container Diagrams) | |
| ' ============================================================================ | |
| ' Containers are deployable units: web apps, APIs, databases, message brokers. | |
| !unquoted procedure Container($alias, $label, $techn="", $descr="") | |
| !if ($techn != "" && $descr != "") | |
| rectangle "==$label\n<size:11>[Container: $techn]</size>\n\n<size:11>$descr</size>" <<container>> as $alias $CONTAINER_BG | |
| !elseif ($techn != "") | |
| rectangle "==$label\n<size:11>[Container: $techn]</size>" <<container>> as $alias $CONTAINER_BG | |
| !elseif ($descr != "") | |
| rectangle "==$label\n<size:11>[Container]</size>\n\n<size:11>$descr</size>" <<container>> as $alias $CONTAINER_BG | |
| !else | |
| rectangle "==$label\n<size:11>[Container]</size>" <<container>> as $alias $CONTAINER_BG | |
| !endif | |
| !endprocedure | |
| !unquoted procedure Container_Ext($alias, $label, $techn="", $descr="") | |
| !if ($techn != "" && $descr != "") | |
| rectangle "==$label\n<size:11>[Container: $techn]</size>\n\n<size:11>$descr</size>" <<container_ext>> as $alias $EXTERNAL_BG | |
| !elseif ($techn != "") | |
| rectangle "==$label\n<size:11>[Container: $techn]</size>" <<container_ext>> as $alias $EXTERNAL_BG | |
| !elseif ($descr != "") | |
| rectangle "==$label\n<size:11>[Container]</size>\n\n<size:11>$descr</size>" <<container_ext>> as $alias $EXTERNAL_BG | |
| !else | |
| rectangle "==$label\n<size:11>[Container]</size>" <<container_ext>> as $alias $EXTERNAL_BG | |
| !endif | |
| !endprocedure | |
| !unquoted procedure ContainerDb($alias, $label, $techn="", $descr="") | |
| !if ($techn != "" && $descr != "") | |
| database "==$label\n<size:11>[Database: $techn]</size>\n\n<size:11>$descr</size>" <<container_db>> as $alias $CONTAINER_BG | |
| !elseif ($techn != "") | |
| database "==$label\n<size:11>[Database: $techn]</size>" <<container_db>> as $alias $CONTAINER_BG | |
| !elseif ($descr != "") | |
| database "==$label\n<size:11>[Database]</size>\n\n<size:11>$descr</size>" <<container_db>> as $alias $CONTAINER_BG | |
| !else | |
| database "==$label\n<size:11>[Database]</size>" <<container_db>> as $alias $CONTAINER_BG | |
| !endif | |
| !endprocedure | |
| !unquoted procedure ContainerDb_Ext($alias, $label, $techn="", $descr="") | |
| !if ($techn != "" && $descr != "") | |
| database "==$label\n<size:11>[Database: $techn]</size>\n\n<size:11>$descr</size>" <<container_db_ext>> as $alias $EXTERNAL_BG | |
| !elseif ($techn != "") | |
| database "==$label\n<size:11>[Database: $techn]</size>" <<container_db_ext>> as $alias $EXTERNAL_BG | |
| !elseif ($descr != "") | |
| database "==$label\n<size:11>[Database]</size>\n\n<size:11>$descr</size>" <<container_db_ext>> as $alias $EXTERNAL_BG | |
| !else | |
| database "==$label\n<size:11>[Database]</size>" <<container_db_ext>> as $alias $EXTERNAL_BG | |
| !endif | |
| !endprocedure | |
| !unquoted procedure ContainerQueue($alias, $label, $techn="", $descr="") | |
| !if ($techn != "" && $descr != "") | |
| queue "==$label\n<size:11>[Queue: $techn]</size>\n\n<size:11>$descr</size>" <<container_queue>> as $alias $CONTAINER_BG | |
| !elseif ($techn != "") | |
| queue "==$label\n<size:11>[Queue: $techn]</size>" <<container_queue>> as $alias $CONTAINER_BG | |
| !elseif ($descr != "") | |
| queue "==$label\n<size:11>[Queue]</size>\n\n<size:11>$descr</size>" <<container_queue>> as $alias $CONTAINER_BG | |
| !else | |
| queue "==$label\n<size:11>[Queue]</size>" <<container_queue>> as $alias $CONTAINER_BG | |
| !endif | |
| !endprocedure | |
| !unquoted procedure ContainerQueue_Ext($alias, $label, $techn="", $descr="") | |
| !if ($techn != "" && $descr != "") | |
| queue "==$label\n<size:11>[Queue: $techn]</size>\n\n<size:11>$descr</size>" <<container_queue_ext>> as $alias $EXTERNAL_BG | |
| !elseif ($techn != "") | |
| queue "==$label\n<size:11>[Queue: $techn]</size>" <<container_queue_ext>> as $alias $EXTERNAL_BG | |
| !elseif ($descr != "") | |
| queue "==$label\n<size:11>[Queue]</size>\n\n<size:11>$descr</size>" <<container_queue_ext>> as $alias $EXTERNAL_BG | |
| !else | |
| queue "==$label\n<size:11>[Queue]</size>" <<container_queue_ext>> as $alias $EXTERNAL_BG | |
| !endif | |
| !endprocedure | |
| ' ============================================================================ | |
| ' COMPONENT MACROS (Level 3 — Component Diagrams) | |
| ' ============================================================================ | |
| ' Components are the major structural building blocks within a container. | |
| !unquoted procedure Component($alias, $label, $techn="", $descr="") | |
| !if ($techn != "" && $descr != "") | |
| rectangle "==$label\n<size:11>[Component: $techn]</size>\n\n<size:11>$descr</size>" <<component>> as $alias $COMPONENT_BG | |
| !elseif ($techn != "") | |
| rectangle "==$label\n<size:11>[Component: $techn]</size>" <<component>> as $alias $COMPONENT_BG | |
| !elseif ($descr != "") | |
| rectangle "==$label\n<size:11>[Component]</size>\n\n<size:11>$descr</size>" <<component>> as $alias $COMPONENT_BG | |
| !else | |
| rectangle "==$label\n<size:11>[Component]</size>" <<component>> as $alias $COMPONENT_BG | |
| !endif | |
| !endprocedure | |
| !unquoted procedure Component_Ext($alias, $label, $techn="", $descr="") | |
| !if ($techn != "" && $descr != "") | |
| rectangle "==$label\n<size:11>[Component: $techn]</size>\n\n<size:11>$descr</size>" <<component_ext>> as $alias $EXTERNAL_BG | |
| !elseif ($techn != "") | |
| rectangle "==$label\n<size:11>[Component: $techn]</size>" <<component_ext>> as $alias $EXTERNAL_BG | |
| !elseif ($descr != "") | |
| rectangle "==$label\n<size:11>[Component]</size>\n\n<size:11>$descr</size>" <<component_ext>> as $alias $EXTERNAL_BG | |
| !else | |
| rectangle "==$label\n<size:11>[Component]</size>" <<component_ext>> as $alias $EXTERNAL_BG | |
| !endif | |
| !endprocedure | |
| ' ============================================================================ | |
| ' BOUNDARY MACROS | |
| ' ============================================================================ | |
| ' Boundaries group related elements. Close each boundary with a matching `}`. | |
| ' | |
| ' Enterprise_Boundary(eb, "My Company") { | |
| ' System(s1, "System A") | |
| ' } | |
| !unquoted procedure Enterprise_Boundary($alias, $label) | |
| rectangle "==$label\n<size:10>[Enterprise]</size>" <<boundary>> as $alias { | |
| !endprocedure | |
| !unquoted procedure System_Boundary($alias, $label) | |
| rectangle "==$label\n<size:10>[System]</size>" <<boundary>> as $alias { | |
| !endprocedure | |
| !unquoted procedure Container_Boundary($alias, $label) | |
| rectangle "==$label\n<size:10>[Container]</size>" <<boundary>> as $alias { | |
| !endprocedure | |
| !unquoted procedure Boundary($alias, $label, $type="") | |
| !if ($type != "") | |
| rectangle "==$label\n<size:10>[$type]</size>" <<boundary>> as $alias { | |
| !else | |
| rectangle "==$label" <<boundary>> as $alias { | |
| !endif | |
| !endprocedure | |
| ' ============================================================================ | |
| ' DEPLOYMENT NODE MACROS (Level 4 — Deployment Diagrams) | |
| ' ============================================================================ | |
| ' Nodes represent deployment infrastructure. Close each node with `}`. | |
| ' | |
| ' Node(web, "Web Server", "Ubuntu 22.04") { | |
| ' Container(api, "API", "ASP.NET Core") | |
| ' } | |
| !unquoted procedure Node($alias, $label, $techn="", $descr="") | |
| !if ($techn != "" && $descr != "") | |
| node "$label\n<size:11>[$techn]</size>\n<size:10>$descr</size>" as $alias { | |
| !elseif ($techn != "") | |
| node "$label\n<size:11>[$techn]</size>" as $alias { | |
| !else | |
| node "$label" as $alias { | |
| !endif | |
| !endprocedure | |
| !unquoted procedure Node_R($alias, $label, $techn="", $descr="") | |
| !if ($techn != "" && $descr != "") | |
| node "$label\n<size:11>[$techn]</size>\n<size:10>$descr</size>" as $alias { | |
| !elseif ($techn != "") | |
| node "$label\n<size:11>[$techn]</size>" as $alias { | |
| !else | |
| node "$label" as $alias { | |
| !endif | |
| !endprocedure | |
| ' ============================================================================ | |
| ' RELATIONSHIP MACROS | |
| ' ============================================================================ | |
| ' Relationships define how elements communicate. Direction suffixes control | |
| ' arrow routing: _U(p), _D(own), _L(eft), _R(ight). | |
| ' | |
| ' Rel(user, api, "Makes API calls to", "JSON/HTTPS") | |
| ' Rel_D(api, db, "Reads from and writes to", "SQL/TCP") | |
| !unquoted procedure Rel($from, $to, $label, $techn="") | |
| !if ($techn != "") | |
| $from --> $to : "<size:11>$label</size>\n<size:10>[$techn]</size>" | |
| !else | |
| $from --> $to : "<size:11>$label</size>" | |
| !endif | |
| !endprocedure | |
| !unquoted procedure Rel_U($from, $to, $label, $techn="") | |
| !if ($techn != "") | |
| $from -up-> $to : "<size:11>$label</size>\n<size:10>[$techn]</size>" | |
| !else | |
| $from -up-> $to : "<size:11>$label</size>" | |
| !endif | |
| !endprocedure | |
| !unquoted procedure Rel_D($from, $to, $label, $techn="") | |
| !if ($techn != "") | |
| $from -down-> $to : "<size:11>$label</size>\n<size:10>[$techn]</size>" | |
| !else | |
| $from -down-> $to : "<size:11>$label</size>" | |
| !endif | |
| !endprocedure | |
| !unquoted procedure Rel_L($from, $to, $label, $techn="") | |
| !if ($techn != "") | |
| $from -left-> $to : "<size:11>$label</size>\n<size:10>[$techn]</size>" | |
| !else | |
| $from -left-> $to : "<size:11>$label</size>" | |
| !endif | |
| !endprocedure | |
| !unquoted procedure Rel_R($from, $to, $label, $techn="") | |
| !if ($techn != "") | |
| $from -right-> $to : "<size:11>$label</size>\n<size:10>[$techn]</size>" | |
| !else | |
| $from -right-> $to : "<size:11>$label</size>" | |
| !endif | |
| !endprocedure | |
| !unquoted procedure BiRel($from, $to, $label, $techn="") | |
| !if ($techn != "") | |
| $from <--> $to : "<size:11>$label</size>\n<size:10>[$techn]</size>" | |
| !else | |
| $from <--> $to : "<size:11>$label</size>" | |
| !endif | |
| !endprocedure | |
| !unquoted procedure Rel_Back($from, $to, $label, $techn="") | |
| !if ($techn != "") | |
| $from <.. $to : "<size:11>$label</size>\n<size:10>[$techn]</size>" | |
| !else | |
| $from <.. $to : "<size:11>$label</size>" | |
| !endif | |
| !endprocedure | |
| !unquoted procedure Rel_Back_D($from, $to, $label, $techn="") | |
| !if ($techn != "") | |
| $from <.down. $to : "<size:11>$label</size>\n<size:10>[$techn]</size>" | |
| !else | |
| $from <.down. $to : "<size:11>$label</size>" | |
| !endif | |
| !endprocedure | |
| ' ============================================================================ | |
| ' LAYOUT HELPERS | |
| ' ============================================================================ | |
| ' Invisible arrows that influence element placement without visible connections. | |
| ' | |
| ' Lay_D(systemA, systemB) ' forces B below A | |
| !unquoted procedure Lay_U($from, $to) | |
| $from -[hidden]up-> $to | |
| !endprocedure | |
| !unquoted procedure Lay_D($from, $to) | |
| $from -[hidden]down-> $to | |
| !endprocedure | |
| !unquoted procedure Lay_L($from, $to) | |
| $from -[hidden]left-> $to | |
| !endprocedure | |
| !unquoted procedure Lay_R($from, $to) | |
| $from -[hidden]right-> $to | |
| !endprocedure | |
| ' ============================================================================ | |
| ' DIAGRAM TYPE HEADERS | |
| ' ============================================================================ | |
| ' Optional title/description helpers. Call at the top of your diagram to add | |
| ' a consistent title block. | |
| ' | |
| ' SHOW_LEGEND() | |
| !unquoted procedure LAYOUT_TOP_DOWN() | |
| top to bottom direction | |
| !endprocedure | |
| !unquoted procedure LAYOUT_LEFT_RIGHT() | |
| left to right direction | |
| !endprocedure | |
| !unquoted procedure SHOW_LEGEND() | |
| legend right | |
| |<$PERSON_BG> <color:$FONT_WHITE>Person</color> | | |
| |<$SYSTEM_BG> <color:$FONT_WHITE>Internal System</color> | | |
| |<$EXTERNAL_BG> <color:$FONT_WHITE>External System</color> | | |
| |<$CONTAINER_BG> <color:$FONT_WHITE>Container</color> | | |
| |<$COMPONENT_BG> Component | | |
| endlegend | |
| !endprocedure | |
| ' ============================================================================ | |
| ' END OF C4 MACRO LIBRARY | |
| ' ============================================================================ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment