create-koppajs 1.1.0 → 1.2.1

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.
Files changed (29) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +123 -122
  3. package/bin/create-koppajs.js +158 -13
  4. package/package.json +2 -1
  5. package/template/package.json +2 -2
  6. package/template/pnpm-lock.yaml +11 -18
  7. package/template-overlays/router/ARCHITECTURE.md +86 -0
  8. package/template-overlays/router/CHANGELOG.md +44 -0
  9. package/template-overlays/router/DEVELOPMENT_RULES.md +57 -0
  10. package/template-overlays/router/README.md +243 -0
  11. package/template-overlays/router/ROADMAP.md +34 -0
  12. package/template-overlays/router/TESTING_STRATEGY.md +67 -0
  13. package/template-overlays/router/docs/adr/0001-keep-the-starter-minimal.md +32 -0
  14. package/template-overlays/router/docs/architecture/module-boundaries.md +39 -0
  15. package/template-overlays/router/docs/meta/maintenance.md +38 -0
  16. package/template-overlays/router/docs/specs/README.md +19 -0
  17. package/template-overlays/router/docs/specs/app-bootstrap.md +42 -0
  18. package/template-overlays/router/docs/specs/router-navigation.md +41 -0
  19. package/template-overlays/router/index.html +14 -0
  20. package/template-overlays/router/package.json +74 -0
  21. package/template-overlays/router/pnpm-lock.yaml +3786 -0
  22. package/template-overlays/router/src/app-view.kpa +128 -0
  23. package/template-overlays/router/src/home-page.kpa +100 -0
  24. package/template-overlays/router/src/main.ts +89 -0
  25. package/template-overlays/router/src/not-found-page.kpa +69 -0
  26. package/template-overlays/router/src/router-page.kpa +102 -0
  27. package/template-overlays/router/src/style.css +51 -0
  28. package/template-overlays/router/tests/e2e/app.spec.ts +38 -0
  29. package/template-overlays/router/tests/integration/main-bootstrap.test.ts +150 -0
package/CHANGELOG.md CHANGED
@@ -16,6 +16,46 @@ _No unreleased changes yet._
16
16
 
17
17
  ---
18
18
 
19
+ ## [1.2.1] — Starter Source Of Truth Cleanup
20
+
21
+ **2026-03-26**
22
+
23
+ Patch release to make the bundled templates the only starter source of truth and
24
+ to refresh the generated starter dependency baseline.
25
+
26
+ ### Changed
27
+
28
+ - documented `template/` and `template-overlays/` as the only maintained source
29
+ of truth for generated starters
30
+ - removed active ecosystem references to the retired `koppajs-example` starter
31
+ repository
32
+ - updated generated starter dependencies to `@koppajs/koppajs-core@^3.0.3` and
33
+ `@koppajs/koppajs-vite-plugin@^1.0.1`
34
+
35
+ ---
36
+
37
+ ## [1.2.0] — Starter Variants And Router Overlay
38
+
39
+ **2026-03-26**
40
+
41
+ ### Added
42
+
43
+ - added an opt-in `router` starter that layers `@koppajs/koppajs-router`, a
44
+ two-page navigation flow, and an explicit fallback route on top of the
45
+ minimal baseline
46
+ - added overlay-based starter support through `template-overlays/` so future
47
+ starter variants can replace only the files that actually differ
48
+
49
+ ### Changed
50
+
51
+ - extended the CLI contract with `--template` and `--router`, plus interactive
52
+ starter selection in TTY runs when no template flag is provided
53
+ - expanded smoke, unit, and generated-template build coverage to validate both
54
+ the default minimal starter and the opt-in router starter
55
+ - updated architecture docs, specs, and ADRs to reflect multi-starter support
56
+
57
+ ---
58
+
19
59
  ## [1.1.0] — Starter & Release Baseline Upgrade
20
60
 
21
61
  **2026-03-17**
package/README.md CHANGED
@@ -1,71 +1,92 @@
1
- <a id="readme-top"></a>
1
+ # create-koppajs
2
+
3
+ `create-koppajs` is the official KoppaJS CLI scaffolder. It creates a new
4
+ project by copying the versioned base starter in `template/`, optionally
5
+ applying a supported starter overlay from `template-overlays/`, and patching a
6
+ small, explicit set of identity files.
7
+
8
+ ## Purpose
9
+
10
+ This repository exists to do one job well:
11
+
12
+ - create a fresh project directory
13
+ - copy the current supported KoppaJS starter baseline
14
+ - optionally add a supported starter variant such as `router`
15
+ - preserve a stable, inspectable bootstrap path for new KoppaJS applications
16
+
17
+ It is not a runtime package and it does not own application behavior after
18
+ generation.
19
+
20
+ ## Repository Classification
21
+
22
+ - Repo type: CLI scaffolding package with a bundled starter family
23
+ - Runtime responsibility: one-shot filesystem scaffolding through
24
+ `bin/create-koppajs.js`
25
+ - Build-time responsibility: publish the starter assets, protect the contract,
26
+ and validate tagged releases
27
+ - UI surface: none at the repository root; the generated starter owns the UI
28
+ - Maturity level: stable, contract-governed, maintenance-first
29
+
30
+ ## Ownership Boundaries
31
+
32
+ - `bin/create-koppajs.js` owns argument parsing, prompting, validation, starter
33
+ selection, template copy, placeholder patching, and next-step output.
34
+ - `template/` owns the default `minimal` starter baseline and is the single
35
+ source of truth for that starter.
36
+ - `template-overlays/` owns the files that differ for opt-in starter variants.
37
+ Together with `template/`, they define the only source of truth for
38
+ generated starter output.
39
+ - `scripts/` and `.github/workflows/` own repository-quality and release
40
+ verification.
41
+ - Root governance files own the repository doctrine and must stay aligned with
42
+ code and workflows.
43
+
44
+ The root package must not take on runtime concerns that belong in generated
45
+ applications, and generated applications must not depend on unpublished root
46
+ files after scaffold completion.
47
+
48
+ ## Public Contract
49
+
50
+ The stable public contract of this repository is:
51
+
52
+ - the `create-koppajs` command and its `--help` / `--version` flags
53
+ - the optional project-name argument and prompt fallback when omitted
54
+ - the optional `--template <name>` and `--router` starter-selection flags
55
+ - the interactive starter-template prompt when no template flag is provided in
56
+ an interactive terminal
57
+ - rejection of invalid project names, invalid template names, and non-empty
58
+ target directories
59
+ - recursive copying of the bundled `template/` directory plus any selected
60
+ overlay
61
+ - restoration of publish-safe dotfiles and dotdirectories during copy
62
+ - patching of generated `package.json`, `README.md`, `CHANGELOG.md`, and
63
+ `RELEASE.md`
64
+ - the generated starter baselines defined by `template/` and
65
+ `template-overlays/`
66
+ - the npm package payload: `bin/`, `template/`, `template-overlays/`,
67
+ `README.md`, `CHANGELOG.md`, and `LICENSE`
68
+
69
+ The governing specs for that contract are:
70
+
71
+ - [docs/specs/cli-scaffolding.md](./docs/specs/cli-scaffolding.md)
72
+ - [docs/specs/template-starter-contract.md](./docs/specs/template-starter-contract.md)
2
73
 
3
- <div align="center">
4
- <img src="https://public-assets-1b57ca06-687a-4142-a525-0635f7649a5c.s3.eu-central-1.amazonaws.com/koppajs/koppajs-logo-text-900x226.png" width="500" alt="KoppaJS Logo">
5
- </div>
6
-
7
- <br>
8
-
9
- <div align="center">
10
- <a href="https://www.npmjs.com/package/create-koppajs"><img src="https://img.shields.io/npm/v/create-koppajs?style=flat-square" alt="npm version"></a>
11
- <a href="./LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-blue?style=flat-square" alt="License"></a>
12
- </div>
13
-
14
- <br>
15
-
16
- <div align="center">
17
- <h1 align="center">create-koppajs</h1>
18
- <h3 align="center">Scaffold a new KoppaJS project in seconds</h3>
19
- <p align="center">
20
- <i>The fastest way to start building with KoppaJS.</i>
21
- </p>
22
- </div>
23
-
24
- <br>
25
-
26
- <div align="center">
27
- <p align="center">
28
- <a href="https://github.com/koppajs/koppajs-documentation">Documentation</a>
29
- &middot;
30
- <a href="https://github.com/koppajs/koppajs-core">KoppaJS Core</a>
31
- &middot;
32
- <a href="https://github.com/koppajs/koppajs-vite-plugin">Vite Plugin</a>
33
- &middot;
34
- <a href="https://github.com/koppajs/create-koppajs/issues">Issues</a>
35
- </p>
36
- </div>
37
-
38
- <br>
39
-
40
- <details>
41
- <summary>Table of Contents</summary>
42
- <ol>
43
- <li><a href="#what-is-this">What is this?</a></li>
44
- <li><a href="#usage">Usage</a></li>
45
- <li><a href="#what-gets-generated">What gets generated</a></li>
46
- <li><a href="#requirements">Requirements</a></li>
47
- <li><a href="#release--governance">Release & Governance</a></li>
48
- <li><a href="#community--contribution">Community & Contribution</a></li>
49
- <li><a href="#license">License</a></li>
50
- </ol>
51
- </details>
52
-
53
- ---
54
-
55
- ## What is this?
56
-
57
- `create-koppajs` is the **official project scaffolder** for KoppaJS.
74
+ ## Usage
58
75
 
59
- It creates a ready-to-run starter project with a single command — no configuration, no dependencies to install first, no boilerplate to write by hand.
76
+ Default starter:
60
77
 
61
- ---
78
+ ```bash
79
+ pnpm create koppajs my-app
80
+ ```
62
81
 
63
- ## Usage
82
+ Router starter:
64
83
 
65
84
  ```bash
66
- pnpm create koppajs my-app
85
+ pnpm create koppajs my-app --template router
67
86
  ```
68
87
 
88
+ Alternative entrypoints:
89
+
69
90
  ```bash
70
91
  npm create koppajs my-app
71
92
  ```
@@ -74,7 +95,11 @@ npm create koppajs my-app
74
95
  npx create-koppajs my-app
75
96
  ```
76
97
 
77
- Then:
98
+ If the target directory name is omitted, the CLI prompts for one. If no
99
+ template flag is provided in an interactive terminal, the CLI also prompts for
100
+ starter selection. Non-interactive runs default to `minimal`.
101
+
102
+ After generation:
78
103
 
79
104
  ```bash
80
105
  cd my-app
@@ -82,88 +107,64 @@ pnpm install
82
107
  pnpm dev
83
108
  ```
84
109
 
85
- If you omit the project name, the CLI will prompt you for one.
86
-
87
- ---
88
-
89
- ## What gets generated
90
-
91
- ```
92
- my-app/
93
- ├── .github/
94
- ├── .husky/
95
- ├── docs/
96
- ├── tests/
97
- ├── CHANGELOG.md
98
- ├── RELEASE.md
99
- ├── AI_CONSTITUTION.md
100
- ├── ARCHITECTURE.md
101
- ├── package.json
102
- ├── .gitignore
103
- ├── README.md
104
- ├── vite.config.mjs
105
- ├── vitest.config.mjs
106
- ├── playwright.config.ts
107
- ├── tsconfig.json
108
- ├── pnpm-lock.yaml
109
- ├── LICENSE
110
- ├── public/
111
- │ └── favicon.svg
112
- └── src/
113
- ├── main.ts
114
- ├── style.css
115
- ├── app-view.kpa
116
- └── counter-component.kpa
117
- ```
118
-
119
- - **Vite** as dev server and bundler
120
- - **TypeScript**, **ESLint**, **Prettier**, **Vitest**, and **Playwright**
121
- - **GitHub workflows**, **Husky**, **lint-staged**, and **Conventional Commits**
122
- - **Meta-layer docs**, ADRs, specs, and a release baseline
123
- - **Two sample components** (app view + counter) aligned with the current
124
- `koppajs-example` starter
110
+ ## Requirements
125
111
 
126
- ---
112
+ - for `create-koppajs`: Node.js `>=20`
113
+ - for generated starter projects: pnpm `>=10` and a starter-supported Node.js
114
+ line, currently `20.19+`, `22.13+`, or `24+`
127
115
 
128
- ## Requirements
116
+ ## Generated Starters
129
117
 
130
- - `create-koppajs`: Node.js >= 20
131
- - Generated starter workflow: pnpm >= 10 plus a starter-supported Node.js line
132
- (currently 20.19+, 22.13+, or 24+)
118
+ The generated project includes one of two supported starters:
133
119
 
134
- ---
120
+ - `minimal` by default: a small KoppaJS application built on Vite and
121
+ TypeScript
122
+ - `router` as opt-in: the same baseline plus `@koppajs/koppajs-router`, a
123
+ simple two-page navigation flow, and an explicit fallback route
135
124
 
136
- ## Release & Governance
125
+ Every starter also includes:
137
126
 
138
- The scaffolded starter now ships with the same quality and governance baseline
139
- as the current official `koppajs-example`, adapted for generated projects:
127
+ - quality tooling through ESLint, Prettier, Vitest, and Playwright
128
+ - local workflow guards through Husky, lint-staged, and commitlint
129
+ - starter governance files, ADR/spec structure, and release-process documents
130
+ - GitHub workflows for CI and tagged releases
140
131
 
141
- - explicit meta docs and ADR/spec structure
142
- - tag-driven `CHANGELOG.md` plus `RELEASE.md`
143
- - Conventional Commit enforcement via `commitlint`
144
- - a generated-project CI/release baseline under `.github/workflows`
132
+ The root repository treats those starters as versioned product surface, not
133
+ test data. `template/` plus the supported overlays are the only source of truth
134
+ for starter behavior.
145
135
 
146
- ---
136
+ ## Ecosystem Fit
147
137
 
148
- ## Community & Contribution
138
+ `create-koppajs` is the canonical entry point for starting a new KoppaJS
139
+ application. It complements:
149
140
 
150
- Issues and pull requests are welcome:
141
+ - `@koppajs/koppajs-core` for runtime behavior
142
+ - `@koppajs/koppajs-router` for optional route orchestration in scaffolded apps
143
+ - `@koppajs/koppajs-vite-plugin` for build integration
144
+ - the maintained KoppaJS starter conventions reflected in `template/` and
145
+ `template-overlays/`
151
146
 
152
- https://github.com/koppajs/create-koppajs/issues
147
+ The repository stays intentionally narrow so the CLI, starter contract, and
148
+ governance baseline can evolve together without hidden behavior.
153
149
 
154
- ## Governance & Architecture
150
+ ## Governance
155
151
 
156
- Repository design and maintenance rules live in the meta layer:
152
+ The root meta layer defines how this repository changes:
157
153
 
158
154
  - [AI_CONSTITUTION.md](./AI_CONSTITUTION.md)
159
155
  - [ARCHITECTURE.md](./ARCHITECTURE.md)
156
+ - [DECISION_HIERARCHY.md](./DECISION_HIERARCHY.md)
160
157
  - [DEVELOPMENT_RULES.md](./DEVELOPMENT_RULES.md)
161
158
  - [TESTING_STRATEGY.md](./TESTING_STRATEGY.md)
162
159
  - [RELEASE.md](./RELEASE.md)
160
+ - [ROADMAP.md](./ROADMAP.md)
163
161
  - [docs/meta/README.md](./docs/meta/README.md)
162
+ - [docs/architecture/README.md](./docs/architecture/README.md)
163
+ - [docs/quality/README.md](./docs/quality/README.md)
164
164
 
165
- ---
165
+ Tagged releases are documented in [CHANGELOG.md](./CHANGELOG.md). Contributor
166
+ workflow rules live in [CONTRIBUTING.md](./CONTRIBUTING.md).
166
167
 
167
168
  ## License
168
169
 
169
- Apache-2.0 — © 2026 KoppaJS, Bastian Bensch
170
+ Apache License 2.0 — © 2026 KoppaJS, Bastian Bensch
@@ -8,17 +8,90 @@ import { createInterface } from "node:readline";
8
8
  const __filename = fileURLToPath(import.meta.url);
9
9
  const __dirname = dirname(__filename);
10
10
  export const TEMPLATE_DIR = join(__dirname, "..", "template");
11
+ export const TEMPLATE_OVERLAY_DIRS = Object.freeze({
12
+ minimal: null,
13
+ router: join(__dirname, "..", "template-overlays", "router"),
14
+ });
15
+ export const DEFAULT_TEMPLATE = "minimal";
11
16
  const CLI_PKG = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
12
17
 
13
18
  // ── Args ────────────────────────────────────────────────────────────
14
19
 
15
20
  export function parseArgs(argv) {
16
21
  const raw = argv.slice(2);
17
- return {
22
+ const parsed = {
18
23
  help: raw.includes("--help") || raw.includes("-h"),
19
24
  version: raw.includes("--version") || raw.includes("-v"),
20
- projectName: raw.find((a) => !a.startsWith("-")) || null,
25
+ projectName: null,
26
+ templateName: null,
27
+ optionError: null,
21
28
  };
29
+
30
+ const setTemplateName = (templateName) => {
31
+ if (!templateName) {
32
+ parsed.optionError = "Option --template requires a value.";
33
+ return false;
34
+ }
35
+
36
+ if (parsed.templateName && parsed.templateName !== templateName) {
37
+ parsed.optionError = "Choose either --router or one --template value.";
38
+ return false;
39
+ }
40
+
41
+ parsed.templateName = templateName;
42
+ return true;
43
+ };
44
+
45
+ for (let index = 0; index < raw.length; index++) {
46
+ const arg = raw[index];
47
+
48
+ if (arg === "--help" || arg === "-h" || arg === "--version" || arg === "-v") {
49
+ continue;
50
+ }
51
+
52
+ if (arg === "--router") {
53
+ if (!setTemplateName("router")) {
54
+ break;
55
+ }
56
+ continue;
57
+ }
58
+
59
+ if (arg === "--template" || arg === "-t") {
60
+ const templateName = raw[index + 1];
61
+
62
+ if (!templateName || templateName.startsWith("-")) {
63
+ parsed.optionError = "Option --template requires a value.";
64
+ break;
65
+ }
66
+
67
+ if (!setTemplateName(templateName)) {
68
+ break;
69
+ }
70
+
71
+ index++;
72
+ continue;
73
+ }
74
+
75
+ if (arg.startsWith("--template=")) {
76
+ if (!setTemplateName(arg.slice("--template=".length))) {
77
+ break;
78
+ }
79
+ continue;
80
+ }
81
+
82
+ if (arg.startsWith("-t=")) {
83
+ if (!setTemplateName(arg.slice("-t=".length))) {
84
+ break;
85
+ }
86
+ continue;
87
+ }
88
+
89
+ if (!arg.startsWith("-") && parsed.projectName === null) {
90
+ parsed.projectName = arg;
91
+ }
92
+ }
93
+
94
+ return parsed;
22
95
  }
23
96
 
24
97
  // ── Help / Version ──────────────────────────────────────────────────
@@ -35,11 +108,14 @@ export function printHelp() {
35
108
  npx create-koppajs [project-name]
36
109
 
37
110
  Options:
38
- --help, -h Show this help message
39
- --version, -v Show version number
111
+ --help, -h Show this help message
112
+ --version, -v Show version number
113
+ --template, -t <name> Starter template: minimal | router
114
+ --router Shortcut for --template router
40
115
 
41
116
  Example:
42
117
  pnpm create koppajs my-app
118
+ pnpm create koppajs my-app --template router
43
119
  `);
44
120
  }
45
121
 
@@ -49,14 +125,14 @@ export function printVersion() {
49
125
 
50
126
  // ── Prompt ──────────────────────────────────────────────────────────
51
127
 
52
- export function promptProjectName() {
128
+ function promptLine(question, closeErrorMessage, input = process.stdin, output = process.stdout) {
53
129
  return new Promise((res, rej) => {
54
- const rl = createInterface({ input: process.stdin, output: process.stdout });
130
+ const rl = createInterface({ input, output });
55
131
  let answered = false;
56
132
  rl.on("close", () => {
57
- if (!answered) rej(new Error("Input closed before a project name was provided."));
133
+ if (!answered) rej(new Error(closeErrorMessage));
58
134
  });
59
- rl.question(" Project name: ", (answer) => {
135
+ rl.question(question, (answer) => {
60
136
  answered = true;
61
137
  rl.close();
62
138
  res(answer.trim());
@@ -64,6 +140,34 @@ export function promptProjectName() {
64
140
  });
65
141
  }
66
142
 
143
+ export function promptProjectName(input = process.stdin, output = process.stdout) {
144
+ return promptLine(
145
+ " Project name: ",
146
+ "Input closed before a project name was provided.",
147
+ input,
148
+ output,
149
+ );
150
+ }
151
+
152
+ export async function promptStarterTemplate(input = process.stdin, output = process.stdout) {
153
+ const answer = (await promptLine(
154
+ ` Starter template (minimal/router) [${DEFAULT_TEMPLATE}]: `,
155
+ "Input closed before a starter template was provided.",
156
+ input,
157
+ output,
158
+ )).toLowerCase();
159
+
160
+ if (answer === "" || answer === "m") {
161
+ return DEFAULT_TEMPLATE;
162
+ }
163
+
164
+ if (answer === "r") {
165
+ return "router";
166
+ }
167
+
168
+ return answer;
169
+ }
170
+
67
171
  // ── Validation ──────────────────────────────────────────────────────
68
172
 
69
173
  export function validateProjectName(name) {
@@ -78,6 +182,16 @@ export function validateProjectName(name) {
78
182
  }
79
183
  }
80
184
 
185
+ export function validateStarterTemplate(templateName) {
186
+ if (Object.hasOwn(TEMPLATE_OVERLAY_DIRS, templateName)) {
187
+ return;
188
+ }
189
+
190
+ throw new Error(
191
+ `Unknown starter template "${templateName}". Supported templates: ${Object.keys(TEMPLATE_OVERLAY_DIRS).join(", ")}.`,
192
+ );
193
+ }
194
+
81
195
  // ── Target directory ────────────────────────────────────────────────
82
196
 
83
197
  export function ensureTargetDir(targetPath) {
@@ -115,6 +229,16 @@ export function copyDirRecursive(src, dest) {
115
229
  }
116
230
  }
117
231
 
232
+ export function copyStarterTemplate(templateName, dest) {
233
+ copyDirRecursive(TEMPLATE_DIR, dest);
234
+
235
+ const overlayDir = TEMPLATE_OVERLAY_DIRS[templateName];
236
+
237
+ if (overlayDir) {
238
+ copyDirRecursive(overlayDir, dest);
239
+ }
240
+ }
241
+
118
242
  // ── Patch package.json ──────────────────────────────────────────────
119
243
 
120
244
  export function patchPackageJson(destDir, projectName) {
@@ -156,8 +280,17 @@ export function printNextSteps(projectName) {
156
280
 
157
281
  // ── Main ────────────────────────────────────────────────────────────
158
282
 
159
- export async function runCli(argv = process.argv, cwd = process.cwd()) {
160
- const { help, version, projectName: argName } = parseArgs(argv);
283
+ export function shouldPromptForTemplateSelection(input = process.stdin, output = process.stdout) {
284
+ return Boolean(input.isTTY && output.isTTY);
285
+ }
286
+
287
+ export async function runCli(
288
+ argv = process.argv,
289
+ cwd = process.cwd(),
290
+ io = { input: process.stdin, output: process.stdout },
291
+ ) {
292
+ const { help, version, projectName: argName, templateName: argTemplateName, optionError } =
293
+ parseArgs(argv);
161
294
 
162
295
  if (help) {
163
296
  printHelp();
@@ -169,17 +302,29 @@ export async function runCli(argv = process.argv, cwd = process.cwd()) {
169
302
  return 0;
170
303
  }
171
304
 
172
- const projectName = argName || (await promptProjectName());
305
+ if (optionError) {
306
+ throw new Error(optionError);
307
+ }
308
+
309
+ const projectName = argName || (await promptProjectName(io.input, io.output));
173
310
 
174
311
  validateProjectName(projectName);
175
312
 
313
+ const templateName =
314
+ argTemplateName ||
315
+ (shouldPromptForTemplateSelection(io.input, io.output)
316
+ ? await promptStarterTemplate(io.input, io.output)
317
+ : DEFAULT_TEMPLATE);
318
+
319
+ validateStarterTemplate(templateName);
320
+
176
321
  const targetDir = resolve(cwd, projectName);
177
322
 
178
323
  ensureTargetDir(targetDir);
179
324
 
180
- console.log(`\n Scaffolding KoppaJS project: ${projectName}\n`);
325
+ console.log(`\n Scaffolding KoppaJS project: ${projectName} (${templateName} starter)\n`);
181
326
 
182
- copyDirRecursive(TEMPLATE_DIR, targetDir);
327
+ copyStarterTemplate(templateName, targetDir);
183
328
  patchPackageJson(targetDir, projectName);
184
329
  patchReadme(targetDir, projectName);
185
330
  patchChangelog(targetDir, projectName);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-koppajs",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Scaffold a new KoppaJS project in seconds.",
@@ -10,6 +10,7 @@
10
10
  "files": [
11
11
  "bin",
12
12
  "template",
13
+ "template-overlays",
13
14
  "CHANGELOG.md",
14
15
  "README.md",
15
16
  "LICENSE"
@@ -42,13 +42,13 @@
42
42
  "prepare": "husky"
43
43
  },
44
44
  "dependencies": {
45
- "@koppajs/koppajs-core": "^3.0.2"
45
+ "@koppajs/koppajs-core": "^3.0.3"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@commitlint/cli": "^20.1.0",
49
49
  "@commitlint/config-conventional": "^20.0.0",
50
50
  "@eslint/js": "^10.0.1",
51
- "@koppajs/koppajs-vite-plugin": "^1.0.0",
51
+ "@koppajs/koppajs-vite-plugin": "^1.0.1",
52
52
  "@playwright/test": "^1.58.2",
53
53
  "@types/node": "^25.4.0",
54
54
  "@vitest/coverage-v8": "^4.0.18",