Skip to content

Commit 69ce455

Browse files
authored
Merge pull request #26 from rogerchappel/agent/oss-1363-pin-next-toolchain
fix(next-app): pin reproducible dependency graph
2 parents 4424e2c + 9aec74a commit 69ce455

4 files changed

Lines changed: 6243 additions & 10 deletions

File tree

‎README.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ StackForge is local-first and review-friendly:
7373

7474
Generated repositories include `scripts/validate.sh` as the default local verification path. It runs the repo's normal local package checks when they exist, including `release:check`, and only runs `agent-qc ready` when `agent-qc` is installed, so `agent-qc` stays optional.
7575

76+
The `next-app` scaffold ships an npm lockfile and an exact, reviewed Next.js
77+
toolchain. Use `npm ci` for a reproducible install and `npm run audit` to check
78+
the production dependency graph for high or critical advisories. The scaffold
79+
temporarily overrides Next.js's bundled `postcss` and `sharp` versions because
80+
the upstream range otherwise resolves releases with active advisories.
81+
7682
`oss-cli` projects also include ReleaseBox by default: `releasebox.config.json`, reviewed/tag-gated GitHub release workflows, and package smoke scripts. The generated release path creates GitHub Releases with attached tarballs while leaving npm and Homebrew publishing disabled until explicitly enabled.
7783

7884
## Local planning docs

‎scripts/smoke-init.sh‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,33 @@ test -f py-api/src/py_api/main.py
173173
node "$repo_root/dist/index.js" init next-app web-app > next.json
174174
test -f web-app/src/app/page.tsx
175175
test -f web-app/eslint.config.mjs
176+
test -f web-app/package-lock.json
177+
node -e '
178+
const pkg = require("./web-app/package.json");
179+
const expected = {
180+
dependencies: { next: "16.2.12", react: "19.1.9", "react-dom": "19.1.9" },
181+
devDependencies: {
182+
"@types/node": "22.20.1",
183+
"@types/react": "19.1.17",
184+
"@types/react-dom": "19.1.11",
185+
eslint: "9.39.5",
186+
"eslint-config-next": "16.2.12",
187+
typescript: "5.9.3"
188+
},
189+
overrides: { postcss: "8.5.23", sharp: "0.35.3" }
190+
};
191+
for (const [field, values] of Object.entries(expected)) {
192+
if (JSON.stringify(pkg[field]) !== JSON.stringify(values)) {
193+
throw new Error(`unexpected next-app ${field}`);
194+
}
195+
}
196+
'
176197
(
177198
cd web-app
178-
npm install
199+
npm ci --ignore-scripts
179200
npm run lint
201+
npm run build
202+
npm run audit
180203
bash scripts/validate.sh
181204
)
182205

‎src/index.ts‎

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ const templateScaffolds: Record<TemplateKey, TemplateScaffold> = {
8080
{ source: 'templates/repo-docs/README.md', destination: 'docs/README.md' },
8181
{ source: 'templates/repo-validate/validate.sh', destination: 'scripts/validate.sh' },
8282
{ destination: 'package.json', content: nextPackageJsonTemplate() },
83+
{ source: 'templates/next-app/package-lock.json', destination: 'package-lock.json', render: true },
8384
{ destination: 'eslint.config.mjs', content: nextEslintConfigTemplate() },
8485
{ destination: 'src/app/page.tsx', content: "export default function Home() {\n return <main>{{PROJECT_NAME}}</main>;\n}\n" },
8586
{ destination: 'src/app/layout.tsx', content: "export default function RootLayout({ children }: { children: React.ReactNode }) {\n return (\n <html lang=\"en\">\n <body>{children}</body>\n </html>\n );\n}\n" }
@@ -519,19 +520,25 @@ function nextPackageJsonTemplate(): string {
519520
"dev": "next dev",
520521
"build": "next build",
521522
"start": "next start",
522-
"lint": "eslint ."
523+
"lint": "eslint .",
524+
"audit": "npm audit --omit=dev --audit-level=high"
523525
},
524526
"dependencies": {
525-
"next": "latest",
526-
"react": "latest",
527-
"react-dom": "latest"
527+
"next": "16.2.12",
528+
"react": "19.1.9",
529+
"react-dom": "19.1.9"
528530
},
529531
"devDependencies": {
530-
"@types/node": "latest",
531-
"@types/react": "latest",
532-
"eslint": "latest",
533-
"eslint-config-next": "latest",
534-
"typescript": "latest"
532+
"@types/node": "22.20.1",
533+
"@types/react": "19.1.17",
534+
"@types/react-dom": "19.1.11",
535+
"eslint": "9.39.5",
536+
"eslint-config-next": "16.2.12",
537+
"typescript": "5.9.3"
538+
},
539+
"overrides": {
540+
"postcss": "8.5.23",
541+
"sharp": "0.35.3"
535542
}
536543
}
537544
`;

0 commit comments

Comments
 (0)