jsgui3-server 0.0.151 → 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 (77) hide show
  1. package/README.md +21 -0
  2. package/admin-ui/v1/controls/admin_shell.js +33 -0
  3. package/admin-ui/v1/server.js +14 -1
  4. package/docs/api-reference.md +120 -2
  5. package/docs/books/website-design/01-introduction.md +73 -0
  6. package/docs/books/website-design/02-current-state.md +195 -0
  7. package/docs/books/website-design/03-base-class.md +181 -0
  8. package/docs/books/website-design/04-webpage.md +307 -0
  9. package/docs/books/website-design/05-website.md +456 -0
  10. package/docs/books/website-design/06-pages-storage.md +170 -0
  11. package/docs/books/website-design/07-api-layer.md +285 -0
  12. package/docs/books/website-design/08-server-integration.md +271 -0
  13. package/docs/books/website-design/09-cross-agent-review.md +190 -0
  14. package/docs/books/website-design/10-open-questions.md +196 -0
  15. package/docs/books/website-design/11-converged-recommendation.md +205 -0
  16. package/docs/books/website-design/12-content-model.md +395 -0
  17. package/docs/books/website-design/13-webpage-module-spec.md +404 -0
  18. package/docs/books/website-design/14-website-module-spec.md +541 -0
  19. package/docs/books/website-design/15-multi-repo-plan.md +275 -0
  20. package/docs/books/website-design/16-minimal-first.md +203 -0
  21. package/docs/books/website-design/17-implementation-report-codex.md +81 -0
  22. package/docs/books/website-design/README.md +43 -0
  23. package/docs/configuration-reference.md +54 -0
  24. package/docs/proposals/jsgui3-website-and-webpage-design-jsgui3-server-support.md +257 -0
  25. package/docs/proposals/jsgui3-website-and-webpage-design-review.md +73 -0
  26. package/docs/proposals/jsgui3-website-and-webpage-design.md +732 -0
  27. package/docs/swagger.md +316 -0
  28. package/examples/controls/1) window/server.js +6 -1
  29. package/examples/controls/21) mvvm and declarative api/check.js +94 -0
  30. package/examples/controls/21) mvvm and declarative api/check_output.txt +25 -0
  31. package/examples/controls/21) mvvm and declarative api/check_output_2.txt +27 -0
  32. package/examples/controls/21) mvvm and declarative api/client.js +241 -0
  33. declarative api/e2e-screenshot-1-name-change.png +0 -0
  34. declarative api/e2e-screenshot-2-toggled.png +0 -0
  35. declarative api/e2e-screenshot-3-final.png +0 -0
  36. declarative api/e2e-screenshot-final.png +0 -0
  37. package/examples/controls/21) mvvm and declarative api/e2e-test.js +175 -0
  38. package/examples/controls/21) mvvm and declarative api/out.html +1 -0
  39. package/examples/controls/21) mvvm and declarative api/page_out.html +1 -0
  40. package/examples/controls/21) mvvm and declarative api/server.js +18 -0
  41. package/examples/data-views/01) query-endpoint/server.js +61 -0
  42. package/labs/website-design/001-base-class-overhead/check.js +162 -0
  43. package/labs/website-design/002-pages-storage/check.js +244 -0
  44. package/labs/website-design/002-pages-storage/results.txt +0 -0
  45. package/labs/website-design/003-type-detection/check.js +193 -0
  46. package/labs/website-design/003-type-detection/results.txt +0 -0
  47. package/labs/website-design/004-two-stage-validation/check.js +314 -0
  48. package/labs/website-design/004-two-stage-validation/results.txt +0 -0
  49. package/labs/website-design/005-normalize-input/check.js +303 -0
  50. package/labs/website-design/006-serve-website-spike/check.js +290 -0
  51. package/labs/website-design/README.md +34 -0
  52. package/labs/website-design/manifest.json +68 -0
  53. package/labs/website-design/run-all.js +60 -0
  54. package/middleware/json-body.js +126 -0
  55. package/openapi.js +474 -0
  56. package/package.json +11 -8
  57. package/publishers/Publishers.js +6 -5
  58. package/publishers/http-function-publisher.js +135 -126
  59. package/publishers/http-webpage-publisher.js +89 -11
  60. package/publishers/query-publisher.js +116 -0
  61. package/publishers/swagger-publisher.js +203 -0
  62. package/publishers/swagger-ui.js +578 -0
  63. package/resources/adapters/array-adapter.js +143 -0
  64. package/resources/query-resource.js +131 -0
  65. package/serve-factory.js +728 -18
  66. package/server.js +421 -103
  67. package/tests/README.md +23 -1
  68. package/tests/admin-ui-jsgui-controls.test.js +16 -1
  69. package/tests/helpers/playwright-e2e-harness.js +326 -0
  70. package/tests/openapi.test.js +319 -0
  71. package/tests/playwright-smoke.test.js +134 -0
  72. package/tests/publish-enhancements.test.js +673 -0
  73. package/tests/query-publisher.test.js +430 -0
  74. package/tests/quick-json-body-test.js +169 -0
  75. package/tests/serve.test.js +425 -122
  76. package/tests/swagger-publisher.test.js +1076 -0
  77. package/tests/test-runner.js +1 -0
@@ -0,0 +1,190 @@
1
+ # Chapter 9: Cross-Agent Review
2
+
3
+ An OpenAI o3 agent was given the original proposals document and asked to review it and contribute to the design discussion. This chapter presents their findings and discusses the responses.
4
+
5
+ ---
6
+
7
+ ## The Review Process
8
+
9
+ The agent was asked to do two things:
10
+
11
+ 1. **Review the proposals** — identify Best and Worst ideas (5 Best, 5 Worst)
12
+ 2. **Contribute to the design** — propose new ideas or refinements, then write a separate server-support document
13
+
14
+ The results were two documents:
15
+ - `jsgui3-website-and-webpage-design-review.md` — the review
16
+ - `jsgui3-website-and-webpage-design-jsgui3-server-support.md` — a detailed server integration proposal
17
+
18
+ ---
19
+
20
+ ## Best Ideas (Their Assessment)
21
+
22
+ ### 1. "Keeping Website/Webpage optional to jsgui3-server"
23
+
24
+ They identified this as the strongest architectural choice. The reasoning: it preserves low-friction serving for simple cases while allowing richer abstractions for apps that want them.
25
+
26
+ **Response**: Agreed completely. This is a hard constraint, not just a design preference. The server's `Server.serve(MyCtrl)` one-liner is one of its best features and must not be complicated.
27
+
28
+ ### 2. "Making inspectability a first-class goal"
29
+
30
+ They praised `toJSON()` and metadata exposure for admin tooling, diagnostics, docs generation, and tests.
31
+
32
+ **Response**: Agreed. The admin UI already introspects the resource pool and router. Having structured `toJSON()` on Website/Webpage gives it a stable contract to display.
33
+
34
+ ### 3. "Supporting multiple page input shapes"
35
+
36
+ Both array and object-map formats were called "pragmatic."
37
+
38
+ **Response**: Agreed. This is about meeting users where they are, not forcing one format.
39
+
40
+ ### 4. "Calling out the API.js export bug"
41
+
42
+ Good proposal hygiene — the design document is grounded in reality and identifies hard runtime blockers.
43
+
44
+ **Response**: The bug (`MediaSourceHandle.exports` instead of `module.exports`) would crash on any `require('./API')` call. Including it prevents someone from trying to use the existing code and being confused.
45
+
46
+ ### 5. "The open-question section is high quality"
47
+
48
+ They noted it addresses exactly the unknowns that matter for primitives.
49
+
50
+ **Response**: Agreed. Design documents should be honest about what they don't know.
51
+
52
+ ---
53
+
54
+ ## Worst Ideas (Their Assessment)
55
+
56
+ ### 1. "Leaning on `Collection` internals (`pages._arr`)"
57
+
58
+ Called the weakest technical direction. Bakes internal details into public behavior, increases fragility.
59
+
60
+ **Response**: **Strongly agree.** The current `http-website-publisher.js` accesses `website.pages._arr` directly. This is an implementation detail of Collection that shouldn't appear in any public interface. Chapter 6 discusses alternatives; Map with method-based access is the cleaner direction.
61
+
62
+ ### 2. "Using `Evented_Class` as a default Webpage model"
63
+
64
+ Called "over-engineered for current needs." Adds boilerplate, coupling, and cognitive load before there's a concrete consumer.
65
+
66
+ **Response**: **Partially disagree.** The reviewer is right that per-field change events are premature. But extending `Evented_Class` as a base class is essentially free — it adds `.on()` and `.raise()` without requiring their use. In an ecosystem where nearly everything extends `Evented_Class`, *not* using it is the choice that needs justification. The counter-argument is detailed in Chapter 3.
67
+
68
+ The key insight the reviewer missed: extending `Evented_Class` does not mean firing events on every property change. You can extend it and only raise events for meaningful lifecycle moments like `'page-added'` or `'ready'`.
69
+
70
+ ### 3. "Hard-coupling primitives to jsgui3-html"
71
+
72
+ Called unnecessary dependency weight that limits reuse.
73
+
74
+ **Response**: **Partially disagree.** Both modules will depend on `jsgui3-html` — this is a stated requirement, not a design choice. The page `content` *is* a jsgui3-html control constructor. The question isn't whether to depend on jsgui3-html but how deeply: just importing `Evented_Class` (light coupling) vs. using Collection, tof, obext, etc. (deep coupling).
75
+
76
+ That said, the reviewer's principle is sound: keep the dependency surface as small as possible even within a required dependency.
77
+
78
+ ### 4. "`instanceof` as a core integration strategy"
79
+
80
+ Called brittle across duplicated installs/workspaces.
81
+
82
+ **Response**: **Agree.** This is a real issue in the jsgui3 ecosystem, where packages are often `npm link`ed during development. Two copies of `jsgui3-website` would break `instanceof`. Chapter 8 discusses alternatives including duck typing and Symbol-based type markers.
83
+
84
+ ### 5. "Defaulting page `path` to `'/'`"
85
+
86
+ Can silently mask configuration mistakes in multi-page scenarios.
87
+
88
+ **Response**: **Agree.** Two pages both defaulting to `/` would silently collide. The proposals in Chapter 4 do not default `path`, making it explicitly required.
89
+
90
+ ---
91
+
92
+ ## Their Design Contributions
93
+
94
+ ### 1. Layered model: core primitives + server adapter
95
+
96
+ **Idea**: Keep primitives lightweight. Put all server-specific logic in jsgui3-server.
97
+
98
+ **Response**: Correct architectural separation. The primitives define *what*, the server decides *how*. The Webpage shouldn't know about Express, HTTP, or bundling.
99
+
100
+ ### 2. Strict minimal contract for primitives
101
+
102
+ **Idea**: Explicitly define what properties each primitive has and stick to it.
103
+
104
+ **Response**: Agreed, with nuance. The contract should be clear, but extensibility should be preserved. Unknown spec properties shouldn't crash the constructor.
105
+
106
+ ### 3. Map semantics with stable methods
107
+
108
+ **Idea**: Use `add_page`, `get_page`, `has_page`, `remove_page`, `list_pages` — never expose storage internals.
109
+
110
+ **Response**: Agreed. This is the recommendation in Chapter 6 (Map option) and is implemented in Chapter 5, approaches B and C.
111
+
112
+ ### 4. Separate endpoint declaration from server publishing
113
+
114
+ **Idea**: `Website_API` stores definitions; the server publishes them.
115
+
116
+ **Response**: Agreed. This is the central principle in Chapter 7. The naming discussion (declare/define/register vs. publish) addresses exactly this.
117
+
118
+ ### 5. Normalize and validate early
119
+
120
+ **Idea**: Route normalization, duplicate detection, and handler checks at construction time.
121
+
122
+ **Response**: Agreed but with limits. Validation in the constructor catches errors early but can be annoying during development when building objects incrementally. The `finalize()` lifecycle model (discussed in Chapter 4, Approach C) offers a compromise: be permissive during construction, validate at finalization.
123
+
124
+ ### 6. Lifecycle semantics instead of full reactivity
125
+
126
+ **Idea**: A simple `finalize()` model — mutable during composition, read-mostly after publish.
127
+
128
+ **Response**: This is the review's most original contribution. It solves the event-system complexity problem without losing safety. The idea is explored in Chapter 4, Approach C.
129
+
130
+ ### 7. Formal `toJSON()` introspection contract
131
+
132
+ **Idea**: Keep serialization deterministic and tool-friendly.
133
+
134
+ **Response**: Agreed. All approaches in Chapters 4 and 5 include `toJSON()`.
135
+
136
+ ---
137
+
138
+ ## Their Server Support Document
139
+
140
+ The OpenAI agent produced a separate, detailed server-integration proposal. Key contributions:
141
+
142
+ ### The Normalized Manifest
143
+
144
+ The document's best idea. Instead of publishers each handling different input formats, a normalization step produces a standard `normalized_website_manifest` that all publishers consume. This includes:
145
+
146
+ - `normalized_page_manifest` — per-page with render_mode, cache_policy, assets, etc.
147
+ - `normalized_api_manifest` — per-endpoint with method, auth, rate_limit, tags
148
+ - `normalized_website_manifest` — site-level with base_path, policies, combined pages and API
149
+
150
+ **Response**: Architecturally excellent. This is the right pattern. The concern is scope — the proposed manifests include many fields (`rate_limit`, `route_priority`, `cache_policy`) that don't have consumers yet. Starting with a minimal manifest and growing it is more pragmatic.
151
+
152
+ ### File-by-file changes
153
+
154
+ The document maps out changes to `serve-factory.js`, all three publishers, `server.js`, and the wrapper modules. It also proposes five new helper modules.
155
+
156
+ **Response**: The analysis is thorough. The recommendation to start with fewer helper files (one `normalize.js` rather than five) is more practical for a first pass.
157
+
158
+ ### Delivery phases
159
+
160
+ Four phases: normalization → publisher modernization → metadata completeness → admin surface.
161
+
162
+ **Response**: Well-ordered. Each phase delivers independently useful value. The first phase (normalization + compatibility) is the right starting point.
163
+
164
+ ---
165
+
166
+ ## Points of Convergence
167
+
168
+ Both agents (and the conversation so far) converge on:
169
+
170
+ 1. Website/Webpage must be optional to the server
171
+ 2. Map-based page storage with method-based API (no `_arr`)
172
+ 3. Server should use capability checks, not `instanceof`
173
+ 4. `toJSON()` for introspection
174
+ 5. Accept multiple input formats (array, object-map, instances)
175
+ 6. API endpoints should carry metadata beyond just name+handler
176
+
177
+ ## Points of Disagreement
178
+
179
+ | Topic | This author | OpenAI reviewer |
180
+ |-------|-------------|-----------------|
181
+ | `Evented_Class` as base | Yes — ecosystem norm, free capability | No — over-engineered |
182
+ | `jsgui3-html` dependency | Required (stated constraint) | Unnecessary weight |
183
+ | When to validate | At construction or finalize | Always at construction |
184
+ | Number of new helper files | Start with 1 | Start with 5 |
185
+
186
+ ---
187
+
188
+ ## Synthesis Forward
189
+
190
+ Chapter 11 captures the current convergence from this chapter: keep primitives optional, use normalized server manifests, avoid storage internals leakage, and ship in phased increments with strict backward compatibility.
@@ -0,0 +1,196 @@
1
+ # Chapter 10: Open Questions
2
+
3
+ These are design decisions that remain unresolved. Each one could go in multiple directions, and the right choice depends on how these modules will actually be used.
4
+
5
+ ---
6
+
7
+ ## 1. Should Webpage manage client-side JS paths?
8
+
9
+ Today, `serve-factory.js` resolves client-side JavaScript paths (`src_path_client_js`). The page just says "my content is this control" and the server figures out what to bundle.
10
+
11
+ **Option A**: Webpage has a `client_js` property that points to the entry file:
12
+ ```js
13
+ new Webpage({
14
+ content: MyCtrl,
15
+ client_js: './client/main.js'
16
+ });
17
+ ```
18
+
19
+ **Option B**: The server infers the bundle path from the content control, as it does today.
20
+
21
+ **Option C**: Both — `client_js` is optional, and if provided, overrides the server's inference.
22
+
23
+ **The tension**: If the Webpage knows its client-side JS path, it becomes more self-contained (good for static site generation, good for admin display). But if it doesn't, the server retains full control over bundling (simpler, less to coordinate).
24
+
25
+ ---
26
+
27
+ ## 2. Static vs. dynamic pages — who decides?
28
+
29
+ A static page serves the same HTML to every request. A dynamic page generates HTML per-request (SSR). Today, all pages are effectively static — bundled once, served forever.
30
+
31
+ **Option A**: Page declares its render mode:
32
+ ```js
33
+ new Webpage({ path: '/profile', content: Profile, render_mode: 'dynamic' });
34
+ ```
35
+
36
+ **Option B**: Server decides based on the content type (function = dynamic, instance = static).
37
+
38
+ **Option C**: Server decides, but page can opt in:
39
+ ```js
40
+ new Webpage({ path: '/profile', content: Profile, dynamic: true });
41
+ ```
42
+
43
+ **The tension**: Render mode has huge server implications (static pre-render vs. per-request handler). Should the page author decide this, or should the server operator? A page author might not understand the performance implications.
44
+
45
+ ---
46
+
47
+ ## 3. Can these modules be used without jsgui3-server?
48
+
49
+ Potential non-server use cases:
50
+ - **Static site generator** — iterate pages, render each to an HTML file
51
+ - **Sitemap generator** — iterate pages, output XML
52
+ - **Documentation tool** — display the website structure
53
+ - **Testing** — assert that a website has the right pages/endpoints
54
+
55
+ If the answer is "yes, these should work standalone," it pushes toward keeping them dependency-light and not assuming a server context. If the answer is "they're primarily for jsgui3-server," more coupling is acceptable.
56
+
57
+ **Current position**: Both packages will depend on `jsgui3-html` (for `Evented_Class`), but nothing from `jsgui3-server`. This makes standalone use possible.
58
+
59
+ ---
60
+
61
+ ## 4. Page ordering
62
+
63
+ Does the order of pages matter?
64
+
65
+ **Yes**: Navigation menus, sitemaps, breadcrumbs all have a natural order. If pages are in a Map, insertion order is preserved — but is that the intended display order?
66
+
67
+ **No**: Pages are identified by path, not position. A navigation component would use explicit ordering, not page insertion order.
68
+
69
+ **Maybe**: An optional `order` or `nav_index` property could let pages opt into ordered display:
70
+ ```js
71
+ new Webpage({ path: '/about', title: 'About', nav_index: 2 });
72
+ ```
73
+
74
+ This doesn't need to be decided now, but the data structure choice (Map preserves order; plain objects have less predictable iteration) has implications.
75
+
76
+ ---
77
+
78
+ ## 5. Nested routes
79
+
80
+ Should a Website support hierarchical page grouping?
81
+
82
+ ```
83
+ /docs
84
+ /docs/getting-started
85
+ /docs/api
86
+ /docs/api/server
87
+ /docs/api/server/serve
88
+ ```
89
+
90
+ **Option A**: Flat list — all pages are siblings. The path hierarchy is implicit in the path strings. Navigation code parses paths to build trees.
91
+
92
+ **Option B**: Page groups — pages can have child pages:
93
+ ```js
94
+ site.add_page({
95
+ path: '/docs',
96
+ content: DocsIndex,
97
+ children: [
98
+ { path: '/docs/getting-started', content: GettingStarted },
99
+ { path: '/docs/api', content: ApiDocs }
100
+ ]
101
+ });
102
+ ```
103
+
104
+ **Option C**: Separate concept — a `Route_Group` or `Page_Group` class that wraps related pages.
105
+
106
+ **The pragmatic answer**: Start flat. If path hierarchy matters, it can be derived from path strings. Adding a formal grouping mechanism before there's a concrete use case for it adds complexity without clear benefit.
107
+
108
+ ---
109
+
110
+ ## 6. Multiple websites on one server
111
+
112
+ Can a single `jsgui3-server` serve multiple websites?
113
+
114
+ Today, `server.js` uses `Website_Group` (a Collection) which implies yes. But the implementation is skeletal. If this is a real requirement, it affects how websites declare their `base_path` and how the server routes between them.
115
+
116
+ ```js
117
+ Server.serve({
118
+ websites: [
119
+ new Website({ name: 'main', base_path: '/', pages: [...] }),
120
+ new Website({ name: 'admin', base_path: '/admin', pages: [...] })
121
+ ]
122
+ });
123
+ ```
124
+
125
+ This might be over-engineering. The more common pattern is one server, one website, multiple pages.
126
+
127
+ ---
128
+
129
+ ## 7. Hot reloading and live updates
130
+
131
+ If a Website raises `'page-added'` events, could the server react to runtime page additions?
132
+
133
+ ```js
134
+ const site = new Website({ pages: [...] });
135
+ Server.serve(site);
136
+
137
+ // Later:
138
+ site.add_page({ path: '/new', content: NewPage });
139
+ // → server automatically adds the route?
140
+ ```
141
+
142
+ This would be powerful for development workflows (add a page, see it immediately without restarting). But it requires publisher support for incremental bundling and route registration. The `finalize()` lifecycle model from Chapter 4 explicitly prevents this by design.
143
+
144
+ **The safe answer**: Don't support it initially. Build for "define site → serve it" as a one-shot workflow. If hot reloading becomes important, `Evented_Class` as the base makes it possible later — the events are there, the server just needs to listen.
145
+
146
+ ---
147
+
148
+ ## 8. Error boundaries
149
+
150
+ When a page's content control throws during rendering, what happens?
151
+
152
+ **Option A**: The server catches it and shows an error page (500).
153
+ **Option B**: The Website has an `error_page` property for a custom error control.
154
+ **Option C**: Each page has its own error boundary.
155
+
156
+ This is entirely a server concern and probably shouldn't be in the Website/Webpage API at all. But it's worth noting because the proposals don't mention it.
157
+
158
+ ---
159
+
160
+ ## 9. The `server` property in Website
161
+
162
+ The current `Website.js` stores `this.server` from the spec:
163
+ ```js
164
+ this.api = new API({ server: this.server });
165
+ ```
166
+
167
+ Should the new Website know about its server?
168
+
169
+ **No**: The Website is an abstract definition. It shouldn't know *how* it's being served. The server consumes the Website, not the other way around.
170
+
171
+ **Yes**: Some use cases (publishing, URL generation) require knowing the server's hostname, port, or base URL. The Website could hold this as metadata.
172
+
173
+ **Compromise**: Don't store a server reference. If the Website needs deployment context, that's provided at serve-time by the server, not stored in the definition.
174
+
175
+ ---
176
+
177
+ ## 10. What to implement first
178
+
179
+ Given everything discussed in this book, what's the minimum viable Website + Webpage that would be useful?
180
+
181
+ **Suggested first pass**:
182
+
183
+ 1. `Webpage` extending `Evented_Class` with explicit properties (Chapter 4, Approach B)
184
+ 2. `Website` using Map-based pages and structured API (Chapter 5, Approach B)
185
+ 3. Fix the API.js export bug (Chapter 2)
186
+ 4. Ship as 0.0.9 of both packages
187
+ 5. Add Website detection to `serve-factory.js` (Chapter 8, minimal approach)
188
+ 6. Test with an example that creates a Website and serves it
189
+
190
+ Everything else — normalization layers, publisher refactoring, admin integration, lifecycle finalization — can follow once the basics work.
191
+
192
+ ---
193
+
194
+ ## Note on Chapter 11
195
+
196
+ Chapter 11 (`11-converged-recommendation.md`) provides an updated synthesis and phased plan that refines this first-pass list into a more explicit baseline contract and delivery sequence.
@@ -0,0 +1,205 @@
1
+ # Chapter 11: Converged Recommendation
2
+
3
+ This chapter turns the debate from previous chapters into a concrete baseline that can be implemented incrementally.
4
+
5
+ The goal is not to "win" every design argument. The goal is to define a stable, useful first version that keeps `jsgui3-server` backward-compatible while unlocking richer website/webpage primitives.
6
+
7
+ ---
8
+
9
+ ## 11.1 Decision Summary
10
+
11
+ | Area | Recommended baseline | Why |
12
+ |---|---|---|
13
+ | Base class | `Evented_Class` with plain property assignment | Ecosystem-consistent, low overhead, no per-property event boilerplate |
14
+ | Webpage contract | Explicit known fields + `toJSON()` + lightweight validation | Improves introspection and catches common mistakes early |
15
+ | Website pages storage | Internal `Map` keyed by normalized path | O(1) lookup, duplicate detection, insertion-order preserved |
16
+ | Website API layer | Structured endpoint registry (Map-backed) with metadata | Supports docs/admin/auth/method semantics without server coupling |
17
+ | Server input handling | Normalize all input shapes into one internal manifest | Keeps publishers simple and removes shape-specific branching |
18
+ | Type detection | Capability checks with optional explicit marker | Avoids brittle `instanceof` behavior in linked/workspace installs |
19
+ | Lifecycle | Optional `finalize()` boundary, not full reactive mutation system | Safer publishing without heavy event complexity |
20
+
21
+ ---
22
+
23
+ ## 11.2 Minimal Stable Primitive Contract
24
+
25
+ The first stable release should guarantee this contract.
26
+
27
+ ### `Webpage`
28
+
29
+ Required:
30
+
31
+ 1. `path` (string, normalized to leading slash)
32
+ 2. `ctrl` (control constructor / renderer)
33
+
34
+ Recommended:
35
+
36
+ 1. `name`
37
+ 2. `title`
38
+ 3. `content` (structured content/i18n data, optional)
39
+ 4. `meta`
40
+ 5. `scripts`
41
+ 6. `stylesheets`
42
+ 7. `render_mode` (`static` or `dynamic`) — see [Chapter 4 discussion](04-webpage.md)
43
+ 8. `toJSON()` for deterministic introspection
44
+
45
+ Compatibility during migration:
46
+
47
+ 1. Accept legacy `content: Function` as an alias for `ctrl`.
48
+ 2. Normalize to `ctrl` internally so server/publisher code has one renderer field.
49
+
50
+ ### `Website`
51
+
52
+ Required:
53
+
54
+ 1. page registry (`add_page`, `get_page`, `has_page`, `remove_page`, `pages`, `routes`)
55
+ 2. API registry (`add_endpoint`/`define_endpoint`, `get_endpoint`, `api_endpoints`)
56
+
57
+ Recommended:
58
+
59
+ 1. `name`
60
+ 2. `meta`
61
+ 3. `assets`
62
+ 4. `base_path`
63
+ 5. `toJSON()` summary for admin/tooling
64
+
65
+ ---
66
+
67
+ ## 11.3 Server Integration Baseline
68
+
69
+ `jsgui3-server` should treat Website/Webpage support as additive and normalize all inputs.
70
+
71
+ ### Input forms to support
72
+
73
+ 1. `Server.serve(MyCtrl)`
74
+ 2. `Server.serve({ pages: {...}, api: {...} })`
75
+ 3. `Server.serve(new Webpage(...))`
76
+ 4. `Server.serve(new Website(...))`
77
+ 5. shape-compatible plain objects for page/site definitions
78
+
79
+ ### Internal flow
80
+
81
+ 1. Detect and normalize input into `normalized_website_manifest`
82
+ 2. Validate normalized routes/endpoints
83
+ 3. Build static and dynamic page route registrations
84
+ 4. Publish API endpoints with method/path metadata
85
+ 5. Expose publication summary for introspection/admin
86
+
87
+ This keeps the publisher pipeline focused on serving, not on input parsing.
88
+
89
+ ---
90
+
91
+ ## 11.4 Validation Policy
92
+
93
+ Use two-stage validation.
94
+
95
+ Construction-time lightweight validation:
96
+
97
+ 1. route is string-like
98
+ 2. handler/content types are sane
99
+ 3. obvious shape errors fail fast
100
+
101
+ Publish-time strict validation:
102
+
103
+ 1. duplicate routes
104
+ 2. invalid HTTP methods
105
+ 3. unresolved assets
106
+ 4. unsupported render modes
107
+
108
+ This avoids over-strict constructors while still giving strong safety before serving.
109
+
110
+ ---
111
+
112
+ ## 11.5 Backward Compatibility Rules
113
+
114
+ These rules should hold through the migration.
115
+
116
+ 1. Existing `Server.serve(...)` signatures continue to work unchanged.
117
+ 2. Existing `api: { name: fn }` remains valid.
118
+ 3. Existing control-first one-liner remains first-class.
119
+ 4. New Website/Webpage primitives are optional convenience, not mandatory API layers.
120
+ 5. Deprecations, if any, should be warning-only for at least one minor cycle.
121
+
122
+ Field migration rule:
123
+
124
+ 1. `Webpage.ctrl` is the canonical renderer field.
125
+ 2. Legacy `Webpage.content` used as a renderer remains accepted as input during migration.
126
+ 3. Server normalization maps both shapes into one internal manifest (`ctrl` canonical, structured content separate).
127
+
128
+ ---
129
+
130
+ ## 11.6 Non-Goals for the First Release
131
+
132
+ To keep scope controlled, do not block first release on:
133
+
134
+ 1. runtime hot-add/remove page re-publication
135
+ 2. nested page-tree abstractions
136
+ 3. full OpenAPI generation
137
+ 4. advanced per-route auth/rate-limit engines
138
+ 5. multi-website orchestration features
139
+
140
+ These can be layered in after stable primitive/server interoperability is proven.
141
+
142
+ ---
143
+
144
+ ## 11.7 Suggested Phased Delivery
145
+
146
+ 1. **Phase A: Primitive stabilization**
147
+ Finalize `Webpage` and `Website` contracts, including `toJSON()` and minimal validation.
148
+
149
+ 2. **Phase B: Server normalization layer**
150
+ Add `normalize_serve_input` + manifest conversion in `serve-factory.js`.
151
+
152
+ 3. **Phase C: Publisher alignment**
153
+ Refactor publishers to consume normalized manifests and remove `._arr`/`instanceof` coupling.
154
+
155
+ 4. **Phase D: Tooling/admin surfacing**
156
+ Expose website manifest and publication summary in admin APIs/UI.
157
+
158
+ Each phase should ship with targeted tests and can be released independently.
159
+
160
+ ---
161
+
162
+ ## 11.8 Recommended First Implementation Target
163
+
164
+ A pragmatic first milestone:
165
+
166
+ 1. Webpage with explicit fields + `toJSON()` + path normalization
167
+ 2. Website with Map-backed page registry + structured API endpoint registry
168
+ 3. Server normalization for Website/Webpage inputs
169
+ 4. Route conflict detection and clear error messages
170
+ 5. No regressions for legacy `Server.serve` usage
171
+
172
+ If this milestone is stable, the architecture is validated and later enhancements become straightforward rather than speculative.
173
+
174
+ ---
175
+
176
+ ## 11.9 Acceptance Criteria for the Milestone
177
+
178
+ 1. A `Website` with at least two pages serves both routes correctly.
179
+ 2. A `Webpage` passed directly to `Server.serve(...)` serves at its declared path.
180
+ 3. Duplicate page paths fail with a deterministic, actionable error.
181
+ 4. API endpoint metadata (`method`, `path`) is preserved through normalization and publication.
182
+ 5. Legacy usage (`Server.serve(MyCtrl)`, `Server.serve({ pages, api })`) still passes existing tests.
183
+
184
+ ---
185
+
186
+ ## 11.10 Forward References
187
+
188
+ The following chapters expand this recommendation into full implementation blueprints:
189
+
190
+ - **[Chapter 12](12-content-model.md)**: Defines the content model — how Webpage holds text strings, structured data, and i18n translations
191
+ - **[Chapter 13](13-webpage-module-spec.md)**: Complete module specification for `jsgui3-webpage` (constructor, every method, validation, test plan)
192
+ - **[Chapter 14](14-website-module-spec.md)**: Complete module specification for `jsgui3-website` (page registry, API registry, finalize cascade)
193
+ - **[Chapter 15](15-multi-repo-plan.md)**: Multi-repo implementation coordination (dependency graph, phased delivery, version pinning)
194
+
195
+ ---
196
+
197
+ ## 11.11 Version Track Alignment
198
+
199
+ To avoid ambiguity across later chapters:
200
+
201
+ 1. **v0.1.x** is the minimal-first track from Chapter 16 (small surface, fast adoption).
202
+ 2. **v0.3.x** is the full-spec target from Chapters 13 and 14 (lifecycle, introspection, i18n helpers, richer API).
203
+ 3. Chapter 15 coordinates both tracks as one migration path, not competing plans.
204
+
205
+ **Current status (Feb 2026)**: Codex implemented the full spec (see [Ch.17](17-implementation-report-codex.md)). Implementation exists in repo source but packages have not yet been published to npm (still v0.0.8 on registry). Server integration (`normalize_serve_input`, `website_manifest`) is live in `serve-factory.js`.