| 1 | --- |
| 2 | /** |
| 3 | * `<LoopDiagram />` — server-rendered SVG of the IaC/SDK generation loop. |
| 4 | * |
| 5 | * Used by the resource-factory blog post: write resources + live tests → |
| 6 | * run against the real API → (all green) ship, with the feedback edge |
| 7 | * unmatched error → patch the SDK, regenerate → retest closing the cycle. |
| 8 | * |
| 9 | * Styled with the brand tokens (parchment panel, moss flow, honey |
| 10 | * feedback edge, JetBrains Mono labels) so it follows the active theme. |
| 11 | * |
| 12 | * Usage in MDX: |
| 13 | * import LoopDiagram from "../../../components/LoopDiagram.astro"; |
| 14 | * <LoopDiagram /> |
| 15 | */ |
| 16 | --- |
| 17 | |
| 18 | <figure class="alc-loop" data-nosnippet> |
| 19 | <svg |
| 20 | class="alc-loop__svg" |
| 21 | viewBox="0 0 760 250" |
| 22 | role="img" |
| 23 | aria-label="The generation loop: write resources and live tests, run them against the real API, every unmatched error becomes an SDK patch and regeneration, retest until green, then ship the IaC and the truthful SDK together." |
| 24 | > |
| 25 | <defs> |
| 26 | <marker |
| 27 | id="alc-loop-arrow" |
| 28 | viewBox="0 0 10 10" |
| 29 | refX="9" |
| 30 | refY="5" |
| 31 | markerWidth="7" |
| 32 | markerHeight="7" |
| 33 | orient="auto-start-reverse" |
| 34 | > |
| 35 | <path d="M0,0 L10,5 L0,10 z" class="alc-loop__head"></path> |
| 36 | </marker> |
| 37 | <marker |
| 38 | id="alc-loop-arrow-warn" |
| 39 | viewBox="0 0 10 10" |
| 40 | refX="9" |
| 41 | refY="5" |
| 42 | markerWidth="7" |
| 43 | markerHeight="7" |
| 44 | orient="auto-start-reverse" |
| 45 | > |
| 46 | <path d="M0,0 L10,5 L0,10 z" class="alc-loop__head--warn"></path> |
| 47 | </marker> |
| 48 | </defs> |
| 49 | |
| 50 | <!-- nodes --> |
| 51 | <rect class="alc-loop__node" x="20" y="30" width="200" height="56" rx="8"></rect> |
| 52 | <rect class="alc-loop__node" x="300" y="30" width="200" height="56" rx="8"></rect> |
| 53 | <rect class="alc-loop__node alc-loop__node--accent" x="580" y="30" width="160" height="56" rx="8"></rect> |
| 54 | <rect class="alc-loop__node alc-loop__node--warn" x="300" y="170" width="200" height="56" rx="8"></rect> |
| 55 | |
| 56 | <g class="alc-loop__label" text-anchor="middle"> |
| 57 | <text x="120" y="53">write resources</text> |
| 58 | <text x="120" y="72">+ live tests</text> |
| 59 | <text x="400" y="53">run against</text> |
| 60 | <text x="400" y="72">the real API</text> |
| 61 | <text x="660" y="53">ship IaC</text> |
| 62 | <text x="660" y="72">+ truthful SDK</text> |
| 63 | <text class="alc-loop__label--warn" x="400" y="193">patch the SDK,</text> |
| 64 | <text class="alc-loop__label--warn" x="400" y="212">regenerate</text> |
| 65 | </g> |
| 66 | |
| 67 | <!-- forward flow --> |
| 68 | <g class="alc-loop__edge"> |
| 69 | <line x1="220" y1="45" x2="296" y2="45" marker-end="url(#alc-loop-arrow)"></line> |
| 70 | <line x1="500" y1="58" x2="576" y2="58" marker-end="url(#alc-loop-arrow)"></line> |
| 71 | </g> |
| 72 | <text class="alc-loop__edge-label" x="538" y="46" text-anchor="middle">all green</text> |
| 73 | |
| 74 | <!-- feedback loop --> |
| 75 | <g class="alc-loop__edge--warn"> |
| 76 | <line x1="420" y1="86" x2="420" y2="166" marker-end="url(#alc-loop-arrow-warn)"></line> |
| 77 | <path d="M300,198 H262 V70 H296" marker-end="url(#alc-loop-arrow-warn)"></path> |
| 78 | </g> |
| 79 | <text class="alc-loop__edge-label alc-loop__edge-label--warn" x="430" y="130">unmatched error</text> |
| 80 | <text class="alc-loop__edge-label alc-loop__edge-label--warn" x="252" y="130" text-anchor="end">retest</text> |
| 81 | </svg> |
| 82 | </figure> |
| 83 | |
| 84 | <style> |
| 85 | .alc-loop { |
| 86 | margin: 1.5rem 0; |
| 87 | background: var(--alc-bg-elev-1); |
| 88 | border: 1px solid var(--alc-hairline-2); |
| 89 | border-radius: var(--alc-radius); |
| 90 | padding: 0.75rem; |
| 91 | overflow-x: auto; |
| 92 | } |
| 93 | |
| 94 | .alc-loop__svg { |
| 95 | display: block; |
| 96 | width: 100%; |
| 97 | height: auto; |
| 98 | max-width: 100%; |
| 99 | } |
| 100 | |
| 101 | .alc-loop__node { |
| 102 | fill: var(--alc-bg-elev-2); |
| 103 | stroke: var(--alc-accent-40); |
| 104 | stroke-width: 1.5; |
| 105 | } |
| 106 | |
| 107 | .alc-loop__node--accent { |
| 108 | stroke: var(--alc-accent); |
| 109 | fill: color-mix(in srgb, var(--alc-accent-soft) 60%, var(--alc-bg-elev-2)); |
| 110 | } |
| 111 | |
| 112 | .alc-loop__node--warn { |
| 113 | stroke: var(--alc-warn); |
| 114 | fill: color-mix(in srgb, var(--alc-warn) 12%, var(--alc-bg-elev-2)); |
| 115 | } |
| 116 | |
| 117 | .alc-loop__label text { |
| 118 | font-family: var(--alc-font-mono); |
| 119 | font-size: 13px; |
| 120 | font-weight: 600; |
| 121 | fill: var(--alc-fg-1); |
| 122 | } |
| 123 | |
| 124 | .alc-loop__label--warn { |
| 125 | fill: var(--alc-fg-1); |
| 126 | } |
| 127 | |
| 128 | .alc-loop__edge line { |
| 129 | stroke: var(--alc-accent-60); |
| 130 | stroke-width: 1.5; |
| 131 | } |
| 132 | |
| 133 | .alc-loop__edge--warn line, |
| 134 | .alc-loop__edge--warn path { |
| 135 | stroke: var(--alc-warn); |
| 136 | stroke-width: 1.5; |
| 137 | fill: none; |
| 138 | } |
| 139 | |
| 140 | .alc-loop__head { |
| 141 | fill: var(--alc-accent); |
| 142 | } |
| 143 | |
| 144 | .alc-loop__head--warn { |
| 145 | fill: var(--alc-warn); |
| 146 | } |
| 147 | |
| 148 | .alc-loop__edge-label { |
| 149 | font-family: var(--alc-font-mono); |
| 150 | font-size: 10.5px; |
| 151 | fill: var(--alc-fg-3); |
| 152 | } |
| 153 | |
| 154 | .alc-loop__edge-label--warn { |
| 155 | fill: var(--alc-warn); |
| 156 | } |
| 157 | </style> |