Problem
webjs create <name> interpolates the app name into GENERATED source as a template-literal value with no character validation: packages/cli/lib/create.js derives displayName from the name and emits it into app/page.ts (export const metadata = { title: '${displayName}' }) and other string-template output. A name containing a single quote, backtick, ${, or backslash breaks the emitted file at the JS/TS syntax level, so the very first npm run dev of the fresh app 500s with a parse error far from the actual cause. The name also lands in the generated package.json name field, where npm has its own rules (lowercase, no spaces, URL-safe). Found during the PR #1060 review (noted as pre-existing, out of that PR's scope).
Design / approach
Validate the name at the CLI boundary BEFORE any file is written, with a clear error naming the offending character and the allowed shape. The pragmatic rule: enforce npm package-name compatibility (lowercase letters, digits, -, ., _, no leading dot/underscore, length cap), which is strictly safer than every interpolation site and matches what create-next-app and npm init enforce. scaffoldApp() should re-validate programmatically (it is a public entry the tests call directly), same as it re-validates --template.
Implementation notes (for the implementing agent)
- Where to edit:
packages/cli/bin/webjs.js (the create dispatch, near the existing --template validation) for the user-facing error, and packages/cli/lib/create.js scaffoldApp() for the programmatic guard (throw a clear Error).
- Landmines:
bun create webjs <name> and npm create webjs route through the same path (create-webjs / webjsdev wrappers are version-locksteped to the cli; do NOT hand-bump them); the displayName derivation (title-cased) must keep working for valid names; error message must respect the prose-punctuation invariant (AGENTS.md item 11).
- Invariants: exactly three templates stays untouched (cli package invariant 1); the validation is a new guard, not a template change.
- Tests:
test/scaffolds/scaffold-template-validation.test.js is the natural home (it already tests the --template rejection). Add: a quote/backtick/${-bearing name is rejected with the clear message; a valid kebab name still scaffolds; the counterfactual (the bad name currently produces a broken app/page.ts) proves the guard fires.
- Docs: the CLI reference row for
webjs create in the root AGENTS.md only if the surface message changes materially (likely N/A).
Acceptance criteria
Problem
webjs create <name>interpolates the app name into GENERATED source as a template-literal value with no character validation:packages/cli/lib/create.jsderivesdisplayNamefrom the name and emits it intoapp/page.ts(export const metadata = { title: '${displayName}' }) and other string-template output. A name containing a single quote, backtick,${, or backslash breaks the emitted file at the JS/TS syntax level, so the very firstnpm run devof the fresh app 500s with a parse error far from the actual cause. The name also lands in the generatedpackage.jsonnamefield, where npm has its own rules (lowercase, no spaces, URL-safe). Found during the PR #1060 review (noted as pre-existing, out of that PR's scope).Design / approach
Validate the name at the CLI boundary BEFORE any file is written, with a clear error naming the offending character and the allowed shape. The pragmatic rule: enforce npm package-name compatibility (lowercase letters, digits,
-,.,_, no leading dot/underscore, length cap), which is strictly safer than every interpolation site and matches whatcreate-next-appandnpm initenforce.scaffoldApp()should re-validate programmatically (it is a public entry the tests call directly), same as it re-validates--template.Implementation notes (for the implementing agent)
packages/cli/bin/webjs.js(thecreatedispatch, near the existing--templatevalidation) for the user-facing error, andpackages/cli/lib/create.jsscaffoldApp()for the programmatic guard (throw a clear Error).bun create webjs <name>andnpm create webjsroute through the same path (create-webjs/webjsdevwrappers are version-locksteped to the cli; do NOT hand-bump them); thedisplayNamederivation (title-cased) must keep working for valid names; error message must respect the prose-punctuation invariant (AGENTS.md item 11).test/scaffolds/scaffold-template-validation.test.jsis the natural home (it already tests the--templaterejection). Add: a quote/backtick/${-bearing name is rejected with the clear message; a valid kebab name still scaffolds; the counterfactual (the bad name currently produces a brokenapp/page.ts) proves the guard fires.webjs createin the root AGENTS.md only if the surface message changes materially (likely N/A).Acceptance criteria
webjs create "bad'name"(and backtick /${variants) exits non-zero with a message naming the allowed shape, writing NO filesscaffoldApp('badname', ...)` throws before writingapp/page.ts