@bleedingdev/modern-js-create 3.2.0-ultramodern.1 → 3.2.0-ultramodern.100

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 (74) hide show
  1. package/README.md +161 -32
  2. package/bin/run.js +0 -0
  3. package/dist/index.js +5105 -770
  4. package/dist/types/locale/en.d.ts +3 -0
  5. package/dist/types/locale/zh.d.ts +3 -0
  6. package/dist/types/ultramodern-workspace.d.ts +11 -0
  7. package/package.json +8 -5
  8. package/template/.agents/skills-lock.json +34 -0
  9. package/template/.codex/hooks.json +16 -0
  10. package/template/.github/renovate.json +53 -0
  11. package/template/.github/workflows/ultramodern-gates.yml.handlebars +34 -10
  12. package/template/.mise.toml.handlebars +2 -0
  13. package/template/AGENTS.md +23 -0
  14. package/template/README.md +60 -34
  15. package/template/api/effect/index.ts.handlebars +14 -41
  16. package/template/api/lambda/hello.ts.handlebars +5 -5
  17. package/template/config/public/locales/cs/translation.json +39 -0
  18. package/template/config/public/locales/en/translation.json +39 -0
  19. package/template/lefthook.yml +10 -0
  20. package/template/modern.config.ts.handlebars +45 -23
  21. package/template/oxfmt.config.ts +15 -0
  22. package/template/oxlint.config.ts +19 -0
  23. package/template/package.json.handlebars +50 -31
  24. package/template/pnpm-workspace.yaml +29 -0
  25. package/template/rstest.config.mts +5 -0
  26. package/template/scripts/bootstrap-agent-skills.mjs +228 -0
  27. package/template/scripts/check-i18n-strings.mjs +94 -0
  28. package/template/scripts/validate-ultramodern.mjs.handlebars +453 -17
  29. package/template/shared/effect/api.ts.handlebars +1 -2
  30. package/template/src/modern-app-env.d.ts +2 -0
  31. package/template/src/modern.runtime.ts.handlebars +17 -3
  32. package/template/src/routes/[lang]/page.tsx.handlebars +211 -0
  33. package/template/src/routes/index.css.handlebars +14 -3
  34. package/template/src/routes/layout.tsx.handlebars +2 -1
  35. package/template/tailwind.config.ts.handlebars +1 -1
  36. package/template/tests/tsconfig.json +7 -0
  37. package/template/tests/ultramodern.contract.test.ts.handlebars +78 -0
  38. package/template/tsconfig.json +107 -2
  39. package/template-workspace/.agents/agent-reference-repos.json +24 -0
  40. package/template-workspace/.agents/rstackjs-agent-skills-LICENSE +21 -0
  41. package/template-workspace/.agents/skills/rsbuild-best-practices/SKILL.md +57 -0
  42. package/template-workspace/.agents/skills/rsdoctor-analysis/SKILL.md +96 -0
  43. package/template-workspace/.agents/skills/rsdoctor-analysis/references/command-map.md +113 -0
  44. package/template-workspace/.agents/skills/rsdoctor-analysis/references/common-analysis-patterns.md +190 -0
  45. package/template-workspace/.agents/skills/rsdoctor-analysis/references/install-rsdoctor-common.md +88 -0
  46. package/template-workspace/.agents/skills/rsdoctor-analysis/references/install-rsdoctor-rspack.md +138 -0
  47. package/template-workspace/.agents/skills/rsdoctor-analysis/references/install-rsdoctor-webpack.md +71 -0
  48. package/template-workspace/.agents/skills/rsdoctor-analysis/references/install-rsdoctor.md +39 -0
  49. package/template-workspace/.agents/skills/rsdoctor-analysis/references/rsdoctor-data-types.md +103 -0
  50. package/template-workspace/.agents/skills/rslib-best-practices/SKILL.md +58 -0
  51. package/template-workspace/.agents/skills/rslib-modern-package/SKILL.md +173 -0
  52. package/template-workspace/.agents/skills/rspack-best-practices/SKILL.md +70 -0
  53. package/template-workspace/.agents/skills/rspack-tracing/SKILL.md +75 -0
  54. package/template-workspace/.agents/skills/rspack-tracing/references/bottlenecks.md +47 -0
  55. package/template-workspace/.agents/skills/rspack-tracing/references/tracing-guide.md +38 -0
  56. package/template-workspace/.agents/skills/rspack-tracing/scripts/analyze_trace.js +184 -0
  57. package/template-workspace/.agents/skills/rstest-best-practices/SKILL.md +133 -0
  58. package/template-workspace/.agents/skills-lock.json +114 -0
  59. package/template-workspace/.codex/hooks.json +16 -0
  60. package/template-workspace/.github/renovate.json +29 -0
  61. package/template-workspace/.github/workflows/ultramodern-workspace-gates.yml.handlebars +54 -0
  62. package/template-workspace/.gitignore.handlebars +5 -0
  63. package/template-workspace/.mise.toml.handlebars +2 -0
  64. package/template-workspace/AGENTS.md +76 -0
  65. package/template-workspace/README.md.handlebars +61 -11
  66. package/template-workspace/lefthook.yml +10 -0
  67. package/template-workspace/oxfmt.config.ts +17 -0
  68. package/template-workspace/oxlint.config.ts +20 -0
  69. package/template-workspace/pnpm-workspace.yaml +32 -2
  70. package/template-workspace/scripts/bootstrap-agent-skills.mjs +264 -0
  71. package/template-workspace/scripts/setup-agent-reference-repos.mjs +368 -0
  72. package/template/biome.json +0 -41
  73. package/template/src/routes/page.tsx.handlebars +0 -119
  74. package/template-workspace/scripts/validate-ultramodern-workspace.mjs.handlebars +0 -276
@@ -3,23 +3,48 @@
3
3
  Generated UltraModern SuperApp workspace.
4
4
 
5
5
  This workspace keeps `presetUltramodern(...)` as the single public
6
- UltraModern.js 3.0 SuperApp surface and scaffolds the canonical Micro Vertical
7
- starter topology:
6
+ UltraModern.js 3.0 SuperApp surface and starts with an explicit shell:
8
7
 
9
- - `apps/shell-super-app` owns shell route assembly and remote manifest wiring.
10
- - `apps/remotes/remote-commerce` owns the commerce vertical remote.
11
- - `apps/remotes/remote-identity` owns the identity vertical remote.
12
- - `apps/remotes/remote-design-system` owns the horizontal design-system remote.
13
- - `services/service-recommendations-effect` owns the Effect BFF service.
14
- - `packages/shared-*` provide placeholders for cross-workspace contracts.
8
+ - `apps/shell-super-app` owns shell route assembly, Module Federation host
9
+ wiring, shared SSR/i18n runtime setup, and the boundary debugger.
10
+ - `packages/shared-*` provide placeholders for cross-workspace contracts,
11
+ design tokens, and Effect API sharing.
12
+ - `verticals/*` is intentionally empty until a real business domain is added.
15
13
 
16
- Run the scaffold validator before adding business code:
14
+ Add a full-stack MicroVertical when the product needs one:
17
15
 
18
16
  ```bash
19
- pnpm ultramodern:check
17
+ pnpm dlx @bleedingdev/modern-js-create transportation --vertical
18
+ pnpm dlx @bleedingdev/modern-js-create payments --vertical
20
19
  ```
21
20
 
22
- The topology and ownership metadata are generated under `topology/`.
21
+ Each added vertical owns its UI/routes, browser-safe Module Federation exposes,
22
+ localized route metadata, CSS prefix, Effect BFF handlers, local API contract,
23
+ and typed client surface. Server handlers and Effect client/contract modules
24
+ stay out of browser exposes.
25
+
26
+ Run the scaffold validator before adding business code and after every
27
+ `--vertical` mutation:
28
+
29
+ ```bash
30
+ mise install
31
+ pnpm install
32
+ pnpm check
33
+ pnpm build
34
+ ```
35
+
36
+ By default, `pnpm install` also prepares read-only agent reference repositories
37
+ under `repos/` for Effect and UltraModern.js source lookup using squashed git
38
+ subtrees. Disable this setup with
39
+ `ULTRAMODERN_SKIP_AGENT_REPOS=1 pnpm install`, or rerun it
40
+ explicitly with `pnpm agents:refs:install`.
41
+
42
+ The topology and ownership metadata are generated under `topology/`. The
43
+ workspace also ships `.github/workflows/ultramodern-workspace-gates.yml` and
44
+ `.github/renovate.json` with read-only workflow permissions, commit-pinned
45
+ actions, frozen installs, StepSecurity audit-mode runner hardening, dependency
46
+ dashboard review, one-day release age, grouped updates, and manual approval for
47
+ major upgrades.
23
48
 
24
49
  Package source metadata is generated at
25
50
  `.modernjs/ultramodern-package-source.json`. The default strategy keeps
@@ -27,3 +52,28 @@ UltraModern.js runtime and tooling packages on `workspace:*` for monorepo
27
52
  development. To create a workspace that can install those packages outside the
28
53
  monorepo, generate with `--ultramodern-package-source install`; generated shared
29
54
  packages still use `workspace:*` because they are part of this workspace.
55
+
56
+ ## Cloudflare Proof
57
+
58
+ Deploy the generated apps, then pass each deployed app's generated public URL
59
+ env key into the proof step. A shell-only workspace only needs the shell URL;
60
+ added verticals use the same `ULTRAMODERN_PUBLIC_URL_<APP_ID>` pattern with
61
+ hyphens converted to underscores and uppercased.
62
+
63
+ ```bash
64
+ pnpm cloudflare:deploy
65
+ ULTRAMODERN_PUBLIC_URL_SHELL_SUPER_APP=https://shell-super-app.example.workers.dev \
66
+ pnpm cloudflare:proof -- --require-public-urls
67
+ ```
68
+
69
+ ## Troubleshooting
70
+
71
+ | Symptom | Current check | Owner |
72
+ | --- | --- | --- |
73
+ | 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 |
74
+ | Install failure | Check the active Node/pnpm from `mise install`; rerun `pnpm install` after the shell sees the pinned versions. | Toolchain setup |
75
+ | Build failure | Run `pnpm check` before `pnpm build`; fix reported format, lint, type, skill, i18n, or generated-contract failures first. | Owning package or generated contract |
76
+ | Missing public URL | Set the env key from `.modernjs/ultramodern-generated-contract.json`, for example `ULTRAMODERN_PUBLIC_URL_SHELL_SUPER_APP`. | Deployment operator |
77
+ | Cloudflare credentials | Confirm Wrangler credentials before `pnpm cloudflare:deploy`; local checks do not prove live Worker access. | Deployment operator |
78
+ | 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 |
79
+ | 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 |
@@ -0,0 +1,10 @@
1
+ pre-commit:
2
+ commands:
3
+ fix-and-check:
4
+ run: pnpm format && pnpm lint:fix && pnpm check
5
+ stage_fixed: true
6
+
7
+ pre-push:
8
+ commands:
9
+ check:
10
+ run: pnpm check
@@ -0,0 +1,17 @@
1
+ import { defineConfig } from 'oxfmt';
2
+ import ultracite from 'ultracite/oxfmt';
3
+
4
+ export default defineConfig({
5
+ extends: [ultracite],
6
+ ignorePatterns: [
7
+ '.agents',
8
+ '**/*.json',
9
+ 'dist',
10
+ 'node_modules',
11
+ 'repos/**',
12
+ '.modern',
13
+ '.modernjs',
14
+ '**/routeTree.gen.ts',
15
+ ],
16
+ singleQuote: true,
17
+ });
@@ -0,0 +1,20 @@
1
+ import { defineConfig } from 'oxlint';
2
+ import core from 'ultracite/oxlint/core';
3
+ import react from 'ultracite/oxlint/react';
4
+
5
+ export default defineConfig({
6
+ env: {
7
+ browser: true,
8
+ node: true,
9
+ },
10
+ extends: [core, react],
11
+ ignorePatterns: [
12
+ '.agents',
13
+ 'dist',
14
+ 'node_modules',
15
+ 'repos/**',
16
+ '.modern',
17
+ '.modernjs',
18
+ '**/routeTree.gen.ts',
19
+ ],
20
+ });
@@ -1,5 +1,35 @@
1
1
  packages:
2
2
  - apps/*
3
- - apps/remotes/*
4
- - services/*
3
+ - verticals/*
5
4
  - packages/*
5
+
6
+ minimumReleaseAge: 1440
7
+ minimumReleaseAgeStrict: true
8
+ minimumReleaseAgeIgnoreMissingTime: false
9
+ minimumReleaseAgeExclude:
10
+ - '@bleedingdev/modern-js-*'
11
+ trustPolicy: no-downgrade
12
+ trustPolicyIgnoreAfter: 1440
13
+ blockExoticSubdeps: true
14
+ engineStrict: true
15
+ pmOnFail: error
16
+ verifyDepsBeforeRun: error
17
+ strictDepBuilds: true
18
+
19
+ peerDependencyRules:
20
+ allowedVersions:
21
+ react: '>=19.0.0'
22
+ typescript: '>=6.0.0'
23
+
24
+ overrides:
25
+ '@tanstack/react-router': 1.170.11
26
+ node-fetch: '^3.3.2'
27
+
28
+ allowBuilds:
29
+ '@swc/core': true
30
+ core-js: true
31
+ esbuild: true
32
+ lefthook: true
33
+ msgpackr-extract: true
34
+ sharp: true
35
+ workerd: true
@@ -0,0 +1,264 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import fs from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+
6
+ const root = process.cwd();
7
+ const lockPath = path.join(root, '.agents/skills-lock.json');
8
+ const checkOnly = process.argv.includes('--check');
9
+ const force = process.argv.includes('--force');
10
+
11
+ const readJson = filePath => JSON.parse(fs.readFileSync(filePath, 'utf-8'));
12
+
13
+ const run = (command, args, options = {}) =>
14
+ execFileSync(command, args, {
15
+ cwd: options.cwd ?? root,
16
+ encoding: 'utf-8',
17
+ stdio: options.stdio ?? ['ignore', 'pipe', 'pipe'],
18
+ });
19
+
20
+ const commandExists = command => {
21
+ try {
22
+ run(command, ['--version'], { stdio: 'ignore' });
23
+ return true;
24
+ } catch {
25
+ return false;
26
+ }
27
+ };
28
+
29
+ const runShell = script =>
30
+ run('sh', ['-lc', script], {
31
+ stdio: 'inherit',
32
+ });
33
+
34
+ const installGit = () => {
35
+ if (commandExists('git')) {
36
+ return;
37
+ }
38
+
39
+ if (commandExists('brew')) {
40
+ run('brew', ['install', 'git'], { stdio: 'inherit' });
41
+ } else if (process.platform === 'linux' && commandExists('apt-get')) {
42
+ const sudo =
43
+ typeof process.getuid === 'function' && process.getuid() === 0
44
+ ? ''
45
+ : 'sudo ';
46
+ runShell(`${sudo}apt-get update && ${sudo}apt-get install -y git`);
47
+ } else if (process.platform === 'linux' && commandExists('dnf')) {
48
+ const sudo =
49
+ typeof process.getuid === 'function' && process.getuid() === 0
50
+ ? ''
51
+ : 'sudo ';
52
+ runShell(`${sudo}dnf install -y git`);
53
+ } else if (process.platform === 'linux' && commandExists('yum')) {
54
+ const sudo =
55
+ typeof process.getuid === 'function' && process.getuid() === 0
56
+ ? ''
57
+ : 'sudo ';
58
+ runShell(`${sudo}yum install -y git`);
59
+ } else if (process.platform === 'linux' && commandExists('apk')) {
60
+ runShell('apk add --no-cache git');
61
+ }
62
+
63
+ if (!commandExists('git')) {
64
+ throw new Error(
65
+ 'Git is required for UltraModern setup. Install git and run pnpm skills:install again.',
66
+ );
67
+ }
68
+ };
69
+
70
+ const isInsideGitWorkTree = () => {
71
+ try {
72
+ return run('git', ['rev-parse', '--is-inside-work-tree']).trim() === 'true';
73
+ } catch {
74
+ return false;
75
+ }
76
+ };
77
+
78
+ const initializeGitRepository = () => {
79
+ if (isInsideGitWorkTree()) {
80
+ return;
81
+ }
82
+
83
+ try {
84
+ run('git', ['init', '-b', 'main'], { stdio: 'inherit' });
85
+ } catch {
86
+ run('git', ['init'], { stdio: 'inherit' });
87
+ run('git', ['branch', '-M', 'main'], { stdio: 'inherit' });
88
+ }
89
+ };
90
+
91
+ const installLefthook = () => {
92
+ try {
93
+ run('lefthook', ['install'], { stdio: 'inherit' });
94
+ } catch (error) {
95
+ console.warn(`Unable to install lefthook hooks: ${error.message}`);
96
+ }
97
+ };
98
+
99
+ const removeTree = dir =>
100
+ fs.rmSync(dir, {
101
+ force: true,
102
+ maxRetries: 5,
103
+ recursive: true,
104
+ retryDelay: 100,
105
+ });
106
+
107
+ const cloneSource = (source, targetDir) => {
108
+ if (source.commit) {
109
+ run('git', ['init', targetDir]);
110
+ run('git', ['remote', 'add', 'origin', source.repository], {
111
+ cwd: targetDir,
112
+ });
113
+ run('git', ['fetch', '--depth', '1', '--quiet', 'origin', source.commit], {
114
+ cwd: targetDir,
115
+ });
116
+ run(
117
+ 'git',
118
+ [
119
+ '-c',
120
+ 'advice.detachedHead=false',
121
+ 'checkout',
122
+ '--detach',
123
+ '--quiet',
124
+ 'FETCH_HEAD',
125
+ ],
126
+ { cwd: targetDir },
127
+ );
128
+ return;
129
+ }
130
+
131
+ const repo = source.repository.replace(/^https:\/\/github.com\//u, '');
132
+ try {
133
+ run('gh', [
134
+ 'repo',
135
+ 'clone',
136
+ repo,
137
+ targetDir,
138
+ '--',
139
+ '--depth',
140
+ '1',
141
+ '--quiet',
142
+ ]);
143
+ } catch {
144
+ run('git', [
145
+ 'clone',
146
+ '--depth',
147
+ '1',
148
+ '--quiet',
149
+ source.repository,
150
+ targetDir,
151
+ ]);
152
+ }
153
+ };
154
+
155
+ const resolveSkillDir = (sourceRoot, skillName) => {
156
+ const candidates = [
157
+ path.join(sourceRoot, skillName),
158
+ path.join(sourceRoot, 'skills', skillName),
159
+ path.join(sourceRoot, 'skills', 'engineering', skillName),
160
+ path.join(sourceRoot, 'skills', 'productivity', skillName),
161
+ ];
162
+ return candidates.find(candidate =>
163
+ fs.existsSync(path.join(candidate, 'SKILL.md')),
164
+ );
165
+ };
166
+
167
+ if (!fs.existsSync(lockPath)) {
168
+ console.error('Missing .agents/skills-lock.json');
169
+ process.exit(1);
170
+ }
171
+
172
+ const lock = readJson(lockPath);
173
+ const installDir = path.join(root, lock.installDir ?? '.agents/skills');
174
+ const sources = lock.sources ?? [];
175
+ const requiredCloneSources = sources.filter(
176
+ source => source.install === 'clone',
177
+ );
178
+ const optionalCloneSources = sources.filter(
179
+ source => source.install === 'clone-if-authorized',
180
+ );
181
+ const requiredSkills = [
182
+ ...(lock.baseline ?? []),
183
+ ...requiredCloneSources.flatMap(source => source.baseline ?? []),
184
+ ].filter(
185
+ (skill, index, skills) =>
186
+ skills.findIndex(candidate => candidate.name === skill.name) === index,
187
+ );
188
+
189
+ if (checkOnly) {
190
+ const missingRequired = requiredSkills
191
+ .map(skill => skill.name)
192
+ .filter(
193
+ skillName => !fs.existsSync(path.join(installDir, skillName, 'SKILL.md')),
194
+ );
195
+ const missingOptional = optionalCloneSources.flatMap(source =>
196
+ (source.baseline ?? [])
197
+ .map(skill => skill.name)
198
+ .filter(
199
+ skillName =>
200
+ !fs.existsSync(path.join(installDir, skillName, 'SKILL.md')),
201
+ ),
202
+ );
203
+
204
+ if (missingRequired.length > 0) {
205
+ console.error(
206
+ `Required agent skills not installed: ${missingRequired.join(', ')}. Run pnpm skills:install.`,
207
+ );
208
+ process.exit(1);
209
+ }
210
+
211
+ if (missingOptional.length > 0) {
212
+ console.warn(
213
+ `Private skills not installed: ${missingOptional.join(', ')}. Run pnpm skills:install if you have access.`,
214
+ );
215
+ } else {
216
+ console.log('Required and private agent skills are installed.');
217
+ process.exit(0);
218
+ }
219
+ console.log('Required agent skills are installed.');
220
+ process.exit(0);
221
+ }
222
+
223
+ fs.mkdirSync(installDir, { recursive: true });
224
+ installGit();
225
+ initializeGitRepository();
226
+
227
+ for (const source of [...requiredCloneSources, ...optionalCloneSources]) {
228
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ultramodern-skills-'));
229
+ try {
230
+ try {
231
+ cloneSource(source, tempDir);
232
+ } catch (error) {
233
+ if (source.install === 'clone-if-authorized') {
234
+ console.warn(
235
+ `Skipping ${source.repository}; current developer may not have access.`,
236
+ );
237
+ continue;
238
+ }
239
+ throw error;
240
+ }
241
+ for (const skill of source.baseline ?? []) {
242
+ const sourceSkillDir = resolveSkillDir(tempDir, skill.name);
243
+ if (!sourceSkillDir) {
244
+ throw new Error(
245
+ `Skill ${skill.name} not found in ${source.repository}`,
246
+ );
247
+ }
248
+ const targetSkillDir = path.join(installDir, skill.name);
249
+ if (fs.existsSync(targetSkillDir)) {
250
+ if (!force) {
251
+ console.log(`Skipping existing ${skill.name}`);
252
+ continue;
253
+ }
254
+ removeTree(targetSkillDir);
255
+ }
256
+ fs.cpSync(sourceSkillDir, targetSkillDir, { recursive: true });
257
+ console.log(`Installed ${skill.name}`);
258
+ }
259
+ } finally {
260
+ removeTree(tempDir);
261
+ }
262
+ }
263
+
264
+ installLefthook();