@bleedingdev/modern-js-create 3.2.0-ultramodern.7 → 3.2.0-ultramodern.70

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 (53) hide show
  1. package/README.md +120 -22
  2. package/dist/index.js +4890 -742
  3. package/dist/types/locale/en.d.ts +3 -0
  4. package/dist/types/locale/zh.d.ts +3 -0
  5. package/dist/types/ultramodern-workspace.d.ts +11 -0
  6. package/package.json +6 -6
  7. package/template/.agents/skills-lock.json +34 -0
  8. package/template/.codex/hooks.json +16 -0
  9. package/template/.github/renovate.json +53 -0
  10. package/template/.github/workflows/ultramodern-gates.yml.handlebars +34 -10
  11. package/template/.mise.toml.handlebars +2 -0
  12. package/template/AGENTS.md +23 -0
  13. package/template/README.md +60 -34
  14. package/template/api/effect/index.ts.handlebars +7 -45
  15. package/template/config/public/locales/cs/translation.json +39 -0
  16. package/template/config/public/locales/en/translation.json +39 -0
  17. package/template/lefthook.yml +10 -0
  18. package/template/modern.config.ts.handlebars +44 -23
  19. package/template/oxfmt.config.ts +8 -0
  20. package/template/oxlint.config.ts +12 -0
  21. package/template/package.json.handlebars +50 -31
  22. package/template/pnpm-workspace.yaml +19 -0
  23. package/template/rstest.config.mts +7 -0
  24. package/template/scripts/bootstrap-agent-skills.mjs +135 -0
  25. package/template/scripts/check-i18n-strings.mjs +83 -0
  26. package/template/scripts/validate-ultramodern.mjs.handlebars +439 -17
  27. package/template/shared/effect/api.ts.handlebars +1 -2
  28. package/template/src/modern-app-env.d.ts +2 -0
  29. package/template/src/modern.runtime.ts.handlebars +17 -3
  30. package/template/src/routes/[lang]/page.tsx.handlebars +212 -0
  31. package/template/src/routes/index.css.handlebars +14 -3
  32. package/template/src/routes/layout.tsx.handlebars +2 -1
  33. package/template/tests/tsconfig.json +7 -0
  34. package/template/tests/ultramodern.contract.test.ts.handlebars +78 -0
  35. package/template/tsconfig.json +106 -2
  36. package/template-workspace/.agents/agent-reference-repos.json +24 -0
  37. package/template-workspace/.agents/skills-lock.json +58 -0
  38. package/template-workspace/.codex/hooks.json +16 -0
  39. package/template-workspace/.github/renovate.json +29 -0
  40. package/template-workspace/.github/workflows/ultramodern-workspace-gates.yml.handlebars +54 -0
  41. package/template-workspace/.gitignore.handlebars +5 -0
  42. package/template-workspace/.mise.toml.handlebars +2 -0
  43. package/template-workspace/AGENTS.md +52 -4
  44. package/template-workspace/README.md.handlebars +33 -10
  45. package/template-workspace/lefthook.yml +10 -0
  46. package/template-workspace/oxfmt.config.ts +17 -0
  47. package/template-workspace/oxlint.config.ts +20 -0
  48. package/template-workspace/pnpm-workspace.yaml +20 -10
  49. package/template-workspace/scripts/bootstrap-agent-skills.mjs +163 -0
  50. package/template-workspace/scripts/setup-agent-reference-repos.mjs +368 -0
  51. package/template/biome.json +0 -41
  52. package/template/src/routes/page.tsx.handlebars +0 -119
  53. package/template-workspace/scripts/validate-ultramodern-workspace.mjs.handlebars +0 -343
@@ -1,6 +1,28 @@
1
1
  # UltraModern Agent Contract
2
2
 
3
- This workspace is generated as an agent-ready UltraModern.js SuperApp. Agents should treat the files under `.agents/skills` as local project instructions, not optional reading.
3
+ This workspace is generated as an agent-ready UltraModern.js SuperApp shell.
4
+ Agents should treat the files under `.agents/skills` as local project
5
+ instructions, not optional reading.
6
+
7
+ ## Quality Gates
8
+
9
+ - `pnpm lint` runs Oxlint with the Ultracite preset.
10
+ - `pnpm format` runs oxfmt.
11
+ - `pnpm typecheck` runs effect-tsgo as the TypeScript checker.
12
+ - `pnpm check` runs formatting, linting, effect-tsgo, private-skill availability checks, and the generated workspace contract.
13
+ - Generated Codex stop hooks and subagent-stop hooks run `pnpm format && pnpm lint:fix && pnpm check`.
14
+ - `postinstall` formats the generated tree, installs agent skills and reference repos, then installs `lefthook` when the workspace is inside a Git worktree. Generated `lefthook.yml` runs `pnpm format && pnpm lint:fix && pnpm check` on pre-commit; pre-push runs `pnpm check`.
15
+
16
+ ## Localized Routes
17
+
18
+ Generated apps keep locale-prefixed entry routes under `src/routes/[lang]`,
19
+ static language links, and canonical plus `hreflang` metadata. A new workspace
20
+ starts shell-only; `create <domain> --vertical` adds route-owned metadata,
21
+ localized resources, and Effect BFF surfaces for that domain. Runtime i18n is
22
+ not enabled in the starter because the current React 19 + Module Federation
23
+ streaming SSR stack must render predictably first. Production builds fail unless
24
+ `MODERN_PUBLIC_SITE_URL` is set per deployed app, so canonical URLs always use
25
+ the production origin.
4
26
 
5
27
  ## Required Skill Baseline
6
28
 
@@ -13,16 +35,42 @@ Use these skills when the task touches the matching subsystem:
13
35
  - `rslib-best-practices`: Shared packages, generated libraries, declaration output, and Rslib configuration.
14
36
  - `rslib-modern-package`: Package contracts for shared libraries, exports, side effects, dependency placement, README, and release readiness.
15
37
  - `rstest-best-practices`: Rstest configuration, test writing, mocking, snapshots, coverage, and CI test behavior.
38
+ - `mf`: Module Federation docs, Modern.js integration, DTS/type checks, shared dependency checks, runtime errors, and observability troubleshooting.
39
+
40
+ The public `module-federation/agent-skills` repository is installed during `pnpm install` and `pnpm skills:install`. `pnpm skills:check` fails when the required public `mf` skill is missing.
41
+
42
+ ## Private Skills
43
+
44
+ ScriptedAlchemy/TechsioCZ skills are private and are cloned only when the current developer is authorized for `TechsioCZ/skills`.
45
+
46
+ ```bash
47
+ pnpm skills:install
48
+ ```
49
+
50
+ The installer copies only the pinned private skills from `.agents/skills-lock.json`: `plan-graph`, `dag`, `subagent-graph`, `helm`, and `debugger-mode`.
51
+
52
+ ## Agent Reference Repositories
53
+
54
+ The workspace installs read-only source references under `repos/` by default during `pnpm install` using `git subtree add --squash`. These repositories are reference material for coding agents, not application source:
55
+
56
+ - `repos/effect` from `Effect-TS/effect`.
57
+ - `repos/ultramodern.js` from `BleedingDev/ultramodern.js`.
58
+
59
+ Agents may read files under `repos/` to understand upstream patterns, APIs, and project conventions. Do not edit files under `repos/`, import from them, or make production code depend on them. To skip this setup, run installs with `ULTRAMODERN_SKIP_AGENT_REPOS=1`.
16
60
 
17
61
  ## Project Priorities
18
62
 
19
63
  - Keep `presetUltramodern` as the single preset.
20
- - Prefer Effect for BFF/service code.
64
+ - Keep the initial workspace shell-only unless a user explicitly asks for a
65
+ starter vertical.
66
+ - Use `create <domain> --vertical` as the growth path for real business
67
+ MicroVerticals.
68
+ - Prefer Effect for BFF code.
21
69
  - Prefer TanStack Router for app routing.
22
- - Keep design-system code as a normal Micro Frontend or shared package, not a special core path.
70
+ - Keep UI-kit or design-system code as ordinary vertical or shared package code, not a special core path.
23
71
  - Keep generated packages explicit and publishable: stable `exports`, correct declarations, small public APIs, and clear ownership metadata.
24
72
  - Do not add migration tooling or codemods unless the project owner explicitly asks for migration work.
25
73
 
26
74
  ## Skill Provenance
27
75
 
28
- The vendored Rstack skills are pinned in `.agents/skills-lock.json`. Do not update, remove, or replace them casually. If a skill needs updating, update the lock file and run `pnpm ultramodern:check`.
76
+ The vendored Rstack skills, public Module Federation skill, and private TechsioCZ skill set are pinned in `.agents/skills-lock.json`. Do not update, remove, or replace them casually. If a skill needs updating, update the lock file and run `pnpm check`.
@@ -3,23 +3,46 @@
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
17
+ pnpm create modern@latest transportation --vertical
18
+ pnpm create modern@latest payments --vertical
19
+ ```
20
+
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
19
31
  pnpm ultramodern:check
20
32
  ```
21
33
 
22
- The topology and ownership metadata are generated under `topology/`.
34
+ By default, `pnpm install` also prepares read-only agent reference repositories
35
+ under `repos/` for Effect and UltraModern.js source lookup using squashed git
36
+ subtrees. Disable this setup with
37
+ `ULTRAMODERN_SKIP_AGENT_REPOS=1 pnpm install`, or rerun it
38
+ explicitly with `pnpm agents:refs:install`.
39
+
40
+ The topology and ownership metadata are generated under `topology/`. The
41
+ workspace also ships `.github/workflows/ultramodern-workspace-gates.yml` and
42
+ `.github/renovate.json` with read-only workflow permissions, commit-pinned
43
+ actions, frozen installs, StepSecurity audit-mode runner hardening, dependency
44
+ dashboard review, one-day release age, grouped updates, and manual approval for
45
+ major upgrades.
23
46
 
24
47
  Package source metadata is generated at
25
48
  `.modernjs/ultramodern-package-source.json`. The default strategy keeps
@@ -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,19 +1,29 @@
1
1
  packages:
2
2
  - apps/*
3
- - apps/remotes/*
4
- - services/*
3
+ - verticals/*
5
4
  - packages/*
6
5
 
6
+ minimumReleaseAge: 0
7
+ blockExoticSubdeps: true
8
+ engineStrict: true
9
+ pmOnFail: error
10
+ verifyDepsBeforeRun: error
11
+ strictDepBuilds: true
12
+
13
+ peerDependencyRules:
14
+ allowedVersions:
15
+ react: '>=19.0.0'
16
+ typescript: '>=6.0.0'
17
+
18
+ overrides:
19
+ '@tanstack/react-router': 1.170.8
20
+ node-fetch: '^3.3.2'
21
+
7
22
  allowBuilds:
8
- '@biomejs/biome': true
9
23
  '@swc/core': true
10
24
  core-js: true
11
25
  esbuild: true
26
+ lefthook: true
12
27
  msgpackr-extract: true
13
-
14
- onlyBuiltDependencies:
15
- - '@biomejs/biome'
16
- - '@swc/core'
17
- - core-js
18
- - esbuild
19
- - msgpackr-extract
28
+ sharp: true
29
+ workerd: true
@@ -0,0 +1,163 @@
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 removeTree = dir =>
21
+ fs.rmSync(dir, {
22
+ force: true,
23
+ maxRetries: 5,
24
+ recursive: true,
25
+ retryDelay: 100,
26
+ });
27
+
28
+ const cloneSource = (source, targetDir) => {
29
+ const repo = source.repository.replace(/^https:\/\/github.com\//u, '');
30
+ try {
31
+ run('gh', ['repo', 'clone', repo, targetDir, '--', '--depth', '1'], {
32
+ stdio: 'inherit',
33
+ });
34
+ } catch {
35
+ run('git', ['clone', '--depth', '1', source.repository, targetDir], {
36
+ stdio: 'inherit',
37
+ });
38
+ }
39
+ if (source.commit) {
40
+ try {
41
+ run('git', ['checkout', source.commit], {
42
+ cwd: targetDir,
43
+ stdio: 'inherit',
44
+ });
45
+ } catch {
46
+ run('git', ['fetch', '--depth', '1', 'origin', source.commit], {
47
+ cwd: targetDir,
48
+ stdio: 'inherit',
49
+ });
50
+ run('git', ['checkout', source.commit], {
51
+ cwd: targetDir,
52
+ stdio: 'inherit',
53
+ });
54
+ }
55
+ }
56
+ };
57
+
58
+ const resolveSkillDir = (sourceRoot, skillName) => {
59
+ const candidates = [
60
+ path.join(sourceRoot, skillName),
61
+ path.join(sourceRoot, 'skills', skillName),
62
+ path.join(sourceRoot, 'skills', 'engineering', skillName),
63
+ path.join(sourceRoot, 'skills', 'productivity', skillName),
64
+ ];
65
+ return candidates.find(candidate =>
66
+ fs.existsSync(path.join(candidate, 'SKILL.md')),
67
+ );
68
+ };
69
+
70
+ if (!fs.existsSync(lockPath)) {
71
+ console.error('Missing .agents/skills-lock.json');
72
+ process.exit(1);
73
+ }
74
+
75
+ const lock = readJson(lockPath);
76
+ const installDir = path.join(root, lock.installDir ?? '.agents/skills');
77
+ const sources = lock.sources ?? [];
78
+ const requiredCloneSources = sources.filter(
79
+ source => source.install === 'clone',
80
+ );
81
+ const optionalCloneSources = sources.filter(
82
+ source => source.install === 'clone-if-authorized',
83
+ );
84
+ const requiredSkills = [
85
+ ...(lock.baseline ?? []),
86
+ ...requiredCloneSources.flatMap(source => source.baseline ?? []),
87
+ ].filter(
88
+ (skill, index, skills) =>
89
+ skills.findIndex(candidate => candidate.name === skill.name) === index,
90
+ );
91
+
92
+ if (checkOnly) {
93
+ const missingRequired = requiredSkills
94
+ .map(skill => skill.name)
95
+ .filter(
96
+ skillName => !fs.existsSync(path.join(installDir, skillName, 'SKILL.md')),
97
+ );
98
+ const missingOptional = optionalCloneSources.flatMap(source =>
99
+ (source.baseline ?? [])
100
+ .map(skill => skill.name)
101
+ .filter(
102
+ skillName =>
103
+ !fs.existsSync(path.join(installDir, skillName, 'SKILL.md')),
104
+ ),
105
+ );
106
+
107
+ if (missingRequired.length > 0) {
108
+ console.error(
109
+ `Required agent skills not installed: ${missingRequired.join(', ')}. Run pnpm skills:install.`,
110
+ );
111
+ process.exit(1);
112
+ }
113
+
114
+ if (missingOptional.length > 0) {
115
+ console.warn(
116
+ `Private skills not installed: ${missingOptional.join(', ')}. Run pnpm skills:install if you have access.`,
117
+ );
118
+ } else {
119
+ console.log('Required and private agent skills are installed.');
120
+ process.exit(0);
121
+ }
122
+ console.log('Required agent skills are installed.');
123
+ process.exit(0);
124
+ }
125
+
126
+ fs.mkdirSync(installDir, { recursive: true });
127
+
128
+ for (const source of [...requiredCloneSources, ...optionalCloneSources]) {
129
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ultramodern-skills-'));
130
+ try {
131
+ try {
132
+ cloneSource(source, tempDir);
133
+ } catch (error) {
134
+ if (source.install === 'clone-if-authorized') {
135
+ console.warn(
136
+ `Skipping ${source.repository}; current developer may not have access.`,
137
+ );
138
+ continue;
139
+ }
140
+ throw error;
141
+ }
142
+ for (const skill of source.baseline ?? []) {
143
+ const sourceSkillDir = resolveSkillDir(tempDir, skill.name);
144
+ if (!sourceSkillDir) {
145
+ throw new Error(
146
+ `Skill ${skill.name} not found in ${source.repository}`,
147
+ );
148
+ }
149
+ const targetSkillDir = path.join(installDir, skill.name);
150
+ if (fs.existsSync(targetSkillDir)) {
151
+ if (!force) {
152
+ console.log(`Skipping existing ${skill.name}`);
153
+ continue;
154
+ }
155
+ removeTree(targetSkillDir);
156
+ }
157
+ fs.cpSync(sourceSkillDir, targetSkillDir, { recursive: true });
158
+ console.log(`Installed ${skill.name}`);
159
+ }
160
+ } finally {
161
+ removeTree(tempDir);
162
+ }
163
+ }