jsgui3-server 0.0.140 → 0.0.142

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/.github/agents/jsgui3-server.agent.md +699 -0
  2. package/.github/instructions/copilot.instructions.md +180 -0
  3. package/.playwright-mcp/page-2025-11-29T23-39-18-629Z.png +0 -0
  4. package/.playwright-mcp/page-2025-11-29T23-39-31-903Z.png +0 -0
  5. package/.playwright-mcp/page-2025-11-30T00-33-56-265Z.png +0 -0
  6. package/.playwright-mcp/page-2025-11-30T00-34-06-619Z.png +0 -0
  7. package/docs/agent-development-guide.md +108 -4
  8. package/docs/api-reference.md +116 -0
  9. package/docs/controls-development.md +127 -0
  10. package/docs/css/luxuryObsidianCss.js +1203 -0
  11. package/docs/css/obsidian-scrollbars.css +370 -0
  12. package/docs/diagrams/jsgui3-stack.svg +568 -0
  13. package/docs/guides/JSGUI3_UI_ARCHITECTURE_GUIDE.md +2527 -0
  14. package/docs/guides/OBSIDIAN_LUXURY_DESIGN_GUIDE.md +847 -0
  15. package/docs/jsgui3-vs-express-comparison.svg +542 -0
  16. package/docs/jsgui3-vs-nestjs-comparison.svg +550 -0
  17. package/docs/publishers-guide.md +76 -0
  18. package/docs/troubleshooting.md +51 -0
  19. package/examples/controls/15) window, observable SSE/README.md +125 -0
  20. package/examples/controls/15) window, observable SSE/check.js +144 -0
  21. package/examples/controls/15) window, observable SSE/client.js +395 -0
  22. package/examples/controls/15) window, observable SSE/server.js +111 -0
  23. package/http/responders/static/Static_Route_HTTP_Responder.js +16 -16
  24. package/module.js +7 -0
  25. package/package.json +9 -8
  26. package/port-utils.js +112 -0
  27. package/serve-factory.js +27 -5
  28. package/tests/README.md +40 -26
  29. package/tests/examples-controls.e2e.test.js +164 -0
  30. package/tests/observable-sse.test.js +363 -0
  31. package/tests/port-utils.test.js +114 -0
  32. package/tests/test-runner.js +13 -12
@@ -0,0 +1,542 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1400 2100" width="1400" height="2100">
3
+ <defs>
4
+ <!-- Industrial Luxury Obsidian Gradients -->
5
+ <linearGradient id="obsidianBg" x1="0%" y1="0%" x2="100%" y2="100%">
6
+ <stop offset="0%" style="stop-color:#050508"/>
7
+ <stop offset="25%" style="stop-color:#0a0d14"/>
8
+ <stop offset="50%" style="stop-color:#0f1420"/>
9
+ <stop offset="75%" style="stop-color:#0a0d14"/>
10
+ <stop offset="100%" style="stop-color:#050508"/>
11
+ </linearGradient>
12
+
13
+ <linearGradient id="goldTitle" x1="0%" y1="0%" x2="100%" y2="0%">
14
+ <stop offset="0%" style="stop-color:#8b7500"/>
15
+ <stop offset="30%" style="stop-color:#ffd700"/>
16
+ <stop offset="50%" style="stop-color:#fffacd"/>
17
+ <stop offset="70%" style="stop-color:#ffd700"/>
18
+ <stop offset="100%" style="stop-color:#8b7500"/>
19
+ </linearGradient>
20
+
21
+ <linearGradient id="cardGradient" x1="0%" y1="0%" x2="0%" y2="100%">
22
+ <stop offset="0%" style="stop-color:#1a1f2e"/>
23
+ <stop offset="50%" style="stop-color:#141824"/>
24
+ <stop offset="100%" style="stop-color:#0f1420"/>
25
+ </linearGradient>
26
+
27
+ <linearGradient id="headerGradient" x1="0%" y1="0%" x2="100%" y2="0%">
28
+ <stop offset="0%" style="stop-color:#0f1420"/>
29
+ <stop offset="50%" style="stop-color:#1a1f2e"/>
30
+ <stop offset="100%" style="stop-color:#0f1420"/>
31
+ </linearGradient>
32
+
33
+ <linearGradient id="goldAccent" x1="0%" y1="0%" x2="100%" y2="0%">
34
+ <stop offset="0%" style="stop-color:transparent"/>
35
+ <stop offset="20%" style="stop-color:#8b7500"/>
36
+ <stop offset="50%" style="stop-color:#c9a227"/>
37
+ <stop offset="80%" style="stop-color:#8b7500"/>
38
+ <stop offset="100%" style="stop-color:transparent"/>
39
+ </linearGradient>
40
+
41
+ <linearGradient id="goldButton" x1="0%" y1="0%" x2="0%" y2="100%">
42
+ <stop offset="0%" style="stop-color:#c9a227"/>
43
+ <stop offset="100%" style="stop-color:#b8960f"/>
44
+ </linearGradient>
45
+
46
+ <!-- Filters for glow effects -->
47
+ <filter id="goldGlow" x="-50%" y="-50%" width="200%" height="200%">
48
+ <feGaussianBlur stdDeviation="3" result="blur"/>
49
+ <feMerge>
50
+ <feMergeNode in="blur"/>
51
+ <feMergeNode in="SourceGraphic"/>
52
+ </feMerge>
53
+ </filter>
54
+
55
+ <filter id="softShadow" x="-20%" y="-20%" width="140%" height="140%">
56
+ <feDropShadow dx="0" dy="4" stdDeviation="10" flood-color="#000000" flood-opacity="0.5"/>
57
+ </filter>
58
+
59
+ <!-- Pattern for subtle grid -->
60
+ <pattern id="gridPattern" width="80" height="80" patternUnits="userSpaceOnUse">
61
+ <path d="M 80 0 L 0 0 0 80" fill="none" stroke="rgba(201,162,39,0.03)" stroke-width="1"/>
62
+ </pattern>
63
+
64
+ <!-- Diagonal hatch pattern -->
65
+ <pattern id="hatchPattern" width="16" height="16" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
66
+ <line x1="0" y1="0" x2="0" y2="16" stroke="rgba(201,162,39,0.02)" stroke-width="1"/>
67
+ </pattern>
68
+ </defs>
69
+
70
+ <!-- ═══════════════════════════════════════════════════════════════════════════════
71
+ BACKGROUND LAYERS
72
+ ═══════════════════════════════════════════════════════════════════════════════ -->
73
+ <rect width="1400" height="2100" fill="url(#obsidianBg)"/>
74
+ <rect width="1400" height="2100" fill="url(#gridPattern)"/>
75
+ <rect width="1400" height="2100" fill="url(#hatchPattern)"/>
76
+
77
+ <!-- Corner flourishes -->
78
+ <ellipse cx="0" cy="0" rx="150" ry="150" fill="radial-gradient(ellipse at 0% 0%, #8b7500 0%, transparent 70%)" opacity="0.25"/>
79
+ <ellipse cx="1400" cy="0" rx="150" ry="150" fill="radial-gradient(ellipse at 100% 0%, #8b7500 0%, transparent 70%)" opacity="0.25"/>
80
+ <ellipse cx="0" cy="2100" rx="150" ry="150" fill="radial-gradient(ellipse at 0% 100%, #8b7500 0%, transparent 70%)" opacity="0.25"/>
81
+ <ellipse cx="1400" cy="2100" rx="150" ry="150" fill="radial-gradient(ellipse at 100% 100%, #8b7500 0%, transparent 70%)" opacity="0.25"/>
82
+
83
+ <!-- ═══════════════════════════════════════════════════════════════════════════════
84
+ HERO SECTION
85
+ ═══════════════════════════════════════════════════════════════════════════════ -->
86
+
87
+ <!-- Hero glow -->
88
+ <ellipse cx="700" cy="100" rx="400" ry="120" fill="rgba(201,162,39,0.12)"/>
89
+
90
+ <!-- Diamond icon -->
91
+ <text x="700" y="70" text-anchor="middle" font-size="40" fill="#c9a227" filter="url(#goldGlow)">◆</text>
92
+
93
+ <!-- Main title -->
94
+ <text x="700" y="130" text-anchor="middle" font-family="Georgia, 'Playfair Display', serif" font-size="48" font-weight="700" fill="url(#goldTitle)" filter="url(#goldGlow)">
95
+ JSGUI3 Server vs Express
96
+ </text>
97
+
98
+ <!-- Subtitle -->
99
+ <text x="700" y="165" text-anchor="middle" font-family="Inter, system-ui, sans-serif" font-size="14" fill="#94a3b8" letter-spacing="3">
100
+ FULL-STACK FRAMEWORK VS MINIMAL HTTP LIBRARY
101
+ </text>
102
+
103
+ <!-- Decorative line under title -->
104
+ <line x1="200" y1="195" x2="1200" y2="195" stroke="url(#goldAccent)" stroke-width="1" opacity="0.6"/>
105
+
106
+ <!-- ═══════════════════════════════════════════════════════════════════════════════
107
+ STAT CARDS
108
+ ═══════════════════════════════════════════════════════════════════════════════ -->
109
+ <g transform="translate(60, 230)">
110
+ <!-- JSGUI3 Stat Card -->
111
+ <g filter="url(#softShadow)">
112
+ <rect x="0" y="0" width="280" height="100" rx="10" fill="url(#cardGradient)" stroke="#334155"/>
113
+ <rect x="0" y="0" width="280" height="3" rx="2" fill="#50c878"/>
114
+ <text x="140" y="50" text-anchor="middle" font-family="Georgia, serif" font-size="28" font-weight="700" fill="#50c878">Full-Stack</text>
115
+ <text x="140" y="75" text-anchor="middle" font-family="Inter, sans-serif" font-size="11" fill="#64748b" text-transform="uppercase" letter-spacing="1">JSGUI3 PHILOSOPHY</text>
116
+ </g>
117
+
118
+ <!-- Express Stat Card -->
119
+ <g transform="translate(320, 0)" filter="url(#softShadow)">
120
+ <rect x="0" y="0" width="280" height="100" rx="10" fill="url(#cardGradient)" stroke="#334155"/>
121
+ <rect x="0" y="0" width="280" height="3" rx="2" fill="#64748b"/>
122
+ <text x="140" y="50" text-anchor="middle" font-family="Georgia, serif" font-size="28" font-weight="700" fill="#94a3b8">Minimal</text>
123
+ <text x="140" y="75" text-anchor="middle" font-family="Inter, sans-serif" font-size="11" fill="#64748b" text-transform="uppercase" letter-spacing="1">EXPRESS PHILOSOPHY</text>
124
+ </g>
125
+
126
+ <!-- Built-in Features Card -->
127
+ <g transform="translate(640, 0)" filter="url(#softShadow)">
128
+ <rect x="0" y="0" width="280" height="100" rx="10" fill="url(#cardGradient)" stroke="#334155"/>
129
+ <rect x="0" y="0" width="280" height="3" rx="2" fill="#da70d6"/>
130
+ <text x="140" y="50" text-anchor="middle" font-family="Georgia, serif" font-size="28" font-weight="700" fill="#da70d6">Batteries</text>
131
+ <text x="140" y="75" text-anchor="middle" font-family="Inter, sans-serif" font-size="11" fill="#64748b" text-transform="uppercase" letter-spacing="1">JSGUI3 INCLUDED</text>
132
+ </g>
133
+
134
+ <!-- Express Ecosystem Card -->
135
+ <g transform="translate(960, 0)" filter="url(#softShadow)">
136
+ <rect x="0" y="0" width="280" height="100" rx="10" fill="url(#cardGradient)" stroke="#334155"/>
137
+ <rect x="0" y="0" width="280" height="3" rx="2" fill="#ffc87c"/>
138
+ <text x="140" y="50" text-anchor="middle" font-family="Georgia, serif" font-size="28" font-weight="700" fill="#ffc87c">50K+</text>
139
+ <text x="140" y="75" text-anchor="middle" font-family="Inter, sans-serif" font-size="11" fill="#64748b" text-transform="uppercase" letter-spacing="1">EXPRESS MIDDLEWARE</text>
140
+ </g>
141
+ </g>
142
+
143
+ <!-- ═══════════════════════════════════════════════════════════════════════════════
144
+ MAIN COMPARISON PANEL
145
+ ═══════════════════════════════════════════════════════════════════════════════ -->
146
+ <g transform="translate(60, 370)" filter="url(#softShadow)">
147
+ <!-- Panel background -->
148
+ <rect x="0" y="0" width="1280" height="1650" rx="16" fill="url(#cardGradient)" stroke="#334155" stroke-width="2"/>
149
+
150
+ <!-- Panel gold border accent -->
151
+ <rect x="2" y="2" width="1276" height="1646" rx="14" fill="none" stroke="url(#goldAccent)" stroke-width="1" opacity="0.4"/>
152
+
153
+ <!-- Panel header -->
154
+ <rect x="0" y="0" width="1280" height="60" rx="16" fill="url(#headerGradient)"/>
155
+ <rect x="0" y="56" width="1280" height="4" fill="#0f1420"/>
156
+ <line x1="0" y1="60" x2="1280" y2="60" stroke="url(#goldAccent)" stroke-width="1" opacity="0.6"/>
157
+
158
+ <!-- Header title -->
159
+ <text x="40" y="38" font-family="Georgia, serif" font-size="18" font-weight="600" fill="#c9a227">◆</text>
160
+ <text x="70" y="38" font-family="Georgia, serif" font-size="18" font-weight="600" fill="#c9a227">Feature Comparison Matrix</text>
161
+ <text x="60" y="38" font-family="Georgia, serif" font-size="10" fill="#c9a227" opacity="0.6">◆</text>
162
+ <text x="340" y="38" font-family="Georgia, serif" font-size="10" fill="#c9a227" opacity="0.6">◆</text>
163
+
164
+ <!-- Column headers -->
165
+ <rect x="0" y="60" width="1280" height="50" fill="#0a0d14"/>
166
+ <line x1="0" y1="110" x2="1280" y2="110" stroke="#334155"/>
167
+
168
+ <text x="200" y="92" text-anchor="middle" font-family="Inter, sans-serif" font-size="11" font-weight="600" fill="#c9a227" letter-spacing="1">FEATURE CATEGORY</text>
169
+ <text x="540" y="92" text-anchor="middle" font-family="Inter, sans-serif" font-size="11" font-weight="600" fill="#c9a227" letter-spacing="1">JSGUI3 SERVER</text>
170
+ <text x="940" y="92" text-anchor="middle" font-family="Inter, sans-serif" font-size="11" font-weight="600" fill="#c9a227" letter-spacing="1">EXPRESS.JS</text>
171
+
172
+ <!-- Vertical dividers -->
173
+ <line x1="380" y1="60" x2="380" y2="1650" stroke="#334155" stroke-dasharray="4,4" opacity="0.5"/>
174
+ <line x1="740" y1="60" x2="740" y2="1650" stroke="#334155" stroke-dasharray="4,4" opacity="0.5"/>
175
+ <line x1="1140" y1="60" x2="1140" y2="1650" stroke="#334155" stroke-dasharray="4,4" opacity="0.5"/>
176
+
177
+ <!-- ═══════════════════════════════════════════════════════════════════════════════
178
+ CORE PHILOSOPHY SECTION
179
+ ═══════════════════════════════════════════════════════════════════════════════ -->
180
+ <g transform="translate(0, 130)">
181
+ <rect x="20" y="0" width="1240" height="30" rx="4" fill="rgba(201,162,39,0.08)"/>
182
+ <text x="40" y="20" font-family="Georgia, serif" font-size="14" font-weight="600" fill="#c9a227">CORE PHILOSOPHY &amp; DESIGN</text>
183
+ </g>
184
+
185
+ <!-- Row 1: Design Philosophy -->
186
+ <g transform="translate(0, 175)">
187
+ <rect x="0" y="0" width="1280" height="55" fill="transparent"/>
188
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
189
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">Design Philosophy</text>
190
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">Fundamental approach to development</text>
191
+
192
+ <!-- JSGUI3 -->
193
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
194
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">Opinionated Full-Stack Framework</text>
195
+
196
+ <!-- Express -->
197
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(148,163,184,0.1)" stroke="#475569"/>
198
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#94a3b8">Minimal Unopinionated HTTP Layer</text>
199
+ </g>
200
+
201
+ <!-- Row 2: Primary Purpose -->
202
+ <g transform="translate(0, 230)">
203
+ <rect x="0" y="0" width="1280" height="55" fill="rgba(26,31,46,0.3)"/>
204
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
205
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">Primary Purpose</text>
206
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">What it's designed to do</text>
207
+
208
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
209
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">Serve Complete GUI Applications</text>
210
+
211
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(148,163,184,0.1)" stroke="#475569"/>
212
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#94a3b8">Handle HTTP Requests/Responses</text>
213
+ </g>
214
+
215
+ <!-- Row 3: Learning Curve -->
216
+ <g transform="translate(0, 285)">
217
+ <rect x="0" y="0" width="1280" height="55" fill="transparent"/>
218
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
219
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">Learning Curve</text>
220
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">Time to productivity</text>
221
+
222
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(255,159,0,0.1)" stroke="#cc7000"/>
223
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#ffc87c">Steeper (More Concepts)</text>
224
+
225
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
226
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">Gentle (Simple API)</text>
227
+ </g>
228
+
229
+ <!-- Row 4: Architecture -->
230
+ <g transform="translate(0, 340)">
231
+ <rect x="0" y="0" width="1280" height="55" fill="rgba(26,31,46,0.3)"/>
232
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
233
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">Architecture Pattern</text>
234
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">Structural organization</text>
235
+
236
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
237
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">Publisher + Resource + Control</text>
238
+
239
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(148,163,184,0.1)" stroke="#475569"/>
240
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#94a3b8">Route → Middleware → Handler</text>
241
+ </g>
242
+
243
+ <!-- ═══════════════════════════════════════════════════════════════════════════════
244
+ BUILT-IN FEATURES SECTION (JSGUI3 ADVANTAGES)
245
+ ═══════════════════════════════════════════════════════════════════════════════ -->
246
+ <g transform="translate(0, 415)">
247
+ <rect x="20" y="0" width="1240" height="30" rx="4" fill="rgba(80,200,120,0.08)"/>
248
+ <text x="40" y="20" font-family="Georgia, serif" font-size="14" font-weight="600" fill="#50c878">BUILT-IN FEATURES (JSGUI3 Advantages)</text>
249
+ </g>
250
+
251
+ <!-- Row 5: UI Components -->
252
+ <g transform="translate(0, 460)">
253
+ <rect x="0" y="0" width="1280" height="55" fill="transparent"/>
254
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
255
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">UI Component System</text>
256
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">Windows, Panels, Buttons, etc.</text>
257
+
258
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
259
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ Full Control Library</text>
260
+
261
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(255,107,107,0.1)" stroke="#8b0000"/>
262
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#ff6b6b">✗ Not Included</text>
263
+ </g>
264
+
265
+ <!-- Row 6: JS/CSS Bundling -->
266
+ <g transform="translate(0, 515)">
267
+ <rect x="0" y="0" width="1280" height="55" fill="rgba(26,31,46,0.3)"/>
268
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
269
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">JS/CSS Bundling</text>
270
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">Asset compilation with ESBuild</text>
271
+
272
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
273
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ Built-in ESBuild</text>
274
+
275
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(255,107,107,0.1)" stroke="#8b0000"/>
276
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#ff6b6b">✗ Requires Webpack/Vite/etc.</text>
277
+ </g>
278
+
279
+ <!-- Row 7: HTML Generation -->
280
+ <g transform="translate(0, 570)">
281
+ <rect x="0" y="0" width="1280" height="55" fill="transparent"/>
282
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
283
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">Server-Side HTML Rendering</text>
284
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">Generate pages from components</text>
285
+
286
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
287
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ Active_HTML_Document</text>
288
+
289
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(255,159,0,0.1)" stroke="#cc7000"/>
290
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#ffc87c">~ res.render() + Template Engine</text>
291
+ </g>
292
+
293
+ <!-- Row 8: Data Binding -->
294
+ <g transform="translate(0, 625)">
295
+ <rect x="0" y="0" width="1280" height="55" fill="rgba(26,31,46,0.3)"/>
296
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
297
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">Reactive Data Binding</text>
298
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">Observable Data_Object system</text>
299
+
300
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
301
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ field() Observables</text>
302
+
303
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(255,107,107,0.1)" stroke="#8b0000"/>
304
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#ff6b6b">✗ Not Applicable</text>
305
+ </g>
306
+
307
+ <!-- Row 9: Content Type Publishers -->
308
+ <g transform="translate(0, 680)">
309
+ <rect x="0" y="0" width="1280" height="55" fill="transparent"/>
310
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
311
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">Content Type Publishers</text>
312
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">Webpage, CSS, JS, Image, SVG, etc.</text>
313
+
314
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
315
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ 14+ Specialized Publishers</text>
316
+
317
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(255,159,0,0.1)" stroke="#cc7000"/>
318
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#ffc87c">~ express.static() Only</text>
319
+ </g>
320
+
321
+ <!-- Row 10: Function Publishing -->
322
+ <g transform="translate(0, 735)">
323
+ <rect x="0" y="0" width="1280" height="55" fill="rgba(26,31,46,0.3)"/>
324
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
325
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">Function → API Endpoint</text>
326
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">Auto JSON serialization</text>
327
+
328
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
329
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ server.publish('name', fn)</text>
330
+
331
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(255,159,0,0.1)" stroke="#cc7000"/>
332
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#ffc87c">~ Manual res.json() Required</text>
333
+ </g>
334
+
335
+ <!-- Row 11: Resource Pool -->
336
+ <g transform="translate(0, 790)">
337
+ <rect x="0" y="0" width="1280" height="55" fill="transparent"/>
338
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
339
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">Resource Pool Management</text>
340
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">Lifecycle &amp; access control</text>
341
+
342
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
343
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ Server_Resource_Pool</text>
344
+
345
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(255,107,107,0.1)" stroke="#8b0000"/>
346
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#ff6b6b">✗ Manual Implementation</text>
347
+ </g>
348
+
349
+ <!-- ═══════════════════════════════════════════════════════════════════════════════
350
+ EXPRESS STRENGTHS SECTION
351
+ ═══════════════════════════════════════════════════════════════════════════════ -->
352
+ <g transform="translate(0, 865)">
353
+ <rect x="20" y="0" width="1240" height="30" rx="4" fill="rgba(148,163,184,0.08)"/>
354
+ <text x="40" y="20" font-family="Georgia, serif" font-size="14" font-weight="600" fill="#94a3b8">EXPRESS STRENGTHS</text>
355
+ </g>
356
+
357
+ <!-- Row 12: Ecosystem -->
358
+ <g transform="translate(0, 910)">
359
+ <rect x="0" y="0" width="1280" height="55" fill="transparent"/>
360
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
361
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">Middleware Ecosystem</text>
362
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">Third-party packages available</text>
363
+
364
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(255,159,0,0.1)" stroke="#cc7000"/>
365
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#ffc87c">Limited (Built-in focused)</text>
366
+
367
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
368
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ 50,000+ npm Middleware</text>
369
+ </g>
370
+
371
+ <!-- Row 13: Community -->
372
+ <g transform="translate(0, 965)">
373
+ <rect x="0" y="0" width="1280" height="55" fill="rgba(26,31,46,0.3)"/>
374
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
375
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">Community Size</text>
376
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">Documentation &amp; support</text>
377
+
378
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(255,159,0,0.1)" stroke="#cc7000"/>
379
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#ffc87c">Niche (Specialized)</text>
380
+
381
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
382
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ Massive (Industry Standard)</text>
383
+ </g>
384
+
385
+ <!-- Row 14: Flexibility -->
386
+ <g transform="translate(0, 1020)">
387
+ <rect x="0" y="0" width="1280" height="55" fill="transparent"/>
388
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
389
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">Architecture Flexibility</text>
390
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">Freedom in structuring code</text>
391
+
392
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(255,159,0,0.1)" stroke="#cc7000"/>
393
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#ffc87c">Convention-based Structure</text>
394
+
395
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
396
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ Complete Freedom</text>
397
+ </g>
398
+
399
+ <!-- Row 15: Bundle Size -->
400
+ <g transform="translate(0, 1075)">
401
+ <rect x="0" y="0" width="1280" height="55" fill="rgba(26,31,46,0.3)"/>
402
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
403
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">Package Size</text>
404
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">Dependencies footprint</text>
405
+
406
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(255,159,0,0.1)" stroke="#cc7000"/>
407
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#ffc87c">Larger (Full Framework)</text>
408
+
409
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
410
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ Tiny (~200KB)</text>
411
+ </g>
412
+
413
+ <!-- ═══════════════════════════════════════════════════════════════════════════════
414
+ COMMON GROUND SECTION
415
+ ═══════════════════════════════════════════════════════════════════════════════ -->
416
+ <g transform="translate(0, 1150)">
417
+ <rect x="20" y="0" width="1240" height="30" rx="4" fill="rgba(111,168,220,0.08)"/>
418
+ <text x="40" y="20" font-family="Georgia, serif" font-size="14" font-weight="600" fill="#6fa8dc">COMMON CAPABILITIES</text>
419
+ </g>
420
+
421
+ <!-- Row 16: Routing -->
422
+ <g transform="translate(0, 1195)">
423
+ <rect x="0" y="0" width="1280" height="55" fill="transparent"/>
424
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
425
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">HTTP Routing</text>
426
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">URL path handling</text>
427
+
428
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
429
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ Router + set_route()</text>
430
+
431
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
432
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ app.get/post/put/delete()</text>
433
+ </g>
434
+
435
+ <!-- Row 17: Middleware -->
436
+ <g transform="translate(0, 1250)">
437
+ <rect x="0" y="0" width="1280" height="55" fill="rgba(26,31,46,0.3)"/>
438
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
439
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">Request Processing</text>
440
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">Pre/post request handling</text>
441
+
442
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
443
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ Router.process()</text>
444
+
445
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
446
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ app.use() Middleware</text>
447
+ </g>
448
+
449
+ <!-- Row 18: Static Files -->
450
+ <g transform="translate(0, 1305)">
451
+ <rect x="0" y="0" width="1280" height="55" fill="transparent"/>
452
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
453
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">Static File Serving</text>
454
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">Serve assets from disk</text>
455
+
456
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
457
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ Multiple Publishers</text>
458
+
459
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
460
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ express.static()</text>
461
+ </g>
462
+
463
+ <!-- Row 19: HTTPS -->
464
+ <g transform="translate(0, 1360)">
465
+ <rect x="0" y="0" width="1280" height="55" fill="rgba(26,31,46,0.3)"/>
466
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
467
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">HTTPS Support</text>
468
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">TLS encryption</text>
469
+
470
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
471
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ https_options Config</text>
472
+
473
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
474
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ https.createServer()</text>
475
+ </g>
476
+
477
+ <!-- Row 20: JSON APIs -->
478
+ <g transform="translate(0, 1415)">
479
+ <rect x="0" y="0" width="1280" height="55" fill="transparent"/>
480
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
481
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">JSON API Creation</text>
482
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">RESTful endpoints</text>
483
+
484
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
485
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ Function Publishers</text>
486
+
487
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
488
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ res.json()</text>
489
+ </g>
490
+
491
+ <!-- Row 21: Error Handling -->
492
+ <g transform="translate(0, 1470)">
493
+ <rect x="0" y="0" width="1280" height="55" fill="rgba(26,31,46,0.3)"/>
494
+ <rect x="0" y="54" width="1280" height="1" fill="#334155" opacity="0.3"/>
495
+ <text x="40" y="25" font-family="Inter, sans-serif" font-size="13" fill="#cbd5e1">Error Handling</text>
496
+ <text x="40" y="42" font-family="Inter, sans-serif" font-size="10" fill="#64748b">Graceful error responses</text>
497
+
498
+ <rect x="400" y="10" width="280" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
499
+ <text x="540" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ Built-in 404/500</text>
500
+
501
+ <rect x="760" y="10" width="360" height="35" rx="4" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
502
+ <text x="940" y="33" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" fill="#50c878">✓ Error Middleware</text>
503
+ </g>
504
+
505
+ <!-- ═══════════════════════════════════════════════════════════════════════════════
506
+ LEGEND
507
+ ═══════════════════════════════════════════════════════════════════════════════ -->
508
+ <g transform="translate(0, 1555)">
509
+ <rect x="20" y="0" width="1240" height="80" rx="8" fill="#0a0d14"/>
510
+ <text x="640" y="25" text-anchor="middle" font-family="Georgia, serif" font-size="12" fill="#64748b" letter-spacing="2">LEGEND</text>
511
+
512
+ <!-- Strong -->
513
+ <rect x="120" y="45" width="16" height="16" rx="3" fill="rgba(80,200,120,0.1)" stroke="#2e8b57"/>
514
+ <text x="145" y="57" font-family="Inter, sans-serif" font-size="11" fill="#50c878">Strong/Native Support</text>
515
+
516
+ <!-- Partial -->
517
+ <rect x="420" y="45" width="16" height="16" rx="3" fill="rgba(255,159,0,0.1)" stroke="#cc7000"/>
518
+ <text x="445" y="57" font-family="Inter, sans-serif" font-size="11" fill="#ffc87c">Partial/Basic Support</text>
519
+
520
+ <!-- Not Available -->
521
+ <rect x="720" y="45" width="16" height="16" rx="3" fill="rgba(255,107,107,0.1)" stroke="#8b0000"/>
522
+ <text x="745" y="57" font-family="Inter, sans-serif" font-size="11" fill="#ff6b6b">Not Available</text>
523
+
524
+ <!-- Different Approach -->
525
+ <rect x="1020" y="45" width="16" height="16" rx="3" fill="rgba(148,163,184,0.1)" stroke="#475569"/>
526
+ <text x="1045" y="57" font-family="Inter, sans-serif" font-size="11" fill="#94a3b8">Different Approach</text>
527
+ </g>
528
+ </g>
529
+
530
+ <!-- ═══════════════════════════════════════════════════════════════════════════════
531
+ FOOTER
532
+ ═══════════════════════════════════════════════════════════════════════════════ -->
533
+ <g transform="translate(0, 2040)">
534
+ <line x1="60" y1="0" x2="1340" y2="0" stroke="#334155"/>
535
+ <text x="700" y="35" text-anchor="middle" font-family="Inter, sans-serif" font-size="11" fill="#64748b">
536
+ JSGUI3 Server v0.0.140 | Industrial Luxury Obsidian Theme | Generated November 2025
537
+ </text>
538
+ <text x="700" y="52" text-anchor="middle" font-family="Inter, sans-serif" font-size="10" fill="#475569">
539
+ JSGUI3: Full-stack GUI framework with batteries included • Express: Minimal HTTP foundation to build upon
540
+ </text>
541
+ </g>
542
+ </svg>