Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,14 @@ StackForge is local-first and review-friendly:

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.

The `next-app` scaffold ships an npm lockfile and an exact, reviewed Next.js
toolchain. Use `npm ci` for a reproducible install and `npm run audit` to check
the production dependency graph for high or critical advisories. The scaffold
temporarily overrides Next.js's bundled `postcss` and `sharp` versions because
the upstream range otherwise resolves releases with active advisories.
The `next-app` scaffold ships an npm lockfile, `.gitignore`, `next-env.d.ts`,
`tsconfig.json`, and an exact, reviewed Next.js toolchain. Its TypeScript
metadata is complete before the first install or build, so framework commands
do not need to rewrite the generated project. Use `npm ci` for a reproducible
install and `npm run audit` to check the production dependency graph for high
or critical advisories. The scaffold temporarily overrides Next.js's bundled
`postcss` and `sharp` versions because the upstream range otherwise resolves
releases with active advisories.

`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.

Expand Down
11 changes: 11 additions & 0 deletions scripts/smoke-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ node "$repo_root/dist/index.js" init next-app web-app > next.json
test -f web-app/src/app/page.tsx
test -f web-app/eslint.config.mjs
test -f web-app/package-lock.json
test -f web-app/.gitignore
test -f web-app/next-env.d.ts
test -f web-app/tsconfig.json
node -e '
const pkg = require("./web-app/package.json");
const expected = {
Expand All @@ -201,11 +204,19 @@ node -e '
'
(
cd web-app
git init -q
git add .
git -c user.name="StackForge Smoke" -c user.email="smoke@example.invalid" commit -qm "test: capture generated scaffold"
npm ci --ignore-scripts
npm run lint
npm run build
npm run audit
bash scripts/validate.sh
test -z "$(git status --porcelain)" || {
echo "next-app verification modified generated scaffold files" >&2
git status --short >&2
exit 1
}
)

echo "smoke-init ok"
45 changes: 45 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ const templateScaffolds: Record<TemplateKey, TemplateScaffold> = {
{ source: 'templates/repo-validate/validate.sh', destination: 'scripts/validate.sh' },
{ destination: 'package.json', content: nextPackageJsonTemplate() },
{ source: 'templates/next-app/package-lock.json', destination: 'package-lock.json', render: true },
{ destination: '.gitignore', content: nextGitignoreTemplate() },
{ destination: 'next-env.d.ts', content: nextEnvironmentDeclarationTemplate() },
{ destination: 'tsconfig.json', content: nextTypeScriptConfigTemplate() },
{ destination: 'eslint.config.mjs', content: nextEslintConfigTemplate() },
{ destination: 'src/app/page.tsx', content: "export default function Home() {\n return <main>{{PROJECT_NAME}}</main>;\n}\n" },
{ 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" }
Expand Down Expand Up @@ -555,6 +558,48 @@ export default defineConfig([
`;
}

function nextGitignoreTemplate(): string {
return `node_modules/
.next/
out/
build/
`;
}

function nextEnvironmentDeclarationTemplate(): string {
return `/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/types/routes.d.ts";

// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
`;
}

function nextTypeScriptConfigTemplate(): string {
return `{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"incremental": true,
"plugins": [{ "name": "next" }]
},
"include": ["next-env.d.ts", ".next/types/**/*.ts", ".next/dev/types/**/*.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}
`;
}

function pythonProjectTemplate(): string {
return `[project]
name = "{{PROJECT_NAME}}"
Expand Down
Loading