@bleedingdev/modern-js-create 3.2.0-ultramodern.99 → 3.4.0-ultramodern.1
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.
- package/README.md +281 -106
- package/bin/run.js +1 -0
- package/dist/cjs/create-package-root.cjs +63 -0
- package/dist/cjs/index.cjs +658 -0
- package/dist/cjs/locale/en.cjs +101 -0
- package/dist/cjs/locale/index.cjs +50 -0
- package/dist/cjs/locale/zh.cjs +101 -0
- package/dist/cjs/ultramodern-package-source.cjs +135 -0
- package/dist/cjs/ultramodern-workspace/add-vertical.cjs +603 -0
- package/dist/cjs/ultramodern-workspace/app-files.cjs +223 -0
- package/dist/cjs/ultramodern-workspace/codesmith.cjs +134 -0
- package/dist/cjs/ultramodern-workspace/contracts.cjs +837 -0
- package/dist/cjs/ultramodern-workspace/demo-components.cjs +422 -0
- package/dist/cjs/ultramodern-workspace/descriptors.cjs +222 -0
- package/dist/cjs/ultramodern-workspace/effect-api.cjs +952 -0
- package/dist/cjs/ultramodern-workspace/fs-io.cjs +191 -0
- package/dist/cjs/ultramodern-workspace/generation-result.cjs +158 -0
- package/dist/cjs/ultramodern-workspace/index.cjs +51 -0
- package/dist/cjs/ultramodern-workspace/locales.cjs +173 -0
- package/dist/cjs/ultramodern-workspace/module-federation.cjs +487 -0
- package/dist/cjs/ultramodern-workspace/naming.cjs +161 -0
- package/dist/cjs/ultramodern-workspace/overlays.cjs +120 -0
- package/dist/cjs/ultramodern-workspace/package-json.cjs +406 -0
- package/dist/cjs/ultramodern-workspace/package-source.cjs +59 -0
- package/dist/cjs/ultramodern-workspace/policy.cjs +248 -0
- package/dist/cjs/ultramodern-workspace/public-api.cjs +47 -0
- package/dist/cjs/ultramodern-workspace/public-surface.cjs +268 -0
- package/dist/cjs/ultramodern-workspace/routes.cjs +375 -0
- package/dist/cjs/ultramodern-workspace/types.cjs +61 -0
- package/dist/cjs/ultramodern-workspace/versions.cjs +161 -0
- package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +154 -0
- package/dist/cjs/ultramodern-workspace/write-workspace.cjs +197 -0
- package/dist/esm/create-package-root.js +14 -0
- package/dist/esm/index.js +621 -0
- package/dist/esm/locale/en.js +63 -0
- package/dist/esm/locale/index.js +9 -0
- package/dist/esm/locale/zh.js +63 -0
- package/dist/esm/ultramodern-package-source.js +63 -0
- package/dist/esm/ultramodern-workspace/add-vertical.js +511 -0
- package/dist/esm/ultramodern-workspace/app-files.js +149 -0
- package/dist/esm/ultramodern-workspace/codesmith.js +86 -0
- package/dist/esm/ultramodern-workspace/contracts.js +742 -0
- package/dist/esm/ultramodern-workspace/demo-components.js +363 -0
- package/dist/esm/ultramodern-workspace/descriptors.js +133 -0
- package/dist/esm/ultramodern-workspace/effect-api.js +854 -0
- package/dist/esm/ultramodern-workspace/fs-io.js +90 -0
- package/dist/esm/ultramodern-workspace/generation-result.js +102 -0
- package/dist/esm/ultramodern-workspace/index.js +3 -0
- package/dist/esm/ultramodern-workspace/locales.js +122 -0
- package/dist/esm/ultramodern-workspace/module-federation.js +415 -0
- package/dist/esm/ultramodern-workspace/naming.js +71 -0
- package/dist/esm/ultramodern-workspace/overlays.js +79 -0
- package/dist/esm/ultramodern-workspace/package-json.js +338 -0
- package/dist/esm/ultramodern-workspace/package-source.js +21 -0
- package/dist/esm/ultramodern-workspace/policy.js +183 -0
- package/dist/esm/ultramodern-workspace/public-api.js +2 -0
- package/dist/esm/ultramodern-workspace/public-surface.js +183 -0
- package/dist/esm/ultramodern-workspace/routes.js +280 -0
- package/dist/esm/ultramodern-workspace/types.js +16 -0
- package/dist/esm/ultramodern-workspace/versions.js +36 -0
- package/dist/esm/ultramodern-workspace/workspace-scripts.js +92 -0
- package/dist/esm/ultramodern-workspace/write-workspace.js +143 -0
- package/dist/esm-node/create-package-root.js +15 -0
- package/dist/esm-node/index.js +622 -0
- package/dist/esm-node/locale/en.js +64 -0
- package/dist/esm-node/locale/index.js +10 -0
- package/dist/esm-node/locale/zh.js +64 -0
- package/dist/esm-node/ultramodern-package-source.js +64 -0
- package/dist/esm-node/ultramodern-workspace/add-vertical.js +512 -0
- package/dist/esm-node/ultramodern-workspace/app-files.js +150 -0
- package/dist/esm-node/ultramodern-workspace/codesmith.js +87 -0
- package/dist/esm-node/ultramodern-workspace/contracts.js +743 -0
- package/dist/esm-node/ultramodern-workspace/demo-components.js +364 -0
- package/dist/esm-node/ultramodern-workspace/descriptors.js +134 -0
- package/dist/esm-node/ultramodern-workspace/effect-api.js +855 -0
- package/dist/esm-node/ultramodern-workspace/fs-io.js +91 -0
- package/dist/esm-node/ultramodern-workspace/generation-result.js +103 -0
- package/dist/esm-node/ultramodern-workspace/index.js +4 -0
- package/dist/esm-node/ultramodern-workspace/locales.js +123 -0
- package/dist/esm-node/ultramodern-workspace/module-federation.js +416 -0
- package/dist/esm-node/ultramodern-workspace/naming.js +72 -0
- package/dist/esm-node/ultramodern-workspace/overlays.js +80 -0
- package/dist/esm-node/ultramodern-workspace/package-json.js +339 -0
- package/dist/esm-node/ultramodern-workspace/package-source.js +22 -0
- package/dist/esm-node/ultramodern-workspace/policy.js +184 -0
- package/dist/esm-node/ultramodern-workspace/public-api.js +3 -0
- package/dist/esm-node/ultramodern-workspace/public-surface.js +184 -0
- package/dist/esm-node/ultramodern-workspace/routes.js +281 -0
- package/dist/esm-node/ultramodern-workspace/types.js +17 -0
- package/dist/esm-node/ultramodern-workspace/versions.js +37 -0
- package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +93 -0
- package/dist/esm-node/ultramodern-workspace/write-workspace.js +144 -0
- package/dist/types/create-package-root.d.ts +1 -0
- package/dist/types/locale/en.d.ts +12 -8
- package/dist/types/locale/index.d.ts +125 -2
- package/dist/types/locale/zh.d.ts +12 -8
- package/dist/types/ultramodern-package-source.d.ts +28 -0
- package/dist/types/ultramodern-workspace/add-vertical.d.ts +36 -0
- package/dist/types/ultramodern-workspace/app-files.d.ts +14 -0
- package/dist/types/ultramodern-workspace/codesmith.d.ts +53 -0
- package/dist/types/ultramodern-workspace/contracts.d.ts +21 -0
- package/dist/types/ultramodern-workspace/demo-components.d.ts +9 -0
- package/dist/types/ultramodern-workspace/descriptors.d.ts +39 -0
- package/dist/types/ultramodern-workspace/effect-api.d.ts +73 -0
- package/dist/types/ultramodern-workspace/fs-io.d.ts +18 -0
- package/dist/types/ultramodern-workspace/generation-result.d.ts +14 -0
- package/dist/types/ultramodern-workspace/index.d.ts +4 -0
- package/dist/types/ultramodern-workspace/locales.d.ts +183 -0
- package/dist/types/ultramodern-workspace/module-federation.d.ts +16 -0
- package/dist/types/ultramodern-workspace/naming.d.ts +16 -0
- package/dist/types/ultramodern-workspace/overlays.d.ts +6 -0
- package/dist/types/ultramodern-workspace/package-json.d.ts +12 -0
- package/dist/types/ultramodern-workspace/package-source.d.ts +2 -0
- package/dist/types/ultramodern-workspace/policy.d.ts +60 -0
- package/dist/types/ultramodern-workspace/public-api.d.ts +3 -0
- package/dist/types/ultramodern-workspace/public-surface.d.ts +37 -0
- package/dist/types/ultramodern-workspace/routes.d.ts +25 -0
- package/dist/types/ultramodern-workspace/types.d.ts +197 -0
- package/dist/types/ultramodern-workspace/versions.d.ts +40 -0
- package/dist/types/ultramodern-workspace/workspace-scripts.d.ts +10 -0
- package/dist/types/ultramodern-workspace/write-workspace.d.ts +4 -0
- package/package.json +58 -15
- package/template-workspace/.github/workflows/ultramodern-workspace-gates.yml.handlebars +23 -10
- package/template-workspace/.mise.toml.handlebars +1 -0
- package/template-workspace/{AGENTS.md → AGENTS.md.handlebars} +20 -9
- package/template-workspace/README.md.handlebars +85 -14
- package/template-workspace/lefthook.yml +18 -4
- package/template-workspace/pnpm-workspace.yaml.handlebars +45 -0
- package/template-workspace/scripts/bootstrap-agent-skills.mjs +69 -75
- package/template-workspace/scripts/setup-agent-reference-repos.mjs +8 -6
- package/templates/app/shell-frame.tsx +49 -0
- package/templates/app/ultramodern-route-head.tsx.handlebars +142 -0
- package/templates/packages/shared-contracts-index.ts +466 -0
- package/templates/workspace-scripts/assert-mf-types.mjs.handlebars +69 -0
- package/templates/workspace-scripts/check-ultramodern-i18n-boundaries.mjs +9 -0
- package/templates/workspace-scripts/generate-public-surface-assets.mjs +529 -0
- package/templates/workspace-scripts/proof-cloudflare-version.mjs +125 -0
- package/templates/workspace-scripts/ultramodern-cloudflare-proof.mjs +851 -0
- package/templates/workspace-scripts/ultramodern-performance-readiness.config.mjs +7 -0
- package/templates/workspace-scripts/ultramodern-performance-readiness.mjs +223 -0
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +986 -0
- package/dist/index.js +0 -6625
- package/dist/types/ultramodern-workspace.d.ts +0 -31
- package/template/.agents/skills-lock.json +0 -34
- package/template/.browserslistrc +0 -4
- package/template/.codex/hooks.json +0 -16
- package/template/.github/renovate.json +0 -53
- package/template/.github/workflows/ultramodern-gates.yml.handlebars +0 -54
- package/template/.gitignore.handlebars +0 -30
- package/template/.mise.toml.handlebars +0 -2
- package/template/.nvmrc +0 -2
- package/template/AGENTS.md +0 -23
- package/template/README.md +0 -105
- package/template/api/effect/index.ts.handlebars +0 -34
- package/template/api/lambda/hello.ts.handlebars +0 -6
- package/template/config/public/locales/cs/translation.json +0 -39
- package/template/config/public/locales/en/translation.json +0 -39
- package/template/lefthook.yml +0 -10
- package/template/modern.config.ts.handlebars +0 -71
- package/template/oxfmt.config.ts +0 -15
- package/template/oxlint.config.ts +0 -19
- package/template/package.json.handlebars +0 -66
- package/template/pnpm-workspace.yaml +0 -29
- package/template/postcss.config.mjs.handlebars +0 -6
- package/template/rstest.config.mts +0 -5
- package/template/scripts/bootstrap-agent-skills.mjs +0 -228
- package/template/scripts/check-i18n-strings.mjs +0 -94
- package/template/scripts/validate-ultramodern.mjs.handlebars +0 -538
- package/template/shared/effect/api.ts.handlebars +0 -17
- package/template/src/modern-app-env.d.ts +0 -3
- package/template/src/modern.runtime.ts.handlebars +0 -23
- package/template/src/routes/[lang]/page.tsx.handlebars +0 -211
- package/template/src/routes/index.css.handlebars +0 -129
- package/template/src/routes/layout.tsx.handlebars +0 -10
- package/template/tailwind.config.ts.handlebars +0 -10
- package/template/tests/tsconfig.json +0 -7
- package/template/tests/ultramodern.contract.test.ts.handlebars +0 -78
- package/template/tsconfig.json +0 -120
- package/template-workspace/pnpm-workspace.yaml +0 -35
package/README.md
CHANGED
|
@@ -8,102 +8,263 @@
|
|
|
8
8
|
A Progressive React Framework for modern web development.
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## UltraModern.js Create
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
For UltraModern.js, use the BleedingDev create package. It defaults to a
|
|
16
|
-
production-ready single app with `presetUltramodern(...)`, TanStack Router,
|
|
17
|
-
Tailwind CSS v4, i18n, Effect BFF, generated quality gates, and published
|
|
18
|
-
BleedingDev package aliases:
|
|
13
|
+
The BleedingDev create package has one supported generated product: an
|
|
14
|
+
UltraModern SuperApp workspace.
|
|
19
15
|
|
|
20
16
|
```bash
|
|
21
|
-
pnpm dlx @bleedingdev/modern-js-create my-
|
|
17
|
+
pnpm dlx @bleedingdev/modern-js-create my-workspace
|
|
22
18
|
```
|
|
23
19
|
|
|
20
|
+
The supported pnpm command contract is the scoped package specifier above:
|
|
21
|
+
`pnpm dlx @bleedingdev/modern-js-create <target>`. Do not shorten it to
|
|
22
|
+
`pnpm dlx modern-js-create`; there is no unscoped `modern-js-create` npm
|
|
23
|
+
package. Release proof runs this scoped form from a temporary pnpm store/cache
|
|
24
|
+
so it cannot pass because of a local link cache.
|
|
25
|
+
|
|
24
26
|
To initialize the empty directory you are already in, pass `.` explicitly:
|
|
25
27
|
|
|
26
28
|
```bash
|
|
27
29
|
pnpm dlx @bleedingdev/modern-js-create .
|
|
28
30
|
```
|
|
29
31
|
|
|
30
|
-
The default is the full UltraModern single-app setup. Create a SuperApp
|
|
31
|
-
workspace explicitly when you need independently owned verticals:
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
pnpm dlx @bleedingdev/modern-js-create my-super-app --ultramodern-workspace
|
|
35
|
-
```
|
|
36
|
-
|
|
37
32
|
The workspace starts shell-only so the first commit has no fake business
|
|
38
33
|
domains to delete. It generates:
|
|
39
34
|
|
|
40
35
|
- `apps/shell-super-app` as the Module Federation host and topology owner.
|
|
41
|
-
- `verticals/*` empty until
|
|
42
|
-
- `packages/shared-*` placeholders for shared contracts, tokens, and
|
|
43
|
-
support.
|
|
44
|
-
- `.modernjs/ultramodern-generated-contract.json` with
|
|
45
|
-
federated CSS, Cloudflare,
|
|
36
|
+
- `verticals/*` empty until a real domain is added with `--vertical`.
|
|
37
|
+
- `packages/shared-*` placeholders for shared contracts, tokens, and Effect
|
|
38
|
+
API support.
|
|
39
|
+
- `.modernjs/ultramodern-generated-contract.json` with Module Federation,
|
|
40
|
+
Effect, i18n, federated CSS, Cloudflare, route publicness, generated
|
|
41
|
+
public-surface, and Zephyr dependency metadata.
|
|
46
42
|
|
|
47
43
|
Validate the generated workspace before making application changes:
|
|
48
44
|
|
|
49
45
|
```bash
|
|
50
|
-
cd my-
|
|
46
|
+
cd my-workspace
|
|
51
47
|
mise install
|
|
52
48
|
pnpm install
|
|
53
49
|
pnpm check
|
|
54
50
|
pnpm build
|
|
55
51
|
```
|
|
56
52
|
|
|
57
|
-
|
|
53
|
+
The generated toolchain baseline is Node `>=26` with pnpm `11+`.
|
|
54
|
+
`packageManager`, `.mise.toml`, generated validation, and CI should all agree
|
|
55
|
+
on that baseline; do not reintroduce Corepack or older pnpm aliases.
|
|
56
|
+
|
|
57
|
+
## TS-Go Compatibility Boundary
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
The supported generator runtime surfaces are:
|
|
60
|
+
|
|
61
|
+
- `@modern-js/create/ultramodern-workspace`
|
|
62
|
+
- `@modern-js/create/ultramodern-workspace/codesmith`
|
|
63
|
+
- The `@bleedingdev/modern-js-create` CLI that delegates to those APIs.
|
|
64
|
+
|
|
65
|
+
These surfaces are plain Node generator code. They must not import
|
|
66
|
+
`typescript`, `@typescript/native-preview`, or TypeScript compiler internals at
|
|
67
|
+
runtime. The package build is the local validation command for this boundary:
|
|
61
68
|
|
|
62
69
|
```bash
|
|
63
|
-
pnpm
|
|
70
|
+
pnpm --filter @modern-js/create build
|
|
64
71
|
```
|
|
65
72
|
|
|
66
|
-
|
|
73
|
+
That command runs the Rslib runtime build and then emits declarations through
|
|
74
|
+
the repo `tsgo:dts` flow. Run `pnpm --filter @modern-js/create test` when
|
|
75
|
+
changing generator behavior; it includes a boundary test that scans generator
|
|
76
|
+
sources, templates, and generated workspace output for compiler API imports.
|
|
77
|
+
|
|
78
|
+
Generated app packages keep stable `typescript` for classic compiler consumers
|
|
79
|
+
such as Module Federation DTS generation, and use `@effect/tsgo` plus
|
|
80
|
+
`@typescript/native-preview` as tooling for `pnpm typecheck`. Generated
|
|
81
|
+
app/package source must not depend on compiler API internals. Existing compiler
|
|
82
|
+
API tests in this package use the stable TypeScript 6 package. If a future AST
|
|
83
|
+
utility is needed, keep it behind a dedicated compatibility module and test it
|
|
84
|
+
against stable `typescript`, not native-preview internals.
|
|
67
85
|
|
|
68
|
-
|
|
69
|
-
|
|
86
|
+
Generated CI does not call the local aggregate. It runs format, lint,
|
|
87
|
+
typecheck, skills, i18n boundary validation, contract validation, and build as
|
|
88
|
+
separate matrix jobs so failures are isolated and parallelizable. Generated
|
|
89
|
+
lefthook config runs separate format and lint-fix commands on pre-commit, then
|
|
90
|
+
runs the read-only primitive gates in parallel on pre-push.
|
|
91
|
+
|
|
92
|
+
For local monorepo dependency testing, add `--workspace`:
|
|
70
93
|
|
|
71
94
|
```bash
|
|
72
|
-
pnpm dlx @bleedingdev/modern-js-create my-
|
|
95
|
+
pnpm dlx @bleedingdev/modern-js-create my-workspace --workspace
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
For package-source validation outside the monorepo, pass explicit
|
|
99
|
+
`--ultramodern-package-*` options.
|
|
100
|
+
|
|
101
|
+
## Automation And Public API
|
|
102
|
+
|
|
103
|
+
The supported runtime import is the public generator subpath. It exposes only
|
|
104
|
+
generator operations and stable result types; CLI argument parsing, prompts,
|
|
105
|
+
registry lookup, and process-exit flows stay private.
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
import {
|
|
109
|
+
addUltramodernVertical,
|
|
110
|
+
generateUltramodernWorkspace,
|
|
111
|
+
planUltramodernVertical,
|
|
112
|
+
} from '@modern-js/create/ultramodern-workspace';
|
|
113
|
+
|
|
114
|
+
const workspace = generateUltramodernWorkspace({
|
|
115
|
+
targetDir: '/tmp/my-workspace',
|
|
116
|
+
packageName: 'my-workspace',
|
|
117
|
+
modernVersion: '3.4.0',
|
|
118
|
+
packageSource: {
|
|
119
|
+
strategy: 'install',
|
|
120
|
+
modernPackageVersion: '3.4.0',
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const plan = planUltramodernVertical({
|
|
125
|
+
workspaceRoot: workspace.workspaceRoot,
|
|
126
|
+
name: 'new-vertical',
|
|
127
|
+
modernVersion: '3.4.0',
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
const vertical = addUltramodernVertical({
|
|
131
|
+
workspaceRoot: workspace.workspaceRoot,
|
|
132
|
+
name: 'new-vertical',
|
|
133
|
+
modernVersion: '3.4.0',
|
|
134
|
+
});
|
|
73
135
|
```
|
|
74
136
|
|
|
75
|
-
|
|
137
|
+
Workspace generation returns `operation`, `workspaceRoot`, `packageScope`,
|
|
138
|
+
`packageSource`, `createdApps`, `createdPaths`, `rewrittenPaths`,
|
|
139
|
+
`assignedPorts`, `moduleFederationNames`, `effectApiPrefixes`,
|
|
140
|
+
`generatedContractPath`, and `warnings`. MicroVertical addition returns the
|
|
141
|
+
same shape for the new vertical and all rewritten integration surfaces.
|
|
142
|
+
|
|
143
|
+
Dry-run is available for MicroVertical addition only. The CLI prints the plan as
|
|
144
|
+
JSON and writes no files:
|
|
76
145
|
|
|
77
146
|
```bash
|
|
78
|
-
pnpm dlx @bleedingdev/modern-js-create
|
|
147
|
+
pnpm dlx @bleedingdev/modern-js-create new-vertical --vertical --dry-run
|
|
148
|
+
pnpm dlx @bleedingdev/modern-js-create --vertical=new-vertical --dry-run
|
|
149
|
+
pnpm dlx @bleedingdev/modern-js-create --vertical-name new-vertical --dry-run
|
|
79
150
|
```
|
|
80
151
|
|
|
81
|
-
|
|
152
|
+
The dry-run object adds `dryRun: true`, `selectedPort`,
|
|
153
|
+
`moduleFederationRemote`, `effectApiPrefix`, `jsonMutations`,
|
|
154
|
+
`shellDependencyChanges`, and `generatedContractChanges`. It still validates
|
|
155
|
+
the workspace before returning a plan.
|
|
156
|
+
|
|
157
|
+
Validation runs before the first filesystem write. Failures name the owning
|
|
158
|
+
contract so automation can stop safely:
|
|
159
|
+
|
|
160
|
+
| Failure area | Typical cause | Fix |
|
|
161
|
+
| --- | --- | --- |
|
|
162
|
+
| Fresh input | Invalid or missing vertical name | Use `<name> --vertical`, `--vertical=<name>`, or `--vertical-name <name>` |
|
|
163
|
+
| Existing topology | Duplicate app ID, package suffix, path, Module Federation name, port, API prefix, or manifest key | Choose a new vertical name or repair the existing topology/local overlay first |
|
|
164
|
+
| Workspace files | Missing or non-object topology, ownership, package-source, local overlay, or generated contract JSON | Restore the generated contract file from source control or rerun from a valid workspace |
|
|
165
|
+
| Tailwind prefix | Existing app already owns the generated CSS prefix | Rename the vertical before generation |
|
|
166
|
+
| Output path | A generated path already exists | Treat it as an existing vertical and do not overwrite it |
|
|
167
|
+
|
|
168
|
+
Package source is explicit and recorded in `.modernjs/ultramodern-package-source.json`.
|
|
169
|
+
|
|
170
|
+
| Strategy | Use when | CLI |
|
|
171
|
+
| --- | --- | --- |
|
|
172
|
+
| `install` | Published BleedingDev package cohort or release proof | Default for the BleedingDev create package; optional `--ultramodern-package-version`, `--ultramodern-package-registry`, `--ultramodern-package-scope`, and `--ultramodern-package-name-prefix` |
|
|
173
|
+
| `workspace` | Local monorepo testing against unreleased packages | `--workspace` or `--ultramodern-package-source=workspace` |
|
|
174
|
+
|
|
175
|
+
## Migrating Older Workspaces
|
|
82
176
|
|
|
83
|
-
|
|
177
|
+
Older generated repos should move by adopting one published BleedingDev cohort
|
|
178
|
+
at a time. Start with a dry-run vertical addition so validation reports
|
|
179
|
+
topology, ownership, package-source, overlay, Tailwind prefix, Module Federation,
|
|
180
|
+
and generated-contract conflicts before files are written:
|
|
84
181
|
|
|
85
182
|
```bash
|
|
86
|
-
pnpm dlx @bleedingdev/modern-js-create
|
|
183
|
+
pnpm dlx @bleedingdev/modern-js-create@latest catalog --vertical --dry-run
|
|
184
|
+
pnpm dlx @bleedingdev/modern-js-create@latest catalog --vertical
|
|
185
|
+
mise install
|
|
186
|
+
mise exec -- pnpm install
|
|
187
|
+
mise exec -- pnpm check
|
|
188
|
+
mise exec -- pnpm build
|
|
87
189
|
```
|
|
88
190
|
|
|
89
|
-
|
|
191
|
+
Use `--ultramodern-package-source=install` for published cohort proof and pin a
|
|
192
|
+
specific release with `--ultramodern-package-version` when CI must prove an
|
|
193
|
+
exact framework version. Keep `--workspace` only for local monorepo testing
|
|
194
|
+
against unpublished packages. After install, run the generated
|
|
195
|
+
`scripts/validate-ultramodern-workspace.mjs` contract check and fix ownership
|
|
196
|
+
conflicts in the owning JSON/config files instead of editing generated package
|
|
197
|
+
metadata by hand.
|
|
90
198
|
|
|
91
|
-
|
|
92
|
-
|
|
199
|
+
## CodeSmith Adapter And Overlays
|
|
200
|
+
|
|
201
|
+
The CodeSmith adapter is exported from:
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
import ultramodernCodeSmith from '@modern-js/create/ultramodern-workspace/codesmith';
|
|
93
205
|
```
|
|
94
206
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
207
|
+
Non-interactive usage passes config directly:
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
await ultramodernCodeSmith({
|
|
211
|
+
config: {
|
|
212
|
+
mode: 'workspace',
|
|
213
|
+
name: 'my-workspace',
|
|
214
|
+
targetDir: '/tmp/my-workspace',
|
|
215
|
+
modernVersion: '3.4.0',
|
|
216
|
+
packageSourceStrategy: 'install',
|
|
217
|
+
modernPackageVersion: '3.4.0',
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
await ultramodernCodeSmith({
|
|
222
|
+
config: {
|
|
223
|
+
mode: 'vertical',
|
|
224
|
+
name: 'new-vertical',
|
|
225
|
+
workspaceRoot: '/tmp/my-workspace',
|
|
226
|
+
dryRun: true,
|
|
227
|
+
logResult: true,
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
The adapter prompts only when a required name is missing and a CodeSmith prompt
|
|
233
|
+
function is available. It returns the same public generation result or dry-run
|
|
234
|
+
plan as the direct API.
|
|
98
235
|
|
|
99
|
-
|
|
100
|
-
|
|
236
|
+
Overlays are explicit CodeSmith generators that run after base workspace or
|
|
237
|
+
MicroVertical generation:
|
|
101
238
|
|
|
102
239
|
```bash
|
|
103
|
-
pnpm dlx @bleedingdev/modern-js-create
|
|
240
|
+
pnpm dlx @bleedingdev/modern-js-create new-vertical --vertical \
|
|
241
|
+
--codesmith-overlay ./generators/vertical-overlay
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
```ts
|
|
245
|
+
addUltramodernVertical({
|
|
246
|
+
workspaceRoot: '/tmp/my-workspace',
|
|
247
|
+
name: 'new-vertical',
|
|
248
|
+
modernVersion: '3.4.0',
|
|
249
|
+
overlays: [
|
|
250
|
+
{
|
|
251
|
+
generator: './generators/vertical-overlay',
|
|
252
|
+
config: { owner: 'workspace' },
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
});
|
|
104
256
|
```
|
|
105
257
|
|
|
106
|
-
|
|
258
|
+
Overlay config receives `workspaceRoot`, `packageScope`, `operation`,
|
|
259
|
+
`generatedApp`, `generatedApps`, `assignedPort`, `assignedPorts`,
|
|
260
|
+
`moduleFederationName`, `moduleFederationNames`, `effectApiPrefix`,
|
|
261
|
+
`effectApiPrefixes`, `packageSource`, and `generationResult`. Overlays extend
|
|
262
|
+
the generated output after base generation; they do not replace, inherit, or
|
|
263
|
+
shadow the base templates. Overlay failures stop the command with an
|
|
264
|
+
`UltraModern CodeSmith overlay failed` error and do not report base generation
|
|
265
|
+
as fully successful.
|
|
266
|
+
|
|
267
|
+
## Vertical Workspace Recipes
|
|
107
268
|
|
|
108
269
|
Use the workspace add flow from the UltraModern workspace root. It derives the
|
|
109
270
|
package path, package name, port, Module Federation name, topology entry, local
|
|
@@ -112,6 +273,8 @@ requested vertical name.
|
|
|
112
273
|
|
|
113
274
|
```bash
|
|
114
275
|
pnpm dlx @bleedingdev/modern-js-create catalog --vertical
|
|
276
|
+
pnpm dlx @bleedingdev/modern-js-create --vertical=catalog
|
|
277
|
+
pnpm dlx @bleedingdev/modern-js-create --vertical-name catalog
|
|
115
278
|
```
|
|
116
279
|
|
|
117
280
|
Use this decision table before adding a vertical:
|
|
@@ -124,33 +287,44 @@ Use this decision table before adding a vertical:
|
|
|
124
287
|
| Design tokens, primitives, generated clients, or domain-neutral utilities | Yes | Use an ordinary workspace package, not a vertical |
|
|
125
288
|
| Feature composites or workflow state shared across verticals | No | Revisit ownership; do not hide it in shared code |
|
|
126
289
|
|
|
127
|
-
|
|
128
|
-
available for compatibility and local package scaffolding, but UltraModern
|
|
129
|
-
vertical additions should use `--vertical` so paths, topology, Effect BFF
|
|
130
|
-
contracts, and local overlays stay consistent.
|
|
131
|
-
|
|
132
|
-
See
|
|
133
|
-
`docs/super-app-rfc-adr/WORKSPACE-0001-micro-vertical-workspace-scaffolding.md`
|
|
134
|
-
for the canonical workspace topology and local orchestration model.
|
|
135
|
-
|
|
136
|
-
The published `@bleedingdev/modern-js-create` package is the preferred
|
|
137
|
-
UltraModern.js entrypoint. The lower-level `--ultramodern-*` flags remain
|
|
138
|
-
available for release engineering and local package-source testing, but users
|
|
139
|
-
should not need them for normal app creation.
|
|
140
|
-
|
|
141
|
-
### SuperApp Architecture Contracts
|
|
290
|
+
## SuperApp Architecture Contracts
|
|
142
291
|
|
|
143
292
|
The generated shell owns route assembly and policy. Each vertical added with
|
|
144
|
-
`--vertical` owns its route subtree,
|
|
145
|
-
client, `localisedUrls`, locale JSON, CSS layer, and
|
|
146
|
-
The shell consumes vertical UI through
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
`
|
|
152
|
-
|
|
153
|
-
|
|
293
|
+
`--vertical` owns its route subtree, Module Federation exposes, Effect BFF
|
|
294
|
+
contract, generated client, `localisedUrls`, locale JSON, CSS layer, and
|
|
295
|
+
Cloudflare Worker output. The shell consumes vertical UI through Module
|
|
296
|
+
Federation manifests and vertical APIs through generated Effect clients
|
|
297
|
+
exported by the vertical packages.
|
|
298
|
+
|
|
299
|
+
Route metadata is route-owned and colocated in
|
|
300
|
+
`src/routes/**/route.meta.ts`. The scaffold regenerates
|
|
301
|
+
`src/routes/ultramodern-route-metadata.ts` as a compatibility manifest for
|
|
302
|
+
Modern.js config, i18n, public head, and public surface contracts; authors
|
|
303
|
+
should not hand-maintain it. Locale JSON is served from
|
|
304
|
+
`/locales/{{lng}}/{{ns}}.json`; Czech and English routes are generated from the
|
|
305
|
+
route owner, not from shell rewrites.
|
|
306
|
+
|
|
307
|
+
Routes default to `privateByDefault: true` and
|
|
308
|
+
`publicnessDefault: private-app-screen`. Public web artifacts are build/deploy
|
|
309
|
+
outputs generated by `scripts/generate-public-surface-assets.mjs` into
|
|
310
|
+
`dist/public` and `.output/public`, not source files under `config/public`.
|
|
311
|
+
Generated public files use only explicit `public && indexable` route metadata,
|
|
312
|
+
so private app screens publish only a disallowing `robots.txt` by default.
|
|
313
|
+
JSON-LD is not inferred from route titles, descriptions, localized paths, app
|
|
314
|
+
names, BFF APIs, or Module Federation metadata. To publish structured data,
|
|
315
|
+
author `jsonLd` explicitly in route metadata for a `public && indexable` route;
|
|
316
|
+
generated apps provide `src/routes/ultramodern-jsonld.ts` helpers for
|
|
317
|
+
`WebPage`, `WebApplication`, `SoftwareApplication`, `BreadcrumbList`,
|
|
318
|
+
`FAQPage`, and `Organization`, while raw JSON-LD remains possible for other
|
|
319
|
+
schema types.
|
|
320
|
+
|
|
321
|
+
Dynamic public routes can expand sitemap entries through route-owned,
|
|
322
|
+
Node-safe ESM providers, normally `route.sitemap.mjs` beside the route
|
|
323
|
+
metadata. The public-surface generator discovers those providers for dynamic
|
|
324
|
+
public routes and still honors explicit `routes.publicSurface.contentSources`
|
|
325
|
+
entries in the generated compatibility manifest. Providers may export
|
|
326
|
+
`entries`, `entries()`, or a default entries/loader returning sitemap entries;
|
|
327
|
+
draft entries and `indexable: false` entries are omitted.
|
|
154
328
|
|
|
155
329
|
CSS federation is explicit:
|
|
156
330
|
|
|
@@ -162,15 +336,36 @@ CSS federation is explicit:
|
|
|
162
336
|
- Tailwind CSS v4 is configured per app through `@tailwindcss/postcss`.
|
|
163
337
|
- Duplicate base styles are forbidden; SSR first paint depends on shared token
|
|
164
338
|
CSS plus Modern/Rspack-emitted app CSS.
|
|
165
|
-
- Apps should not inject remote `async-index.css` paths, hardcode remote
|
|
166
|
-
stylesheet links, or disable filename hashing to make CSS URLs predictable.
|
|
167
|
-
UltraModern SSR resolves federated CSS from build output and MF manifests so
|
|
168
|
-
generated shells and demos can keep normal hashed assets.
|
|
169
339
|
|
|
170
|
-
|
|
171
|
-
manifest markers in lockstep for the same vertical version.
|
|
340
|
+
## Public URL Environment Variables
|
|
172
341
|
|
|
173
|
-
|
|
342
|
+
Generated apps must not bake absolute `http://localhost:<port>` URLs into asset
|
|
343
|
+
configuration. Public URL and asset prefix environment variables have distinct
|
|
344
|
+
roles, and stale aliases should not be carried forward when regenerating or
|
|
345
|
+
updating workspaces.
|
|
346
|
+
|
|
347
|
+
| Variable | Role | Feeds |
|
|
348
|
+
| --- | --- | --- |
|
|
349
|
+
| `MODERN_PUBLIC_SITE_URL` | Canonical site origin for public SEO output only | Canonical, hreflang, sitemap `<loc>`, robots `Sitemap:` |
|
|
350
|
+
| `MODERN_ASSET_PREFIX` | Preferred JS/CSS/static asset prefix | Modern/Rspack-emitted asset URLs |
|
|
351
|
+
| `ULTRAMODERN_ASSET_PREFIX` | UltraModern compatibility asset prefix | Modern/Rspack-emitted asset URLs when `MODERN_ASSET_PREFIX` is unset |
|
|
352
|
+
| `ULTRAMODERN_PUBLIC_URL_<APP_ID>` | Per-app deployment/proof URL | Cloudflare proof inputs and Module Federation remote URLs |
|
|
353
|
+
|
|
354
|
+
Asset URLs use this precedence: `MODERN_ASSET_PREFIX` →
|
|
355
|
+
`ULTRAMODERN_ASSET_PREFIX` → origin-relative `/`. `MODERN_PUBLIC_SITE_URL` is
|
|
356
|
+
canonical/SEO-only and must not be used as an asset-prefix fallback.
|
|
357
|
+
SEO output uses `MODERN_PUBLIC_SITE_URL`; if it is unset, generated local and
|
|
358
|
+
preview outputs remain non-public until deployment proof provides explicit
|
|
359
|
+
public URLs.
|
|
360
|
+
|
|
361
|
+
Without public URLs configured, asset paths are origin-relative (`/`), and the
|
|
362
|
+
dev server uses `dev.assetPrefix: '/'` — so apps work through tunnels and
|
|
363
|
+
reverse proxies (ngrok, cloudflared) without triggering Chrome's Local Network
|
|
364
|
+
Access prompt or mixed-content errors. Shell-only workspaces can set
|
|
365
|
+
`MODERN_PUBLIC_SITE_URL` for SEO output without changing where assets load
|
|
366
|
+
from.
|
|
367
|
+
|
|
368
|
+
## Cloudflare And Zephyr Proof
|
|
174
369
|
|
|
175
370
|
Each generated workspace app has:
|
|
176
371
|
|
|
@@ -181,9 +376,12 @@ Each generated workspace app has:
|
|
|
181
376
|
- `zephyr-rspack-plugin` wired through the generated Modern.js Rspack bridge.
|
|
182
377
|
|
|
183
378
|
Deploy first, then pass each deployed app's generated public URL env key into
|
|
184
|
-
the proof step.
|
|
185
|
-
|
|
186
|
-
|
|
379
|
+
the proof step. The proof script reads the generated contract and checks the
|
|
380
|
+
Cloudflare Worker surface, including public-route sitemap/robots consistency,
|
|
381
|
+
preview noindex behavior, unknown-route status, asset headers, byte budgets,
|
|
382
|
+
and public sourcemap exposure. Shell-only workspaces only need the shell URL;
|
|
383
|
+
added verticals use the same `ULTRAMODERN_PUBLIC_URL_<APP_ID>` pattern with
|
|
384
|
+
hyphens converted to underscores and uppercased:
|
|
187
385
|
|
|
188
386
|
```bash
|
|
189
387
|
pnpm cloudflare:deploy
|
|
@@ -192,50 +390,27 @@ ULTRAMODERN_PUBLIC_URL_TRANSPORTATION=https://transportation.example.workers.dev
|
|
|
192
390
|
pnpm cloudflare:proof -- --require-public-urls
|
|
193
391
|
```
|
|
194
392
|
|
|
195
|
-
Without public URLs and credentials, use local
|
|
393
|
+
Without public URLs and credentials, use local primitive gates and `pnpm build`
|
|
196
394
|
evidence only; do not claim live Cloudflare or Zephyr selection has been
|
|
197
395
|
proven.
|
|
198
396
|
|
|
199
|
-
|
|
397
|
+
## Troubleshooting
|
|
200
398
|
|
|
201
399
|
| Symptom | Current check | Owner |
|
|
202
400
|
| --- | --- | --- |
|
|
203
401
|
| 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 |
|
|
204
402
|
| Install failure | Check the active Node/pnpm from `mise install`; rerun `pnpm install` after the shell sees the pinned versions. | Toolchain setup |
|
|
205
|
-
| Build failure | Run `pnpm check` before `pnpm build`; fix
|
|
403
|
+
| 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 |
|
|
206
404
|
| Missing public URL | Set the env key from `.modernjs/ultramodern-generated-contract.json`, for example `ULTRAMODERN_PUBLIC_URL_SHELL_SUPER_APP`. | Deployment operator |
|
|
207
405
|
| Cloudflare credentials | Confirm Wrangler credentials before `pnpm cloudflare:deploy`; local checks do not prove live Worker access. | Deployment operator |
|
|
208
406
|
| 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 |
|
|
209
407
|
| 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 |
|
|
210
408
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
When testing unreleased Modern.js packages from a local monorepo checkout, use
|
|
214
|
-
workspace protocol dependencies:
|
|
215
|
-
|
|
216
|
-
```bash
|
|
217
|
-
pnpm dlx @bleedingdev/modern-js-create my-app --workspace
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
For package-source validation of the full SuperApp workspace, generate with the
|
|
221
|
-
workspace package source, then run the generated contract gate:
|
|
222
|
-
|
|
223
|
-
```bash
|
|
224
|
-
pnpm dlx @bleedingdev/modern-js-create my-super-app --ultramodern-workspace --ultramodern-package-source workspace
|
|
225
|
-
cd my-super-app
|
|
226
|
-
pnpm install
|
|
227
|
-
pnpm check
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
## Documentation
|
|
409
|
+
## Modern.js Documentation
|
|
231
410
|
|
|
232
411
|
- [English Documentation](https://modernjs.dev/en/)
|
|
233
412
|
- [中文文档](https://modernjs.dev)
|
|
234
413
|
|
|
235
|
-
## Contributing
|
|
236
|
-
|
|
237
|
-
Please read the [Contributing Guide](https://github.com/web-infra-dev/modern.js/blob/main/CONTRIBUTING.md).
|
|
238
|
-
|
|
239
414
|
## License
|
|
240
415
|
|
|
241
416
|
Modern.js is [MIT licensed](https://github.com/web-infra-dev/modern.js/blob/main/LICENSE).
|
package/bin/run.js
CHANGED
|
@@ -0,0 +1,63 @@
|
|
|
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
|
+
const MAX_WALK_UP_LEVELS = 5;
|
|
47
|
+
function resolveCreatePackageRoot(fromDir) {
|
|
48
|
+
let candidate = fromDir;
|
|
49
|
+
for(let level = 0; level <= MAX_WALK_UP_LEVELS; level++){
|
|
50
|
+
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;
|
|
51
|
+
const parent = external_node_path_default().dirname(candidate);
|
|
52
|
+
if (parent === candidate) break;
|
|
53
|
+
candidate = parent;
|
|
54
|
+
}
|
|
55
|
+
throw new Error(`Unable to resolve the @modern-js/create package root (a directory containing both package.json and template-workspace/) within ${MAX_WALK_UP_LEVELS} levels above ${fromDir}`);
|
|
56
|
+
}
|
|
57
|
+
exports.resolveCreatePackageRoot = __webpack_exports__.resolveCreatePackageRoot;
|
|
58
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
59
|
+
"resolveCreatePackageRoot"
|
|
60
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
61
|
+
Object.defineProperty(exports, '__esModule', {
|
|
62
|
+
value: true
|
|
63
|
+
});
|