-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathARCHITECTURE_DIAGRAM.drawio
More file actions
360 lines (360 loc) · 45.5 KB
/
Copy pathARCHITECTURE_DIAGRAM.drawio
File metadata and controls
360 lines (360 loc) · 45.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/29.3.6 Chrome/140.0.7339.249 Electron/38.8.0 Safari/537.36">
<diagram name="TEMPO - Complete Architecture" id="complete-architecture">
<mxGraphModel dx="-283" dy="1203" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="2000" pageHeight="1500" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="title" parent="1" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;fontStyle=1;fontColor=#000000;" value="TEMPO - Complete Architecture &amp; Dependencies" vertex="1">
<mxGeometry height="40" width="800" x="2540" y="400" as="geometry" />
</mxCell>
<mxCell id="legend" parent="1" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="LEGEND" vertex="1">
<mxGeometry height="180" width="400" x="2050" y="3100" as="geometry" />
</mxCell>
<mxCell id="legend-frontend" parent="legend" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#d5e8d4;strokeColor=#82b366;fontColor=#000000;" value="Frontend Layer (React/Vite)" vertex="1">
<mxGeometry height="25" width="200" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="legend-backend" parent="legend" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#f8cecc;strokeColor=#b85450;fontColor=#000000;" value="Backend Layer (Go)" vertex="1">
<mxGeometry height="25" width="200" x="10" y="60" as="geometry" />
</mxCell>
<mxCell id="legend-electron" parent="legend" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#dae8fc;strokeColor=#6c8ebf;fontColor=#000000;" value="Electron Wrapper" vertex="1">
<mxGeometry height="25" width="200" x="10" y="90" as="geometry" />
</mxCell>
<mxCell id="legend-external" parent="legend" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#ffe6cc;strokeColor=#d79b00;fontColor=#000000;" value="External Services" vertex="1">
<mxGeometry height="25" width="200" x="10" y="120" as="geometry" />
</mxCell>
<mxCell id="stats" parent="1" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="PROJECT STATISTICS" vertex="1">
<mxGeometry height="280" width="670" x="2490" y="3100" as="geometry" />
</mxCell>
<mxCell id="stats-detail" parent="stats" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="Total Dependencies:
• Frontend: 42 npm packages
• Backend: 4 Go modules (+ transitive dependencies)
• Dev Tools: 11 packages

Lines of Code:
• Creation.jsx: 4,824 lines
• Go Backend: ~750 lines (7 files)
• Total Frontend Components: ~15,000+ lines

Binary Sizes:
• backend.exe: 19.4 MB (pure Go, no dependencies)
• Final installer: ~100 MB (includes Electron runtime)

Build Time:
• Frontend (Vite): ~3-4 minutes
• Backend (Go): ~5-10 seconds
• Electron packaging: ~30-60 seconds" vertex="1">
<mxGeometry height="240" width="630" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="electron-container" parent="1" style="swimlane;whiteSpace=wrap;html=1;fontSize=16;fontStyle=1;fillColor=#fff2cc;strokeColor=#d6b656;strokeWidth=3;fontColor=#000000;" value="<font style="">ELECTRON DESKTOP APPLICATION</font>" vertex="1">
<mxGeometry height="1970" width="3270" x="2010" y="810" as="geometry" />
</mxCell>
<mxCell id="electron-main" parent="electron-container" style="swimlane;whiteSpace=wrap;html=1;fontSize=14;fontStyle=1;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;fontColor=#000000;" value="ELECTRON MAIN PROCESS" vertex="1">
<mxGeometry height="480" width="400" x="1770" y="100" as="geometry" />
</mxCell>
<mxCell id="electron-files" parent="electron-main" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="Files" vertex="1">
<mxGeometry height="140" width="360" x="20" y="40" as="geometry" />
</mxCell>
<mxCell id="main-js" parent="electron-files" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="electron/main.cjs
• BrowserWindow creation
• backend.exe spawn + dynamic port selection
• Optional: uvicorn calliope-runner (port 5000)
• Docker service management
• IPC handlers, file dialogs
• App lifecycle management" vertex="1">
<mxGeometry height="50" width="340" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="preload-js" parent="electron-files" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="electron/preload.cjs
• Context bridge setup
• IPC communication API
• Security isolation" vertex="1">
<mxGeometry height="45" width="340" x="10" y="85" as="geometry" />
</mxCell>
<mxCell id="electron-deps" parent="electron-main" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="Dependencies" vertex="1">
<mxGeometry height="240" width="360" x="20" y="190" as="geometry" />
</mxCell>
<mxCell id="electron-pkg" parent="electron-deps" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#d5e8d4;strokeColor=#82b366;fontColor=#000000;" value="electron@40.4.1
• Chromium engine
• Node.js integration
• Native APIs" vertex="1">
<mxGeometry height="45" width="340" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="electron-builder-pkg" parent="electron-deps" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#d5e8d4;strokeColor=#82b366;fontColor=#000000;" value="electron-builder@26.7.0
• NSIS installer creation
• Code signing
• Auto-update support" vertex="1">
<mxGeometry height="45" width="340" x="10" y="80" as="geometry" />
</mxCell>
<mxCell id="electron-store-pkg" parent="electron-deps" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#d5e8d4;strokeColor=#82b366;fontColor=#000000;" value="electron-store@11.0.2
• Persistent settings storage
• JSON configuration
• User preferences" vertex="1">
<mxGeometry height="45" width="340" x="10" y="130" as="geometry" />
</mxCell>
<mxCell id="concurrently-pkg" parent="electron-deps" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#d5e8d4;strokeColor=#82b366;fontColor=#000000;" value="concurrently@9.2.1
wait-on@9.0.4
• Dev server coordination" vertex="1">
<mxGeometry height="45" width="340" x="10" y="180" as="geometry" />
</mxCell>
<mxCell id="frontend-container" parent="electron-container" style="swimlane;whiteSpace=wrap;html=1;fontSize=14;fontStyle=1;fillColor=#d5e8d4;strokeColor=#82b366;strokeWidth=2;fontColor=#000000;" value="REACT FRONTEND (VITE)" vertex="1">
<mxGeometry height="920" width="720" x="920" y="100" as="geometry" />
</mxCell>
<mxCell id="frontend-core" parent="frontend-container" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="Core Framework" vertex="1">
<mxGeometry height="140" width="680" x="20" y="40" as="geometry" />
</mxCell>
<mxCell id="react-pkg" parent="frontend-core" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="react@19.2.0 + react-dom@19.2.0
• Component-based UI
• Virtual DOM
• Hooks (useState, useEffect, useCallback, useMemo)" vertex="1">
<mxGeometry height="45" width="660" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="vite-pkg" parent="frontend-core" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="vite@7.2.4 + @vitejs/plugin-react@5.1.1
• ES modules bundler
• Hot Module Replacement (HMR)
• Production optimization" vertex="1">
<mxGeometry height="45" width="660" x="10" y="80" as="geometry" />
</mxCell>
<mxCell id="frontend-ui" parent="frontend-container" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="UI Libraries &amp; Styling" vertex="1">
<mxGeometry height="240" width="680" x="20" y="190" as="geometry" />
</mxCell>
<mxCell id="mui-pkg" parent="frontend-ui" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="@mui/material@7.3.7 + @mui/icons-material@7.3.7
@emotion/react@11.14.0 + @emotion/styled@11.14.1
• Material Design components
• CSS-in-JS styling" vertex="1">
<mxGeometry height="50" width="660" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="tailwind-pkg" parent="frontend-ui" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="tailwindcss@3.4.17 + autoprefixer@10.4.23 + postcss@8.5.6
• Utility-first CSS framework
• JIT compilation
• Custom design system" vertex="1">
<mxGeometry height="45" width="660" x="10" y="85" as="geometry" />
</mxCell>
<mxCell id="framer-pkg" parent="frontend-ui" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="framer-motion@12.23.27
• Animation library
• Gesture detection
• Transitions &amp; spring physics" vertex="1">
<mxGeometry height="45" width="660" x="10" y="135" as="geometry" />
</mxCell>
<mxCell id="icons-pkg" parent="frontend-ui" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="react-icons@5.5.0 + lucide-react@0.562.0
• Icon libraries (Font Awesome, Heroicons, etc.)
• Lucide icon set" vertex="1">
<mxGeometry height="45" width="660" x="10" y="185" as="geometry" />
</mxCell>
<mxCell id="frontend-map" parent="frontend-container" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="Map &amp; GIS Visualization" vertex="1">
<mxGeometry height="190" width="680" x="20" y="440" as="geometry" />
</mxCell>
<mxCell id="maplibre-pkg" parent="frontend-map" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="maplibre-gl@5.16.0 + react-map-gl@8.1.0
• Vector tile rendering
• WebGL acceleration
• Custom map styles
• GeoJSON layer support" vertex="1">
<mxGeometry height="60" width="660" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="deckgl-pkg" parent="frontend-map" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="deck.gl@9.2.5 + @deck.gl/core@9.2.5 + @deck.gl/layers@9.2.5 + @deck.gl/react@9.2.5
• GPU-accelerated data visualization
• Large dataset rendering (millions of points)
• Custom layer types (Scatterplot, Arc, Line, GeoJson)
• 3D visualization support" vertex="1">
<mxGeometry height="75" width="660" x="10" y="95" as="geometry" />
</mxCell>
<mxCell id="frontend-charts" parent="frontend-container" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="Charts &amp; Data Visualization" vertex="1">
<mxGeometry height="140" width="680" x="20" y="640" as="geometry" />
</mxCell>
<mxCell id="echarts-pkg" parent="frontend-charts" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="echarts@6.0.0 + echarts-for-react@3.0.5
• Interactive charts (line, bar, scatter, heatmap)
• Real-time data updates" vertex="1">
<mxGeometry height="45" width="660" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="apexcharts-pkg" parent="frontend-charts" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="apexcharts@5.3.6 + react-apexcharts@1.9.0
recharts@3.6.0
• Additional charting options
• Responsive charts" vertex="1">
<mxGeometry height="45" width="660" x="10" y="80" as="geometry" />
</mxCell>
<mxCell id="frontend-utils" parent="frontend-container" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="Utilities &amp; Data Processing" vertex="1">
<mxGeometry height="110" width="680" x="20" y="790" as="geometry" />
</mxCell>
<mxCell id="data-pkg" parent="frontend-utils" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="papaparse@5.5.3 • file-saver@2.0.5 • jszip@3.10.1
flatpickr@4.6.13 • clsx@2.1.1 • tailwind-merge@3.4.0
react-spring@10.0.3 • react-use-measure@2.1.7
• CSV parsing • File downloads • ZIP compression • Date pickers • Utility classes" vertex="1">
<mxGeometry height="65" width="660" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="creation-component" parent="frontend-container" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#fff2cc;strokeColor=#d6b656;fontColor=#000000;" value="<font style="">src/components/Creation.jsx (4824 lines)<br>• Main model creation interface<br>• MapLibre map integration<br>• Location management (add, edit, delete)<br>• Technology assignment<br>• Link creation between locations<br>• Run Model functionality (handleRunModel)<br>• Job polling with progress updates<br>• State: locations, links, technologies, isRunningModel, jobProgress</font>" vertex="1">
<mxGeometry height="120" width="660" x="20" y="40" as="geometry" />
</mxCell>
<mxCell id="other-components" parent="frontend-container" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#fff2cc;strokeColor=#d6b656;fontColor=#000000;" value="Other Components
• BulkImport.jsx / CSVUploader.jsx — CSV import (locations, links)
• Export.jsx — YAML/ZIP export (via calliope_adapter)
• Locations.jsx / LocationEditDialog.jsx — Location editor
• Models.jsx / ModelSelector.jsx — Saved models browser
• Configuration.jsx — App settings (GeoServer, ports)
• GlobalDataPanel.jsx — Global parameters &amp; time-series
• TimeSeries.jsx — Time series data editor
• Results.jsx — Results viewer (ECharts, Recharts)
• CCSCreationPanel.jsx / CCSConfiguration.jsx / CCSGlobalPanel.jsx
• H2CreationPanel.jsx / H2Configuration.jsx / H2GlobalPanel.jsx
• TechnologiesData.js — Built-in JS technology library
• src/services/api.js — Go backend client (port 8082)" vertex="1">
<mxGeometry height="110" width="660" x="20" y="170" as="geometry" />
</mxCell>
<mxCell id="backend-container" parent="electron-container" style="swimlane;whiteSpace=wrap;html=1;fontSize=14;fontStyle=1;fillColor=#f8cecc;strokeColor=#b85450;strokeWidth=2;fontColor=#000000;" value="GO BACKEND (REST API)" vertex="1">
<mxGeometry height="920" width="640" x="150" y="100" as="geometry" />
</mxCell>
<mxCell id="backend-core" parent="backend-container" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="Core Files" vertex="1">
<mxGeometry height="140" width="600" x="20" y="40" as="geometry" />
</mxCell>
<mxCell id="main-go" parent="backend-core" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="backend-go/main.go (50 lines)
• Entry point
• CLI flags (--port, --db)
• SQLite initialization
• Gin server startup
• PID file management" vertex="1">
<mxGeometry height="80" width="580" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="backend-api" parent="backend-container" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="API Server" vertex="1">
<mxGeometry height="220" width="600" x="20" y="190" as="geometry" />
</mxCell>
<mxCell id="server-go" parent="backend-api" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="internal/api/server.go
• Gin router, strict CORS (Electron renderer + local Vite)
• POST/GET /api/models — save, list models
• GET/PUT/DELETE /api/models/:id — manage model
• POST /api/models/:id/run — submit optimization job
• GET /api/jobs/:id — job status
• GET /api/jobs/:id/results — optimization results
• POST/GET/DELETE /api/completed-runs — run history
• GET /api/osm/:layer — OSM layer (GeoServer or Overpass)
• GET /api/osm/layers — available layers
• GET /api/osm/regions — loaded regions
• POST /api/osm/download — trigger region download
• GET /api/geocode — geocode location name
• GET /tech/health + ANY /tech/api/v1/* — OEO tech DB proxy
• GET /api/health — health check" vertex="1">
<mxGeometry height="170" width="580" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="backend-clients" parent="backend-container" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="External Clients" vertex="1">
<mxGeometry height="220" width="600" x="20" y="420" as="geometry" />
</mxCell>
<mxCell id="calliope-client" parent="backend-clients" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="internal/calliope/client.go
• RunModel() — POST /run with JSON model config
• StreamJobLogs() — GET /run/{id}/stream SSE reader
• GetJobStatus() — derive status from SSE events
• GetResults() — extract results from SSE done event
• CancelJob() — DELETE /run/{id}
• GenerateModelYAML() — ModelConfig → Calliope YAML
 – Locations with coordinates
 – Technologies per location
 – Links with distance calculation
 – Technology definitions with constraints" vertex="1">
<mxGeometry height="90" width="580" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="geoserver-client" parent="backend-clients" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="internal/geoserver/client.go (100 lines)
• GetOSMLayer() - WFS GetFeature request
• URL: /wfs?service=WFS&amp;version=2.0.0&amp;request=GetFeature
• GeoJSON output format
• CQL filters for region
• 5-minute cache TTL
• Layers: substations, power_plants, power_lines, communes, districts" vertex="1">
<mxGeometry height="80" width="580" x="10" y="125" as="geometry" />
</mxCell>
<mxCell id="backend-data" parent="backend-container" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="Data &amp; Storage" vertex="1">
<mxGeometry height="250" width="600" x="20" y="650" as="geometry" />
</mxCell>
<mxCell id="models-go" parent="backend-data" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="internal/models/model.go (120 lines)
• Location {id, name, lat, lon, technologies[], constraints{}}
• Link {id, source, target, distance, technology, constraints{}}
• Technology {name, type, carrier, carrier_in[], carrier_out[], constraints{}}
• ModelConfig - Complete model structure
• Job {id, model_id, status, progress, result, error}" vertex="1">
<mxGeometry height="80" width="580" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="storage-go" parent="backend-data" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="internal/storage/database.go (150 lines)
• SQLite database with pure Go driver (modernc.org/sqlite)
• TABLE models (id, name, config TEXT, created_at, updated_at)
• TABLE jobs (id TEXT, model_id, status, progress, result, error, created_at, updated_at)
• SaveModel(), GetModel(), ListModels()
• CreateJob(), UpdateJob(), GetJob()
• JSON serialization for config and results" vertex="1">
<mxGeometry height="90" width="580" x="10" y="115" as="geometry" />
</mxCell>
<mxCell id="config-file" parent="backend-data" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="config.yaml
• geoserver.url: http://localhost:8081/geoserver
• calliope.url: http://localhost:5000
• server.port: 8082" vertex="1">
<mxGeometry height="30" width="580" x="10" y="210" as="geometry" />
</mxCell>
<mxCell id="external-services" parent="electron-container" style="swimlane;whiteSpace=wrap;html=1;fontSize=14;fontStyle=1;fillColor=#ffe6cc;strokeColor=#d79b00;strokeWidth=2;fontColor=#000000;" value="EXTERNAL SERVICES" vertex="1">
<mxGeometry height="360" width="3680" x="160" y="1260" as="geometry" />
</mxCell>
<mxCell id="geoserver-service" parent="external-services" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="GEOSERVER (Docker: 8080 | Backend: 8081)" vertex="1">
<mxGeometry height="280" width="560" x="40" y="40" as="geometry" />
</mxCell>
<mxCell id="geoserver-info" parent="geoserver-service" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="OSM Infrastructure Data Provider

Technology:
• Jetty Server (kartoza/geoserver Docker image)
• Web Feature Service (WFS) 2.0.0
• GeoJSON output format
• Go backend connects at 8081/geoserver
• User web UI accessible at 8080/geoserver/web

Available Layers:
• osm:osm_substations — Electrical substations
• osm:osm_power_plants — Power generation facilities
• osm:osm_power_lines — Transmission lines
• osm:osm_communes — Administrative boundaries
• osm:osm_districts — Regional districts

Features:
• CQL filtering by region
• Spatial bounding-box queries
• Pre-processed Geofabrik OSM data
• 5-minute response cache in Go backend
• Fallback: Overpass API when unavailable" vertex="1">
<mxGeometry height="230" width="540" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="calliope-service" parent="external-services" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="CALLIOPE RUNNER SERVICE (Port 5000)" vertex="1">
<mxGeometry height="280" width="560" x="640" y="40" as="geometry" />
</mxCell>
<mxCell id="calliope-info" parent="calliope-service" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="Energy System Optimization Engine

Technology:
• FastAPI (Python) HTTP service on port 5000
• calliope_service.py → calliope_runner.py (worker thread)
• adapters/calliope_adapter.py — YAML conversion
• adapters/pypsa_adapter.py — experimental
• adapters/osemosys_adapter.py — experimental
• Deploy: uvicorn or docker-compose.yml

API Endpoints:
• GET /health — service health check
• POST /run — submit JSON job, returns {job_id}
• GET /run/{job_id}/stream — SSE log stream
• DELETE /run/{job_id} — cancel job

Input: JSON model config (converted to Calliope YAML in memory)

Output:
• Optimal capacity decisions
• Energy flows (carrier in/out)
• Cost breakdown
• System metrics (JSON)" vertex="1">
<mxGeometry height="230" width="540" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="sqlite-db" parent="external-services" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="SQLITE DATABASE" vertex="1">
<mxGeometry height="280" width="560" x="1240" y="40" as="geometry" />
</mxCell>
<mxCell id="sqlite-info" parent="sqlite-db" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="Local Persistent Storage

File: calliope.db
Driver: modernc.org/sqlite (Pure Go)

Tables:

models
• id INTEGER PRIMARY KEY AUTOINCREMENT
• name TEXT NOT NULL
• config TEXT NOT NULL (JSON serialized ModelConfig)
• created_at TIMESTAMP
• updated_at TIMESTAMP

jobs
• id TEXT PRIMARY KEY (UUID)
• model_id INTEGER FOREIGN KEY
• status TEXT (pending, running, completed, failed)
• progress INTEGER (0-100)
• result TEXT (JSON results)
• error TEXT
• created_at TIMESTAMP
• updated_at TIMESTAMP" vertex="1">
<mxGeometry height="230" width="540" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="oeo-tech-service" parent="external-services" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="OEO TECH DATABASE API (Port 8000)" vertex="1">
<mxGeometry height="280" width="540" x="1860" y="40" as="geometry" />
</mxCell>
<mxCell id="oeo-tech-info" parent="oeo-tech-service" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="Technology Parameter Service (optional)

Technology:
• Python REST service on port 8000
• Open Energy Ontology (OEO) aligned data
• Techno-economic parameters

Go backend proxies at:
• GET /tech/health
• ANY /tech/api/v1/* → http://localhost:8000

Frontend can call via proxy:
• Technology costs, efficiencies, lifetimes
• Enriches TechnologiesData.js at runtime

Note: Optional — app uses bundled
TechnologiesData.js when unavailable" vertex="1">
<mxGeometry height="230" width="520" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="h2-service" parent="external-services" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="H₂ PLANT SIM SERVICE (Port 8765)" vertex="1">
<mxGeometry height="280" width="540" x="2460" y="40" as="geometry" />
</mxCell>
<mxCell id="h2-service-info" parent="h2-service" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="Hydrogen Plant Simulation (optional)

Technology:
• FastAPI + OpenModelica on port 8765
• VITE_H2_SERVICE_URL env var override
• Vite dev proxy: /h2-proxy → 8765

Frontend client: src/services/hydrogenService.js
• WebSocket-first connection
• HTTP polling fallback after 3s timeout

Endpoints:
• POST /simulate — submit plant parameters
• GET /jobs/{id} — poll status
• WS / — real-time telemetry stream

Offline fallback:
• src/services/h2Physics.js

Models: PEM/Alkaline electrolyser, H₂ storage,
compression, fuel cell (~85-90% accuracy)" vertex="1">
<mxGeometry height="230" width="520" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="ccs-service" parent="external-services" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="CCS SIM SERVICE (Port 8766)" vertex="1">
<mxGeometry height="280" width="540" x="3060" y="40" as="geometry" />
</mxCell>
<mxCell id="ccs-service-info" parent="ccs-service" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="CCS Chain Simulation (optional)

Technology:
• FastAPI + OpenModelica on port 8766
• VITE_CCS_SERVICE_URL env var override
• Vite dev proxy: /ccs-proxy → 8766

Frontend client: src/services/ccsService.js
• WebSocket-first connection
• HTTP polling fallback after 3s timeout

Endpoints:
• POST /simulate — submit chain parameters
• GET /jobs/{id} — poll status
• WS / — real-time telemetry stream

Offline fallback:
• src/services/ccsPhysics.js

Models: Amine absorption, stripper reboiler,
multi-stage compression, CO₂ injection
(~85-90% accuracy vs Simulink)" vertex="1">
<mxGeometry height="230" width="520" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="arrow1" edge="1" parent="electron-container" source="electron-main" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=3;strokeColor=#6c8ebf;endArrow=classic;endFill=1;fontColor=#000000;" target="frontend-container">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="arrow1-label" connectable="0" parent="arrow1" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontStyle=1;fontColor=#FFFFFF;" value="IPC
Communication" vertex="1">
<mxGeometry relative="1" x="-0.1" y="2" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="arrow2" edge="1" parent="electron-container" source="frontend-container" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=3;strokeColor=#82b366;endArrow=classic;endFill=1;fontColor=#000000;" target="backend-container">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1280" y="1190" />
<mxPoint x="470" y="1190" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="arrow2-label" connectable="0" parent="arrow2" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontStyle=1;fontColor=#FFFFFF;" value="HTTP REST API
localhost:8082" vertex="1">
<mxGeometry relative="1" x="-0.1" y="2" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="arrow3" edge="1" parent="electron-container" source="backend-container" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=3;strokeColor=#d79b00;endArrow=classic;endFill=1;startArrow=classic;startFill=1;fontColor=#000000;" target="geoserver-service">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="340" y="1190" />
<mxPoint x="340" y="1190" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="arrow3-label" connectable="0" parent="arrow3" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontStyle=1;fontColor=#FFFFFF;" value="WFS 2.0.0
GeoJSON" vertex="1">
<mxGeometry relative="1" x="-0.1" y="2" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="arrow4" edge="1" parent="electron-container" source="backend-container" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=3;strokeColor=#d79b00;endArrow=classic;endFill=1;startArrow=classic;startFill=1;fontColor=#000000;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" target="calliope-service">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="820" y="560" />
<mxPoint x="820" y="1240" />
<mxPoint x="1080" y="1240" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="arrow4-label" connectable="0" parent="arrow4" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontStyle=1;fontColor=#FFFFFF;" value="Job Submission
SSE Log Stream
Results Fetch" vertex="1">
<mxGeometry relative="1" x="-0.1" y="2" as="geometry">
<mxPoint y="10" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="arrow5" edge="1" parent="electron-container" source="backend-container" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=3;strokeColor=#9673a6;endArrow=classic;endFill=1;startArrow=classic;startFill=1;fontColor=#000000;" target="sqlite-db">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="860" y="560" />
<mxPoint x="860" y="1120" />
<mxPoint x="1570" y="1120" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="arrow5-label" connectable="0" parent="arrow5" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontStyle=1;fontColor=#FFFFFF;" value="CRUD
Operations" vertex="1">
<mxGeometry relative="1" x="-0.1" y="2" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="arrow6" edge="1" parent="electron-container" source="electron-main" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=3;strokeColor=#b85450;endArrow=classic;endFill=1;fontColor=#000000;" target="backend-container">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1970" y="60" />
<mxPoint x="860" y="60" />
<mxPoint x="860" y="560" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="arrow6-label" connectable="0" parent="arrow6" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontStyle=1;fontColor=#FFFFFF;" value="Process
Spawn/Kill" vertex="1">
<mxGeometry relative="1" x="-0.1" y="2" as="geometry">
<mxPoint x="20" y="-10" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="backend-deps" parent="electron-container" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#ffe6cc;strokeColor=#d79b00;fontColor=#000000;" value="Go Dependencies" vertex="1">
<mxGeometry height="280" width="380" x="2240" y="200" as="geometry" />
</mxCell>
<mxCell id="gin-pkg" parent="backend-deps" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#d5e8d4;strokeColor=#82b366;fontColor=#000000;" value="gin-gonic/gin@1.10.0
• HTTP web framework
• Router &amp; middleware
• JSON binding
• CORS support" vertex="1">
<mxGeometry height="60" width="280" x="40" y="40" as="geometry" />
</mxCell>
<mxCell id="sqlite-pkg" parent="backend-deps" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#d5e8d4;strokeColor=#82b366;fontColor=#000000;" value="modernc.org/sqlite@1.29.1
• Pure Go SQLite driver
• No CGO required
• No C compiler needed
• Cross-platform" vertex="1">
<mxGeometry height="65" width="280" x="40" y="105" as="geometry" />
</mxCell>
<mxCell id="uuid-pkg" parent="backend-deps" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#d5e8d4;strokeColor=#82b366;fontColor=#000000;" value="google/uuid@1.6.0
• UUID generation
• Job ID tracking" vertex="1">
<mxGeometry height="40" width="280" x="40" y="175" as="geometry" />
</mxCell>
<mxCell id="yaml-pkg" parent="backend-deps" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#d5e8d4;strokeColor=#82b366;fontColor=#000000;" value="gopkg.in/yaml.v3@3.0.1
• YAML generation
• Calliope model files" vertex="1">
<mxGeometry height="40" width="280" x="40" y="220" as="geometry" />
</mxCell>
<mxCell id="arrow-tech-api" edge="1" parent="electron-container" source="backend-container" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;strokeColor=#9673a6;endArrow=classic;endFill=1;dashed=1;fontColor=#000000;" target="oeo-tech-service" vertex="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="arrow-tech-api-label" connectable="0" parent="arrow-tech-api" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontStyle=1;fontColor=#FFFFFF;" value="Proxy
/tech/api/v1/*" vertex="1">
<mxGeometry relative="1" x="-0.1" y="2" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="arrow-h2" edge="1" parent="electron-container" source="frontend-container" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;strokeColor=#82b366;endArrow=classic;endFill=1;dashed=1;fontColor=#000000;" target="h2-service" vertex="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="arrow-h2-label" connectable="0" parent="arrow-h2" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontStyle=1;fontColor=#FFFFFF;" value="WS + HTTP
/h2-proxy" vertex="1">
<mxGeometry relative="1" x="-0.1" y="2" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="arrow-ccs" edge="1" parent="electron-container" source="frontend-container" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;strokeColor=#82b366;endArrow=classic;endFill=1;dashed=1;fontColor=#000000;" target="ccs-service" vertex="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="arrow-ccs-label" connectable="0" parent="arrow-ccs" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontStyle=1;fontColor=#FFFFFF;" value="WS + HTTP
/ccs-proxy" vertex="1">
<mxGeometry relative="1" x="-0.1" y="2" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="arrow-calliope-direct" edge="1" parent="electron-container" source="frontend-container" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;strokeColor=#6c8ebf;endArrow=classic;endFill=1;dashed=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;fontColor=#000000;" target="calliope-service" vertex="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="750" y="560" />
<mxPoint x="750" y="1400" />
<mxPoint x="1080" y="1400" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="arrow-calliope-direct-label" connectable="0" parent="arrow-calliope-direct" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontStyle=1;fontColor=#FFFFFF;" value="Direct SSE
calliopeClient.js" vertex="1">
<mxGeometry relative="1" x="-0.1" y="2" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="frontend-components" parent="1" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#ffe6cc;strokeColor=#d79b00;fontColor=#000000;" value="Main Components" vertex="1">
<mxGeometry height="420" width="860" x="5350" y="810" as="geometry" />
</mxCell>
<mxCell id="dataflow-info" parent="frontend-components" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontColor=#000000;" value="DATA FLOW" vertex="1">
<mxGeometry height="180" width="400" x="440" y="230" as="geometry" />
</mxCell>
<mxCell id="flow-detail" parent="dataflow-info" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="1. User creates model in React UI
2. Frontend POST /api/models → Go backend
3. Backend stores ModelConfig in SQLite
4. User clicks ‘Run Model’
5. Frontend POST /api/models/:id/run → Go backend
6. Backend POST /run → calliope_service.py
7. Backend opens SSE GET /run/{id}/stream
8. calliope_runner.py executes Calliope solver
9. [CALLIOPE] log events stream back via SSE
10. Frontend polls status, displays progress
11. Results saved to SQLite completed-runs
12. Results visualised in Results view" vertex="1">
<mxGeometry height="135" width="380" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="build-info" parent="frontend-components" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="BUILD &amp; DEPLOYMENT" vertex="1">
<mxGeometry height="180" width="400" y="230" as="geometry" />
</mxCell>
<mxCell id="nsis-info" parent="build-info" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="NSIS Installer
• Windows installer creation
• Desktop shortcuts
• Start menu integration
• Uninstaller generation" vertex="1">
<mxGeometry height="65" width="380" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="dist-info" parent="build-info" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="Distribution Package
• Single .exe installer
• Embedded backend.exe (19.4 MB)
• Self-contained runtime
• No external dependencies" vertex="1">
<mxGeometry height="65" width="380" x="10" y="100" as="geometry" />
</mxCell>
<mxCell id="dev-tools" parent="frontend-components" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="DEVELOPMENT TOOLS" vertex="1">
<mxGeometry height="180" width="400" y="30" as="geometry" />
</mxCell>
<mxCell id="eslint-info" parent="dev-tools" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="ESLint (@eslint/js@9.39.1)
• Code quality
• React hooks plugin
• React refresh plugin" vertex="1">
<mxGeometry height="50" width="380" x="10" y="30" as="geometry" />
</mxCell>
<mxCell id="go-info" parent="dev-tools" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#e1d5e7;strokeColor=#9673a6;fontColor=#000000;" value="Go 1.26.0
• Cross-compilation
• Fast compilation
• Static binary output" vertex="1">
<mxGeometry height="50" width="380" x="10" y="85" as="geometry" />
</mxCell>
<mxCell id="ports-info" parent="frontend-components" style="swimlane;whiteSpace=wrap;html=1;fontSize=12;fontStyle=1;fillColor=#fff2cc;strokeColor=#d6b656;fontColor=#000000;" value="PORT CONFIGURATION" vertex="1">
<mxGeometry height="180" width="400" x="440" y="30" as="geometry">
<mxRectangle height="30" width="180" x="2670" y="950" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="ports-detail" parent="ports-info" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#000000;" value="Port Allocation:

• 5173 — Vite Dev Server (development only)
• 8082 — Go Backend REST API
• 5000 — Calliope Runner Service (FastAPI)
• 8080 — GeoServer (Docker, user-facing)
• 8081 — GeoServer (Go backend config.yaml)
• 8000 — OEO Tech Database API (optional)
• 8765 — H₂ Plant Simulation Service (optional)
• 8766 — CCS Simulation Service (optional)

Protocols:
• HTTP/REST (JSON) — all services
• SSE — calliope log streaming
• WebSocket — H₂/CCS real-time telemetry" vertex="1">
<mxGeometry height="135" width="380" x="10" y="30" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>