create-template-project 1.0.0 → 1.1.2

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/README.md CHANGED
@@ -27,7 +27,7 @@ pnpm dlx create-template-project interactive
27
27
  - **Seed File Protection:** Files in `src/`, all `*.md` files, and other core files are skipped to protect your application logic and custom documentation.
28
28
  - **Tooling Sync:** Keeps your project's boilerplate (linting, CI, configs, scripts) up-to-date with the latest template versions.
29
29
  - **No-Build Option:** Supports creating simple projects without a build step (strips Vite).
30
- - **GitHub Integration:** Automatically initializes a Git repository and can create a GitHub repository using the `gh` CLI.
30
+ - **GitHub Integration:** Automatically initializes a Git repository and can create a GitHub repository (including initial commit and push) using the `gh` CLI.
31
31
  - **CI Ready:** Generates GitHub Actions workflows for automated testing and linting.
32
32
 
33
33
  ## Installation
@@ -89,9 +89,8 @@ create-template-project update --template cli
89
89
  - `-a, --author <author>`: Author name (defaults to 'git config user.name')
90
90
  - `--github-username <username>`: GitHub username (defaults to 'git config github.user')
91
91
  - `-p, --package-manager <pm>`: Package manager (`npm`, `pnpm`, `yarn`) (defaults to `pnpm`)
92
- - `--create-github-repository`: Create GitHub project (requires `gh` CLI authenticated)
92
+ - `--create-github-repository`: Create GitHub repository and push initial commit (requires `gh` CLI authenticated)
93
93
  - `--path <path>`: Output directory (mandatory)
94
- - `--install-dependencies`: Install dependencies after scaffolding
95
94
  - `--build`: Run the CI script (lint, build, test) after scaffolding
96
95
  - `--no-progress`: Do not show progress indicators
97
96
 
@@ -103,9 +102,8 @@ create-template-project update --template cli
103
102
  - `-a, --author <author>`: Author name (defaults to 'git config user.name')
104
103
  - `--github-username <username>`: GitHub username (defaults to 'git config github.user')
105
104
  - `-p, --package-manager <pm>`: Package manager (`npm`, `pnpm`, `yarn`) (defaults to `pnpm`)
106
- - `--create-github-repository`: Create GitHub project (requires `gh` CLI authenticated)
105
+ - `--create-github-repository`: Create GitHub repository and push initial commit (requires `gh` CLI authenticated)
107
106
  - `-d, --directory <path>`: Output directory (defaults to `.`)
108
- - `--install-dependencies`: Install dependencies after updating
109
107
  - `--build`: Run the CI script (lint, build, test) after updating
110
108
  - `--dev`: Run the dev server after updating
111
109
  - `--open`: Open the browser after updating
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "dependencies": {
3
3
  "vite": {
4
- "version": "8.0.2",
4
+ "version": "8.0.3",
5
5
  "description": "Native-ESM powered web dev build tool"
6
6
  },
7
7
  "@vitejs/plugin-react": {
@@ -9,15 +9,15 @@
9
9
  "description": "The default Vite plugin for React projects."
10
10
  },
11
11
  "@vitest/browser": {
12
- "version": "4.1.1",
12
+ "version": "4.1.2",
13
13
  "description": "Run Vitest in the browser."
14
14
  },
15
15
  "@vitest/browser-playwright": {
16
- "version": "4.1.1",
16
+ "version": "4.1.2",
17
17
  "description": "Playwright provider for Vitest browser mode."
18
18
  },
19
19
  "playwright": {
20
- "version": "1.58.2",
20
+ "version": "1.59.1",
21
21
  "description": "Framework for Web-browser automation."
22
22
  },
23
23
  "debug": {
@@ -37,11 +37,11 @@
37
37
  "description": "TypeScript definitions for debug."
38
38
  },
39
39
  "@types/node": {
40
- "version": "25.5.0",
40
+ "version": "25.5.2",
41
41
  "description": "TypeScript definitions for Node.js."
42
42
  },
43
43
  "@vitest/coverage-v8": {
44
- "version": "4.1.1",
44
+ "version": "4.1.2",
45
45
  "description": "V8 coverage provider for Vitest."
46
46
  },
47
47
  "conventional-changelog": {
@@ -53,23 +53,23 @@
53
53
  "description": "Modern native git hooks made easy."
54
54
  },
55
55
  "oxlint": {
56
- "version": "1.56.0",
56
+ "version": "1.58.0",
57
57
  "description": "A JavaScript linter written in Rust."
58
58
  },
59
59
  "oxlint-tsgolint": {
60
- "version": "0.17.1",
60
+ "version": "0.19.0",
61
61
  "description": "TypeScript-specific rules for oxlint."
62
62
  },
63
63
  "oxfmt": {
64
- "version": "0.41.0",
64
+ "version": "0.43.0",
65
65
  "description": "High performance JavaScript / TypeScript formatter."
66
66
  },
67
67
  "typescript": {
68
- "version": "5.9.3",
68
+ "version": "6.0.2",
69
69
  "description": "A superset of JavaScript that compiles to clean JavaScript output."
70
70
  },
71
71
  "vitest": {
72
- "version": "4.1.1",
72
+ "version": "4.1.2",
73
73
  "description": "A Vite-native unit test framework."
74
74
  },
75
75
  "commander": {
@@ -125,23 +125,23 @@
125
125
  "description": "TypeScript definitions for React DOM."
126
126
  },
127
127
  "@playwright/test": {
128
- "version": "1.58.2",
128
+ "version": "1.59.1",
129
129
  "description": "End-to-end testing framework."
130
130
  },
131
131
  "@trpc/server": {
132
- "version": "11.15.0",
132
+ "version": "11.16.0",
133
133
  "description": "tRPC server library."
134
134
  },
135
135
  "@trpc/client": {
136
- "version": "11.15.0",
136
+ "version": "11.16.0",
137
137
  "description": "tRPC client library."
138
138
  },
139
139
  "@trpc/react-query": {
140
- "version": "11.15.0",
140
+ "version": "11.16.0",
141
141
  "description": "tRPC integration for React Query."
142
142
  },
143
143
  "@tanstack/react-query": {
144
- "version": "5.95.2",
144
+ "version": "5.96.2",
145
145
  "description": "Powerful asynchronous state management for TS/JS."
146
146
  },
147
147
  "zod": {
@@ -149,9 +149,13 @@
149
149
  "description": "TypeScript-first schema validation with static type inference."
150
150
  },
151
151
  "react-router-dom": {
152
- "version": "7.13.2",
152
+ "version": "7.14.0",
153
153
  "description": "Declarative routing for React web applications."
154
154
  },
155
+ "release-it": {
156
+ "version": "19.2.4",
157
+ "description": "Interactive release-tool for Git repositories."
158
+ },
155
159
  "cors": {
156
160
  "version": "2.8.6",
157
161
  "description": "Node.js CORS middleware."
@@ -165,7 +169,7 @@
165
169
  "description": "ESLint plugin for finding regexp mistakes and style guide violations."
166
170
  },
167
171
  "vitest-browser-react": {
168
- "version": "2.1.0",
172
+ "version": "2.2.0",
169
173
  "description": "Native React testing utilities for Vitest browser mode."
170
174
  }
171
175
  }
package/dist/index.js CHANGED
@@ -32,7 +32,6 @@ var ProjectOptionsSchema = z.object({
32
32
  createGithubRepository: z.boolean().optional().default(false),
33
33
  directory: z.string(),
34
34
  update: z.boolean().optional().default(false),
35
- installDependencies: z.boolean().optional().default(false),
36
35
  build: z.boolean().optional().default(false),
37
36
  progress: z.boolean().optional().default(true)
38
37
  });
@@ -258,6 +257,10 @@ var getBaseTemplate = (_opts) => {
258
257
  name: "conventional-changelog",
259
258
  description: "Automated release notes."
260
259
  },
260
+ {
261
+ name: "release-it",
262
+ description: "Automated release workflow."
263
+ },
261
264
  {
262
265
  name: "debug",
263
266
  description: "Structured logging for debugging."
@@ -268,7 +271,10 @@ var getBaseTemplate = (_opts) => {
268
271
  }
269
272
  ],
270
273
  dependencies: { zod: "zod" },
271
- devDependencies: { "eslint-plugin-regexp": "" },
274
+ devDependencies: {
275
+ "eslint-plugin-regexp": "",
276
+ "release-it": ""
277
+ },
272
278
  scripts: {},
273
279
  files: [],
274
280
  templateDir: getTemplateDir(__dirname$5, "base")
@@ -497,7 +503,6 @@ var MOCK_OPTS = {
497
503
  directory: ".",
498
504
  packageManager: "npm",
499
505
  update: false,
500
- installDependencies: false,
501
506
  build: false,
502
507
  progress: true,
503
508
  createGithubRepository: false
@@ -540,6 +545,17 @@ var getAllTemplatesInfo = () => {
540
545
  //#endregion
541
546
  //#region src/cli.ts
542
547
  var pathExists$1 = (p) => fs.access(p).then(() => true).catch(() => false);
548
+ var stripQuotes = (str) => {
549
+ if (typeof str !== "string") return str;
550
+ let result = str.trim();
551
+ while (result.length >= 2) {
552
+ const first = result[0];
553
+ const last = result[result.length - 1];
554
+ if (first === "\"" && last === "\"" || first === "'" && last === "'") result = result.substring(1, result.length - 1).trim();
555
+ else break;
556
+ }
557
+ return result;
558
+ };
543
559
  var getDefaultAuthor = async () => {
544
560
  try {
545
561
  const { stdout } = await execa("git", ["config", "user.name"]);
@@ -609,7 +625,7 @@ Templates:
609
625
  p.outro("Use \"create\" to scaffold a new project.");
610
626
  process.exit(0);
611
627
  });
612
- program.command("create").description("Create a new project from a template").option("-t, --template <type>", "Template type (cli, web-vanilla, web-app, web-fullstack)").option("-n, --name <name>", "Project name").option("--description <description>", "Project description").option("-k, --keywords <keywords>", "Project keywords (comma separated)").option("-a, --author <author>", "Author name (defaults to 'git config user.name')").option("--github-username <username>", "GitHub username (defaults to 'git config github.user')").option("-p, --package-manager <pm>", "Package manager (npm, pnpm, yarn)", "pnpm").option("--create-github-repository", "Create GitHub project").requiredOption("--path <path>", "Output directory").option("--install-dependencies", "Install dependencies after scaffolding", false).option("--build", "Run the CI script (lint, build, test) after scaffolding", false).option("--no-progress", "Do not show progress indicators").action(async (opts) => {
628
+ program.command("create").description("Create a new project from a template").option("-t, --template <type>", "Template type (cli, web-vanilla, web-app, web-fullstack)").option("-n, --name <name>", "Project name").option("--description <description>", "Project description").option("-k, --keywords <keywords>", "Project keywords (comma separated)").option("-a, --author <author>", "Author name (defaults to 'git config user.name')").option("--github-username <username>", "GitHub username (defaults to 'git config github.user')").option("-p, --package-manager <pm>", "Package manager (npm, pnpm, yarn)", "pnpm").option("--create-github-repository", "Create GitHub repository and push initial commit").requiredOption("--path <path>", "Output directory").option("--build", "Run the CI script (lint, build, test) after scaffolding", false).option("--no-progress", "Do not show progress indicators").action(async (opts) => {
613
629
  debug$2("Executing \"create\" command with options: %O", opts);
614
630
  commandResult = {
615
631
  ...opts,
@@ -637,7 +653,7 @@ Restrictions & Behavior:
637
653
  - package.json: Dependencies and scripts are merged. Existing versions are preserved unless they are missing.
638
654
  - Merging: For non-seed files, the tool attempts to merge template changes. If a conflict occurs, it will be marked with standard git conflict markers.
639
655
  - Confirmation: The command will always show a summary of proposed changes (ADD, MODIFY) and ask for your confirmation before applying them.
640
- `).option("-t, --template <type>", "Template type (cli, web-vanilla, web-app, web-fullstack)").option("--description <description>", "Project description").option("-k, --keywords <keywords>", "Project keywords (comma separated)").option("-a, --author <author>", "Author name (defaults to 'git config user.name')").option("--github-username <username>", "GitHub username (defaults to 'git config github.user')").option("-p, --package-manager <pm>", "Package manager (npm, pnpm, yarn)", "pnpm").option("--create-github-repository", "Create GitHub project").option("-d, --directory <path>", "Output directory", ".").option("--install-dependencies", "Install dependencies after scaffolding", false).option("--build", "Run the CI script (lint, build, test) after updating", false).option("--dev", "Run the dev server after scaffolding", false).option("--open", "Open the browser after scaffolding", false).option("--no-progress", "Do not show progress indicators").action(async (opts) => {
656
+ `).option("-t, --template <type>", "Template type (cli, web-vanilla, web-app, web-fullstack)").option("--description <description>", "Project description").option("-k, --keywords <keywords>", "Project keywords (comma separated)").option("-a, --author <author>", "Author name (defaults to 'git config user.name')").option("--github-username <username>", "GitHub username (defaults to 'git config github.user')").option("-p, --package-manager <pm>", "Package manager (npm, pnpm, yarn)", "pnpm").option("--create-github-repository", "Create GitHub repository and push initial commit").option("-d, --directory <path>", "Output directory", ".").option("--build", "Run the CI script (lint, build, test) after updating", false).option("--dev", "Run the dev server after scaffolding", false).option("--open", "Open the browser after scaffolding", false).option("--no-progress", "Do not show progress indicators").action(async (opts) => {
641
657
  debug$2("Executing \"update\" command with options: %O", opts);
642
658
  const directory = path.resolve(opts.directory);
643
659
  const pkgPath = path.join(directory, "package.json");
@@ -834,29 +850,16 @@ Restrictions & Behavior:
834
850
  process.exit(0);
835
851
  }
836
852
  }
837
- const installDependenciesRes = await p.confirm({
838
- message: "Should we install dependencies?",
853
+ const build = await p.confirm({
854
+ message: "Should we run the CI script (lint, build, test)?",
839
855
  initialValue: true
840
856
  });
841
- if (p.isCancel(installDependenciesRes)) {
857
+ if (p.isCancel(build)) {
842
858
  p.cancel("Operation cancelled.");
843
859
  process.exit(0);
844
860
  }
845
- const installDependencies = installDependenciesRes;
846
- let build = false;
847
- if (installDependencies) {
848
- const res = await p.confirm({
849
- message: "Should we run the CI script (lint, build, test)?",
850
- initialValue: true
851
- });
852
- if (p.isCancel(res)) {
853
- p.cancel("Operation cancelled.");
854
- process.exit(0);
855
- }
856
- build = res;
857
- }
858
861
  const createGithubRepositoryRes = await p.confirm({
859
- message: "Should we create a GitHub repository?",
862
+ message: "Create GitHub repository and push initial commit?",
860
863
  initialValue: false
861
864
  });
862
865
  if (p.isCancel(createGithubRepositoryRes)) {
@@ -874,7 +877,6 @@ Restrictions & Behavior:
874
877
  createGithubRepository: createGithubRepositoryRes,
875
878
  directory: projectDir,
876
879
  update,
877
- installDependencies,
878
880
  build,
879
881
  progress: true
880
882
  };
@@ -896,6 +898,13 @@ Restrictions & Behavior:
896
898
  p.cancel("Unknown command or missing options.");
897
899
  process.exit(1);
898
900
  }
901
+ if (commandResult.template) commandResult.template = stripQuotes(commandResult.template);
902
+ if (commandResult.projectName) commandResult.projectName = stripQuotes(commandResult.projectName);
903
+ if (commandResult.description) commandResult.description = stripQuotes(commandResult.description);
904
+ if (commandResult.keywords) commandResult.keywords = stripQuotes(commandResult.keywords);
905
+ if (commandResult.author) commandResult.author = stripQuotes(commandResult.author);
906
+ if (commandResult.githubUsername) commandResult.githubUsername = stripQuotes(commandResult.githubUsername);
907
+ if (commandResult.packageManager) commandResult.packageManager = stripQuotes(commandResult.packageManager);
899
908
  debug$2("Validating command result with Zod");
900
909
  const validationResult = ProjectOptionsSchema.safeParse(commandResult);
901
910
  if (!validationResult.success) {
@@ -909,7 +918,6 @@ Restrictions & Behavior:
909
918
  p.cancel(`Directory "${projectDir}" already exists. Use the "update" command to update.`);
910
919
  process.exit(1);
911
920
  }
912
- if (commandResult.build) commandResult.installDependencies = true;
913
921
  return commandResult;
914
922
  };
915
923
  //#endregion
@@ -993,7 +1001,7 @@ var generateProject = async (opts) => {
993
1001
  description: config.description
994
1002
  });
995
1003
  } else {
996
- log.warn(`Dependency "${dep}" not found in master configuration. Using empty version.`);
1004
+ log.warn(`Dependency "${dep}" not found in central configuration. Using empty version.`);
997
1005
  debug$1(`Dependency "${dep}" missing in config`);
998
1006
  }
999
1007
  }
@@ -1001,6 +1009,7 @@ var generateProject = async (opts) => {
1001
1009
  let finalPkg = {
1002
1010
  name: projectName,
1003
1011
  version: "0.1.0",
1012
+ private: true,
1004
1013
  description: opts.description || "TODO: Add project description",
1005
1014
  keywords: opts.keywords ? opts.keywords.split(",").map((k) => k.trim()) : ["TODO: Add keywords"],
1006
1015
  homepage: `https://github.com/${githubUsername}/${projectName}#readme`,
@@ -1273,7 +1282,7 @@ var generateProject = async (opts) => {
1273
1282
  githubSkipped: !opts.createGithubRepository || isUpdate,
1274
1283
  githubError: "",
1275
1284
  depsInstalled: false,
1276
- depsSkipped: !opts.installDependencies,
1285
+ depsSkipped: !opts.build,
1277
1286
  ciRun: false,
1278
1287
  ciSkipped: !opts.build || !finalPkg.scripts.ci
1279
1288
  };
@@ -1281,13 +1290,13 @@ var generateProject = async (opts) => {
1281
1290
  if (!await pathExists(path.join(projectDir, ".git"))) {
1282
1291
  debug$1("Initializing Git repository");
1283
1292
  try {
1284
- debug$1("Executing: git init");
1285
- await execa("git", ["init"], {
1293
+ debug$1("Executing: git init --initial-branch=main");
1294
+ await execa("git", ["init", "--initial-branch=main"], {
1286
1295
  cwd: projectDir,
1287
1296
  stdio,
1288
1297
  preferLocal: true
1289
1298
  });
1290
- log.success("Initialized Git repository (git init).");
1299
+ log.success("Initialized Git repository (main branch).");
1291
1300
  states.gitInitialized = true;
1292
1301
  } catch (e) {
1293
1302
  debug$1("Failed to initialize Git: %O", e);
@@ -1295,32 +1304,7 @@ var generateProject = async (opts) => {
1295
1304
  log.error(`Failed to initialize Git: ${e.message}${detail}`);
1296
1305
  }
1297
1306
  } else states.gitInitialized = true;
1298
- if (opts.createGithubRepository && !isUpdate) {
1299
- debug$1("Creating GitHub repository");
1300
- try {
1301
- debug$1("Executing: gh repo create %s --public --source=. --remote=origin", projectName);
1302
- await execa("gh", [
1303
- "repo",
1304
- "create",
1305
- projectName,
1306
- "--public",
1307
- "--source=.",
1308
- "--remote=origin"
1309
- ], {
1310
- cwd: projectDir,
1311
- stdio,
1312
- preferLocal: true
1313
- });
1314
- log.success("Created GitHub repository (gh repo create).");
1315
- states.githubCreated = true;
1316
- } catch (e) {
1317
- debug$1("Failed to create GitHub repository: %O", e);
1318
- const detail = e.stdout || e.stderr ? `\n\nOutput:\n${e.stdout}\n${e.stderr}` : "";
1319
- log.warn(`Failed to create GitHub repository: ${e.message}${detail}\nEnsure "gh" CLI is installed and authenticated.`);
1320
- states.githubError = e.message;
1321
- }
1322
- }
1323
- if (opts.installDependencies) {
1307
+ if (opts.build) {
1324
1308
  debug$1("Installing dependencies using %s", pm);
1325
1309
  const s = spinner();
1326
1310
  s.start(`Installing dependencies using ${pm}...`);
@@ -1379,6 +1363,51 @@ var generateProject = async (opts) => {
1379
1363
  throw new Error(`Failed to run CI script: ${e.message}${detail}`);
1380
1364
  }
1381
1365
  }
1366
+ if (opts.createGithubRepository && !isUpdate) {
1367
+ debug$1("Creating and pushing GitHub repository");
1368
+ const s = spinner();
1369
+ s.start("Creating and pushing GitHub repository...");
1370
+ try {
1371
+ debug$1("Executing: git add .");
1372
+ await execa("git", ["add", "."], {
1373
+ cwd: projectDir,
1374
+ stdio,
1375
+ preferLocal: true
1376
+ });
1377
+ debug$1("Executing: git commit -m \"chore: initial scaffold\"");
1378
+ await execa("git", [
1379
+ "commit",
1380
+ "-m",
1381
+ "chore: initial scaffold"
1382
+ ], {
1383
+ cwd: projectDir,
1384
+ stdio,
1385
+ preferLocal: true
1386
+ });
1387
+ debug$1("Executing: gh repo create %s --public --source=. --remote=origin --push", projectName);
1388
+ await execa("gh", [
1389
+ "repo",
1390
+ "create",
1391
+ projectName,
1392
+ "--public",
1393
+ "--source=.",
1394
+ "--remote=origin",
1395
+ "--push"
1396
+ ], {
1397
+ cwd: projectDir,
1398
+ stdio,
1399
+ preferLocal: true
1400
+ });
1401
+ s.stop(`\x1b[1G\x1b[2K\x1b[32m◆\x1b[39m Created GitHub repository and pushed initial commit.`);
1402
+ states.githubCreated = true;
1403
+ } catch (e) {
1404
+ debug$1("Failed to create/push GitHub repository: %O", e);
1405
+ s.stop("Failed to create/push GitHub repository.");
1406
+ const detail = e.stdout || e.stderr ? `\n\nOutput:\n${e.stdout}\n${e.stderr}` : "";
1407
+ log.warn(`Failed to create/push GitHub repository: ${e.message}${detail}\nEnsure "gh" CLI is installed and authenticated.`);
1408
+ states.githubError = e.message;
1409
+ }
1410
+ }
1382
1411
  let hasErrors = false;
1383
1412
  let hasWarnings = false;
1384
1413
  const errorMessages = [];
@@ -1421,8 +1450,8 @@ async function generateGeneratedMd(projectDir, opts, pm, states, isUpdate, statu
1421
1450
  `- [x] Scaffold project files and directories`,
1422
1451
  `- [x] Configure \`package.json\` with appropriate dependencies`,
1423
1452
  `- [${states.depsInstalled ? "x" : " "}] Install dependencies using \`${pm}\`${states.depsSkipped ? " *(Skipped)*" : ""}`,
1424
- `- [${states.gitInitialized ? "x" : " "}] Initialize Git repository`,
1425
- `- [${states.githubCreated ? "x" : " "}] Create GitHub repository${states.githubSkipped ? " *(Skipped)*" : states.githubError ? " *(Failed)*" : ""}`,
1453
+ `- [${states.gitInitialized ? "x" : " "}] Initialize Git repository (main branch)`,
1454
+ `- [${states.githubCreated ? "x" : " "}] Create and push GitHub repository${states.githubSkipped ? " *(Skipped)*" : states.githubError ? " *(Failed)*" : ""}`,
1426
1455
  `- [${states.ciRun ? "x" : " "}] Run initial CI pipeline (lint, build, test)${states.ciSkipped ? " *(Skipped)*" : ""}`,
1427
1456
  "",
1428
1457
  ...isUpdate ? [
@@ -1519,19 +1548,17 @@ async function generateGeneratedMd(projectDir, opts, pm, states, isUpdate, statu
1519
1548
  "| `gh pr checkout <pr-number>` | Checkout a Pull Request branch locally |",
1520
1549
  "| `gh issue create` | Create a new Issue |",
1521
1550
  "| `gh issue list` | List all open Issues |",
1522
- "| `gh repo delete <owner>/<repo> --confirm` | Dangerously delete a repository completely (use with caution!) |",
1551
+ "| `gh repo delete <owner>/<repo> --yes` | Dangerously delete a repository completely (use with caution!) |",
1523
1552
  "",
1524
1553
  "---",
1525
1554
  "",
1526
1555
  "## 🚀 Creating a Release",
1527
1556
  "This project uses Conventional Commits and automated changelogs. To create a new release:",
1528
- "1. **Verify build/tests:** `pnpm run ci`",
1529
- "2. **Bump version:** `pnpm version <patch|minor|major> --no-git-tag-version`",
1530
- "3. **Update changelog:** `pnpm run create-changelog`",
1531
- "4. **Commit changes:** `git add . && git commit -m \"chore(release): $(node -p 'require(\"./package.json\").version')\"`",
1532
- "5. **Tag & Push:** `git tag v$(node -p 'require(\"./package.json\").version') && git push && git push --tags`",
1533
- "6. **Create GitHub Release:** `gh release create v$(node -p 'require(\"./package.json\").version') --generate-notes`",
1534
- "7. **Publish (if applicable):** `pnpm publish`",
1557
+ "1. **Run the release command:** `pnpm release`",
1558
+ "",
1559
+ "This single command will automatically run your CI suite, bump the version, generate a changelog, create a Git tag, push to GitHub, and create a GitHub release.",
1560
+ "",
1561
+ "**Note:** NPM publishing is disabled by default. See `CONTRIBUTING.md` for details on how to enable it.",
1535
1562
  "",
1536
1563
  "---",
1537
1564
  "",
@@ -0,0 +1,23 @@
1
+ {
2
+ "npm": {
3
+ "publish": false
4
+ },
5
+ "git": {
6
+ "requireCleanWorkingDir": true,
7
+ "commit": true,
8
+ "commitMessage": "chore(release): ${version}",
9
+ "tag": true,
10
+ "tagName": "v${version}",
11
+ "push": true,
12
+ "pushArgs": ["--follow-tags"]
13
+ },
14
+ "github": {
15
+ "release": true,
16
+ "autoGenerate": true
17
+ },
18
+ "hooks": {
19
+ "before:init": "pnpm run ci",
20
+ "after:bump": "pnpm run create-changelog",
21
+ "before:git:commit": "git add CHANGELOG.md"
22
+ }
23
+ }
@@ -1,9 +1,86 @@
1
1
  # Agent Guidelines: {{projectName}}
2
2
 
3
- Build/Lint/Test:
3
+ This document provides essential instructions for autonomous agents (like Cursor, GitHub Copilot, or CLI agents) working on the `{{projectName}}` repository.
4
+
5
+ ## Build/Lint/Test
6
+
4
7
  - `pnpm run ci`: Runs lint, build, and all tests.
5
8
  - `pnpm run dev`: Starts the development server.
6
- - `pnpm run test`: Runs unit tests (browser-based for web projects).
9
+ - `pnpm run test`: Runs unit tests.
7
10
  - `pnpm run integration-test`: Runs integration tests.
8
11
  - `pnpm exec vitest <file>`: Runs a specific test file.
9
12
  - `pnpm run lint`: Lints and formats the codebase (oxlint + oxfmt).
13
+
14
+ ## Project Overview
15
+
16
+ A modern project built with {{projectName}}, emphasizing type safety, performance, and best practices.
17
+
18
+ ## Build, Lint, and Test Commands
19
+
20
+ ### Core Commands
21
+
22
+ - **Install dependencies:** `pnpm install`
23
+ - **Build project:** `pnpm run build`
24
+ - **Lint code:** `pnpm run lint` (runs `tsc`, `oxlint`, and `oxfmt`)
25
+ - **Run all tests:** `pnpm run test` (uses `vitest` with coverage)
26
+ - **Run CI suite:** `pnpm run ci` (lint + build + test)
27
+ - **Run integration tests:** `pnpm run integration-test`
28
+
29
+ ### Targeted Testing
30
+
31
+ - **Run a single test file:** `pnpm exec vitest src/index.test.ts`
32
+ - **Run tests matching a pattern:** `pnpm exec vitest -t "feature"`
33
+ - **Watch mode:** `pnpm exec vitest`
34
+
35
+ ## Code Style & Conventions
36
+
37
+ ### Language & Runtime
38
+
39
+ - **TypeScript:** Strict mode is mandatory. Use explicit types for function boundaries.
40
+ - **Node.js:** Targets >= 22.0.0.
41
+ - **ESM:** The project uses ES Modules (`"type": "module"` in `package.json`).
42
+
43
+ ### Imports
44
+
45
+ - **Extensions:** Always use `.js` extensions in relative imports (e.g., `import { main } from './lib.js';`) to comply with ESM requirements in Node.js, even though source files are `.ts`.
46
+ - **Built-ins:** Use the `node:` prefix for built-in modules (e.g., `import path from 'node:path';`).
47
+
48
+ ### Formatting
49
+
50
+ - **Tooling:** oxfmt is enforced via `pnpm run lint`.
51
+ - **Indentation:** Tabs are used for indentation.
52
+ - **Quotes:** Single quotes for strings, except when double quotes prevent escaping.
53
+
54
+ ### Architecture & Types
55
+
56
+ - **Modularity:** Keep logic modularized.
57
+ - **Type Safety:** Use `zod` for runtime schema validation and `z.infer` for type definitions.
58
+ - **Immutability:** Prefer `readonly` and `const` where possible to ensure data integrity.
59
+
60
+ ### Naming Conventions
61
+
62
+ - **Variables/Functions:** `camelCase`.
63
+ - **Constants:** `UPPER_SNAKE_CASE`.
64
+ - **Files:** `kebab-case.ts`.
65
+
66
+ ### Error Handling
67
+
68
+ - **CLI Errors:** Throw descriptive errors.
69
+ - **Safety:** Always use `try...finally` or `using` (if applicable) to ensure resources like file handles or connections are closed.
70
+ - **Validation:** Validate all user inputs and CLI arguments using Zod schemas before processing.
71
+
72
+ ## Mandatory Completion Protocol (Definition of Done)
73
+
74
+ No task involving code changes is considered complete until the agent provides the following "Evidence of Done" in its final response:
75
+
76
+ 1. **CI Verification:** The agent MUST run `pnpm run ci` and include the full terminal output (showing `Found 0 warnings and 0 errors` and `Tests passed`).
77
+ 2. **Test Coverage:** The agent MUST ensure that all new code is covered by tests and all existing tests pass.
78
+
79
+ **Failure to provide these logs means the task is INCOMPLETE.** The user is encouraged to reject any response that lacks this section.
80
+
81
+ ## Git Workflow
82
+
83
+ - **Conventional Commits:** Adhere to the specification (e.g., `feat:`, `fix:`, `chore:`, `test:`).
84
+ - **Hooks:** Husky runs `pnpm run ci` on pre-commit. Do not bypass hooks.
85
+ - **Branches:** Use descriptive branch names like `feat/feature-name` or `fix/issue-description`.
86
+
@@ -21,11 +21,22 @@ We follow the **Conventional Commits** specification. This is **enforced** by `c
21
21
 
22
22
  ## Release Process
23
23
 
24
- 1. **Verify**: `pnpm run ci`
25
- 2. **Bump Version**: `pnpm version <patch|minor|major> --no-git-tag-version`
26
- 3. **Update Changelog**: `pnpm run create-changelog`
27
- 4. **Commit**: `git add . && git commit -m "chore(release): $(node -p 'require("./package.json").version')"`
28
- 5. **Tag & Push**: `git tag v$(node -p 'require("./package.json").version') && git push && git push --tags`
29
- 6. **Create GitHub Release**: `gh release create v$(node -p 'require("./package.json").version') --generate-notes`
30
- 7. **Publish**: `pnpm publish`
24
+ To release a new version:
25
+
26
+ ```sh
27
+ pnpm release -- patch # or minor / major
28
+ ```
29
+
30
+ This will automatically:
31
+ 1. Run the CI suite (`pnpm run ci`).
32
+ 2. Bump the version in `package.json`.
33
+ 3. Update the `CHANGELOG.md`.
34
+ 4. Commit, tag, and push the changes.
35
+ 5. Create a GitHub release with auto-generated notes.
36
+ 6. Publish to npm (if configured).
37
+
38
+ **Note:** NPM publishing is **disabled** by default for new projects. To enable it:
39
+ 1. Set `"private": false` in `package.json`.
40
+ 2. Set `"publish": true` in `.release-it.json`.
41
+ 3. Ensure you have the necessary `NPM_TOKEN` configured.
31
42
 
@@ -1,6 +1,9 @@
1
1
  import { defineConfig } from "oxlint";
2
2
  import pluginRegexp from "eslint-plugin-regexp";
3
3
 
4
+ /** Filter out core ESLint rules bundled into eslint-plugin-regexp recommended config */
5
+ const regexpPluginRules = Object.fromEntries(Object.entries(pluginRegexp.configs.recommended.rules ?? {}).filter(([key]) => key.startsWith("regexp/")));
6
+
4
7
  const commonIgnore = [
5
8
  "**/.*",
6
9
  "node_modules/**",
@@ -32,7 +35,7 @@ export const linter = defineConfig({
32
35
  correctness: "error",
33
36
  },
34
37
  rules: {
35
- ...pluginRegexp.configs.recommended.rules,
38
+ ...regexpPluginRules,
36
39
  curly: ["error", "all"],
37
40
  "typescript/no-unused-vars": [
38
41
  "error",
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "{{projectName}}",
3
3
  "version": "0.1.0",
4
+ "private": true,
4
5
  "type": "module",
5
6
  "scripts": {
6
7
  "lint": "tsc && oxlint --disable-nested-config src client server tests *.config.ts && npm run format:check",
7
8
  "format": "oxfmt --write .",
8
9
  "format:check": "oxfmt --check .",
9
10
  "test": "vitest run --coverage",
11
+ "release": "release-it",
10
12
  "ci": "npm run lint && npm run build && npm run test",
11
13
  "create-changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
12
14
  "prepare": "husky"
@@ -25,6 +27,7 @@
25
27
  "oxlint": "",
26
28
  "oxlint-tsgolint": "",
27
29
  "oxfmt": "",
30
+ "release-it": "",
28
31
  "eslint-plugin-regexp": "",
29
32
  "typescript": "",
30
33
  "vitest": ""
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "create-template-project",
3
- "version": "1.0.0",
3
+ "version": "1.1.2",
4
+ "private": false,
4
5
  "description": "An ultra-modular, type-safe Node.js CLI tool used to scaffold new project templates (CLI, Webpage, Webapp, Fullstack) with best-practice configurations pre-installed.",
5
6
  "keywords": [
6
7
  "boilerplate",
@@ -54,17 +55,18 @@
54
55
  "format": "oxfmt --write src scripts *.config.ts",
55
56
  "format:check": "oxfmt --check src scripts *.config.ts",
56
57
  "test": "vitest run --coverage --exclude '**/*.integration.*.test.ts'",
57
- "integration-test:cli": "rimraf ./temp/cli && node ./dist/index.js create --package-manager=pnpm --build --debug --no-progress --template=cli --name=cli --author=\"Jon Doe\" --github-username=\"jon-doe\" --path=./temp/cli",
58
- "integration-test:web-vanilla": "rimraf ./temp/web-vanilla && node ./dist/index.js create --package-manager=pnpm --build --debug --no-progress --template=web-vanilla --name=web-vanilla --author=\"Jon Doe\" --github-username=\"jon-doe\" --path=./temp/web-vanilla",
59
- "integration-test:web-app": "rimraf ./temp/web-app && node ./dist/index.js create --package-manager=pnpm --build --debug --no-progress --template=web-app --name=web-app --author=\"Jon Doe\" --github-username=\"jon-doe\" --path=./temp/web-app",
60
- "integration-test:web-fullstack": "rimraf ./temp/web-fullstack && node ./dist/index.js create --package-manager=pnpm --build --debug --no-progress --template=web-fullstack --name=web-fullstack --author=\"Jon Doe\" --github-username=\"jon-doe\" --path=./temp/web-fullstack",
58
+ "integration-test:cli": "rimraf --max-retries=3 ./temp/cli && node ./dist/index.js create --package-manager=pnpm --build --debug --no-progress --template=cli --name=cli --author=\"Jon Doe\" --github-username=\"jon-doe\" --path=./temp/cli",
59
+ "integration-test:web-vanilla": "rimraf --max-retries=3 ./temp/web-vanilla && node ./dist/index.js create --package-manager=pnpm --build --debug --no-progress --template=web-vanilla --name=web-vanilla --author=\"Jon Doe\" --github-username=\"jon-doe\" --path=./temp/web-vanilla",
60
+ "integration-test:web-app": "rimraf --max-retries=3 ./temp/web-app && node ./dist/index.js create --package-manager=pnpm --build --debug --no-progress --template=web-app --name=web-app --author=\"Jon Doe\" --github-username=\"jon-doe\" --path=./temp/web-app",
61
+ "integration-test:web-fullstack": "rimraf --max-retries=3 ./temp/web-fullstack && node ./dist/index.js create --package-manager=pnpm --build --debug --no-progress --template=web-fullstack --name=web-fullstack --author=\"Jon Doe\" --github-username=\"jon-doe\" --path=./temp/web-fullstack",
61
62
  "integration-test": "pnpm run integration-test:cli && pnpm run integration-test:web-vanilla && pnpm run integration-test:web-app && pnpm run integration-test:web-fullstack",
62
63
  "ci": "pnpm run lint && pnpm run build && pnpm run test",
63
64
  "create-changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
64
- "prepare": "husky"
65
+ "prepare": "husky",
66
+ "release": "release-it"
65
67
  },
66
68
  "dependencies": {
67
- "@clack/prompts": "1.1.0",
69
+ "@clack/prompts": "1.2.0",
68
70
  "commander": "14.0.3",
69
71
  "debug": "4.4.3",
70
72
  "execa": "9.6.1",
@@ -75,19 +77,20 @@
75
77
  "@commitlint/config-conventional": "20.5.0",
76
78
  "@types/cli-progress": "3.11.6",
77
79
  "@types/debug": "4.1.13",
78
- "@vitest/coverage-v8": "4.1.1",
80
+ "@vitest/coverage-v8": "4.1.2",
79
81
  "conventional-changelog": "7.2.0",
80
- "conventional-changelog-angular": "8.3.0",
82
+ "conventional-changelog-angular": "8.3.1",
81
83
  "eslint-plugin-regexp": "3.1.0",
82
84
  "husky": "9.1.7",
83
- "oxfmt": "0.41.0",
84
- "oxlint": "1.56.0",
85
- "oxlint-tsgolint": "0.17.1",
86
- "pnpm": "10.32.1",
85
+ "oxfmt": "0.43.0",
86
+ "oxlint": "1.58.0",
87
+ "oxlint-tsgolint": "0.19.0",
88
+ "pnpm": "10.33.0",
89
+ "release-it": "19.2.4",
87
90
  "rimraf": "6.1.3",
88
- "typescript": "5.9.3",
89
- "vite": "8.0.2",
90
- "vitest": "4.1.1"
91
+ "typescript": "6.0.2",
92
+ "vite": "8.0.3",
93
+ "vitest": "4.1.2"
91
94
  },
92
95
  "engines": {
93
96
  "node": ">=22"