@bleedingdev/modern-js-create 3.2.0-ultramodern.12 → 3.2.0-ultramodern.120

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 (75) hide show
  1. package/README.md +146 -74
  2. package/bin/run.js +0 -0
  3. package/dist/cjs/create-package-root.cjs +65 -0
  4. package/dist/cjs/index.cjs +498 -0
  5. package/dist/cjs/locale/en.cjs +94 -0
  6. package/dist/cjs/locale/index.cjs +50 -0
  7. package/dist/cjs/locale/zh.cjs +94 -0
  8. package/dist/cjs/ultramodern-package-source.cjs +135 -0
  9. package/dist/cjs/ultramodern-workspace.cjs +6797 -0
  10. package/dist/esm/create-package-root.js +16 -0
  11. package/dist/esm/index.js +461 -0
  12. package/dist/esm/locale/en.js +56 -0
  13. package/dist/esm/locale/index.js +9 -0
  14. package/dist/esm/locale/zh.js +56 -0
  15. package/dist/esm/ultramodern-package-source.js +63 -0
  16. package/dist/esm/ultramodern-workspace.js +6738 -0
  17. package/dist/esm-node/create-package-root.js +17 -0
  18. package/dist/esm-node/index.js +462 -0
  19. package/dist/esm-node/locale/en.js +57 -0
  20. package/dist/esm-node/locale/index.js +10 -0
  21. package/dist/esm-node/locale/zh.js +57 -0
  22. package/dist/esm-node/ultramodern-package-source.js +64 -0
  23. package/dist/esm-node/ultramodern-workspace.js +6739 -0
  24. package/dist/types/create-package-root.d.ts +1 -0
  25. package/dist/types/locale/en.d.ts +7 -7
  26. package/dist/types/locale/index.d.ts +111 -2
  27. package/dist/types/locale/zh.d.ts +7 -7
  28. package/dist/types/ultramodern-package-source.d.ts +28 -0
  29. package/dist/types/ultramodern-workspace.d.ts +12 -3
  30. package/package.json +33 -15
  31. package/template-workspace/.agents/agent-reference-repos.json +24 -0
  32. package/template-workspace/.agents/skills-lock.json +19 -0
  33. package/template-workspace/.codex/hooks.json +16 -0
  34. package/template-workspace/.github/renovate.json +29 -0
  35. package/template-workspace/.github/workflows/ultramodern-workspace-gates.yml.handlebars +70 -0
  36. package/template-workspace/.gitignore.handlebars +5 -0
  37. package/template-workspace/.mise.toml.handlebars +2 -0
  38. package/template-workspace/AGENTS.md +43 -11
  39. package/template-workspace/README.md.handlebars +116 -11
  40. package/template-workspace/lefthook.yml +24 -0
  41. package/template-workspace/oxfmt.config.ts +1 -0
  42. package/template-workspace/oxlint.config.ts +1 -0
  43. package/template-workspace/pnpm-workspace.yaml +31 -8
  44. package/template-workspace/scripts/bootstrap-agent-skills.mjs +204 -21
  45. package/template-workspace/scripts/setup-agent-reference-repos.mjs +370 -0
  46. package/dist/index.js +0 -2626
  47. package/template/.agents/skills-lock.json +0 -34
  48. package/template/.browserslistrc +0 -4
  49. package/template/.github/workflows/ultramodern-gates.yml.handlebars +0 -30
  50. package/template/.gitignore.handlebars +0 -30
  51. package/template/.nvmrc +0 -2
  52. package/template/AGENTS.md +0 -25
  53. package/template/README.md +0 -79
  54. package/template/api/effect/index.ts.handlebars +0 -23
  55. package/template/api/lambda/hello.ts.handlebars +0 -6
  56. package/template/config/public/locales/cs/translation.json +0 -39
  57. package/template/config/public/locales/en/translation.json +0 -39
  58. package/template/modern.config.ts.handlebars +0 -53
  59. package/template/oxfmt.config.ts +0 -8
  60. package/template/oxlint.config.ts +0 -12
  61. package/template/package.json.handlebars +0 -67
  62. package/template/postcss.config.mjs.handlebars +0 -6
  63. package/template/scripts/bootstrap-agent-skills.mjs +0 -95
  64. package/template/scripts/check-i18n-strings.mjs +0 -83
  65. package/template/scripts/validate-ultramodern.mjs.handlebars +0 -178
  66. package/template/shared/effect/api.ts.handlebars +0 -17
  67. package/template/src/modern-app-env.d.ts +0 -1
  68. package/template/src/modern.runtime.ts.handlebars +0 -23
  69. package/template/src/routes/index.css.handlebars +0 -129
  70. package/template/src/routes/layout.tsx.handlebars +0 -9
  71. package/template/src/routes/page.tsx.handlebars +0 -155
  72. package/template/tailwind.config.ts.handlebars +0 -10
  73. package/template/tsconfig.json +0 -120
  74. package/template-workspace/scripts/check-i18n-strings.mjs +0 -83
  75. package/template-workspace/scripts/validate-ultramodern-workspace.mjs.handlebars +0 -433
package/README.md CHANGED
@@ -8,117 +8,189 @@
8
8
  A Progressive React Framework for modern web development.
9
9
  </p>
10
10
 
11
- ## Getting Started
11
+ ## UltraModern.js Create
12
12
 
13
- Please follow [Quick Start](https://modernjs.dev/en/guides/get-started/quick-start) to get started with Modern.js.
14
-
15
- For UltraModern.js, use the BleedingDev create package. It defaults to the
16
- canonical SuperApp workspace and published BleedingDev package aliases:
13
+ The BleedingDev create package has one supported generated product: an
14
+ UltraModern SuperApp workspace.
17
15
 
18
16
  ```bash
19
- pnpm dlx @bleedingdev/modern-js-create my-super-app
17
+ pnpm dlx @bleedingdev/modern-js-create my-workspace
20
18
  ```
21
19
 
22
- ### Router Template
23
-
24
- You can scaffold a TanStack Router first template:
20
+ To initialize the empty directory you are already in, pass `.` explicitly:
25
21
 
26
22
  ```bash
27
- npx @modern-js/create my-app --router tanstack
23
+ pnpm dlx @bleedingdev/modern-js-create .
28
24
  ```
29
25
 
30
- ### Tailwind Template
31
-
32
- You can scaffold Tailwind CSS v4 setup (PostCSS + starter utility classes):
26
+ The workspace starts shell-only so the first commit has no fake business
27
+ domains to delete. It generates:
33
28
 
34
- ```bash
35
- npx @modern-js/create my-app --tailwind
36
- ```
29
+ - `apps/shell-super-app` as the Module Federation host and topology owner.
30
+ - `verticals/*` empty until a real domain is added with `--vertical`.
31
+ - `packages/shared-*` placeholders for shared contracts, tokens, and Effect
32
+ API support.
33
+ - `.modernjs/ultramodern-generated-contract.json` with Module Federation,
34
+ Effect, i18n, federated CSS, Cloudflare, route publicness, generated
35
+ public-surface, and Zephyr dependency metadata.
37
36
 
38
- You can combine both options:
37
+ Validate the generated workspace before making application changes:
39
38
 
40
39
  ```bash
41
- npx @modern-js/create my-app --router tanstack --tailwind
40
+ cd my-workspace
41
+ mise install
42
+ pnpm install
43
+ pnpm check
44
+ pnpm build
42
45
  ```
43
46
 
44
- ### BFF Runtime Template
47
+ Generated CI does not call the local aggregate. It runs format, lint,
48
+ typecheck, skills, i18n boundary validation, contract validation, and build as
49
+ separate matrix jobs so failures are isolated and parallelizable. Generated
50
+ lefthook config runs separate format and lint-fix commands on pre-commit, then
51
+ runs the read-only primitive gates in parallel on pre-push.
45
52
 
46
- You can scaffold BFF APIs with the current default runtime:
53
+ For local monorepo dependency testing, add `--workspace`:
47
54
 
48
55
  ```bash
49
- npx @modern-js/create my-app --bff
56
+ pnpm dlx @bleedingdev/modern-js-create my-workspace --workspace
50
57
  ```
51
58
 
52
- You can explicitly scaffold Effect HttpApi runtime for BFF:
53
-
54
- ```bash
55
- npx @modern-js/create my-app --bff-runtime effect
56
- ```
57
-
58
- To scaffold Hono runtime explicitly:
59
-
60
- ```bash
61
- npx @modern-js/create my-app --bff-runtime hono
62
- ```
59
+ For package-source validation outside the monorepo, pass explicit
60
+ `--ultramodern-package-*` options.
63
61
 
64
- Generated starters expose `presetUltramodern(...)` as the public opinionated
65
- config wrapper when you want the full Ultramodern setup surface in
66
- `modern.config.ts`.
62
+ ## Vertical Workspace Recipes
67
63
 
68
- You can combine TanStack Router + Tailwind + Effect BFF in one command:
64
+ Use the workspace add flow from the UltraModern workspace root. It derives the
65
+ package path, package name, port, Module Federation name, topology entry, local
66
+ overlay, ownership entry, Effect BFF surface, and root `dev:*` script from the
67
+ requested vertical name.
69
68
 
70
69
  ```bash
71
- npx @modern-js/create my-app --router tanstack --tailwind --bff-runtime effect
70
+ pnpm dlx @bleedingdev/modern-js-create catalog --vertical
72
71
  ```
73
72
 
74
- ### Micro Vertical Workspace Recipes
75
-
76
- Use the existing create flags to scaffold packages inside a Micro Vertical
77
- workspace. The shell and remotes use TanStack Router; services use Effect by
78
- default, with Hono kept as an explicit compatibility lane.
73
+ Use this decision table before adding a vertical:
74
+
75
+ | Need | Keep inside current vertical | Create a new vertical |
76
+ | --- | --- | --- |
77
+ | Route or widget changes with the same product owner, release train, and fallback behavior | Yes | No |
78
+ | Route subtree needs independent rollout, rollback, or incident ownership | No | `--vertical` |
79
+ | UI and Effect BFF must version, deploy, and roll back together | No | `--vertical` |
80
+ | Design tokens, primitives, generated clients, or domain-neutral utilities | Yes | Use an ordinary workspace package, not a vertical |
81
+ | Feature composites or workflow state shared across verticals | No | Revisit ownership; do not hide it in shared code |
82
+
83
+ ## SuperApp Architecture Contracts
84
+
85
+ The generated shell owns route assembly and policy. Each vertical added with
86
+ `--vertical` owns its route subtree, Module Federation exposes, Effect BFF
87
+ contract, generated client, `localisedUrls`, locale JSON, CSS layer, and
88
+ Cloudflare Worker output. The shell consumes vertical UI through Module
89
+ Federation manifests and vertical APIs through generated Effect clients
90
+ exported by the vertical packages.
91
+
92
+ Route metadata is route-owned and colocated in
93
+ `src/routes/**/route.meta.ts`. The scaffold regenerates
94
+ `src/routes/ultramodern-route-metadata.ts` as a compatibility manifest for
95
+ Modern.js config, i18n, public head, and public surface contracts; authors
96
+ should not hand-maintain it. Locale JSON is served from
97
+ `/locales/{{lng}}/{{ns}}.json`; Czech and English routes are generated from the
98
+ route owner, not from shell rewrites.
99
+
100
+ Routes default to `privateByDefault: true` and
101
+ `publicnessDefault: private-app-screen`. Public web artifacts are build/deploy
102
+ outputs generated by `scripts/generate-public-surface-assets.mjs` into
103
+ `dist/public` and `.output/public`, not source files under `config/public`.
104
+ Generated public files use only explicit `public && indexable` route metadata,
105
+ so private app screens publish only a disallowing `robots.txt` by default.
106
+
107
+ Dynamic public routes can expand sitemap entries through route-owned,
108
+ Node-safe ESM providers, normally `route.sitemap.mjs` beside the route
109
+ metadata. The public-surface generator discovers those providers for dynamic
110
+ public routes and still honors explicit `routes.publicSurface.contentSources`
111
+ entries in the generated compatibility manifest. Providers may export
112
+ `entries`, `entries()`, or a default entries/loader returning sitemap entries;
113
+ draft entries and `indexable: false` entries are omitted.
114
+
115
+ CSS federation is explicit:
116
+
117
+ - `packages/shared-design-tokens` exports `./tokens.css` and owns
118
+ `ultramodern-shared-tokens`.
119
+ - The shell owns shell base and overlay CSS only.
120
+ - Verticals own their vertical CSS layer and `[data-app-id="<vertical>"]`
121
+ root marker.
122
+ - Tailwind CSS v4 is configured per app through `@tailwindcss/postcss`.
123
+ - Duplicate base styles are forbidden; SSR first paint depends on shared token
124
+ CSS plus Modern/Rspack-emitted app CSS.
125
+
126
+ ## Public URL Environment Variables
127
+
128
+ Generated apps no longer bake absolute `http://localhost:<port>` URLs into
129
+ asset configuration. Two environment variables now have distinct roles in
130
+ controlling where assets are served from and where SEO output links point.
131
+
132
+ | Variable | Role | Feeds |
133
+ | --- | --- | --- |
134
+ | `ULTRAMODERN_PUBLIC_URL_<APP_ID>` | Per-app deployment and asset origin | `output.assetPrefix`, Module Federation remote URLs |
135
+ | `MODERN_PUBLIC_SITE_URL` | Site-wide public origin for SEO output | Canonical, hreflang, sitemap `<loc>`, robots `Sitemap:` |
136
+
137
+ Asset URLs use this precedence: `ULTRAMODERN_PUBLIC_URL_<APP_ID>` →
138
+ `MODERN_PUBLIC_SITE_URL` → inferred workers.dev URL → origin-relative `/`.
139
+ SEO and site origin prefer: `MODERN_PUBLIC_SITE_URL` →
140
+ `ULTRAMODERN_PUBLIC_URL_<APP_ID>` → inferred workers.dev → `http://localhost:<port>`.
141
+
142
+ Without public URLs configured, asset paths are origin-relative (`/`), and the
143
+ dev server uses `dev.assetPrefix: '/'` — so apps work through tunnels and
144
+ reverse proxies (ngrok, cloudflared) without triggering Chrome's Local Network
145
+ Access prompt or mixed-content errors. Shell-only workspaces can set just
146
+ `MODERN_PUBLIC_SITE_URL` for SEO output.
147
+
148
+ ## Cloudflare And Zephyr Proof
149
+
150
+ Each generated workspace app has:
151
+
152
+ - `cloudflare:build`, `cloudflare:deploy`, `cloudflare:preview`, and
153
+ `cloudflare:proof` scripts.
154
+ - Cloudflare metadata in `.modernjs/ultramodern-generated-contract.json`.
155
+ - `zephyr:dependencies` for any consumed verticals.
156
+ - `zephyr-rspack-plugin` wired through the generated Modern.js Rspack bridge.
157
+
158
+ Deploy first, then pass each deployed app's generated public URL env key into
159
+ the proof step. The proof script reads the generated contract and checks the
160
+ Cloudflare Worker surface, including public-route sitemap/robots consistency,
161
+ preview noindex behavior, unknown-route status, asset headers, byte budgets,
162
+ and public sourcemap exposure. Shell-only workspaces only need the shell URL;
163
+ added verticals use the same `ULTRAMODERN_PUBLIC_URL_<APP_ID>` pattern with
164
+ hyphens converted to underscores and uppercased:
79
165
 
80
166
  ```bash
81
- npx @modern-js/create apps/shell --router tanstack --tailwind --workspace --sub
82
- npx @modern-js/create apps/remotes/catalog --router tanstack --tailwind --workspace --sub
83
- npx @modern-js/create apps/remotes/design-system --router tanstack --tailwind --workspace --sub
84
- npx @modern-js/create services/catalog-api --bff-runtime effect --workspace --sub
85
- npx @modern-js/create services/legacy-api --bff-runtime hono --workspace --sub
167
+ pnpm cloudflare:deploy
168
+ ULTRAMODERN_PUBLIC_URL_SHELL_SUPER_APP=https://shell-super-app.example.workers.dev \
169
+ ULTRAMODERN_PUBLIC_URL_TRANSPORTATION=https://transportation.example.workers.dev \
170
+ pnpm cloudflare:proof -- --require-public-urls
86
171
  ```
87
172
 
88
- When a design system needs independent deployment, treat it as a horizontal
89
- Module Federation remote with the same topology, trust, SSR, compatibility, and
90
- fallback expectations as feature remotes. Otherwise shared packages should be
91
- regular workspace packages for tokens, primitives, generated clients, or
92
- domain-neutral utilities. Keep feature composites and workflow logic owned by a
93
- shell, remote, or service package.
94
-
95
- See
96
- `docs/super-app-rfc-adr/WORKSPACE-0001-micro-vertical-workspace-scaffolding.md`
97
- for the canonical workspace topology and local orchestration model.
98
-
99
- The published `@bleedingdev/modern-js-create` package is the preferred
100
- UltraModern.js entrypoint. The lower-level `--ultramodern-*` flags remain
101
- available for release engineering and local package-source testing, but users
102
- should not need them for normal app creation.
173
+ Without public URLs and credentials, use local primitive gates and `pnpm build`
174
+ evidence only; do not claim live Cloudflare or Zephyr selection has been
175
+ proven.
103
176
 
104
- ### Local Monorepo Testing
177
+ ## Troubleshooting
105
178
 
106
- When testing unreleased Modern.js packages from a local monorepo checkout, use
107
- workspace protocol dependencies:
179
+ | Symptom | Current check | Owner |
180
+ | --- | --- | --- |
181
+ | Package cohort mismatch | Regenerate with one package source strategy, run `mise install`, then rerun `pnpm install` from the activated shell. | Generated workspace package source metadata |
182
+ | Install failure | Check the active Node/pnpm from `mise install`; rerun `pnpm install` after the shell sees the pinned versions. | Toolchain setup |
183
+ | Build failure | Run the matching primitive gate (`pnpm lint`, `pnpm typecheck`, `pnpm i18n:boundaries`, `pnpm contract:check`) before `pnpm build`; fix the owning failure first. | Owning package or generated contract |
184
+ | Missing public URL | Set the env key from `.modernjs/ultramodern-generated-contract.json`, for example `ULTRAMODERN_PUBLIC_URL_SHELL_SUPER_APP`. | Deployment operator |
185
+ | Cloudflare credentials | Confirm Wrangler credentials before `pnpm cloudflare:deploy`; local checks do not prove live Worker access. | Deployment operator |
186
+ | Asset or CSS 404 | Rebuild with `pnpm build` or `pnpm cloudflare:deploy` and inspect emitted Modern/Rspack asset paths instead of hardcoding CSS URLs. | Framework/runtime asset pipeline |
187
+ | Federation manifest failure | Run the shell and vertical build scripts, then check each deployed `/mf-manifest.json` URL used by the shell. | Module Federation owner |
108
188
 
109
- ```bash
110
- npx @modern-js/create my-app --router tanstack --bff-runtime effect --workspace
111
- ```
112
-
113
- ## Documentation
189
+ ## Modern.js Documentation
114
190
 
115
191
  - [English Documentation](https://modernjs.dev/en/)
116
192
  - [中文文档](https://modernjs.dev)
117
193
 
118
- ## Contributing
119
-
120
- Please read the [Contributing Guide](https://github.com/web-infra-dev/modern.js/blob/main/CONTRIBUTING.md).
121
-
122
194
  ## License
123
195
 
124
196
  Modern.js is [MIT licensed](https://github.com/web-infra-dev/modern.js/blob/main/LICENSE).
package/bin/run.js CHANGED
File without changes
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.n = (module)=>{
5
+ var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
6
+ __webpack_require__.d(getter, {
7
+ a: getter
8
+ });
9
+ return getter;
10
+ };
11
+ })();
12
+ (()=>{
13
+ __webpack_require__.d = (exports1, getters, values)=>{
14
+ var define = (defs, kind)=>{
15
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
16
+ enumerable: true,
17
+ [kind]: defs[key]
18
+ });
19
+ };
20
+ define(getters, "get");
21
+ define(values, "value");
22
+ };
23
+ })();
24
+ (()=>{
25
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
26
+ })();
27
+ (()=>{
28
+ __webpack_require__.r = (exports1)=>{
29
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
30
+ value: 'Module'
31
+ });
32
+ Object.defineProperty(exports1, '__esModule', {
33
+ value: true
34
+ });
35
+ };
36
+ })();
37
+ var __webpack_exports__ = {};
38
+ __webpack_require__.r(__webpack_exports__);
39
+ __webpack_require__.d(__webpack_exports__, {
40
+ resolveCreatePackageRoot: ()=>resolveCreatePackageRoot
41
+ });
42
+ const external_node_fs_namespaceObject = require("node:fs");
43
+ var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
44
+ const external_node_path_namespaceObject = require("node:path");
45
+ var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
46
+ function resolveCreatePackageRoot(fromDir) {
47
+ const candidates = [
48
+ fromDir,
49
+ external_node_path_default().resolve(fromDir, '..'),
50
+ external_node_path_default().resolve(fromDir, '..', '..')
51
+ ];
52
+ const seen = new Set();
53
+ for (const candidate of candidates)if (!seen.has(candidate)) {
54
+ seen.add(candidate);
55
+ if (external_node_fs_default().existsSync(external_node_path_default().join(candidate, 'package.json')) && external_node_fs_default().existsSync(external_node_path_default().join(candidate, 'template-workspace'))) return candidate;
56
+ }
57
+ throw new Error('Unable to resolve create package root');
58
+ }
59
+ exports.resolveCreatePackageRoot = __webpack_exports__.resolveCreatePackageRoot;
60
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
61
+ "resolveCreatePackageRoot"
62
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
63
+ Object.defineProperty(exports, '__esModule', {
64
+ value: true
65
+ });