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,699 @@
1
+ # jsgui3-server Agent Instructions
2
+
3
+ **Purpose**: Agent guidance for working on the jsgui3-server codebase - the ES6 JSGUI server that delivers controls to the browser.
4
+
5
+ **Core Principle**: jsgui3-server bundles and serves jsgui3 controls, handling JavaScript bundling (ESBuild), CSS extraction, and HTTP publishing. All UI controls inherit from `Active_HTML_Document` and run isomorphically (server-rendered, client-activated).
6
+
7
+ ---
8
+
9
+ ## ⚠️ CRITICAL: Understand the Full Stack
10
+
11
+ **You cannot effectively work on jsgui3-server without understanding the JSGUI3 ecosystem.** This server is the delivery mechanism for a multi-package framework. Changes here often involve understanding behavior defined in dependent packages.
12
+
13
+ ### The JSGUI3 Package Ecosystem
14
+
15
+ ```
16
+ ┌─────────────────────────────────────────────────────────────────┐
17
+ │ YOUR APPLICATION │
18
+ │ (client.js with your Custom_Control class) │
19
+ └─────────────────────────────────────────────────────────────────┘
20
+
21
+
22
+ ┌─────────────────────────────────────────────────────────────────┐
23
+ │ jsgui3-server (THIS REPO) │
24
+ │ • HTTP server, routing, publishers │
25
+ │ • ESBuild bundling of client JS │
26
+ │ • CSS extraction from control classes │
27
+ │ • Server-side rendering → client activation │
28
+ └─────────────────────────────────────────────────────────────────┘
29
+ │ │ │ │
30
+ ▼ ▼ ▼ ▼
31
+ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
32
+ │jsgui3-client│ │ jsgui3-html │ │jsgui3-webpage│ │jsgui3-website│
33
+ │ │ │ │ │ │ │ │
34
+ │ Browser DOM │ │HTML element │ │ Single page │ │ Multi-page │
35
+ │ abstraction │ │ classes │ │ abstraction │ │ site model │
36
+ │ & controls │ │ (div, span) │ │ │ │ │
37
+ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
38
+ │ │
39
+ ▼ ▼
40
+ ┌─────────────────────────────────┐
41
+ │ obext │
42
+ │ Observable data objects with │
43
+ │ field() reactive properties │
44
+ │ (Data_Object, Data_Value) │
45
+ └─────────────────────────────────┘
46
+ ```
47
+
48
+ ### Package Responsibilities
49
+
50
+ | Package | Version | Role | Key Classes/Exports |
51
+ |---------|---------|------|---------------------|
52
+ | **jsgui3-server** | 0.0.140 | HTTP delivery, bundling | `Server`, `serve()`, Publishers |
53
+ | **jsgui3-client** | 0.0.120 | Browser-side control system | `Control`, DOM abstractions |
54
+ | **jsgui3-html** | 0.0.170 | HTML element hierarchy | `div`, `span`, `button`, `input`, etc. |
55
+ | **jsgui3-webpage** | 0.0.8 | Single page model | `Webpage` |
56
+ | **jsgui3-website** | 0.0.8 | Multi-page site model | `Website` |
57
+ | **obext** | 0.0.31 | Reactive data binding | `Data_Object`, `Data_Value`, `field()` |
58
+ | **lang-tools** | 0.0.41 | Type checking utilities | `tof()`, `get()`, `set()` |
59
+ | **fnl/fnlfs** | 0.0.37/34 | Functional utilities, async FS | Functional patterns |
60
+
61
+ ### Why This Matters
62
+
63
+ 1. **Control classes** (`Active_HTML_Document`) inherit from `jsgui3-client`, not this repo
64
+ 2. **HTML elements** (`this.body.add.div()`) come from `jsgui3-html`
65
+ 3. **Data binding** (`field()`, `Data_Object`) comes from `obext`
66
+ 4. **The `context` object** is created by `jsgui3-client` and flows through everything
67
+ 5. **CSS extraction** looks for static `.css` properties defined by `jsgui3-client` patterns
68
+
69
+ ### Isomorphic Lifecycle (The Key Concept)
70
+
71
+ ```
72
+ SERVER SIDE CLIENT SIDE
73
+ ─────────── ───────────
74
+ 1. new My_Control(spec)
75
+ └─ compose() builds virtual DOM
76
+
77
+ 2. control.render_html()
78
+ └─ Serializes to HTML string
79
+
80
+ 3. HTTP Response ────────────────────► Browser receives HTML
81
+
82
+ 4. new My_Control({ el: dom_element })
83
+ └─ spec.el present = HYDRATION
84
+ └─ compose() SKIPPED (if (!spec.el))
85
+
86
+ 5. control.activate()
87
+ └─ Binds events to real DOM
88
+ └─ Runs client-only code
89
+ ```
90
+
91
+ **This is why `if (!spec.el) { compose(); }` is mandatory** — without it, content duplicates on activation.
92
+
93
+ ---
94
+
95
+ ## ⚡ Quick Start (30 seconds)
96
+
97
+ ```bash
98
+ # Run any example:
99
+ cd "examples/controls/1) window"
100
+ node server.js
101
+ # → Open http://localhost:52000
102
+
103
+ # Run tests:
104
+ npm test # All tests
105
+ npm run test:mocha # Mocha tests
106
+ npm run test:bundlers # Bundler tests only
107
+ npm run test:publishers # Publisher tests
108
+
109
+ # CLI (defaults to port 8080):
110
+ node cli.js serve --port 8080
111
+ ```
112
+
113
+ ### Auto-Port Selection
114
+
115
+ The server supports automatic free port selection to avoid conflicts:
116
+
117
+ ```javascript
118
+ // Using Server.serve() with auto port
119
+ Server.serve({
120
+ Ctrl: My_Control,
121
+ src_path_client_js,
122
+ port: 'auto' // Auto-select a free port
123
+ });
124
+
125
+ // Or port: 0 for OS-assigned port
126
+ Server.serve({ Ctrl, port: 0 });
127
+
128
+ // Port utilities available directly
129
+ const { get_free_port, is_port_available } = require('jsgui3-server');
130
+ const port = await get_free_port();
131
+ ```
132
+
133
+ ---
134
+
135
+ ## 🏗️ Architecture at a Glance
136
+
137
+ ```
138
+ Server.serve({ Ctrl, src_path_client_js })
139
+
140
+
141
+ ┌─────────────────────────────────────────┐
142
+ │ JSGUI_Single_Process_Server │
143
+ │ │
144
+ │ ┌──────────┐ ┌──────────┐ ┌───────┐ │
145
+ │ │ Bundler │ │ Router │ │ Pool │ │
146
+ │ │ (ESBuild)│ │ (Routes) │ │(Rsrcs)│ │
147
+ │ └────┬─────┘ └────┬─────┘ └───┬───┘ │
148
+ │ │ │ │ │
149
+ │ ▼ ▼ ▼ │
150
+ │ ┌──────────────────────────────────┐ │
151
+ │ │ Publishers │ │
152
+ │ │ • http-webpage-publisher │ │
153
+ │ │ • http-function-publisher │ │
154
+ │ │ • http-website-publisher │ │
155
+ │ │ • http-css-publisher │ │
156
+ │ │ • http-js-publisher │ │
157
+ │ │ • http-html-publisher │ │
158
+ │ │ • http-image (png/jpeg/svg) │ │
159
+ │ │ • + 7 more specialized types │ │
160
+ │ └──────────────────────────────────┘ │
161
+ └─────────────────────────────────────────┘
162
+ ```
163
+
164
+ **Key Files:**
165
+ - `server.js` — `JSGUI_Single_Process_Server` class
166
+ - `serve-factory.js` — `Server.serve()` simplified API
167
+ - `cli.js` — Command-line interface (default port 8080)
168
+ - `publishers/` — HTTP content type handlers (14+ types)
169
+ - `controls/Active_HTML_Document.js` — Base control class
170
+ - `resources/` — Data resource abstractions
171
+
172
+ ---
173
+
174
+ ## 📐 Conventions (MANDATORY)
175
+
176
+ ### Naming
177
+ ```javascript
178
+ // Variables, functions, utilities → snake_case
179
+ const my_variable = 'value';
180
+ function process_data(input) { ... }
181
+
182
+ // Classes and constructors → PascalCase
183
+ class My_Custom_Control extends Active_HTML_Document { ... }
184
+ class HTTP_Function_Publisher extends HTTP_Publisher { ... }
185
+ ```
186
+
187
+ ### Control Pattern (The Canonical Form)
188
+ ```javascript
189
+ class My_Control extends Active_HTML_Document {
190
+ constructor(spec = {}) {
191
+ // 1. Set __type_name BEFORE super()
192
+ spec.__type_name = spec.__type_name || 'my_control';
193
+ super(spec);
194
+
195
+ // 2. Extract context
196
+ const { context } = this;
197
+
198
+ // 3. Define compose() for UI building
199
+ const compose = () => {
200
+ // Build UI here
201
+ const btn = this.body.add.button('Click Me');
202
+ btn.on('click', () => console.log('clicked'));
203
+ };
204
+
205
+ // 4. Conditional compose - only if not hydrating from DOM
206
+ if (!spec.el) { compose(); }
207
+ }
208
+
209
+ activate() {
210
+ // 5. Guard against double activation
211
+ if (!this.__active) {
212
+ super.activate();
213
+ // Event binding, DOM measurements, etc.
214
+ }
215
+ }
216
+ }
217
+
218
+ // 6. CSS as static property
219
+ My_Control.css = `
220
+ .my_control { padding: 16px; }
221
+ .my_control button { cursor: pointer; }
222
+ `;
223
+ ```
224
+
225
+ ### Server Startup Pattern
226
+ ```javascript
227
+ const Server = require('jsgui3-server');
228
+ const My_Control = require('./client.js');
229
+ const src_path_client_js = __dirname + '/client.js';
230
+
231
+ // Simple API (recommended)
232
+ Server.serve({
233
+ Ctrl: My_Control,
234
+ src_path_client_js,
235
+ port: 8080
236
+ }).then(server => {
237
+ console.log(`Server running on port ${server.port}`);
238
+ });
239
+
240
+ // Or with manual control:
241
+ const server = new Server({
242
+ Ctrl: My_Control,
243
+ src_path_client_js
244
+ });
245
+ server.on('ready', () => {
246
+ server.start(8080);
247
+ });
248
+ ```
249
+
250
+ ### Data Binding Pattern
251
+ ```javascript
252
+ const { Data_Object, field } = require('obext');
253
+
254
+ class Counter_Control extends Active_HTML_Document {
255
+ constructor(spec = {}) {
256
+ spec.__type_name = spec.__type_name || 'counter_control';
257
+ super(spec);
258
+
259
+ // Observable data model
260
+ const model = new Data_Object({
261
+ count: field(0)
262
+ });
263
+
264
+ const compose = () => {
265
+ const display = this.body.add.span();
266
+ const btn = this.body.add.button('+');
267
+
268
+ // Reactive binding - updates automatically when count changes
269
+ model.on('change.count', (e) => {
270
+ display.text = `Count: ${e.value}`;
271
+ });
272
+
273
+ btn.on('click', () => {
274
+ model.count++;
275
+ });
276
+
277
+ // Initial render
278
+ display.text = `Count: ${model.count}`;
279
+ };
280
+
281
+ if (!spec.el) { compose(); }
282
+ }
283
+ }
284
+ ```
285
+
286
+ ---
287
+
288
+ ## 🔧 API Endpoints
289
+
290
+ ```javascript
291
+ // In server.js (after server created)
292
+ server.on('ready', () => {
293
+ // Simple function endpoint
294
+ server.publish('/api/status', () => {
295
+ return { status: 'ok', uptime: process.uptime() };
296
+ });
297
+
298
+ // Async endpoint
299
+ server.publish('/api/data', async (req) => {
300
+ const data = await fetch_data();
301
+ return data;
302
+ });
303
+
304
+ server.start(8080);
305
+ });
306
+ ```
307
+
308
+ ---
309
+
310
+ ## ⚠️ Known Issues (Check Before Working)
311
+
312
+ | Issue | Location | Impact |
313
+ |-------|----------|--------|
314
+ | Website publisher incomplete | `publishers/http-website-publisher.js` | Multi-page sites may fail |
315
+ | Multiple "ready" events | `server.js` start() | Race conditions |
316
+ | No default holding page | Server startup | Error on misconfiguration |
317
+ | `/admin` route not wired | Server startup | No admin interface |
318
+ | Inconsistent path naming | Various | `src_path_client_js` vs `disk_path_client_js` |
319
+
320
+ **Always check** `docs/agent-development-guide.md` for the current broken functionality tracker.
321
+
322
+ ---
323
+
324
+ ## 📁 Directory Structure
325
+
326
+ ```
327
+ jsgui3-server/
328
+ ├── server.js # Main server class
329
+ ├── serve-factory.js # Server.serve() API
330
+ ├── cli.js # CLI interface
331
+ ├── module.js # Package entry point
332
+ ├── page-context.js # Server-side page context
333
+ ├── static-page-context.js # Static rendering context
334
+
335
+ ├── controls/ # Built-in controls
336
+ │ ├── Active_HTML_Document.js # Base control class
337
+ │ ├── page/ # Page-specific controls
338
+ │ └── panel/ # Panel controls
339
+
340
+ ├── publishers/ # HTTP content handlers (14+ types)
341
+ │ ├── http-publisher.js # Base class
342
+ │ ├── http-webpage-publisher.js # Single-page apps
343
+ │ ├── http-website-publisher.js # Multi-page sites
344
+ │ ├── http-function-publisher.js # API endpoints
345
+ │ ├── http-css-publisher.js # CSS serving
346
+ │ ├── http-js-publisher.js # JavaScript serving
347
+ │ ├── http-html-publisher.js # HTML serving
348
+ │ ├── http-png-publisher.js # PNG images
349
+ │ ├── http-jpeg-publisher.js # JPEG images
350
+ │ ├── http-svg-publisher.js # SVG images
351
+ │ └── ... # + more specialized types
352
+
353
+ ├── resources/ # Data abstractions
354
+ │ └── server-resource-pool.js
355
+
356
+ ├── website/ # Website/webpage abstractions
357
+ ├── examples/controls/ # Example applications (numbered)
358
+ ├── tests/ # Test suite
359
+ └── docs/ # Documentation
360
+ ```
361
+
362
+ ---
363
+
364
+ ## 🧪 Testing
365
+
366
+ ```bash
367
+ # All tests
368
+ npm test
369
+
370
+ # Specific test suites
371
+ npm run test:bundlers # Bundling system
372
+ npm run test:publishers # Publisher system
373
+ npm run test:config # Configuration validation
374
+ npm run test:e2e # End-to-end tests
375
+ npm run test:errors # Error handling
376
+ npm run test:content # Content analysis
377
+ npm run test:performance # Performance tests
378
+ npm run test:assigners # Assigner tests
379
+
380
+ # Debug mode
381
+ npm run test:debug
382
+ npm run test:verbose
383
+ ```
384
+
385
+ **Test patterns:**
386
+ - Test files: `tests/*.test.js`
387
+ - Use `tests/test-runner.js` as the runner
388
+ - Integration tests should start/stop server cleanly
389
+
390
+ ---
391
+
392
+ ## 📚 Documentation Index
393
+
394
+ | Need | Read |
395
+ |------|------|
396
+ | Quick start, architecture | `README.md` |
397
+ | Comprehensive API reference | `docs/comprehensive-documentation.md` |
398
+ | Server API design | `docs/simple-server-api-design.md` |
399
+ | System architecture | `docs/system-architecture.md` |
400
+ | Control development | `docs/controls-development.md` |
401
+ | Publisher system | `docs/publishers-guide.md` |
402
+ | Resources system | `docs/resources-guide.md` |
403
+ | Agent workflow patterns | `docs/GUIDE_TO_AGENTIC_WORKFLOWS_BY_GROK.md` |
404
+ | **Broken functionality** | `docs/agent-development-guide.md` |
405
+ | CLI reference | `docs/cli-reference.md` |
406
+ | Troubleshooting | `docs/troubleshooting.md` |
407
+
408
+ ---
409
+
410
+ ## ❌ Anti-Patterns
411
+
412
+ ### ❌ Don't bypass the context system
413
+ ```javascript
414
+ // WRONG - Direct document access
415
+ document.getElementById('my-element');
416
+
417
+ // RIGHT - Use control's DOM abstraction
418
+ this.body.add.div({ id: 'my-element' });
419
+ ```
420
+
421
+ ### ❌ Don't forget conditional compose
422
+ ```javascript
423
+ // WRONG - Always composes (breaks hydration)
424
+ constructor(spec = {}) {
425
+ super(spec);
426
+ compose(); // ← Will duplicate content when activating
427
+ }
428
+
429
+ // RIGHT - Conditional compose
430
+ constructor(spec = {}) {
431
+ super(spec);
432
+ const compose = () => { ... };
433
+ if (!spec.el) { compose(); } // ← Only compose if not hydrating
434
+ }
435
+ ```
436
+
437
+ ### ❌ Don't activate twice
438
+ ```javascript
439
+ // WRONG - No guard
440
+ activate() {
441
+ super.activate();
442
+ // Bindings happen every time activate() is called
443
+ }
444
+
445
+ // RIGHT - Guard against double activation
446
+ activate() {
447
+ if (!this.__active) {
448
+ super.activate();
449
+ // Bindings happen once
450
+ }
451
+ }
452
+ ```
453
+
454
+ ### ❌ Don't serve without waiting for 'ready'
455
+ ```javascript
456
+ // WRONG - May start before bundling complete
457
+ const server = new Server({ Ctrl, src_path_client_js });
458
+ server.start(8080);
459
+
460
+ // RIGHT - Wait for ready event
461
+ server.on('ready', () => {
462
+ server.start(8080);
463
+ });
464
+
465
+ // OR use Server.serve() which handles this
466
+ Server.serve({ Ctrl, src_path_client_js, port: 8080 });
467
+ ```
468
+
469
+ ---
470
+
471
+ ## 🔄 Development Workflow
472
+
473
+ 1. **Check existing patterns** in `examples/controls/` before creating new features (naming: `N) description`)
474
+ 2. **Follow the numbered example convention** (`1) window`, `2) two windows`, etc.) for new examples
475
+ 3. **Update `docs/agent-development-guide.md`** when finding broken functionality
476
+ 4. **Run relevant tests** before and after changes
477
+ 5. **CSS goes on the control class** as a static `.css` property, not in separate files
478
+
479
+ ---
480
+
481
+ ## 🚀 Quick Recipes
482
+
483
+ ### Add a new control
484
+ ```bash
485
+ # Create in examples/controls/ using the naming convention:
486
+ # "N) descriptive name" where N is the next number
487
+ mkdir "examples/controls/15) window, my_feature"
488
+ # Add client.js (the control) and server.js (bootstrap)
489
+ ```
490
+
491
+ ### Debug bundling issues
492
+ ```bash
493
+ JSGUI_DEBUG=1 node server.js
494
+ ```
495
+
496
+ ### Find CSS extraction issues
497
+ Check `bundler.extract_css_from_ctrl()` in bundler code - CSS must be a static property.
498
+
499
+ ### Test a single publisher
500
+ ```bash
501
+ npm run test:publishers
502
+ ```
503
+
504
+ ---
505
+
506
+ ## 📝 Session Protocol
507
+
508
+ When working on this codebase:
509
+
510
+ 1. **Check known issues first** — Read `docs/agent-development-guide.md` "Known Issues" section
511
+ 2. **Document what you find** — Update the broken functionality tracker immediately
512
+ 3. **Follow patterns** — Use examples in `examples/controls/` as reference
513
+ 4. **Test your changes** — Run relevant test suites
514
+ 5. **Update docs** — Keep implementation status current
515
+
516
+ ---
517
+
518
+ ## 🎯 Strategic Direction: Making jsgui3-server Well-Rounded
519
+
520
+ **Philosophy**: jsgui3-server is designed to be a *complete GUI delivery system*, not a general-purpose HTTP framework. Focus improvements on what makes it uniquely valuable: delivering interactive controls from server to browser with minimal boilerplate.
521
+
522
+ ### 🔮 Observable-First Architecture (Key Differentiator)
523
+
524
+ jsgui3-server uses `fnl` observables throughout. This is not just an implementation detail — it's a **strategic advantage** that should be exposed at the API level.
525
+
526
+ #### Current Observable Infrastructure
527
+
528
+ **The `obs()` factory** from `fnl` creates observables with `next`, `complete`, `error` callbacks:
529
+
530
+ ```javascript
531
+ const {obs} = require('fnl');
532
+
533
+ // Observable pattern used throughout jsgui3-server
534
+ const my_operation = obs((next, complete, error) => {
535
+ // Emit intermediate results
536
+ next({ progress: 50 });
537
+ next({ progress: 100 });
538
+
539
+ // Signal completion with final value
540
+ complete({ result: 'done' });
541
+
542
+ // Or signal error
543
+ // error(new Error('something failed'));
544
+
545
+ return []; // cleanup functions
546
+ });
547
+
548
+ // Consuming observables
549
+ my_operation.on('next', data => console.log('Progress:', data));
550
+ my_operation.on('complete', result => console.log('Done:', result));
551
+ my_operation.on('error', err => console.error('Failed:', err));
552
+ ```
553
+
554
+ #### Where Observables Are Currently Used
555
+
556
+ | Location | Purpose |
557
+ |----------|---------|
558
+ | `publishers/http-observable-publisher.js` | **SSE streaming** — already implements Server-Sent Events! |
559
+ | `resources/processors/bundlers/webpage-bundler.js` | Multi-stage bundling with progress |
560
+ | `resources/processors/bundlers/js-bundler.js` | JS compilation progress |
561
+ | `resources/processors/bundlers/css-bundler.js` | CSS extraction progress |
562
+ | `publishers/http-website-publisher.js` | Website build pipeline |
563
+ | ESBuild bundlers | Async compilation with status updates |
564
+
565
+ #### Observable Publisher (Already Exists!)
566
+
567
+ `HTTP_Observable_Publisher` already implements SSE:
568
+
569
+ ```javascript
570
+ // Server-side (existing code in http-observable-publisher.js)
571
+ const Observable_Publisher = require('./publishers/http-observable-publisher');
572
+
573
+ // Creates SSE endpoint that streams observable events
574
+ // Response format: text/event-stream with chunked transfer
575
+ // event: message\ndata: {"key": "value"}\n\n
576
+ ```
577
+
578
+ #### Strategic Opportunity: Unified Observable API
579
+
580
+ **Current gap**: No easy way to publish an observable from `Server.serve()`. The infrastructure exists but isn't wired to the simple API.
581
+
582
+ **Proposed enhancement**:
583
+ ```javascript
584
+ // Goal: Make this work seamlessly
585
+ server.publish('/api/progress', () => {
586
+ return obs((next, complete, error) => {
587
+ // Long-running operation with progress updates
588
+ for (let i = 0; i <= 100; i += 10) {
589
+ setTimeout(() => next({ progress: i }), i * 100);
590
+ }
591
+ setTimeout(() => complete({ status: 'done' }), 1100);
592
+ });
593
+ });
594
+
595
+ // Function publisher should detect observable return type
596
+ // and automatically use SSE/WebSocket transport
597
+ ```
598
+
599
+ **Client-side consumption** (future direction):
600
+ ```javascript
601
+ // In browser, jsgui3-client could provide:
602
+ const stream = context.subscribe('/api/progress');
603
+ stream.on('next', data => update_progress_bar(data.progress));
604
+ stream.on('complete', result => show_complete(result));
605
+ ```
606
+
607
+ #### Observable vs Promise vs Callback
608
+
609
+ | Return Type | Detection | Transport | Use Case |
610
+ |-------------|-----------|-----------|----------|
611
+ | **Observable** | Has `.on('next')` | SSE or WebSocket | Streaming, progress, real-time |
612
+ | **Promise** | `tf(result) === 'p'` | Single HTTP response | Async one-shot |
613
+ | **Plain value** | Object/string/array | Single HTTP response | Sync one-shot |
614
+
615
+ The `HTTP_Function_Publisher` already detects promises (`tfr === 'p'`). Extend to detect observables.
616
+
617
+ ### What's Working Well (Don't Break These)
618
+
619
+ | Feature | Status | Why It Works |
620
+ |---------|--------|--------------|
621
+ | `Server.serve({ Ctrl })` | ✅ Solid | One-liner to serve a control — the core value proposition |
622
+ | HTTP_Webpage_Publisher | ✅ Solid | Bundles JS/CSS/HTML automatically |
623
+ | ESBuild bundling | ✅ Solid | Fast, reliable JS compilation |
624
+ | Function publishers | ✅ Solid | `server.publish('name', fn)` for JSON APIs |
625
+ | Control lifecycle | ✅ Solid | Isomorphic render → activate pattern |
626
+
627
+ ### What Needs Completion (Highest Impact)
628
+
629
+ These are incomplete implementations that block real use cases:
630
+
631
+ #### 1. **HTTP_Website_Publisher** — Currently Broken
632
+ ```
633
+ Location: publishers/http-website-publisher.js
634
+ Problem: Contains "Possibly missing website publishing code" — multi-page sites don't work
635
+ Impact: Users can't build multi-page apps without workarounds
636
+ ```
637
+ **The fix**: Complete the bundling loop for `website.pages._arr.length > 1`. The code structure exists but throws `'NYI'`.
638
+
639
+ #### 2. **Default Holding Page** — Missing
640
+ ```
641
+ Location: server.js constructor (when no Ctrl provided)
642
+ Problem: Server fails or serves nothing when started without content
643
+ Impact: Confusing first-run experience
644
+ ```
645
+ **The fix**: Serve a minimal HTML page with "jsgui3-server running" + links to docs. This is a ~20 line addition.
646
+
647
+ #### 3. **Single "Ready" Signal** — Fragmented
648
+ ```
649
+ Location: server.js start() method
650
+ Problem: Multiple places emit 'ready', unclear when truly ready
651
+ Impact: Race conditions, startup timing issues
652
+ ```
653
+ **The fix**: Consolidate to one `this.raise('ready')` after all listeners bound. Remove redundant emissions.
654
+
655
+ ### What Would Be Genuinely Useful (Medium Priority)
656
+
657
+ These align with jsgui3-server's purpose of delivering GUIs:
658
+
659
+ | Feature | Why It Fits | Approach |
660
+ |---------|-------------|----------|
661
+ | **Admin panel at `/admin`** | Server should be self-documenting | Wire up existing `Web_Admin_Panel_Control` |
662
+ | **Graceful shutdown** | Production readiness | Handle SIGINT, close HTTP servers, print confirmation |
663
+ | **Watch mode** | Development ergonomics | `cli.js dev` with file watching + auto-restart |
664
+
665
+ ### What NOT to Add (Framework Bloat)
666
+
667
+ Resist adding features just because other frameworks have them:
668
+
669
+ | Avoid | Reason |
670
+ |-------|--------|
671
+ | Complex middleware chains | Express already exists; jsgui3 is for GUI delivery, not generic HTTP |
672
+ | Database integrations | Out of scope; users can add their own |
673
+ | Authentication systems | Too opinionated; provide hooks instead |
674
+ | Template engines (EJS/Pug) | jsgui3 controls ARE the templating system |
675
+ | REST scaffolding | Function publishers already handle this simply |
676
+
677
+ ### The Litmus Test for New Features
678
+
679
+ Before adding anything, ask:
680
+
681
+ 1. **Does it make serving a JSGUI3 control easier?** If not, probably don't add it.
682
+ 2. **Can it be done in userland with existing APIs?** If yes, document the pattern instead.
683
+ 3. **Does it work with the isomorphic lifecycle?** Server-render → client-activate must remain seamless.
684
+
685
+ ### Recommended Next Steps (In Order)
686
+
687
+ 1. **Fix HTTP_Website_Publisher** — unblocks multi-page apps
688
+ 2. **Add default holding page** — improves first-run experience
689
+ 3. **Consolidate ready signal** — eliminates race conditions
690
+ 4. **Wire up `/admin` route** — makes server self-documenting
691
+ 5. **Add graceful shutdown** — production readiness
692
+ 6. **Integrate Observable_Publisher into function publisher** — auto-detect observable returns and use SSE
693
+ 7. **Client-side observable consumption** — `context.subscribe()` API in jsgui3-client
694
+
695
+ Each of these is a focused fix, not a large refactor. The codebase structure is sound; it just needs completion of existing patterns.
696
+
697
+ ---
698
+
699
+ *Last updated: November 2025 - Added full stack documentation, strategic direction, and observable-first architecture*