jsgui3-server 0.0.150 → 0.0.152

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 (86) hide show
  1. package/.github/instructions/copilot.instructions.md +1 -0
  2. package/AGENTS.md +2 -0
  3. package/README.md +89 -13
  4. package/admin-ui/v1/controls/admin_shell.js +702 -669
  5. package/admin-ui/v1/server.js +14 -1
  6. package/docs/api-reference.md +504 -306
  7. package/docs/books/creating-a-new-admin-ui/README.md +20 -20
  8. package/docs/books/website-design/01-introduction.md +73 -0
  9. package/docs/books/website-design/02-current-state.md +195 -0
  10. package/docs/books/website-design/03-base-class.md +181 -0
  11. package/docs/books/website-design/04-webpage.md +307 -0
  12. package/docs/books/website-design/05-website.md +456 -0
  13. package/docs/books/website-design/06-pages-storage.md +170 -0
  14. package/docs/books/website-design/07-api-layer.md +285 -0
  15. package/docs/books/website-design/08-server-integration.md +271 -0
  16. package/docs/books/website-design/09-cross-agent-review.md +190 -0
  17. package/docs/books/website-design/10-open-questions.md +196 -0
  18. package/docs/books/website-design/11-converged-recommendation.md +205 -0
  19. package/docs/books/website-design/12-content-model.md +395 -0
  20. package/docs/books/website-design/13-webpage-module-spec.md +404 -0
  21. package/docs/books/website-design/14-website-module-spec.md +541 -0
  22. package/docs/books/website-design/15-multi-repo-plan.md +275 -0
  23. package/docs/books/website-design/16-minimal-first.md +203 -0
  24. package/docs/books/website-design/17-implementation-report-codex.md +81 -0
  25. package/docs/books/website-design/README.md +43 -0
  26. package/docs/comprehensive-documentation.md +220 -220
  27. package/docs/configuration-reference.md +281 -204
  28. package/docs/middleware-guide.md +236 -0
  29. package/docs/proposals/jsgui3-website-and-webpage-design-jsgui3-server-support.md +257 -0
  30. package/docs/proposals/jsgui3-website-and-webpage-design-review.md +73 -0
  31. package/docs/proposals/jsgui3-website-and-webpage-design.md +732 -0
  32. package/docs/swagger.md +316 -0
  33. package/docs/system-architecture.md +24 -18
  34. package/examples/controls/1) window/server.js +6 -1
  35. package/examples/controls/21) mvvm and declarative api/check.js +94 -0
  36. package/examples/controls/21) mvvm and declarative api/check_output.txt +25 -0
  37. package/examples/controls/21) mvvm and declarative api/check_output_2.txt +27 -0
  38. package/examples/controls/21) mvvm and declarative api/client.js +241 -0
  39. declarative api/e2e-screenshot-1-name-change.png +0 -0
  40. declarative api/e2e-screenshot-2-toggled.png +0 -0
  41. declarative api/e2e-screenshot-3-final.png +0 -0
  42. declarative api/e2e-screenshot-final.png +0 -0
  43. package/examples/controls/21) mvvm and declarative api/e2e-test.js +175 -0
  44. package/examples/controls/21) mvvm and declarative api/out.html +1 -0
  45. package/examples/controls/21) mvvm and declarative api/page_out.html +1 -0
  46. package/examples/controls/21) mvvm and declarative api/server.js +18 -0
  47. package/examples/data-views/01) query-endpoint/server.js +61 -0
  48. package/labs/website-design/001-base-class-overhead/check.js +162 -0
  49. package/labs/website-design/002-pages-storage/check.js +244 -0
  50. package/labs/website-design/002-pages-storage/results.txt +0 -0
  51. package/labs/website-design/003-type-detection/check.js +193 -0
  52. package/labs/website-design/003-type-detection/results.txt +0 -0
  53. package/labs/website-design/004-two-stage-validation/check.js +314 -0
  54. package/labs/website-design/004-two-stage-validation/results.txt +0 -0
  55. package/labs/website-design/005-normalize-input/check.js +303 -0
  56. package/labs/website-design/006-serve-website-spike/check.js +290 -0
  57. package/labs/website-design/README.md +34 -0
  58. package/labs/website-design/manifest.json +68 -0
  59. package/labs/website-design/run-all.js +60 -0
  60. package/middleware/compression.js +217 -0
  61. package/middleware/index.js +15 -0
  62. package/middleware/json-body.js +126 -0
  63. package/module.js +3 -0
  64. package/openapi.js +474 -0
  65. package/package.json +11 -8
  66. package/publishers/Publishers.js +6 -5
  67. package/publishers/http-function-publisher.js +135 -126
  68. package/publishers/http-webpage-publisher.js +89 -11
  69. package/publishers/query-publisher.js +116 -0
  70. package/publishers/swagger-publisher.js +203 -0
  71. package/publishers/swagger-ui.js +578 -0
  72. package/resources/adapters/array-adapter.js +143 -0
  73. package/resources/query-resource.js +131 -0
  74. package/serve-factory.js +756 -18
  75. package/server.js +502 -123
  76. package/tests/README.md +23 -1
  77. package/tests/admin-ui-jsgui-controls.test.js +16 -1
  78. package/tests/helpers/playwright-e2e-harness.js +326 -0
  79. package/tests/openapi.test.js +319 -0
  80. package/tests/playwright-smoke.test.js +134 -0
  81. package/tests/publish-enhancements.test.js +673 -0
  82. package/tests/query-publisher.test.js +430 -0
  83. package/tests/quick-json-body-test.js +169 -0
  84. package/tests/serve.test.js +425 -122
  85. package/tests/swagger-publisher.test.js +1076 -0
  86. package/tests/test-runner.js +1 -0
@@ -0,0 +1,236 @@
1
+ # Middleware Guide
2
+
3
+ jsgui3-server includes a lightweight middleware pipeline inspired by Express's `app.use()`. Middleware functions run **before** every request reaches the router, letting you add cross-cutting concerns — compression, CORS, logging, auth — without modifying route handlers.
4
+
5
+ ## Quick Start
6
+
7
+ ```javascript
8
+ const Server = require('jsgui3-server');
9
+ const { compression } = require('jsgui3-server/middleware');
10
+
11
+ const server = new Server({ Ctrl: My_Control, src_path_client_js: __dirname + '/client.js' });
12
+
13
+ // Enable gzip/deflate/brotli compression for JSON, HTML, CSS, JS responses
14
+ server.use(compression());
15
+
16
+ server.on('ready', () => server.start(8080));
17
+ ```
18
+
19
+ Or via `Server.serve()`:
20
+
21
+ ```javascript
22
+ Server.serve({
23
+ Ctrl: My_Control,
24
+ src_path_client_js: __dirname + '/client.js',
25
+ compression: true, // shorthand: enables compression with defaults
26
+ port: 8080
27
+ });
28
+ ```
29
+
30
+ ---
31
+
32
+ ## API
33
+
34
+ ### `server.use(fn)`
35
+
36
+ Register a middleware function. Middleware is executed in registration order before the request reaches the router.
37
+
38
+ | Parameter | Type | Description |
39
+ |-----------|------|-------------|
40
+ | `fn` | `function(req, res, next)` | Middleware function |
41
+
42
+ **Returns:** `this` (chainable)
43
+
44
+ **Middleware signature:**
45
+ ```javascript
46
+ function my_middleware(req, res, next) {
47
+ // Do work before routing
48
+ // ...
49
+ next(); // Continue to next middleware / router
50
+ // -- or --
51
+ next(err); // Skip remaining middleware, trigger error handler
52
+ }
53
+ ```
54
+
55
+ **Example — request logger:**
56
+ ```javascript
57
+ server.use((req, res, next) => {
58
+ console.log(`${req.method} ${req.url}`);
59
+ next();
60
+ });
61
+ ```
62
+
63
+ **Example — CORS headers:**
64
+ ```javascript
65
+ server.use((req, res, next) => {
66
+ res.setHeader('Access-Control-Allow-Origin', '*');
67
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
68
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
69
+ if (req.method === 'OPTIONS') {
70
+ res.writeHead(204);
71
+ res.end();
72
+ return; // Don't call next() — request is handled
73
+ }
74
+ next();
75
+ });
76
+ ```
77
+
78
+ ### `Server.serve()` Options
79
+
80
+ | Option | Type | Description |
81
+ |--------|------|-------------|
82
+ | `middleware` | `function \| function[]` | One or more middleware functions to register |
83
+ | `compression` | `boolean \| object` | Enable built-in compression middleware. Pass `true` for defaults or an options object |
84
+
85
+ ```javascript
86
+ Server.serve({
87
+ Ctrl: My_Control,
88
+ src_path_client_js: __dirname + '/client.js',
89
+ middleware: [
90
+ (req, res, next) => { console.log(req.url); next(); }
91
+ ],
92
+ compression: { threshold: 512 },
93
+ port: 8080
94
+ });
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Built-in Middleware
100
+
101
+ ### `compression([options])`
102
+
103
+ Response compression middleware. Transparently compresses response bodies when:
104
+
105
+ 1. The client sends an `Accept-Encoding` header matching a supported algorithm
106
+ 2. The response `Content-Type` is compressible (JSON, HTML, CSS, JS, XML, SVG, plain text)
107
+ 3. The body size meets or exceeds the threshold
108
+
109
+ Streaming responses (SSE, chunked writes via `res.write()`) are passed through uncompressed.
110
+
111
+ ```javascript
112
+ const { compression } = require('jsgui3-server/middleware');
113
+ server.use(compression());
114
+ ```
115
+
116
+ **Options:**
117
+
118
+ | Option | Type | Default | Description |
119
+ |--------|------|---------|-------------|
120
+ | `threshold` | `number` | `1024` | Minimum body size in bytes to compress |
121
+ | `level` | `number` | `Z_DEFAULT_COMPRESSION` | zlib compression level (1–9, or -1 for default) |
122
+
123
+ **Encoding negotiation priority:** gzip → deflate → brotli
124
+
125
+ gzip is preferred for dynamic content because it offers the best speed/ratio trade-off. Brotli provides better compression ratios but is significantly slower for on-the-fly compression; it's more appropriate for pre-compressed static assets.
126
+
127
+ **Compressible content types:**
128
+ - `application/json`
129
+ - `text/html`, `text/plain`, `text/css`, `text/xml`, `text/csv`
130
+ - `application/javascript`, `text/javascript`
131
+ - `application/xml`, `application/xhtml+xml`, `application/manifest+json`
132
+ - `image/svg+xml`
133
+
134
+ **What is NOT compressed:**
135
+ - Bodies smaller than `threshold`
136
+ - Non-text content types (images, video, binary)
137
+ - Responses with an existing `Content-Encoding` header
138
+ - Streaming responses (where `res.write()` is called before `res.end()`)
139
+
140
+ ---
141
+
142
+ ## How It Works
143
+
144
+ ### Execution Order
145
+
146
+ ```
147
+ HTTP Request
148
+
149
+
150
+ middleware[0](req, res, next) ──next()──►
151
+ middleware[1](req, res, next) ──next()──►
152
+ ...
153
+ middleware[n](req, res, next) ──next()──►
154
+ server_router.process(req, res) ◄── routing + publishers
155
+ ```
156
+
157
+ ### Response Wrapping (Compression Pattern)
158
+
159
+ The compression middleware intercepts `res.writeHead()` and `res.end()`:
160
+
161
+ 1. **`res.writeHead()`** — Buffers the status code and headers instead of sending them immediately
162
+ 2. **`res.end(body)`** — Checks the content type and body size; if compressible, compresses the body, updates `Content-Encoding` and `Content-Length` headers, then sends everything
163
+ 3. **`res.write(chunk)`** — If called (streaming), flushes buffered headers and passes writes through unmodified
164
+
165
+ This means compression is transparent to publishers and route handlers — they continue to write responses normally.
166
+
167
+ ---
168
+
169
+ ## Writing Custom Middleware
170
+
171
+ ### Basic Pattern
172
+
173
+ ```javascript
174
+ function my_middleware(req, res, next) {
175
+ // 1. Pre-processing (before routing)
176
+ // Modify req, set headers, check auth, etc.
177
+
178
+ // 2. Continue the chain
179
+ next();
180
+
181
+ // 3. Post-processing is NOT supported in this simple model.
182
+ // For response wrapping, intercept res.end() like compression does.
183
+ }
184
+ ```
185
+
186
+ ### Response Wrapping Pattern
187
+
188
+ To modify the response body (like compression does), intercept `res.end()`:
189
+
190
+ ```javascript
191
+ function response_timer(req, res, next) {
192
+ const start = Date.now();
193
+ const _end = res.end;
194
+
195
+ res.end = function () {
196
+ res.setHeader('X-Response-Time', `${Date.now() - start}ms`);
197
+ _end.apply(res, arguments);
198
+ };
199
+
200
+ next();
201
+ }
202
+
203
+ server.use(response_timer);
204
+ ```
205
+
206
+ ### Error Handling
207
+
208
+ If a middleware throws or calls `next(err)`, the error handler sends a 500 response and logs the error. Remaining middleware and routing are skipped.
209
+
210
+ ```javascript
211
+ server.use((req, res, next) => {
212
+ try {
213
+ validate_request(req);
214
+ next();
215
+ } catch (err) {
216
+ next(err); // → 500 Internal Server Error
217
+ }
218
+ });
219
+ ```
220
+
221
+ ---
222
+
223
+ ## Access via Module Exports
224
+
225
+ ```javascript
226
+ // Direct require
227
+ const { compression } = require('jsgui3-server/middleware');
228
+
229
+ // Via Server class
230
+ const Server = require('jsgui3-server');
231
+ const { compression } = Server.middleware;
232
+
233
+ // Via jsgui module
234
+ const jsgui = require('jsgui3-server');
235
+ const { compression } = jsgui.middleware;
236
+ ```
@@ -0,0 +1,257 @@
1
+ # Proposal: jsgui3-server Support for New Website/Webpage Primitives
2
+
3
+ > **Date**: 2026-02-16
4
+ > **Status**: Proposal for review (no implementation)
5
+ > **Companion docs**:
6
+ > `docs/proposals/jsgui3-website-and-webpage-design.md`
7
+ > `docs/proposals/jsgui3-website-and-webpage-design-review.md`
8
+
9
+ ## 1. Purpose
10
+
11
+ Define the server-side changes required so `jsgui3-server` can fully support richer `jsgui3-website` / `jsgui3-webpage` primitives and the extra information they encapsulate, while preserving backward compatibility with existing `Server.serve(...)` usage.
12
+
13
+ ## 2. Core Integration Principles
14
+
15
+ 1. `jsgui3-server` should accept both classic inputs (Ctrl/functions/options) and new primitive objects.
16
+ 2. Integration should use capability/shape normalization, not fragile runtime class identity checks.
17
+ 3. Primitive metadata should flow into routing, bundling, HTTP headers, and admin introspection.
18
+ 4. Static and dynamic page rendering must be first-class, explicit modes.
19
+ 5. Existing behavior must remain intact by default.
20
+
21
+ ## 3. Current Gaps in jsgui3-server
22
+
23
+ 1. `publishers/http-website-publisher.js` depends on `instanceof Website` and `website.pages._arr` internals.
24
+ 2. `publishers/http-website-publisher.js` has incomplete multi-page publication code paths (`NYI`).
25
+ 3. `serve-factory.js` mainly normalizes function/options inputs, not richer website primitives.
26
+ 4. API publishing currently assumes `api` as a plain name→handler map; endpoint metadata is not preserved.
27
+ 5. Per-page metadata (render mode, page-level assets, cache hints, tags) is not represented in publication decisions.
28
+ 6. Admin/tooling introspection is not using a stable website manifest contract.
29
+
30
+ ## 4. Proposed Server Data Contract (Internal)
31
+
32
+ Add an internal, normalized manifest that all publishers consume.
33
+
34
+ ### 4.1 `normalized_website_manifest`
35
+
36
+ ```js
37
+ {
38
+ name,
39
+ base_path,
40
+ meta,
41
+ assets,
42
+ pages: [normalized_page_manifest],
43
+ api_endpoints: [normalized_api_manifest],
44
+ policies
45
+ }
46
+ ```
47
+
48
+ ### 4.2 `normalized_page_manifest`
49
+
50
+ ```js
51
+ {
52
+ id,
53
+ name,
54
+ path,
55
+ title,
56
+ content,
57
+ render_mode, // 'static' | 'dynamic'
58
+ head,
59
+ meta,
60
+ assets,
61
+ scripts,
62
+ stylesheets,
63
+ cache_policy,
64
+ route_priority
65
+ }
66
+ ```
67
+
68
+ ### 4.3 `normalized_api_manifest`
69
+
70
+ ```js
71
+ {
72
+ name,
73
+ method,
74
+ path,
75
+ handler,
76
+ description,
77
+ auth,
78
+ rate_limit,
79
+ tags
80
+ }
81
+ ```
82
+
83
+ The key idea: all incoming forms normalize into this one server contract before routing/bundling begins.
84
+
85
+ ## 5. File-by-File Changes in jsgui3-server
86
+
87
+ ### 5.1 `serve-factory.js`
88
+
89
+ Add a normalization phase before server startup.
90
+
91
+ 1. Add helpers such as `normalize_serve_input`, `normalize_website_input`, `normalize_webpage_input`, `normalize_api_input`.
92
+ 2. Accept additional input forms: `new Website(...)`, website-like plain objects with `pages`, `new Webpage(...)`, and webpage-like plain objects with `path` + `content`.
93
+ 3. Build `normalized_website_manifest` and attach it to `server_instance`.
94
+ 4. Preserve old `ctrl/page/pages/api` options by translating them into the same normalized manifest.
95
+ 5. Resolve route conflicts early with deterministic precedence rules.
96
+
97
+ Impact: `serve-factory.js` becomes the single place where compatibility and input variability are handled.
98
+
99
+ ### 5.2 `publishers/http-webpageorsite-publisher.js`
100
+
101
+ Refactor this shared base to consume a normalized manifest instead of raw ad hoc shape assumptions.
102
+
103
+ 1. Add `prepare_manifest_bundle(manifest, options)` entrypoint.
104
+ 2. Split shared logic into clear units such as `prepare_shared_client_bundle`, `prepare_page_static_assets`, and `build_static_route_response_items`.
105
+ 3. Keep SSR-only mode supported when no client bundle path exists.
106
+
107
+ Impact: all page/site publishers share one bundling and route-item preparation pipeline.
108
+
109
+ ### 5.3 `publishers/http-webpage-publisher.js`
110
+
111
+ Extend single-page publisher to honor encapsulated page metadata.
112
+
113
+ 1. Respect `render_mode`.
114
+ 2. `static`: pre-render HTML and serve static response items.
115
+ 3. `dynamic`: register request-time render handler for that route.
116
+ 4. Inject page-level assets/scripts/stylesheets in addition to shared site assets.
117
+ 5. Apply page-level response policies (`cache_policy`, optional headers).
118
+ 6. Include page manifest details in emitted `ready` payload for introspection.
119
+
120
+ Impact: one-page apps gain parity with multi-page site semantics.
121
+
122
+ ### 5.4 `publishers/http-website-publisher.js`
123
+
124
+ This file needs the largest rewrite.
125
+
126
+ 1. Remove hard dependency on `instanceof Website` and `website.pages._arr`.
127
+ 2. Accept normalized website manifest from `serve-factory.js`.
128
+ 3. For each page in `manifest.pages`, route by render mode (static page: pre-render + static route registration, dynamic page: register dynamic render handler).
129
+ 4. Register API endpoints from `manifest.api_endpoints` with method/path semantics.
130
+ 5. Add support for site-level `base_path` prefixing.
131
+ 6. Emit a structured publication summary object (`routes`, `assets`, `api`, `warnings`).
132
+
133
+ Impact: `HTTP_Website_Publisher` becomes complete and deterministic for multi-page websites.
134
+
135
+ ### 5.5 `server.js`
136
+
137
+ Add lightweight hooks so publication metadata can be surfaced consistently.
138
+
139
+ 1. Add structured route registration helper for static and dynamic routes.
140
+ 2. Add endpoint publication helper that accepts method/path metadata.
141
+ 3. Preserve existing `publish(name, fn)` API but map it to default endpoint metadata.
142
+ 4. Expose `server_instance.website_manifest` and `server_instance.publication_summary` for tooling/admin.
143
+
144
+ Impact: no breaking API change, but much better visibility.
145
+
146
+ ### 5.6 `website/website.js` and `website/webpage.js`
147
+
148
+ Keep these wrappers, but add comments and type-guards that describe the normalized contract expected by server internals.
149
+
150
+ Impact: clearer boundaries between primitive packages and server adapters.
151
+
152
+ ### 5.7 New helper modules (recommended)
153
+
154
+ Create a dedicated server-side normalization area.
155
+
156
+ 1. `website/normalize_website_manifest.js`
157
+ 2. `website/normalize_page_manifest.js`
158
+ 3. `website/normalize_api_manifest.js`
159
+ 4. `website/resolve_route_conflicts.js`
160
+ 5. `website/build_publication_summary.js`
161
+
162
+ Impact: removes format-specific logic from publishers and centralizes compatibility policy.
163
+
164
+ ## 6. Primitive Field → Server Behavior Mapping
165
+
166
+ | Primitive field | Server subsystem | Required behavior |
167
+ |---|---|---|
168
+ | `page.path` | Router | Normalize leading slash, register route, detect conflicts |
169
+ | `page.render_mode` | Publisher/rendering | Choose static pre-render vs dynamic request-time render |
170
+ | `page.content` | Renderer | Validate constructor/function and render consistently |
171
+ | `page.assets/scripts/stylesheets` | Bundling/publish | Include per-page resources in route item list |
172
+ | `page.cache_policy` | HTTP response | Set cache headers for HTML/assets |
173
+ | `page.meta/head` | HTML generation | Emit tags into rendered document |
174
+ | `website.base_path` | Routing | Prefix all page and API routes deterministically |
175
+ | `website.assets` | Bundling | Register site-wide static assets |
176
+ | `website.api` / endpoint metadata | API publisher | Publish endpoints with method/path/description/auth metadata |
177
+ | `website.meta` | Admin/introspection | Expose in summary and diagnostics APIs |
178
+
179
+ ## 7. Backward Compatibility Strategy
180
+
181
+ 1. Maintain current `Server.serve(Ctrl)` behavior unchanged.
182
+ 2. Maintain current options object behavior (`ctrl`, `page`, `pages`, `api`).
183
+ 3. Introduce a compatibility normalization layer that converts old options to manifest format.
184
+ 4. Keep `server.publish(name, fn)` valid; internally convert to `{ method: 'GET', path: '/api/:name' }` (or current default route convention).
185
+ 5. Log non-breaking warnings when deprecated shapes are detected.
186
+
187
+ ## 8. Error Handling and Diagnostics
188
+
189
+ Standardize errors from normalization and publication stages.
190
+
191
+ 1. `invalid_page_definition`
192
+ 2. `invalid_api_endpoint`
193
+ 3. `duplicate_route`
194
+ 4. `unsupported_render_mode`
195
+ 5. `asset_resolution_failure`
196
+
197
+ Each error should include:
198
+
199
+ 1. `code`
200
+ 2. `message`
201
+ 3. `context` (`page_id`, `route`, `endpoint_name`, `source`)
202
+
203
+ This is necessary for actionable admin UX and debugging.
204
+
205
+ ## 9. Testing Changes Required
206
+
207
+ ### 9.1 Unit tests
208
+
209
+ 1. Normalization from legacy inputs to manifest.
210
+ 2. Route conflict detection and precedence.
211
+ 3. API endpoint normalization (method/path defaults).
212
+ 4. Render mode routing decisions.
213
+
214
+ ### 9.2 Integration tests
215
+
216
+ 1. Single-page static primitive.
217
+ 2. Single-page dynamic primitive.
218
+ 3. Multi-page mixed static/dynamic website.
219
+ 4. Website with API endpoint metadata.
220
+ 5. Base path + asset publication behavior.
221
+ 6. Legacy `Server.serve` calls still passing unchanged.
222
+
223
+ ### 9.3 Regression tests
224
+
225
+ 1. No client JS path still starts server in SSR-only mode.
226
+ 2. Admin route still comes up with website manifest present.
227
+ 3. Existing compression and middleware pipeline remains intact.
228
+
229
+ ## 10. Suggested Delivery Phases
230
+
231
+ 1. **Phase 1: normalization + compatibility**
232
+ Implement manifest normalization in `serve-factory.js`, keep existing publishers mostly intact.
233
+
234
+ 2. **Phase 2: publisher modernization**
235
+ Refactor `http-webpageorsite-publisher.js`, `http-webpage-publisher.js`, `http-website-publisher.js` to consume normalized manifest and remove `_arr`/`instanceof` coupling.
236
+
237
+ 3. **Phase 3: metadata completeness**
238
+ Implement full field mapping (assets, cache policy, endpoint metadata, introspection summary).
239
+
240
+ 4. **Phase 4: admin/tooling surface**
241
+ Expose publication summaries and diagnostics for admin views and debugging.
242
+
243
+ ## 11. Recommended Initial Scope
244
+
245
+ For a practical first milestone, support this subset end-to-end.
246
+
247
+ 1. `website.pages` with explicit `path` + `content`
248
+ 2. `page.render_mode` (`static`/`dynamic`)
249
+ 3. `website.api` endpoint metadata (`method`, `path`, `handler`)
250
+ 4. normalized publication summary
251
+ 5. full backward compatibility with current `Server.serve` signatures
252
+
253
+ This gives immediate value without requiring every advanced field on day one.
254
+
255
+ ## 12. Outcome
256
+
257
+ With these changes, `jsgui3-server` will be able to serve richer website/webpage primitives as first-class inputs, preserve all encapsulated structure/metadata, and remain backward compatible with existing users.
@@ -0,0 +1,73 @@
1
+ # Review: jsgui3-website-and-webpage-design
2
+
3
+ > **Date**: 2026-02-16
4
+ > **Scope**: Review + design contributions only (no implementation)
5
+
6
+ ## Best ideas
7
+
8
+ 1. **Keeping `jsgui3-website` / `jsgui3-webpage` optional to `jsgui3-server` is the strongest architectural choice.**
9
+ Reason: this preserves low-friction serving for simple cases while still allowing richer abstractions for apps that want them.
10
+
11
+ 2. **Making inspectability a first-class goal (`toJSON()`, metadata exposure) is excellent.**
12
+ Reason: admin tooling, diagnostics, docs generation, and tests all benefit from a stable introspection surface.
13
+
14
+ 3. **Supporting multiple page input shapes (`Array` and object-map) is pragmatic.**
15
+ Reason: object-map is concise for route-centric definitions, while arrays are better for ordered or generated page sets.
16
+
17
+ 4. **Calling out the `API.js` export bug explicitly is very good proposal hygiene.**
18
+ Reason: the proposal is grounded in reality and identifies a hard runtime blocker.
19
+
20
+ 5. **The open-question section is high quality and correctly focused.**
21
+ Reason: it addresses exactly the unknowns that matter for primitives (dynamic rendering, ordering, nesting, server vs page concerns).
22
+
23
+ ## Worst ideas
24
+
25
+ 1. **Leaning on `Collection` internals (`pages._arr`) is the weakest technical direction.**
26
+ Reason: this bakes internal details into public behavior, increases fragility, and makes future refactors painful.
27
+
28
+ 2. **Using `Evented_Class` as a default `Webpage` model is over-engineered for current needs.**
29
+ Reason: it adds boilerplate, coupling, and cognitive load before there is a concrete consumer that needs per-field change events.
30
+
31
+ 3. **Hard-coupling primitives to `jsgui3-html` creates unnecessary dependency weight.**
32
+ Reason: website/webpage definitions are mostly domain objects; making them require the full UI/control stack limits reuse (including non-server tooling).
33
+
34
+ 4. **`instanceof` as a core integration strategy is brittle across duplicated installs/workspaces.**
35
+ Reason: two copies of a package can fail `instanceof` even when shape-compatible; server boundaries should prefer capability checks and normalization.
36
+
37
+ 5. **Defaulting page `path` to `'/'` can silently mask configuration mistakes.**
38
+ Reason: accidental missing routes become root collisions; this should be explicit in multi-page scenarios.
39
+
40
+ ## Contributions to the design discussion
41
+
42
+ 1. **Use a layered model: core primitives + server adapter layer.**
43
+ Core primitives should be plain and lightweight (`Webpage`, `Website`, `Website_Api`) with minimal runtime dependencies. Server-specific translation can stay in `jsgui3-server`.
44
+
45
+ 2. **Define a strict minimal contract for primitives.**
46
+ For `Webpage`: `path`, `title`, `content`, `meta`, `assets`, `render_mode` (`static` / `dynamic`).
47
+ For `Website`: page registry, endpoint registry, metadata, and deterministic serialization.
48
+
49
+ 3. **Prefer `Map` semantics for page identity, but expose stable methods, not internals.**
50
+ Use `add_page`, `get_page`, `has_page`, `remove_page`, `list_pages`; do not expose storage internals like `_arr`.
51
+
52
+ 4. **Separate endpoint declaration from server publishing.**
53
+ `Website_Api` should store endpoint definitions (`name`, `method`, `path`, `handler`, `description`, `auth`) while `jsgui3-server` decides how to publish them.
54
+
55
+ 5. **Normalize and validate early.**
56
+ Route normalization (`/` prefix), duplicate policy, and handler/type checks should happen when constructing primitives, not at publish time.
57
+
58
+ 6. **Add lifecycle semantics instead of full reactivity.**
59
+ A simple `finalize()` (or equivalent) model is likely enough: mutable during composition, read-mostly after publish. This gives safety without event-system complexity.
60
+
61
+ 7. **Make introspection a formal API contract.**
62
+ Keep `toJSON()` deterministic and tool-friendly so admin UIs and docs generators can rely on it without peeking into implementation details.
63
+
64
+ ## Suggested direction
65
+
66
+ A strong near-term path is effectively **Webpage B-lite + Website C-lite**:
67
+
68
+ - Keep property helpers and introspection.
69
+ - Use `Map`-style semantics for routes and endpoint registration.
70
+ - Avoid `Evented_Class` and `Collection._arr` coupling.
71
+ - Keep primitives lightweight and let `jsgui3-server` own serving/bundling mechanics.
72
+
73
+ This keeps the primitives expressive enough for creative website/page design while staying robust for server integration.