create-lumen 1.2.0-beta.1 → 2.0.0-alpha.0

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 (136) hide show
  1. package/README.md +56 -10
  2. package/bin/cli.js +18 -4
  3. package/package.json +18 -4
  4. package/schema/fixtures/index.js +62 -0
  5. package/schema/fixtures/v2/invalid/invalid-manifest-version.json +33 -0
  6. package/schema/fixtures/v2/invalid/malformed-paths.json +33 -0
  7. package/schema/fixtures/v2/invalid/missing-required-fields.json +17 -0
  8. package/schema/fixtures/v2/invalid/next-type-based.json +33 -0
  9. package/schema/fixtures/v2/invalid/next-vite.json +33 -0
  10. package/schema/fixtures/v2/invalid/react-bundler.json +34 -0
  11. package/schema/fixtures/v2/invalid/react-hybrid.json +33 -0
  12. package/schema/fixtures/v2/invalid/react-variant-mismatch.json +33 -0
  13. package/schema/fixtures/v2/invalid/shadcn-without-tailwind.json +33 -0
  14. package/schema/fixtures/v2/invalid/v1-flat-config.json +11 -0
  15. package/schema/fixtures/v2/valid/full-kitchen-sink.json +35 -0
  16. package/schema/fixtures/v2/valid/next-app-router-feature-based.json +35 -0
  17. package/schema/fixtures/v2/valid/next-app-router-hybrid.json +35 -0
  18. package/schema/fixtures/v2/valid/next-app-router-none.json +33 -0
  19. package/schema/fixtures/v2/valid/next-pages-router-feature-based.json +35 -0
  20. package/schema/fixtures/v2/valid/next-pages-router-hybrid.json +35 -0
  21. package/schema/fixtures/v2/valid/next-pages-router-none.json +33 -0
  22. package/schema/fixtures/v2/valid/react-vite-feature-based.json +33 -0
  23. package/schema/fixtures/v2/valid/react-vite-none.json +33 -0
  24. package/schema/fixtures/v2/valid/react-vite-type-based.json +33 -0
  25. package/schema/lumen.config.v2.json +216 -0
  26. package/src/cli-args.js +294 -0
  27. package/src/css.js +20 -9
  28. package/src/dependencies.js +27 -12
  29. package/src/engine/capabilities.js +218 -0
  30. package/src/engine/index.js +2 -0
  31. package/src/engine/providers/base-provider.js +219 -0
  32. package/src/injector.js +26 -13
  33. package/src/main.js +52 -10
  34. package/src/manifest/emit.js +120 -0
  35. package/src/manifest/index.js +11 -0
  36. package/src/manifest/paths.js +128 -0
  37. package/src/manifest/schema.js +212 -0
  38. package/src/prompts.js +26 -6
  39. package/templates/conditional/linting/eslint/next/eslint.config.mjs +16 -0
  40. package/templates/css/tailwind/postcss.config.mjs +5 -0
  41. /package/templates/architectures/{component-based → type-based}/main.jsx +0 -0
  42. /package/templates/architectures/{component-based → type-based}/main.tsx +0 -0
  43. /package/templates/architectures/{component-based → type-based}/src/App.jsx +0 -0
  44. /package/templates/architectures/{component-based → type-based}/src/App.tsx +0 -0
  45. /package/templates/architectures/{component-based → type-based}/src/components/common/Button.jsx +0 -0
  46. /package/templates/architectures/{component-based → type-based}/src/components/common/Button.tsx +0 -0
  47. /package/templates/architectures/{component-based → type-based}/src/components/common/index.js +0 -0
  48. /package/templates/architectures/{component-based → type-based}/src/components/common/index.ts +0 -0
  49. /package/templates/architectures/{component-based → type-based}/src/components/form/.gitkeep +0 -0
  50. /package/templates/architectures/{component-based → type-based}/src/config/.gitkeep +0 -0
  51. /package/templates/architectures/{component-based → type-based}/src/hooks/useApp.js +0 -0
  52. /package/templates/architectures/{component-based → type-based}/src/hooks/useApp.ts +0 -0
  53. /package/templates/architectures/{component-based → type-based}/src/hooks/useLocalStorage.jsx +0 -0
  54. /package/templates/architectures/{component-based → type-based}/src/hooks/useLocalStorage.ts +0 -0
  55. /package/templates/architectures/{component-based → type-based}/src/layouts/MainLayout.jsx +0 -0
  56. /package/templates/architectures/{component-based → type-based}/src/layouts/MainLayout.tsx +0 -0
  57. /package/templates/architectures/{component-based → type-based}/src/pages/Home/Home.jsx +0 -0
  58. /package/templates/architectures/{component-based → type-based}/src/pages/Home/Home.tsx +0 -0
  59. /package/templates/architectures/{component-based → type-based}/src/pages/Home/index.js +0 -0
  60. /package/templates/architectures/{component-based → type-based}/src/pages/Home/index.ts +0 -0
  61. /package/templates/architectures/{component-based → type-based}/src/providers/.gitkeep +0 -0
  62. /package/templates/architectures/{component-based → type-based}/src/providers/AppProvider.jsx +0 -0
  63. /package/templates/architectures/{component-based → type-based}/src/providers/AppProvider.tsx +0 -0
  64. /package/templates/architectures/{component-based → type-based}/src/providers/appcontext.js +0 -0
  65. /package/templates/architectures/{component-based → type-based}/src/providers/appcontext.ts +0 -0
  66. /package/templates/architectures/{component-based → type-based}/src/services/.gitkeep +0 -0
  67. /package/templates/architectures/{component-based → type-based}/src/store/.gitkeep +0 -0
  68. /package/templates/architectures/{component-based → type-based}/src/styles/.gitkeep +0 -0
  69. /package/templates/architectures/{component-based → type-based}/src/types/index.js +0 -0
  70. /package/templates/architectures/{component-based → type-based}/src/types/index.ts +0 -0
  71. /package/templates/architectures/{component-based → type-based}/src/utils/cn.jsx +0 -0
  72. /package/templates/architectures/{component-based → type-based}/src/utils/cn.ts +0 -0
  73. /package/templates/conditional/axios/{component-based → type-based}/src/config/axios.config.js +0 -0
  74. /package/templates/conditional/axios/{component-based → type-based}/src/config/axios.config.ts +0 -0
  75. /package/templates/conditional/axios/{component-based → type-based}/src/services/axios.client.js +0 -0
  76. /package/templates/conditional/axios/{component-based → type-based}/src/services/axios.client.ts +0 -0
  77. /package/templates/conditional/axios/{component-based → type-based}/src/services/user.service.js +0 -0
  78. /package/templates/conditional/axios/{component-based → type-based}/src/services/user.service.ts +0 -0
  79. /package/templates/conditional/fetch/{component-based → type-based}/src/config/api.config.js +0 -0
  80. /package/templates/conditional/fetch/{component-based → type-based}/src/config/api.config.ts +0 -0
  81. /package/templates/conditional/fetch/{component-based → type-based}/src/services/api.client.js +0 -0
  82. /package/templates/conditional/fetch/{component-based → type-based}/src/services/api.client.ts +0 -0
  83. /package/templates/conditional/fetch/{component-based → type-based}/src/services/user.service.js +0 -0
  84. /package/templates/conditional/fetch/{component-based → type-based}/src/services/user.service.ts +0 -0
  85. /package/templates/conditional/icons/huge/{component-based → type-based}/bootstrap/src/pages/Home/Home.jsx +0 -0
  86. /package/templates/conditional/icons/huge/{component-based → type-based}/bootstrap/src/pages/Home/Home.tsx +0 -0
  87. /package/templates/conditional/icons/huge/{component-based → type-based}/src/pages/Home/Home.jsx +0 -0
  88. /package/templates/conditional/icons/huge/{component-based → type-based}/src/pages/Home/Home.tsx +0 -0
  89. /package/templates/conditional/icons/huge/{component-based → type-based}/tailwind/src/pages/Home/Home.jsx +0 -0
  90. /package/templates/conditional/icons/huge/{component-based → type-based}/tailwind/src/pages/Home/Home.tsx +0 -0
  91. /package/templates/conditional/icons/lucide/{component-based → type-based}/bootstrap/src/pages/Home/Home.jsx +0 -0
  92. /package/templates/conditional/icons/lucide/{component-based → type-based}/bootstrap/src/pages/Home/Home.tsx +0 -0
  93. /package/templates/conditional/icons/lucide/{component-based → type-based}/src/pages/Home/Home.jsx +0 -0
  94. /package/templates/conditional/icons/lucide/{component-based → type-based}/src/pages/Home/Home.tsx +0 -0
  95. /package/templates/conditional/icons/lucide/{component-based → type-based}/tailwind/src/pages/Home/Home.jsx +0 -0
  96. /package/templates/conditional/icons/lucide/{component-based → type-based}/tailwind/src/pages/Home/Home.tsx +0 -0
  97. /package/templates/conditional/router/{component-based → type-based}/bootstrap/src/layouts/MainLayout.jsx +0 -0
  98. /package/templates/conditional/router/{component-based → type-based}/bootstrap/src/layouts/MainLayout.tsx +0 -0
  99. /package/templates/conditional/router/{component-based → type-based}/src/App.jsx +0 -0
  100. /package/templates/conditional/router/{component-based → type-based}/src/App.tsx +0 -0
  101. /package/templates/conditional/router/{component-based → type-based}/src/layouts/MainLayout.jsx +0 -0
  102. /package/templates/conditional/router/{component-based → type-based}/src/layouts/MainLayout.tsx +0 -0
  103. /package/templates/conditional/router/{component-based → type-based}/src/router/guards/AuthGuard.jsx +0 -0
  104. /package/templates/conditional/router/{component-based → type-based}/src/router/guards/AuthGuard.tsx +0 -0
  105. /package/templates/conditional/router/{component-based → type-based}/src/router/guards/GuestGuard.jsx +0 -0
  106. /package/templates/conditional/router/{component-based → type-based}/src/router/guards/GuestGuard.tsx +0 -0
  107. /package/templates/conditional/router/{component-based → type-based}/src/router/index.jsx +0 -0
  108. /package/templates/conditional/router/{component-based → type-based}/src/router/index.tsx +0 -0
  109. /package/templates/conditional/router/{component-based → type-based}/tailwind/src/layouts/MainLayout.jsx +0 -0
  110. /package/templates/conditional/router/{component-based → type-based}/tailwind/src/layouts/MainLayout.tsx +0 -0
  111. /package/templates/conditional/state/redux/{component-based → type-based}/src/pages/Home/counterSlice.jsx +0 -0
  112. /package/templates/conditional/state/redux/{component-based → type-based}/src/pages/Home/counterSlice.ts +0 -0
  113. /package/templates/conditional/state/redux/{component-based → type-based}/src/providers/StoreProvider.jsx +0 -0
  114. /package/templates/conditional/state/redux/{component-based → type-based}/src/providers/StoreProvider.tsx +0 -0
  115. /package/templates/conditional/state/redux/{component-based → type-based}/src/store/hooks.js +0 -0
  116. /package/templates/conditional/state/redux/{component-based → type-based}/src/store/hooks.ts +0 -0
  117. /package/templates/conditional/state/redux/{component-based → type-based}/src/store/index.js +0 -0
  118. /package/templates/conditional/state/redux/{component-based → type-based}/src/store/index.ts +0 -0
  119. /package/templates/conditional/state/zustand/{component-based → type-based}/src/store/useCounterStore.jsx +0 -0
  120. /package/templates/conditional/state/zustand/{component-based → type-based}/src/store/useCounterStore.ts +0 -0
  121. /package/templates/conditional/testing/jest/{component-based → type-based}/src/__tests__/App.test.jsx +0 -0
  122. /package/templates/conditional/testing/jest/{component-based → type-based}/src/__tests__/App.test.tsx +0 -0
  123. /package/templates/conditional/testing/vitest/{component-based → type-based}/src/__tests__/App.test.jsx +0 -0
  124. /package/templates/conditional/testing/vitest/{component-based → type-based}/src/__tests__/App.test.tsx +0 -0
  125. /package/templates/css/component-styles/bootstrap/{component-based → type-based}/src/components/common/Button.jsx +0 -0
  126. /package/templates/css/component-styles/bootstrap/{component-based → type-based}/src/components/common/Button.tsx +0 -0
  127. /package/templates/css/component-styles/bootstrap/{component-based → type-based}/src/layouts/MainLayout.jsx +0 -0
  128. /package/templates/css/component-styles/bootstrap/{component-based → type-based}/src/layouts/MainLayout.tsx +0 -0
  129. /package/templates/css/component-styles/bootstrap/{component-based → type-based}/src/pages/Home/Home.jsx +0 -0
  130. /package/templates/css/component-styles/bootstrap/{component-based → type-based}/src/pages/Home/Home.tsx +0 -0
  131. /package/templates/css/component-styles/tailwind/{component-based → type-based}/src/components/common/Button.jsx +0 -0
  132. /package/templates/css/component-styles/tailwind/{component-based → type-based}/src/components/common/Button.tsx +0 -0
  133. /package/templates/css/component-styles/tailwind/{component-based → type-based}/src/layouts/MainLayout.jsx +0 -0
  134. /package/templates/css/component-styles/tailwind/{component-based → type-based}/src/layouts/MainLayout.tsx +0 -0
  135. /package/templates/css/component-styles/tailwind/{component-based → type-based}/src/pages/Home/Home.jsx +0 -0
  136. /package/templates/css/component-styles/tailwind/{component-based → type-based}/src/pages/Home/Home.tsx +0 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # create-lumen
2
2
 
3
- A scaffolder that generates production-ready React + Vite projects (feature-based or component-based).
3
+ A scaffolder that generates production-ready React + Vite projects (feature-based or type-based).
4
4
 
5
5
  Note: this repository is the CLI scaffolder itself, not a generated app. Generated projects live in the target folder you create.
6
6
 
@@ -14,15 +14,44 @@ cd my-app
14
14
  npm run dev
15
15
  ```
16
16
 
17
- Non-interactive Quick Setup (TypeScript + Tailwind + Feature-based + Router + ESLint + Prettier + Vitest), no prompts:
17
+ ### Non-interactive flags
18
+
19
+ Quick Setup (TypeScript + Tailwind + Feature-based + Router + ESLint + Prettier + Vitest), no prompts:
18
20
 
19
21
  ```bash
20
22
  npm create lumen my-app -- -y
21
23
  # or
22
24
  npm create lumen -- -y my-app
25
+ # or
26
+ npm create lumen my-app -- --yes
27
+ ```
28
+
29
+ Scaffold using a template preset (`react-ts`, `react-js`, `react-type-ts`, `react-type-js`):
30
+
31
+ ```bash
32
+ npm create lumen my-app -- --template react-ts
33
+ # or
34
+ npm create lumen my-app -- -t react-type-js
35
+ ```
36
+
37
+ Drive scaffolding directly from a manifest file or inline JSON (manifest v2):
38
+
39
+ ```bash
40
+ # From file
41
+ npm create lumen my-app -- --manifest ./lumen.config.json
42
+
43
+ # From inline JSON
44
+ npm create lumen my-app -- -m '{"manifestVersion":2,"framework":{"name":"react","variant":"vite"},...}'
23
45
  ```
24
46
 
25
- The CLI ignores flag arguments when resolving the project name, so `-y` can appear before or after the app name without being mistaken for the folder name.
47
+ The CLI parses options cleanly regardless of flag ordering, so flags can appear before or after the project name.
48
+
49
+ Display help and version:
50
+
51
+ ```bash
52
+ npm create lumen -- --help
53
+ npm create lumen -- --version
54
+ ```
26
55
 
27
56
  Run the scaffolder locally (development / testing the generator):
28
57
 
@@ -35,14 +64,16 @@ create-lumen my-app # after npm link
35
64
 
36
65
  ## Features
37
66
 
38
- - Architecture choice: feature-based or component-based
67
+ - Architecture choice: feature-based or type-based (with Next.js hybrid/none in v2)
39
68
  - TypeScript or JavaScript output
40
- - CSS frameworks: Tailwind, Bootstrap, or none
69
+ - CSS frameworks: Tailwind CSS v4 (CSS-first `@theme`, v3 dropped), Bootstrap 5.3+, or none
41
70
  - Optional state management: Zustand or Redux Toolkit
42
71
  - Optional router (React Router)
43
72
  - Optional testing: Vitest or Jest
44
- - Linting: ESLint (default) or Oxlint
73
+ - Linting: ESLint (default), Oxlint, or Biome
45
74
  - Code formatter: Prettier or Oxfmt (chosen after the linter; `eslint-config-prettier` is auto-wired for the ESLint + Prettier combo)
75
+ - Manifest v2: Emits a deterministic `lumen.config.json` validated against JSON Schema Draft 2020-12
76
+ - Explicit path mapping: Target directories declared for `lumen-cli` code generation
46
77
  - Optional Axios setup and icon libraries
47
78
  - Auto `git init`, generated `README` (with a project description reflecting the chosen tooling) and `LICENSE`
48
79
  - `.env.example` scaffolded, and the generated `.gitignore` excludes env files (`.env`, `.env.*`) while keeping `.env.example`
@@ -123,7 +154,7 @@ src/
123
154
  └── utils
124
155
  ```
125
156
 
126
- Component-based (example):
157
+ Type-based (example):
127
158
 
128
159
  ```
129
160
  src/
@@ -132,7 +163,6 @@ src/
132
163
  │   ├── common
133
164
  │   └── form
134
165
  ├── config # API config (when an axios/fetch client is chosen)
135
- ├── hooks
136
166
  ├── layouts
137
167
  ├── main.tsx
138
168
  ├── pages
@@ -153,9 +183,25 @@ src/
153
183
  └── utils
154
184
  ```
155
185
 
156
- ## Roadmap
186
+ ## Manifest v2 & Ecosystem Architecture
187
+
188
+ `create-lumen` is part of the Lumen ecosystem alongside **`lumen-cli`**:
189
+
190
+ - **`create-lumen` (this repo):** The bootstrap scaffolder that initializes project repositories and writes an explicit, strictly validated `lumen.config.json` manifest (`manifestVersion: 2`) into the project root.
191
+ - **`lumen-cli`:** The companion developer CLI that reads `lumen.config.json` to generate components, features, hooks, and services at the paths declared in `manifest.paths`.
192
+
193
+ ### Ecosystem Documentation & Contracts
194
+
195
+ - **[Manifest v2 Overview](./docs/manifest-v2.md):** Specification of the nested schema and validation behavior.
196
+ - **[Shared Contract: `create-lumen` ↔ `lumen-cli`](./docs/contracts/manifest-v2-contract.md):** The agreed contract for path mapping, barrel conventions, and version negotiation.
197
+ - **[v1 to v2 Migration Guide](./docs/migration/v1-to-v2.md):** Complete guide for migrating generated projects and legacy flat configs to v2.
198
+
199
+ ## Roadmap & Planning
157
200
 
158
- Released versions live in [`docs/CHANGELOG.md`](./docs/CHANGELOG.md); planned work is tracked in [`docs/ROADMAP.md`](./docs/ROADMAP.md).
201
+ - **Changelog:** Notable changes are documented in [`docs/CHANGELOG.md`](./docs/CHANGELOG.md) (Keep a Changelog format).
202
+ - **Roadmap:** Milestones (M1 through M5) are tracked in [`docs/ROADMAP.md`](./docs/ROADMAP.md).
203
+ - **Visual Plan:** Dependency graphs and parallel wave execution plans live in [`docs/PLAN.md`](./docs/PLAN.md).
204
+ - **Branching Workflow:** Guide for branch conventions and PR checklist in [`docs/BRANCHING.md`](./docs/BRANCHING.md).
159
205
 
160
206
  ## Requirements
161
207
 
package/bin/cli.js CHANGED
@@ -3,14 +3,23 @@
3
3
  import { readFile } from "node:fs/promises";
4
4
  import chalk from "chalk";
5
5
  import "../register.js";
6
+ import { parseCliArgs, printHelp } from "../src/cli-args.js";
6
7
 
7
8
  const { version } = JSON.parse(
8
9
  await readFile(new URL("../package.json", import.meta.url), "utf8")
9
10
  );
10
11
 
11
- const args = process.argv.slice(2);
12
- const quickSetup = args.includes("-y");
13
- const projectName = args.find((a) => !a.startsWith("-"));
12
+ const cliArgs = parseCliArgs(process.argv.slice(2));
13
+
14
+ if (cliArgs.help) {
15
+ printHelp();
16
+ process.exit(0);
17
+ }
18
+
19
+ if (cliArgs.version) {
20
+ console.log(version);
21
+ process.exit(0);
22
+ }
14
23
 
15
24
  console.log(
16
25
  chalk.bold.cyan("\n ✦ LUMEN") +
@@ -22,7 +31,12 @@ console.log(
22
31
 
23
32
  const { main } = await import("@/main.js");
24
33
 
25
- main({ quickSetup, projectName }).catch((e) => {
34
+ main({
35
+ quickSetup: cliArgs.quickSetup,
36
+ projectName: cliArgs.projectName,
37
+ manifest: cliArgs.manifest,
38
+ template: cliArgs.template,
39
+ }).catch((e) => {
26
40
  console.error(chalk.red("\nError:"), e.message || e);
27
41
  process.exit(1);
28
42
  });
package/package.json CHANGED
@@ -1,20 +1,26 @@
1
1
  {
2
2
  "name": "create-lumen",
3
- "version": "1.2.0-beta.1",
4
- "description": "Scaffold a React + Vite project with architecture choice: feature-based or component-based.",
3
+ "version": "2.0.0-alpha.0",
4
+ "description": "Scaffold a React + Vite project with architecture choice: feature-based or type-based.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "create-lumen": "bin/cli.js"
8
8
  },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/LUMEN-SH/create-lumen"
12
+ },
9
13
  "files": [
10
14
  "bin/",
11
15
  "register.js",
12
16
  "src/",
13
17
  "templates/",
18
+ "schema/",
14
19
  "README.md",
15
20
  "LICENSE"
16
21
  ],
17
22
  "scripts": {
23
+ "gen:schema": "node scripts/generate-schema.mjs",
18
24
  "test": "node --import ./register.js --test \"tests/unit/*.test.mjs\" \"tests/smoke/*.test.mjs\"",
19
25
  "verify:vendor": "node --import ./register.js tests/verify/install-vendor.mjs",
20
26
  "verify:offline": "node --import ./register.js tests/verify/verify-offline.mjs",
@@ -31,7 +37,7 @@
31
37
  "react",
32
38
  "typescript",
33
39
  "feature-based",
34
- "component-based",
40
+ "type-based",
35
41
  "architecture",
36
42
  "starter",
37
43
  "boilerplate"
@@ -41,9 +47,17 @@
41
47
  "dependencies": {
42
48
  "@clack/prompts": "^0.11.0",
43
49
  "chalk": "^5.6.2",
44
- "execa": "^9.6.0"
50
+ "execa": "^9.6.0",
51
+ "zod": "4.6.5",
52
+ "zod-validation-error": "4.0.0"
45
53
  },
46
54
  "engines": {
47
55
  "node": ">=18"
56
+ },
57
+ "devDependencies": {
58
+ "@eslint/js": "^10.0.1",
59
+ "@microsoft/eslint-formatter-sarif": "^3.1.0",
60
+ "eslint": "^10.10.0",
61
+ "globals": "^17.12.0"
48
62
  }
49
63
  }
@@ -0,0 +1,62 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = path.dirname(__filename);
7
+
8
+ export const FIXTURES_DIR = __dirname;
9
+ export const VALID_FIXTURES_DIR = path.join(__dirname, "v2", "valid");
10
+ export const INVALID_FIXTURES_DIR = path.join(__dirname, "v2", "invalid");
11
+
12
+ /**
13
+ * Loads all valid manifest fixtures as an array of { name, filename, manifest }.
14
+ * @returns {Promise<Array<{ name: string, filename: string, manifest: object }>>}
15
+ */
16
+ export async function loadValidFixtures() {
17
+ const files = (await readdir(VALID_FIXTURES_DIR)).filter((f) => f.endsWith(".json"));
18
+ const fixtures = [];
19
+ for (const filename of files) {
20
+ const filePath = path.join(VALID_FIXTURES_DIR, filename);
21
+ const content = await readFile(filePath, "utf8");
22
+ fixtures.push({
23
+ name: path.basename(filename, ".json"),
24
+ filename,
25
+ manifest: JSON.parse(content),
26
+ });
27
+ }
28
+ return fixtures;
29
+ }
30
+
31
+ /**
32
+ * Loads all invalid manifest fixtures as an array of { name, filename, manifest }.
33
+ * @returns {Promise<Array<{ name: string, filename: string, manifest: object }>>}
34
+ */
35
+ export async function loadInvalidFixtures() {
36
+ const files = (await readdir(INVALID_FIXTURES_DIR)).filter((f) => f.endsWith(".json"));
37
+ const fixtures = [];
38
+ for (const filename of files) {
39
+ const filePath = path.join(INVALID_FIXTURES_DIR, filename);
40
+ const content = await readFile(filePath, "utf8");
41
+ fixtures.push({
42
+ name: path.basename(filename, ".json"),
43
+ filename,
44
+ manifest: JSON.parse(content),
45
+ });
46
+ }
47
+ return fixtures;
48
+ }
49
+
50
+ /**
51
+ * Loads a single fixture by category ('valid' | 'invalid') and fixture name.
52
+ * @param {'valid' | 'invalid'} category
53
+ * @param {string} name
54
+ * @returns {Promise<object>}
55
+ */
56
+ export async function getFixture(category, name) {
57
+ const dir = category === "valid" ? VALID_FIXTURES_DIR : INVALID_FIXTURES_DIR;
58
+ const filename = name.endsWith(".json") ? name : `${name}.json`;
59
+ const filePath = path.join(dir, filename);
60
+ const content = await readFile(filePath, "utf8");
61
+ return JSON.parse(content);
62
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 3,
4
+ "framework": {
5
+ "name": "react",
6
+ "variant": "vite"
7
+ },
8
+ "styling": {
9
+ "engine": "tailwind"
10
+ },
11
+ "architecture": {
12
+ "type": "feature-based"
13
+ },
14
+ "ui": {
15
+ "kit": "none"
16
+ },
17
+ "docs": {
18
+ "language": "en"
19
+ },
20
+ "paths": {
21
+ "features": "src/features",
22
+ "components": "src/shared/components",
23
+ "services": "src/shared/services",
24
+ "hooks": "src/shared/hooks",
25
+ "pages": "src/app/router",
26
+ "ui": "src/shared/components/ui"
27
+ },
28
+ "tooling": {
29
+ "language": "ts",
30
+ "linter": "eslint",
31
+ "formatter": "prettier"
32
+ }
33
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "react",
6
+ "variant": "vite"
7
+ },
8
+ "styling": {
9
+ "engine": "tailwind"
10
+ },
11
+ "architecture": {
12
+ "type": "feature-based"
13
+ },
14
+ "ui": {
15
+ "kit": "none"
16
+ },
17
+ "docs": {
18
+ "language": "en"
19
+ },
20
+ "paths": {
21
+ "features": "",
22
+ "components": "src/shared/components",
23
+ "services": "src/shared/services",
24
+ "hooks": "src/shared/hooks",
25
+ "pages": "src/app/router",
26
+ "ui": "src/shared/components/ui"
27
+ },
28
+ "tooling": {
29
+ "language": "ts",
30
+ "linter": "eslint",
31
+ "formatter": "prettier"
32
+ }
33
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "react",
6
+ "variant": "vite"
7
+ },
8
+ "styling": {
9
+ "engine": "tailwind"
10
+ },
11
+ "architecture": {
12
+ "type": "feature-based"
13
+ },
14
+ "ui": {
15
+ "kit": "none"
16
+ }
17
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "next",
6
+ "variant": "app-router"
7
+ },
8
+ "styling": {
9
+ "engine": "tailwind"
10
+ },
11
+ "architecture": {
12
+ "type": "type-based"
13
+ },
14
+ "ui": {
15
+ "kit": "none"
16
+ },
17
+ "docs": {
18
+ "language": "en"
19
+ },
20
+ "paths": {
21
+ "features": "src/components",
22
+ "components": "src/components",
23
+ "services": "src/services",
24
+ "hooks": "src/hooks",
25
+ "pages": "app",
26
+ "ui": "src/components/ui"
27
+ },
28
+ "tooling": {
29
+ "language": "ts",
30
+ "linter": "eslint",
31
+ "formatter": "prettier"
32
+ }
33
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "next",
6
+ "variant": "vite"
7
+ },
8
+ "styling": {
9
+ "engine": "tailwind"
10
+ },
11
+ "architecture": {
12
+ "type": "feature-based"
13
+ },
14
+ "ui": {
15
+ "kit": "none"
16
+ },
17
+ "docs": {
18
+ "language": "en"
19
+ },
20
+ "paths": {
21
+ "features": "src/features",
22
+ "components": "src/shared/components",
23
+ "services": "src/shared/services",
24
+ "hooks": "src/shared/hooks",
25
+ "pages": "app",
26
+ "ui": "src/shared/components/ui"
27
+ },
28
+ "tooling": {
29
+ "language": "ts",
30
+ "linter": "eslint",
31
+ "formatter": "prettier"
32
+ }
33
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "react",
6
+ "variant": "vite",
7
+ "bundler": "turbopack"
8
+ },
9
+ "styling": {
10
+ "engine": "tailwind"
11
+ },
12
+ "architecture": {
13
+ "type": "feature-based"
14
+ },
15
+ "ui": {
16
+ "kit": "none"
17
+ },
18
+ "docs": {
19
+ "language": "en"
20
+ },
21
+ "paths": {
22
+ "features": "src/features",
23
+ "components": "src/shared/components",
24
+ "services": "src/shared/services",
25
+ "hooks": "src/shared/hooks",
26
+ "pages": "src/app/router",
27
+ "ui": "src/shared/components/ui"
28
+ },
29
+ "tooling": {
30
+ "language": "ts",
31
+ "linter": "eslint",
32
+ "formatter": "prettier"
33
+ }
34
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "react",
6
+ "variant": "vite"
7
+ },
8
+ "styling": {
9
+ "engine": "tailwind"
10
+ },
11
+ "architecture": {
12
+ "type": "hybrid"
13
+ },
14
+ "ui": {
15
+ "kit": "none"
16
+ },
17
+ "docs": {
18
+ "language": "en"
19
+ },
20
+ "paths": {
21
+ "features": "src/features",
22
+ "components": "src/shared/components",
23
+ "services": "src/shared/services",
24
+ "hooks": "src/shared/hooks",
25
+ "pages": "src/app/router",
26
+ "ui": "src/shared/components/ui"
27
+ },
28
+ "tooling": {
29
+ "language": "ts",
30
+ "linter": "eslint",
31
+ "formatter": "prettier"
32
+ }
33
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "react",
6
+ "variant": "app-router"
7
+ },
8
+ "styling": {
9
+ "engine": "tailwind"
10
+ },
11
+ "architecture": {
12
+ "type": "feature-based"
13
+ },
14
+ "ui": {
15
+ "kit": "none"
16
+ },
17
+ "docs": {
18
+ "language": "en"
19
+ },
20
+ "paths": {
21
+ "features": "src/features",
22
+ "components": "src/shared/components",
23
+ "services": "src/shared/services",
24
+ "hooks": "src/shared/hooks",
25
+ "pages": "src/app/router",
26
+ "ui": "src/shared/components/ui"
27
+ },
28
+ "tooling": {
29
+ "language": "ts",
30
+ "linter": "eslint",
31
+ "formatter": "prettier"
32
+ }
33
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "react",
6
+ "variant": "vite"
7
+ },
8
+ "styling": {
9
+ "engine": "bootstrap"
10
+ },
11
+ "architecture": {
12
+ "type": "feature-based"
13
+ },
14
+ "ui": {
15
+ "kit": "shadcn"
16
+ },
17
+ "docs": {
18
+ "language": "en"
19
+ },
20
+ "paths": {
21
+ "features": "src/features",
22
+ "components": "src/shared/components",
23
+ "services": "src/shared/services",
24
+ "hooks": "src/shared/hooks",
25
+ "pages": "src/app/router",
26
+ "ui": "src/shared/components/ui"
27
+ },
28
+ "tooling": {
29
+ "language": "ts",
30
+ "linter": "eslint",
31
+ "formatter": "prettier"
32
+ }
33
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "framework": "react",
3
+ "css": "tailwind",
4
+ "architecture": "feature-based",
5
+ "language": "ts",
6
+ "router": true,
7
+ "stateManagement": "none",
8
+ "iconLibrary": "none",
9
+ "apiClient": "none",
10
+ "testing": "vitest"
11
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "react",
6
+ "variant": "vite"
7
+ },
8
+ "styling": {
9
+ "engine": "tailwind"
10
+ },
11
+ "architecture": {
12
+ "type": "feature-based"
13
+ },
14
+ "ui": {
15
+ "kit": "shadcn"
16
+ },
17
+ "docs": {
18
+ "language": "en"
19
+ },
20
+ "paths": {
21
+ "features": "src/features",
22
+ "components": "src/shared/components",
23
+ "services": "src/shared/services",
24
+ "hooks": "src/shared/hooks",
25
+ "pages": "src/app/router",
26
+ "ui": "src/shared/components/ui"
27
+ },
28
+ "tooling": {
29
+ "language": "ts",
30
+ "linter": "biome",
31
+ "formatter": "prettier"
32
+ },
33
+ "reactCompiler": true,
34
+ "agentDocs": true
35
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "next",
6
+ "variant": "app-router",
7
+ "bundler": "turbopack",
8
+ "adapter": "vercel"
9
+ },
10
+ "styling": {
11
+ "engine": "tailwind"
12
+ },
13
+ "architecture": {
14
+ "type": "feature-based"
15
+ },
16
+ "ui": {
17
+ "kit": "none"
18
+ },
19
+ "docs": {
20
+ "language": "en"
21
+ },
22
+ "paths": {
23
+ "features": "src/features",
24
+ "components": "src/shared/components",
25
+ "services": "src/shared/services",
26
+ "hooks": "src/shared/hooks",
27
+ "pages": "app",
28
+ "ui": "src/shared/components/ui"
29
+ },
30
+ "tooling": {
31
+ "language": "ts",
32
+ "linter": "eslint",
33
+ "formatter": "prettier"
34
+ }
35
+ }