generator-white-label 9.0.0 → 10.0.0

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 (98) hide show
  1. package/CLI.md +13 -17
  2. package/EXISTING_APPLICATIONS.md +155 -0
  3. package/PACKAGE_MANAGERS.md +6 -4
  4. package/README.md +135 -153
  5. package/app/404.ts +28 -0
  6. package/app/README.md +19 -7
  7. package/{scaffold/no-jsx/app → app}/assets/script/index.ts +1 -0
  8. package/{scaffold/no-jsx/app → app}/assets/script/tasks/TaskView.ts +1 -1
  9. package/app/assets/view/CodeBlock.ts +15 -0
  10. package/app/assets/view/examples/tasks/TaskExample.ts +50 -0
  11. package/app/assets/view/examples/tasks/task-state.ts +1 -1
  12. package/app/assets/view/layout/SiteFooter.ts +11 -0
  13. package/app/assets/view/layout/SiteHeader.ts +17 -0
  14. package/app/assets/view/page-data.ts +2 -2
  15. package/app/assets/view/sections/GettingStartedSection.ts +26 -0
  16. package/app/assets/view/sections/HeroSection.ts +15 -0
  17. package/app/assets/view/sections/LiveExampleSection.ts +24 -0
  18. package/app/assets/view/sections/PackageDocsSection.ts +69 -0
  19. package/app/assets/view/sections/{SourceGuideSection.tsx → SourceGuideSection.ts} +11 -16
  20. package/app/index.ts +50 -0
  21. package/cli/index.ts +4 -41
  22. package/dist/app/404.d.ts +1 -1
  23. package/dist/app/404.js +18 -2
  24. package/dist/app/404.js.map +1 -1
  25. package/dist/app/assets/script/index.d.ts +1 -6
  26. package/dist/app/assets/script/index.js +1 -6
  27. package/dist/app/assets/script/index.js.map +1 -1
  28. package/dist/app/assets/script/tasks/TaskView.d.ts +1 -6
  29. package/dist/app/assets/script/tasks/TaskView.js +2 -8
  30. package/dist/app/assets/script/tasks/TaskView.js.map +1 -1
  31. package/dist/app/assets/view/CodeBlock.d.ts +3 -3
  32. package/dist/app/assets/view/CodeBlock.js +4 -2
  33. package/dist/app/assets/view/CodeBlock.js.map +1 -1
  34. package/dist/app/assets/view/examples/tasks/TaskExample.d.ts +2 -8
  35. package/dist/app/assets/view/examples/tasks/TaskExample.js +41 -9
  36. package/dist/app/assets/view/examples/tasks/TaskExample.js.map +1 -1
  37. package/dist/app/assets/view/examples/tasks/task-state.d.ts +1 -1
  38. package/dist/app/assets/view/examples/tasks/task-state.js.map +1 -1
  39. package/dist/app/assets/view/layout/SiteFooter.d.ts +2 -2
  40. package/dist/app/assets/view/layout/SiteFooter.js +8 -3
  41. package/dist/app/assets/view/layout/SiteFooter.js.map +1 -1
  42. package/dist/app/assets/view/layout/SiteHeader.d.ts +2 -8
  43. package/dist/app/assets/view/layout/SiteHeader.js +14 -9
  44. package/dist/app/assets/view/layout/SiteHeader.js.map +1 -1
  45. package/dist/app/assets/view/page-data.d.ts +2 -2
  46. package/dist/app/assets/view/page-data.js.map +1 -1
  47. package/dist/app/assets/view/sections/GettingStartedSection.d.ts +1 -1
  48. package/dist/app/assets/view/sections/GettingStartedSection.js +21 -6
  49. package/dist/app/assets/view/sections/GettingStartedSection.js.map +1 -1
  50. package/dist/app/assets/view/sections/HeroSection.d.ts +2 -8
  51. package/dist/app/assets/view/sections/HeroSection.js +12 -9
  52. package/dist/app/assets/view/sections/HeroSection.js.map +1 -1
  53. package/dist/app/assets/view/sections/LiveExampleSection.d.ts +2 -6
  54. package/dist/app/assets/view/sections/LiveExampleSection.js +17 -7
  55. package/dist/app/assets/view/sections/LiveExampleSection.js.map +1 -1
  56. package/dist/app/assets/view/sections/PackageDocsSection.d.ts +1 -1
  57. package/dist/app/assets/view/sections/PackageDocsSection.js +57 -20
  58. package/dist/app/assets/view/sections/PackageDocsSection.js.map +1 -1
  59. package/dist/app/assets/view/sections/SourceGuideSection.d.ts +2 -7
  60. package/dist/app/assets/view/sections/SourceGuideSection.js +20 -8
  61. package/dist/app/assets/view/sections/SourceGuideSection.js.map +1 -1
  62. package/dist/app/index.d.ts +2 -8
  63. package/dist/app/index.js +36 -11
  64. package/dist/app/index.js.map +1 -1
  65. package/dist/cli/index.d.ts +0 -3
  66. package/dist/cli/index.js +4 -36
  67. package/dist/cli/index.js.map +1 -1
  68. package/dist/scaffold/index.d.ts +2 -13
  69. package/dist/scaffold/index.js +17 -53
  70. package/dist/scaffold/index.js.map +1 -1
  71. package/dist/scripts/build.js +97 -28
  72. package/dist/scripts/build.js.map +1 -1
  73. package/dist/server/handler.js +2 -9
  74. package/dist/server/handler.js.map +1 -1
  75. package/package.json +22 -22
  76. package/pnpm-workspace.yaml +0 -1
  77. package/scaffold/AGENTS.md +13 -8
  78. package/scaffold/index.ts +17 -57
  79. package/scripts/build.ts +90 -30
  80. package/server/handler.ts +2 -10
  81. package/tsconfig.site.json +1 -4
  82. package/app/404.tsx +0 -28
  83. package/app/assets/script/index.tsx +0 -13
  84. package/app/assets/script/tasks/TaskView.tsx +0 -24
  85. package/app/assets/view/CodeBlock.tsx +0 -17
  86. package/app/assets/view/examples/tasks/TaskExample.tsx +0 -63
  87. package/app/assets/view/layout/SiteFooter.tsx +0 -11
  88. package/app/assets/view/layout/SiteHeader.tsx +0 -23
  89. package/app/assets/view/sections/GettingStartedSection.tsx +0 -27
  90. package/app/assets/view/sections/HeroSection.tsx +0 -21
  91. package/app/assets/view/sections/LiveExampleSection.tsx +0 -29
  92. package/app/assets/view/sections/PackageDocsSection.tsx +0 -69
  93. package/app/index.tsx +0 -54
  94. package/scaffold/no-jsx/README.md +0 -73
  95. package/scaffold/no-jsx/app/404.ts +0 -10
  96. package/scaffold/no-jsx/app/assets/view/examples/tasks/TaskExample.ts +0 -39
  97. package/scaffold/no-jsx/app/index.ts +0 -58
  98. package/tsconfig.site.no-jsx.json +0 -24
package/CLI.md CHANGED
@@ -7,7 +7,7 @@ CLI ──────> createProject() ──────> project
7
7
  Node API ─┘
8
8
  ```
9
9
 
10
- `createProject()` owns the scaffold, including destination safety. The CLI translates command-line input into that API.
10
+ `createProject()` owns the canonical tagged-template scaffold, including destination safety. The CLI translates command-line input into that API; it does not maintain a second generation path.
11
11
 
12
12
  ## Create a project
13
13
 
@@ -36,23 +36,21 @@ npm install && npm test
36
36
  # or: pnpm install && pnpm test
37
37
  ```
38
38
 
39
- When run interactively, the CLI asks whether page and view templates should use JSX/TSX. JSX is optional: choose **Yes** for White Label's first-party JSX syntax such as `<section>...</section>`, or **No** for plain TypeScript functions that return HTML strings. Both choices produce the same working starter application and features.
39
+ The generated project uses ordinary `.ts` files and White Label View's first-party tagged HTML templates:
40
40
 
41
- Choose **No** when you want plain string templates or plan to use a third-party renderer. Install that renderer in the generated application and call it from the View `template` function; White Label does not require an adapter. See [Template engines and JSX options](https://whitelabeljs.org/docs/view/#template-engines) for the tested third-party engines and rendering contract.
41
+ ```ts
42
+ import {html} from 'white-label-view/html';
42
43
 
43
- For scripts and non-interactive use, choose explicitly:
44
-
45
- ```sh
46
- white-label create my-project --jsx
47
- white-label create my-project --no-jsx
48
-
49
- npx generator-white-label create my-project --jsx
50
- npx generator-white-label create my-project --no-jsx
44
+ export default function Page(data: {title: string}) {
45
+ return html`<main><h1>${data.title}</h1></main>`;
46
+ }
51
47
  ```
52
48
 
53
- The same `--jsx` and `--no-jsx` flags work through `yarn dlx` and `pnpm dlx`.
49
+ Dynamic text and quoted-attribute values are escaped by the tagged-template runtime. Use `attributes()` for conditional/opening-tag attributes and reserve `unsafeHTML()` for application-owned content that is already trusted or sanitized.
54
50
 
55
- If no choice can be asked interactively and neither flag is supplied, JSX is the default.
51
+ There is no generator renderer prompt and no `--jsx` or `--no-jsx` flag. If a project prefers JSX, Handlebars, Eta, EJS, Mustache, Nunjucks, Pug, or another renderer, add it as an application dependency and return its rendered output from View's `template` function. JSX remains a tested third-party option rather than a generator-owned runtime.
52
+
53
+ See [Template engines](https://whitelabeljs.org/docs/view/#template-engines) for tested integrations and trust boundaries.
56
54
 
57
55
  Run `white-label --help` for usage. See [`PACKAGE_MANAGERS.md`](PACKAGE_MANAGERS.md) for package-manager compatibility details.
58
56
 
@@ -62,13 +60,10 @@ Run `white-label --help` for usage. See [`PACKAGE_MANAGERS.md`](PACKAGE_MANAGERS
62
60
  import {createProject} from 'generator-white-label';
63
61
 
64
62
  await createProject({
65
- destination: '/absolute/path/to/my-project',
66
- jsx: false
63
+ destination: '/absolute/path/to/my-project'
67
64
  });
68
65
  ```
69
66
 
70
- Set `jsx: true` for JSX/TSX templates or `jsx: false` for plain TypeScript and HTML strings. Use `jsx: false` as the starting point when another template engine should own rendering. Omitting `jsx` defaults to `true`.
71
-
72
67
  `createProject()` uses the same destination-safety rule as the CLI: missing and empty directories are allowed; non-empty directories are rejected before project content is written.
73
68
 
74
69
  ## Read the implementation
@@ -77,6 +72,7 @@ The source is intentionally small enough to teach the design:
77
72
 
78
73
  - `scaffold/index.ts` — project creation and destination-safety boundary
79
74
  - `cli/index.ts` — command-line adapter
75
+ - `app/` — canonical TypeScript/tagged-template starter
80
76
  - `test/` — executable contracts
81
77
 
82
78
  Creation behavior belongs in one place. Future integrations should call `createProject()` rather than copy templates or reimplement generation logic.
@@ -0,0 +1,155 @@
1
+ # Adopt White Label in an existing server-rendered application
2
+
3
+ White Label does not require a rewrite. Existing applications should install only the runtime packages a feature needs and integrate them at explicit boundaries.
4
+
5
+ The **generator is intentionally for new projects** and refuses to scaffold over a non-empty destination. If an application already exists—SFCC/SFRA, a CMS, Rails, PHP, Java, .NET, another server-rendered stack, or a long-lived frontend—do not regenerate the host application. Add White Label to one feature or DOM region at a time.
6
+
7
+ This is one of the strongest White Label use cases: modern TypeScript structure and lifecycle where it helps, while the existing platform keeps ownership of routing, business rules, initial HTML, and the rest of the page.
8
+
9
+ ## When this pattern fits
10
+
11
+ Incremental adoption is a good fit when:
12
+
13
+ - the server or CMS already renders meaningful HTML;
14
+ - public URLs, SEO, accessibility, or no-JavaScript behavior matter;
15
+ - a rewrite would be disproportionate to the feature being added;
16
+ - teams want observable state, lifecycle, application events, or URL-backed interaction without introducing a full frontend framework;
17
+ - multiple teams/features need clear ownership boundaries on the same page;
18
+ - commerce/account/content flows must keep authoritative business logic on the server.
19
+
20
+ It is less compelling for experiences that are intentionally fully client-owned and deeply stateful across most of the viewport, such as editors, design tools, complex collaborative workspaces, or other applications where a component framework already provides valuable shared conventions.
21
+
22
+ ## Install only the needed primitives
23
+
24
+ Start with the actual responsibility the feature needs:
25
+
26
+ ```sh
27
+ npm install white-label-view white-label-model
28
+ ```
29
+
30
+ Add Router or Mediator only when the feature genuinely needs URL state or cross-module events:
31
+
32
+ ```sh
33
+ npm install white-label-router white-label-mediator
34
+ ```
35
+
36
+ White Label packages do not require the generator at runtime and do not require one another unless the application chooses to compose them.
37
+
38
+ A useful rule is:
39
+
40
+ ```text
41
+ existing platform owns the page
42
+ +
43
+ White Label owns a deliberate feature boundary
44
+ ```
45
+
46
+ ## Adopt existing server-rendered markup
47
+
48
+ `white-label-view` can own lifecycle around an element that already exists instead of replacing the host application's rendering system.
49
+
50
+ ```ts
51
+ import {Model} from 'white-label-model';
52
+ import View from 'white-label-view';
53
+
54
+ const status = document.querySelector<HTMLElement>('[data-filter-status]')!;
55
+ const filters = new Model({color: ''});
56
+
57
+ const statusView = new View({
58
+ parentElement: status.parentElement!,
59
+ element: status,
60
+ model: filters,
61
+ update(element, data) {
62
+ const state = data as {color: string};
63
+ element.textContent = state.color
64
+ ? `Color filter: ${state.color}`
65
+ : 'No color filter selected';
66
+ return true;
67
+ }
68
+ }).initialize();
69
+ ```
70
+
71
+ No client template is required when an attached existing element can be updated in place. The host remains responsible for the initial HTML; View owns only the adopted root and its lifecycle.
72
+
73
+ Keep ownership narrow. Unrelated server-rendered siblings, headers, forms, navigation, and page chrome should remain outside the View unless the feature genuinely owns them.
74
+
75
+ `destroy()` removes the root the View owns. If the host application expects that element to remain after enhancement teardown, choose an ownership boundary that can be removed safely rather than treating host-owned markup as disposable.
76
+
77
+ ## Scope progressive routing to one enhanced region
78
+
79
+ By default, Router listens for opted-in `data-pushstate` links across the document. An embedded or incrementally adopted feature can limit that interception to its own DOM region:
80
+
81
+ ```ts
82
+ import Router from 'white-label-router';
83
+
84
+ const refinementArea = document.querySelector<HTMLElement>('[data-refinements]')!;
85
+ const router = new Router();
86
+
87
+ router.navigationRoot = refinementArea;
88
+ router.routes = {
89
+ '/search': (_scope, location) => {
90
+ filters.update({color: location.data.query.prefv1 || ''});
91
+ }
92
+ };
93
+ router.initialize();
94
+ ```
95
+
96
+ Only eligible links whose click event reaches that navigation root are enhanced by that Router. Other page links retain the host application's normal behavior. Multiple independently owned regions can therefore coexist without every Router claiming document-wide link handling.
97
+
98
+ `navigationRoot` controls click-listener ownership. It is deliberately separate from `router.scope`, which remains the value passed to route handlers.
99
+
100
+ ## Add state and events only where needed
101
+
102
+ A feature does not need the full White Label stack.
103
+
104
+ Use `white-label-model` when the feature needs observable state. Load data through the application's existing fetch/client/service layer, validate it at that boundary when appropriate, then apply it to Model. Model should not replace a backend API, persistence layer, or framework store solely for architectural symmetry.
105
+
106
+ Use `white-label-mediator` when separate modules need to exchange intent without importing one another. Direct function calls are clearer when there is already an ownership relationship. Avoid turning a mediator into an unstructured global event namespace.
107
+
108
+ ## Preserve the host application's server contract
109
+
110
+ White Label should not duplicate or bypass server-owned responsibilities. Keep these in the existing platform when it already owns them:
111
+
112
+ - authentication and authorization;
113
+ - pricing, inventory, tax, promotions, checkout, and other authoritative business rules;
114
+ - canonical URLs and directly requestable public routes;
115
+ - initial semantic content and crawlable navigation;
116
+ - CSRF/session protections and trusted API boundaries;
117
+ - CMS/content governance and server-side personalization rules;
118
+ - persistence, queues, retries, and cross-process workflows.
119
+
120
+ Use White Label where a client-side state, lifecycle, event, or URL boundary adds value. Normal server navigation is still the right choice when enhancement does not materially improve the interaction.
121
+
122
+ ## SEO and accessibility boundary
123
+
124
+ For public content, keep the important information in the initial response. Progressive enhancement should improve interaction rather than become a prerequisite for discovery or comprehension.
125
+
126
+ Prefer:
127
+
128
+ - real `href` values and directly requestable routes;
129
+ - semantic headings, forms, controls, landmarks, and status regions in initial HTML;
130
+ - server/static ownership of canonical URLs, titles, descriptions, robots directives, and structured data;
131
+ - deliberate focus handling after meaningful client-side navigation or content replacement;
132
+ - client behavior that preserves keyboard, context-menu, modified-click, and no-JavaScript behavior.
133
+
134
+ Do not treat source-level metadata as proof of search-engine indexing. Validate deployed behavior and indexing with actual production/search-console evidence.
135
+
136
+ ## Teardown
137
+
138
+ Long-lived shells and dynamically mounted regions should release the objects they own:
139
+
140
+ ```ts
141
+ statusView.destroy();
142
+ router.destroy();
143
+ filters.destroy();
144
+ ```
145
+
146
+ Also destroy a feature-owned Mediator when that event boundary leaves the application lifecycle.
147
+
148
+ ## Commerce and SFCC example
149
+
150
+ The White Label demo repository contains a concrete Salesforce B2C Commerce / SFRA example using the same incremental boundary:
151
+
152
+ - [SFCC / SFRA progressive enhancement recipe](https://github.com/bshack/white-label-demo-site/blob/main/docs/recipes/sfcc-sfra-progressive-enhancement.md)
153
+ - [Incremental JavaScript for server-rendered applications](https://whitelabeljs.org/guides/incremental-javascript-for-server-rendered-apps/)
154
+
155
+ The same pattern applies to other server-rendered stacks: keep the server as the source of truth, then adopt only the client-side regions that need richer behavior.
@@ -10,9 +10,9 @@ yarn dlx generator-white-label create my-project
10
10
  pnpm dlx generator-white-label create my-project
11
11
  ```
12
12
 
13
- The same `--jsx` and `--no-jsx` options are available through every invocation path. JSX is optional: use `--jsx` for the first-party White Label JSX runtime, or `--no-jsx` for plain TypeScript templates and as the starting point for a third-party template engine.
13
+ Every invocation creates the same canonical TypeScript/tagged-template starter. There are no renderer-selection flags.
14
14
 
15
- See [Template engines and JSX options](https://whitelabeljs.org/docs/view/#template-engines) for tested third-party renderers and the View rendering contract.
15
+ White Label View remains template-engine agnostic. Projects that prefer JSX or a third-party renderer can install it after generation and return its rendered output from View's `template` function. See [Template engines](https://whitelabeljs.org/docs/view/#template-engines) for tested integrations and trust boundaries.
16
16
 
17
17
  ## Work with a generated project
18
18
 
@@ -26,10 +26,12 @@ pnpm install && pnpm test
26
26
 
27
27
  Generated manifests require the supported Node.js runtime but do not require a specific package manager. Nested scripts use Node's `--run` support instead of invoking npm internally.
28
28
 
29
- Generated projects use exact npm versions for the four first-party White Label packages. They also carry narrow install-script approvals for the dependencies that actually need lifecycle builds: `esbuild`, `@parcel/watcher`, and `white-label-view`. npm uses pinned `allowScripts` entries, Yarn uses pinned `dependenciesMeta` build permissions, and pnpm uses `onlyBuiltDependencies`.
29
+ Generated projects use exact npm versions for the four first-party White Label packages. Install/build lifecycle approvals are limited to dependencies that need native or generated artifacts during installation: `esbuild` and `@parcel/watcher`. npm uses pinned `allowScripts` entries, Yarn uses pinned `dependenciesMeta` build permissions, and pnpm uses `onlyBuiltDependencies`. Published White Label runtime packages include their built output and do not receive lifecycle-script approval in generated projects.
30
30
 
31
- Yarn's package-age security gate is left enabled for ordinary dependencies. The generated `.yarnrc.yml` preapproves only `white-label-mediator`, `white-label-model`, `white-label-router`, and `white-label-view` so a newly published White Label release can be installed immediately without disabling Yarn's protection for the rest of the dependency graph.
31
+ Yarn's package-age security gate is left enabled for ordinary dependencies. The generated `.yarnrc.yml` preapproves only `white-label-mediator`, `white-label-model`, `white-label-router`, and `white-label-view` so a newly published coordinated White Label release can be installed immediately without disabling Yarn's protection for the rest of the dependency graph. Package-age preapproval does not grant lifecycle-script execution.
32
32
 
33
33
  ## Repository development
34
34
 
35
35
  The committed `package-lock.json` remains the generator repository's canonical dependency lockfile and npm remains the maintenance/audit path used by primary CI. Compatibility CI packs the real generator artifact and verifies its API and CLI under npm, Yarn, and pnpm. Alternate lockfiles are not committed merely for compatibility testing.
36
+
37
+ Generator 10 depends on `white-label-view@7`. View 7's implementation is merged but not yet published, so coordinated CI temporarily builds and injects the exact merged View 7 revision for integration testing. The release lockfile remains registry-based; do not replace it with a Git dependency or treat the temporary packed artifact as a published dependency. Normal registry installation remains a release gate until View 7 is published.