@bleedingdev/modern-js-create 3.2.0-ultramodern.29 → 3.2.0-ultramodern.30

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/package.json CHANGED
@@ -21,7 +21,7 @@
21
21
  "engines": {
22
22
  "node": ">=20"
23
23
  },
24
- "version": "3.2.0-ultramodern.29",
24
+ "version": "3.2.0-ultramodern.30",
25
25
  "types": "./dist/types/index.d.ts",
26
26
  "main": "./dist/index.js",
27
27
  "bin": {
@@ -39,9 +39,9 @@
39
39
  "devDependencies": {
40
40
  "@rslib/core": "0.21.5",
41
41
  "@types/node": "^25.9.1",
42
- "@typescript/native-preview": "7.0.0-dev.20260526.1",
42
+ "@typescript/native-preview": "7.0.0-dev.20260527.2",
43
43
  "tsx": "^4.22.3",
44
- "@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.2.0-ultramodern.29"
44
+ "@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.2.0-ultramodern.30"
45
45
  },
46
46
  "publishConfig": {
47
47
  "registry": "https://registry.npmjs.org/",
@@ -54,6 +54,6 @@
54
54
  "start": "node ./dist/index.js"
55
55
  },
56
56
  "ultramodern": {
57
- "frameworkVersion": "3.2.0-ultramodern.29"
57
+ "frameworkVersion": "3.2.0-ultramodern.30"
58
58
  }
59
59
  }
@@ -29,27 +29,26 @@ jobs:
29
29
  egress-policy: audit
30
30
 
31
31
  - name: Checkout
32
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
32
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
33
33
  with:
34
34
  fetch-depth: 1
35
35
  persist-credentials: false
36
36
 
37
- - name: Setup pnpm
38
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
39
-
40
37
  - name: Setup Node.js
41
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
38
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
42
39
  with:
43
40
  node-version: 24
44
- cache: pnpm
41
+
42
+ - name: Setup mise
43
+ uses: jdx/mise-action@5ac50f778e26fac95da98d50503682459e86d566 # v3.2.0
45
44
 
46
45
  - name: Install Dependencies
47
- run: pnpm install --frozen-lockfile
46
+ run: mise exec -- pnpm install --frozen-lockfile
48
47
 
49
48
  - name: Validate Ultramodern Contract
50
- run: pnpm run ultramodern:check
49
+ run: mise exec -- pnpm run ultramodern:check
51
50
 
52
51
  - name: Build
53
52
  env:
54
53
  MODERN_PUBLIC_SITE_URL: http://localhost:8080
55
- run: pnpm run build
54
+ run: mise exec -- pnpm run build
@@ -0,0 +1,2 @@
1
+ [tools]
2
+ pnpm = "{{pnpmVersion}}"
@@ -8,7 +8,7 @@ This project is generated for Codex-first UltraModern.js work.
8
8
  - `pnpm format` runs oxfmt.
9
9
  - `pnpm typecheck` runs effect-tsgo as the TypeScript checker.
10
10
  - `pnpm i18n:check` rejects hardcoded user-visible JSX text.
11
- - `pnpm ultramodern:check` verifies the generated contract.
11
+ - `mise exec -- pnpm ultramodern:check` verifies the generated contract.
12
12
 
13
13
  ## Internationalization
14
14
 
@@ -5,7 +5,8 @@
5
5
  Install the dependencies:
6
6
 
7
7
  ```bash
8
- pnpm install
8
+ mise install
9
+ mise exec -- pnpm install
9
10
  ```
10
11
 
11
12
  ## Get Started
@@ -13,19 +14,19 @@ pnpm install
13
14
  Start the dev server:
14
15
 
15
16
  ```bash
16
- pnpm dev
17
+ mise exec -- pnpm dev
17
18
  ```
18
19
 
19
20
  Build the app for production:
20
21
 
21
22
  ```bash
22
- pnpm build
23
+ mise exec -- pnpm build
23
24
  ```
24
25
 
25
26
  Validate the generated Ultramodern preset contract locally:
26
27
 
27
28
  ```bash
28
- pnpm run ultramodern:check
29
+ mise exec -- pnpm run ultramodern:check
29
30
  ```
30
31
 
31
32
  The generated preset defaults are opt-out. Disable specific contracts via env vars:
@@ -37,12 +38,12 @@ MODERN_BASELINE_ENABLE_TELEMETRY_EXPORTERS=false
37
38
  ```
38
39
 
39
40
  The generated starter also includes `.github/workflows/ultramodern-gates.yml`
40
- and `.github/renovate.json`. The workflow runs `pnpm run ultramodern:check` and
41
- `pnpm run build` on every push and pull request with read-only permissions,
42
- commit-pinned actions, frozen installs, and StepSecurity audit-mode runner
43
- hardening. Renovate is configured for dependency dashboard review, one-day
44
- release age, grouped updates, action digest pinning, and manual approval for
45
- major upgrades.
41
+ and `.github/renovate.json`. The workflow runs
42
+ `mise exec -- pnpm run ultramodern:check` and `mise exec -- pnpm run build` on
43
+ every push and pull request with read-only permissions, commit-pinned actions,
44
+ frozen installs, and StepSecurity audit-mode runner hardening. Renovate is
45
+ configured for dependency dashboard review, one-day release age, grouped
46
+ updates, action digest pinning, and manual approval for major upgrades.
46
47
 
47
48
  ## Micro Vertical Workspaces
48
49
 
@@ -51,10 +52,10 @@ the UltraModern add flow. It derives paths, package names, ports, Module
51
52
  Federation names, topology entries, overlays, ownership, and root dev scripts:
52
53
 
53
54
  ```bash
54
- npx @modern-js/create catalog --microvertical remote
55
- npx @modern-js/create design-system --microvertical horizontal-remote
56
- npx @modern-js/create catalog-api --microvertical service
57
- npx @modern-js/create catalog-contracts --microvertical shared
55
+ mise exec -- pnpm dlx @modern-js/create catalog --microvertical remote
56
+ mise exec -- pnpm dlx @modern-js/create design-system --microvertical horizontal-remote
57
+ mise exec -- pnpm dlx @modern-js/create catalog-api --microvertical service
58
+ mise exec -- pnpm dlx @modern-js/create catalog-contracts --microvertical shared
58
59
  ```
59
60
 
60
61
  The canonical topology is documented in
@@ -76,7 +77,7 @@ Verticals.
76
77
  Preview the production build locally:
77
78
 
78
79
  ```bash
79
- pnpm serve
80
+ mise exec -- pnpm serve
80
81
  ```
81
82
 
82
83
  For more information, see the
@@ -3,7 +3,7 @@
3
3
  "version": "0.1.0",
4
4
  "private": true,
5
5
  "type": "module",
6
- "packageManager": "pnpm@11.4.0",
6
+ "packageManager": "pnpm@{{pnpmVersion}}",
7
7
  "scripts": {
8
8
  "reset": "npx rimraf node_modules ./**/node_modules",
9
9
  "dev": "modern dev",
@@ -48,7 +48,7 @@
48
48
  "@types/node": "^20",
49
49
  "@types/react": "^19.1.8",
50
50
  "@types/react-dom": "^19.1.6",
51
- "@typescript/native-preview": "7.0.0-dev.20260526.1",
51
+ "@typescript/native-preview": "7.0.0-dev.20260527.2",
52
52
  "happy-dom": "^20.9.0",
53
53
  {{#unless isSubproject}}
54
54
  "lint-staged": "~17.0.5",
@@ -71,6 +71,6 @@
71
71
  }{{/unless}},
72
72
  "engines": {
73
73
  "node": ">=20",
74
- "pnpm": ">=11.4.0 <11.5.0"
74
+ "pnpm": ">={{pnpmVersion}} <11.5.0"
75
75
  }
76
76
  }
@@ -25,6 +25,19 @@ const readPnpmConfig = (key) => {
25
25
  };
26
26
  const isSubproject = {{isSubproject}};
27
27
  const enableTailwind = {{enableTailwind}};
28
+ const expectedPnpmVersion = '{{pnpmVersion}}';
29
+ const activePnpmVersion = execFileSync('pnpm', ['--version'], {
30
+ cwd: process.cwd(),
31
+ encoding: 'utf-8',
32
+ stdio: ['ignore', 'pipe', 'pipe'],
33
+ }).trim();
34
+
35
+ if (activePnpmVersion !== expectedPnpmVersion) {
36
+ console.error(
37
+ `Generated app requires pnpm ${expectedPnpmVersion}; active pnpm is ${activePnpmVersion}. Run mise install, then rerun through mise exec -- pnpm ...`,
38
+ );
39
+ process.exit(1);
40
+ }
28
41
 
29
42
  if (!fs.existsSync(configPath)) {
30
43
  console.error('modern.config.ts not found');
@@ -98,6 +111,7 @@ const requiredPaths = [
98
111
  'config/public/locales/cs/translation.json',
99
112
  'src/modern-app-env.d.ts',
100
113
  'src/routes/index.css',
114
+ 'src/routes/layout.tsx',
101
115
  'src/routes/[lang]/page.tsx',
102
116
  'tests/ultramodern.contract.test.ts',
103
117
  ];
@@ -115,27 +129,7 @@ if (fs.existsSync(path.resolve(process.cwd(), 'src/routes/page.tsx'))) {
115
129
  process.exit(1);
116
130
  }
117
131
 
118
- const routeCss = fs.readFileSync(path.resolve(process.cwd(), 'src/routes/index.css'), 'utf-8');
119
- if (enableTailwind) {
120
- if (!routeCss.includes("@import 'tailwindcss';")) {
121
- console.error('src/routes/index.css must import Tailwind CSS by default');
122
- process.exit(1);
123
- }
124
- const postcssConfig = fs.readFileSync(path.resolve(process.cwd(), 'postcss.config.mjs'), 'utf-8');
125
- if (!postcssConfig.includes("'@tailwindcss/postcss'")) {
126
- console.error('postcss.config.mjs must configure @tailwindcss/postcss');
127
- process.exit(1);
128
- }
129
- const tailwindConfig = fs.readFileSync(path.resolve(process.cwd(), 'tailwind.config.ts'), 'utf-8');
130
- if (!tailwindConfig.includes("content: ['./src/**/*.{js,ts,jsx,tsx}']")) {
131
- console.error('tailwind.config.ts must scan generated source files');
132
- process.exit(1);
133
- }
134
- } else {
135
- if (routeCss.includes("@import 'tailwindcss';")) {
136
- console.error('src/routes/index.css must omit Tailwind CSS when disabled');
137
- process.exit(1);
138
- }
132
+ if (!enableTailwind) {
139
133
  if (
140
134
  fs.existsSync(path.resolve(process.cwd(), 'postcss.config.mjs')) ||
141
135
  fs.existsSync(path.resolve(process.cwd(), 'tailwind.config.ts'))
@@ -157,7 +151,10 @@ for (const requiredSnippet of [
157
151
  'permissions:\n contents: read',
158
152
  'pull_request:',
159
153
  'persist-credentials: false',
160
- 'pnpm install --frozen-lockfile',
154
+ 'jdx/mise-action',
155
+ 'mise exec -- pnpm install --frozen-lockfile',
156
+ 'mise exec -- pnpm run ultramodern:check',
157
+ 'mise exec -- pnpm run build',
161
158
  'MODERN_PUBLIC_SITE_URL: http://localhost:8080',
162
159
  'timeout-minutes:',
163
160
  'egress-policy: audit',
@@ -192,33 +189,6 @@ if (
192
189
  }
193
190
  {{/unless}}
194
191
 
195
- const pageContent = fs.readFileSync(
196
- path.resolve(process.cwd(), 'src/routes/[lang]/page.tsx'),
197
- 'utf-8',
198
- );
199
- for (const token of [
200
- 'rel="canonical"',
201
- 'rel="alternate"',
202
- 'hrefLang="x-default"',
203
- 'localizedPath(',
204
- '<a',
205
- {{#if isTanstackRouter}}
206
- "@modern-js/plugin-tanstack/runtime",
207
- {{/if}}
208
- ]) {
209
- if (!pageContent.includes(token)) {
210
- console.error(`Localized route is missing ${token}`);
211
- process.exit(1);
212
- }
213
- }
214
- {{#if isTanstackRouter}}
215
- const deprecatedTanstackRuntime = '@modern-js/runtime/' + 'tanstack-router';
216
- if (pageContent.includes(deprecatedTanstackRuntime)) {
217
- console.error('Localized route must import TanStack runtime from @modern-js/plugin-tanstack/runtime');
218
- process.exit(1);
219
- }
220
- {{/if}}
221
-
222
192
  if (templateManifest.schemaVersion !== 1) {
223
193
  manifestErrors.push('schemaVersion');
224
194
  }
@@ -318,13 +288,19 @@ if (packageJson.private !== true) {
318
288
  process.exit(1);
319
289
  }
320
290
 
321
- if (packageJson.packageManager !== 'pnpm@11.4.0') {
322
- console.error('Generated app package must pin pnpm@11.4.0');
291
+ const miseConfig = fs.readFileSync(path.resolve(process.cwd(), '.mise.toml'), 'utf-8');
292
+ if (!miseConfig.includes(`pnpm = "${expectedPnpmVersion}"`)) {
293
+ console.error(`Generated app must pin pnpm ${expectedPnpmVersion} in .mise.toml`);
294
+ process.exit(1);
295
+ }
296
+
297
+ if (packageJson.packageManager !== `pnpm@${expectedPnpmVersion}`) {
298
+ console.error(`Generated app package must pin pnpm@${expectedPnpmVersion}`);
323
299
  process.exit(1);
324
300
  }
325
301
 
326
- if (packageJson.engines?.pnpm !== '>=11.4.0 <11.5.0') {
327
- console.error('Generated app package must require pnpm >=11.4.0 <11.5.0');
302
+ if (packageJson.engines?.pnpm !== `>=${expectedPnpmVersion} <11.5.0`) {
303
+ console.error(`Generated app package must require pnpm >=${expectedPnpmVersion} <11.5.0`);
328
304
  process.exit(1);
329
305
  }
330
306
 
@@ -6,7 +6,6 @@ import { Effect } from '@modern-js/plugin-bff/effect-client';
6
6
  import { useEffect, useState } from 'react';
7
7
  {{/if}}
8
8
  import { useTranslation } from 'react-i18next';
9
- import '../index.css';
10
9
 
11
10
  const fallbackLanguage = 'en';
12
11
  const supportedLanguages = ['en', 'cs'] as const;
@@ -128,7 +127,7 @@ const Index = () => {
128
127
  <code className="code">modern.config.ts</code>
129
128
  {/* i18n-ignore technical token */}
130
129
  {t('home.description.afterConfig')}
131
- <code className="code">pnpm run ultramodern:check</code>
130
+ <code className="code">mise exec -- pnpm run ultramodern:check</code>
132
131
  {/* i18n-ignore technical token */}
133
132
  {t('home.description.end')}
134
133
  </p>
@@ -1,4 +1,5 @@
1
1
  import { Outlet } from '{{routerRuntimeImport}}';
2
+ import './index.css';
2
3
 
3
4
  export default function Layout() {
4
5
  return (
@@ -14,32 +14,15 @@ describe('generated UltraModern contract', () => {
14
14
  true,
15
15
  );
16
16
  expect(fs.existsSync(path.join(root, 'src/routes/page.tsx'))).toBe(false);
17
-
18
- const page = readText('src/routes/[lang]/page.tsx');
19
- expect(page).toContain('rel="canonical"');
20
- expect(page).toContain('rel="alternate"');
21
- expect(page).toContain('hrefLang="x-default"');
22
- expect(page).toContain('localizedPath(');
17
+ expect(fs.existsSync(path.join(root, 'src/routes/layout.tsx'))).toBe(true);
23
18
  {{#if enableTailwind}}
24
- expect(readText('src/routes/index.css')).toContain(
25
- "@import 'tailwindcss';",
26
- );
27
- expect(readText('postcss.config.mjs')).toContain('@tailwindcss/postcss');
28
- expect(readText('tailwind.config.ts')).toContain(
29
- "content: ['./src/**/*.{js,ts,jsx,tsx}']",
30
- );
19
+ expect(fs.existsSync(path.join(root, 'postcss.config.mjs'))).toBe(true);
20
+ expect(fs.existsSync(path.join(root, 'tailwind.config.ts'))).toBe(true);
31
21
  {{/if}}
32
22
  {{#unless enableTailwind}}
33
- expect(readText('src/routes/index.css')).not.toContain(
34
- "@import 'tailwindcss';",
35
- );
36
23
  expect(fs.existsSync(path.join(root, 'postcss.config.mjs'))).toBe(false);
37
24
  expect(fs.existsSync(path.join(root, 'tailwind.config.ts'))).toBe(false);
38
25
  {{/unless}}
39
-
40
- const config = readText('rstest.config.mts');
41
- expect(config).toContain("withModernConfig()");
42
- expect(config).toContain("testEnvironment: 'happy-dom'");
43
26
  });
44
27
 
45
28
  test('retains package-source metadata for generated Modern.js packages', () => {
@@ -29,27 +29,26 @@ jobs:
29
29
  egress-policy: audit
30
30
 
31
31
  - name: Checkout
32
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
32
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
33
33
  with:
34
34
  fetch-depth: 1
35
35
  persist-credentials: false
36
36
 
37
- - name: Setup pnpm
38
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
39
-
40
37
  - name: Setup Node.js
41
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
38
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
42
39
  with:
43
40
  node-version: 24
44
- cache: pnpm
41
+
42
+ - name: Setup mise
43
+ uses: jdx/mise-action@5ac50f778e26fac95da98d50503682459e86d566 # v3.2.0
45
44
 
46
45
  - name: Install Dependencies
47
- run: pnpm install --frozen-lockfile
46
+ run: mise exec -- pnpm install --frozen-lockfile
48
47
 
49
48
  - name: Validate Ultramodern Workspace Contract
50
- run: pnpm run ultramodern:check
49
+ run: mise exec -- pnpm run ultramodern:check
51
50
 
52
51
  - name: Build Workspace Apps
53
52
  env:
54
53
  MODERN_PUBLIC_SITE_URL: http://localhost:8080
55
- run: pnpm build
54
+ run: mise exec -- pnpm build
@@ -0,0 +1,2 @@
1
+ [tools]
2
+ pnpm = "{{pnpmVersion}}"
@@ -26,7 +26,7 @@ Use these skills when the task touches the matching subsystem:
26
26
  - `rstest-best-practices`: Rstest configuration, test writing, mocking, snapshots, coverage, and CI test behavior.
27
27
  - `mf`: Module Federation docs, Modern.js integration, DTS/type checks, shared dependency checks, runtime errors, and observability troubleshooting.
28
28
 
29
- 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.
29
+ The public `module-federation/agent-skills` repository is installed during `mise exec -- pnpm install` and `mise exec -- pnpm skills:install`. `mise exec -- pnpm skills:check` fails when the required public `mf` skill is missing.
30
30
 
31
31
  ## Private Skills
32
32
 
@@ -40,7 +40,7 @@ The installer copies only the allowlisted private skills from `.agents/skills-lo
40
40
 
41
41
  ## Agent Reference Repositories
42
42
 
43
- 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:
43
+ The workspace installs read-only source references under `repos/` by default during `mise exec -- pnpm install` using `git subtree add --squash`. These repositories are reference material for coding agents, not application source:
44
44
 
45
45
  - `repos/effect` from `Effect-TS/effect`.
46
46
  - `repos/ultramodern.js` from `BleedingDev/ultramodern.js`.
@@ -25,13 +25,15 @@ packages.
25
25
  Run the scaffold validator before adding business code:
26
26
 
27
27
  ```bash
28
- pnpm ultramodern:check
28
+ mise install
29
+ mise exec -- pnpm ultramodern:check
29
30
  ```
30
31
 
31
- By default, `pnpm install` also prepares read-only agent reference repositories
32
+ By default, `mise exec -- pnpm install` also prepares read-only agent reference repositories
32
33
  under `repos/` for Effect and UltraModern.js source lookup using squashed git
33
- subtrees. Disable this setup with `ULTRAMODERN_SKIP_AGENT_REPOS=1 pnpm install`,
34
- or rerun it explicitly with `pnpm agents:refs:install`.
34
+ subtrees. Disable this setup with
35
+ `ULTRAMODERN_SKIP_AGENT_REPOS=1 mise exec -- pnpm install`, or rerun it
36
+ explicitly with `mise exec -- pnpm agents:refs:install`.
35
37
 
36
38
  The topology and ownership metadata are generated under `topology/`. The
37
39
  workspace also ships `.github/workflows/ultramodern-workspace-gates.yml` and
@@ -8,6 +8,7 @@ const tanstackVersion = '1.170.8';
8
8
  const tailwindEnabled = '{{tailwindEnabled}}' === 'true';
9
9
  const tailwindVersion = '^4.3.0';
10
10
  const tailwindPostcssVersion = '^4.3.0';
11
+ const expectedPnpmVersion = '{{pnpmVersion}}';
11
12
  const rstackAgentSkillsCommit = '61c948b42512e223bad44b83af4080eba48b2677';
12
13
  const moduleFederationAgentSkillsCommit = '07bb5b6c43ad457609e00c081b72d4c42508ec76';
13
14
  const modernPackages = [
@@ -52,6 +53,11 @@ const designSystemRemotePath = 'apps/remotes/remote-design-system';
52
53
 
53
54
  const readText = (relativePath) => fs.readFileSync(path.join(root, relativePath), 'utf-8');
54
55
  const readJson = (relativePath) => JSON.parse(readText(relativePath));
56
+ const activePnpmVersion = execFileSync('pnpm', ['--version'], {
57
+ cwd: root,
58
+ encoding: 'utf-8',
59
+ stdio: ['ignore', 'pipe', 'pipe'],
60
+ }).trim();
55
61
  const readPnpmConfig = (key) => {
56
62
  const env = { ...process.env };
57
63
  for (const envKey of Object.keys(env)) {
@@ -79,6 +85,11 @@ const assertNotExists = (relativePath) => {
79
85
  assert(!fs.existsSync(path.join(root, relativePath)), `Unexpected ${relativePath}`);
80
86
  };
81
87
 
88
+ assert(
89
+ activePnpmVersion === expectedPnpmVersion,
90
+ `Generated workspace requires pnpm ${expectedPnpmVersion}; active pnpm is ${activePnpmVersion}. Run mise install, then rerun through mise exec -- pnpm ...`,
91
+ );
92
+
82
93
  const requiredPaths = [
83
94
  'AGENTS.md',
84
95
  '.gitignore',
@@ -119,6 +130,7 @@ const requiredPaths = [
119
130
  'apps/shell-super-app/locales/en/translation.json',
120
131
  'apps/shell-super-app/locales/cs/translation.json',
121
132
  'apps/shell-super-app/src/routes/index.css',
133
+ 'apps/shell-super-app/src/routes/layout.tsx',
122
134
  'apps/shell-super-app/src/routes/[lang]/page.tsx',
123
135
  'apps/remotes/remote-commerce/package.json',
124
136
  'apps/remotes/remote-commerce/modern.config.ts',
@@ -131,6 +143,7 @@ const requiredPaths = [
131
143
  'apps/remotes/remote-commerce/locales/en/translation.json',
132
144
  'apps/remotes/remote-commerce/locales/cs/translation.json',
133
145
  'apps/remotes/remote-commerce/src/routes/index.css',
146
+ 'apps/remotes/remote-commerce/src/routes/layout.tsx',
134
147
  'apps/remotes/remote-commerce/src/routes/[lang]/page.tsx',
135
148
  'apps/remotes/remote-identity/package.json',
136
149
  'apps/remotes/remote-identity/modern.config.ts',
@@ -143,6 +156,7 @@ const requiredPaths = [
143
156
  'apps/remotes/remote-identity/locales/en/translation.json',
144
157
  'apps/remotes/remote-identity/locales/cs/translation.json',
145
158
  'apps/remotes/remote-identity/src/routes/index.css',
159
+ 'apps/remotes/remote-identity/src/routes/layout.tsx',
146
160
  'apps/remotes/remote-identity/src/routes/[lang]/page.tsx',
147
161
  'apps/remotes/remote-design-system/package.json',
148
162
  'apps/remotes/remote-design-system/modern.config.ts',
@@ -152,6 +166,7 @@ const requiredPaths = [
152
166
  'apps/remotes/remote-design-system/locales/en/translation.json',
153
167
  'apps/remotes/remote-design-system/locales/cs/translation.json',
154
168
  'apps/remotes/remote-design-system/src/routes/index.css',
169
+ 'apps/remotes/remote-design-system/src/routes/layout.tsx',
155
170
  'apps/remotes/remote-design-system/src/routes/[lang]/page.tsx',
156
171
  'packages/shared-contracts/src/index.ts',
157
172
  'packages/shared-design-tokens/src/index.ts',
@@ -211,10 +226,18 @@ const expectedModernDependency = (packageName) => {
211
226
 
212
227
  assert(rootPackage.private === true, 'Root package must be private');
213
228
  assert(rootPackage.modernjs?.preset === 'presetUltramodern', 'Root must declare presetUltramodern');
214
- assert(rootPackage.packageManager === 'pnpm@11.4.0', 'Root must pin pnpm 11.4.0');
229
+ const miseConfig = readText('.mise.toml');
230
+ assert(
231
+ miseConfig.includes(`pnpm = "${expectedPnpmVersion}"`),
232
+ `Root must pin pnpm ${expectedPnpmVersion} in .mise.toml`,
233
+ );
234
+ assert(
235
+ rootPackage.packageManager === `pnpm@${expectedPnpmVersion}`,
236
+ `Root must pin pnpm ${expectedPnpmVersion}`,
237
+ );
215
238
  assert(
216
- rootPackage.engines?.pnpm === '>=11.4.0 <11.5.0',
217
- 'Root must require pnpm >=11.4.0 <11.5.0',
239
+ rootPackage.engines?.pnpm === `>=${expectedPnpmVersion} <11.5.0`,
240
+ `Root must require pnpm >=${expectedPnpmVersion} <11.5.0`,
218
241
  );
219
242
  assert(
220
243
  JSON.stringify(readPnpmConfig('packages')) ===
@@ -278,8 +301,10 @@ for (const requiredSnippet of [
278
301
  'permissions:\n contents: read',
279
302
  'pull_request:',
280
303
  'persist-credentials: false',
281
- 'pnpm install --frozen-lockfile',
282
- 'pnpm build',
304
+ 'jdx/mise-action',
305
+ 'mise exec -- pnpm install --frozen-lockfile',
306
+ 'mise exec -- pnpm run ultramodern:check',
307
+ 'mise exec -- pnpm build',
283
308
  'MODERN_PUBLIC_SITE_URL: http://localhost:8080',
284
309
  'timeout-minutes:',
285
310
  'egress-policy: audit',
@@ -554,7 +579,7 @@ for (const packagePath of appPackagePaths) {
554
579
  `${packagePath} must include TypeScript 6 only as the stable JS TypeScript package for Module Federation DTS generation`,
555
580
  );
556
581
  assert(
557
- packageJson.devDependencies?.['@typescript/native-preview'] === '7.0.0-dev.20260526.1',
582
+ packageJson.devDependencies?.['@typescript/native-preview'] === '7.0.0-dev.20260527.2',
558
583
  `${packagePath} must include TypeScript 7 native preview for mandatory native typechecking`,
559
584
  );
560
585
  assert(
@@ -666,27 +691,11 @@ for (const appDirectory of [
666
691
  'apps/remotes/remote-identity',
667
692
  'apps/remotes/remote-design-system',
668
693
  ]) {
669
- const css = readText(`${appDirectory}/src/routes/index.css`);
670
694
  if (tailwindEnabled) {
671
- assert(
672
- css.includes("@import 'tailwindcss';"),
673
- `${appDirectory} must import Tailwind CSS by default`,
674
- );
675
- const postcssConfig = readText(`${appDirectory}/postcss.config.mjs`);
676
- assert(
677
- postcssConfig.includes("'@tailwindcss/postcss'"),
678
- `${appDirectory} must configure the Tailwind CSS PostCSS plugin`,
679
- );
680
- const tailwindConfig = readText(`${appDirectory}/tailwind.config.ts`);
681
- assert(
682
- tailwindConfig.includes("content: ['./src/**/*.{js,jsx,ts,tsx}']"),
683
- `${appDirectory} must scan app source files for Tailwind CSS classes`,
684
- );
685
- } else {
686
- assert(
687
- !css.includes("@import 'tailwindcss';"),
688
- `${appDirectory} must omit Tailwind CSS import when Tailwind is disabled`,
689
- );
695
+ assertExists(`${appDirectory}/postcss.config.mjs`);
696
+ assertExists(`${appDirectory}/tailwind.config.ts`);
697
+ }
698
+ if (!tailwindEnabled) {
690
699
  assert(
691
700
  !fs.existsSync(path.join(root, appDirectory, 'postcss.config.mjs')),
692
701
  `${appDirectory} must not write PostCSS config when Tailwind is disabled`,
@@ -744,20 +753,6 @@ for (const configPath of [
744
753
  );
745
754
  }
746
755
 
747
- for (const routePath of [
748
- 'apps/shell-super-app/src/routes/[lang]/page.tsx',
749
- 'apps/remotes/remote-commerce/src/routes/[lang]/page.tsx',
750
- 'apps/remotes/remote-identity/src/routes/[lang]/page.tsx',
751
- 'apps/remotes/remote-design-system/src/routes/[lang]/page.tsx',
752
- ]) {
753
- const route = readText(routePath);
754
- assert(route.includes('rel="canonical"'), `${routePath} must emit canonical metadata`);
755
- assert(route.includes('rel="alternate"'), `${routePath} must emit alternate locale metadata`);
756
- assert(route.includes('hrefLang="x-default"'), `${routePath} must emit x-default metadata`);
757
- assert(route.includes('localizedPath('), `${routePath} must build localized URLs`);
758
- assert(route.includes("import '../index.css';"), `${routePath} must import route CSS`);
759
- }
760
-
761
756
  const shellMf = readText('apps/shell-super-app/module-federation.config.ts');
762
757
  assert(shellMf.includes("name: 'shellSuperApp'"), 'Shell MF config must name the shell');
763
758
  assert(
@@ -797,9 +792,8 @@ assert(
797
792
  );
798
793
  assert(
799
794
  generatedContract.packageManager?.manager === 'pnpm' &&
800
- generatedContract.packageManager?.version === '11.4.0' &&
801
- generatedContract.packageManager?.toolchain === 'mise' &&
802
- generatedContract.packageManager?.corepack === false,
795
+ generatedContract.packageManager?.version === expectedPnpmVersion &&
796
+ generatedContract.packageManager?.toolchain === 'mise',
803
797
  'Generated contract must declare the pnpm 11/mise toolchain policy',
804
798
  );
805
799
 
@@ -935,7 +929,7 @@ assert(
935
929
  'Template manifest must list every private agent skill allowlist entry',
936
930
  );
937
931
  assert(
938
- manifest.validation?.expectedCommands?.includes('pnpm run ultramodern:check'),
932
+ manifest.validation?.expectedCommands?.includes('mise exec -- pnpm run ultramodern:check'),
939
933
  'Template manifest must document the validation command',
940
934
  );
941
935
  assert(
@@ -1,2 +0,0 @@
1
- [tools]
2
- pnpm = "11.4.0"
@@ -1,2 +0,0 @@
1
- [tools]
2
- pnpm = "11.4.0"