create-lumen 2.0.0-alpha.1 → 2.0.0-beta.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 (190) hide show
  1. package/README.md +38 -12
  2. package/bin/cli.js +3 -1
  3. package/package.json +3 -3
  4. package/schema/fixtures/v2/invalid/shadcn-without-tailwind.json +1 -1
  5. package/schema/fixtures/v2/valid/react-vite-type-based.json +1 -1
  6. package/schema/lumen.config.v2.json +0 -1
  7. package/src/cli-args.js +169 -7
  8. package/src/configure.js +12 -4
  9. package/src/css.js +14 -30
  10. package/src/dependencies.js +36 -20
  11. package/src/engine/capabilities.js +195 -4
  12. package/src/engine/composition.js +736 -0
  13. package/src/engine/index.js +1 -0
  14. package/src/engine/providers/base-provider.js +4 -4
  15. package/src/injector.js +294 -446
  16. package/src/main.js +38 -16
  17. package/src/manifest/emit.js +1 -1
  18. package/src/manifest/schema.js +1 -1
  19. package/src/prompts.js +581 -238
  20. package/src/readme.js +23 -2
  21. package/src/scaffold.js +17 -0
  22. package/templates/architectures/hybrid/main.jsx +10 -0
  23. package/templates/architectures/hybrid/main.tsx +10 -0
  24. package/templates/architectures/hybrid/src/App.jsx +20 -0
  25. package/templates/architectures/hybrid/src/App.tsx +20 -0
  26. package/templates/architectures/hybrid/src/shared/components/ui/Button.jsx +31 -0
  27. package/templates/architectures/hybrid/src/shared/components/ui/Button.tsx +36 -0
  28. package/templates/architectures/hybrid/src/shared/components/ui/index.js +1 -0
  29. package/templates/architectures/hybrid/src/shared/components/ui/index.ts +1 -0
  30. package/templates/architectures/hybrid/src/shared/hooks/useLocalStorage.jsx +28 -0
  31. package/templates/architectures/hybrid/src/shared/hooks/useLocalStorage.ts +28 -0
  32. package/templates/architectures/hybrid/src/shared/layouts/.gitkeep +0 -0
  33. package/templates/architectures/hybrid/src/shared/stores/.gitkeep +0 -0
  34. package/templates/architectures/hybrid/src/shared/styles/.gitkeep +0 -0
  35. package/templates/architectures/hybrid/src/shared/types/index.js +20 -0
  36. package/templates/architectures/hybrid/src/shared/types/index.ts +16 -0
  37. package/templates/architectures/hybrid/src/shared/utils/cn.jsx +3 -0
  38. package/templates/architectures/hybrid/src/shared/utils/cn.ts +5 -0
  39. package/templates/architectures/none/main.jsx +10 -0
  40. package/templates/architectures/none/main.tsx +10 -0
  41. package/templates/architectures/none/src/App.jsx +15 -0
  42. package/templates/architectures/none/src/App.tsx +15 -0
  43. package/templates/architectures/none/src/styles/.gitkeep +1 -0
  44. package/templates/architectures/none/src/types/index.js +20 -0
  45. package/templates/architectures/none/src/types/index.ts +16 -0
  46. package/templates/bases/next/app-router/js/.provenance.json +19 -0
  47. package/templates/bases/next/app-router/js/README.md +36 -0
  48. package/templates/bases/next/app-router/js/jsconfig.json +7 -0
  49. package/templates/bases/next/app-router/js/next.config.mjs +6 -0
  50. package/templates/bases/next/app-router/js/package.json +15 -0
  51. package/templates/bases/next/app-router/js/public/file.svg +1 -0
  52. package/templates/bases/next/app-router/js/public/globe.svg +1 -0
  53. package/templates/bases/next/app-router/js/public/next.svg +1 -0
  54. package/templates/bases/next/app-router/js/public/vercel.svg +1 -0
  55. package/templates/bases/next/app-router/js/public/window.svg +1 -0
  56. package/templates/bases/next/app-router/js/src/app/api/hello/route.js +5 -0
  57. package/templates/bases/next/app-router/js/src/app/blog/[slug]/page.js +33 -0
  58. package/templates/bases/next/app-router/js/src/app/favicon.ico +0 -0
  59. package/templates/bases/next/app-router/js/src/app/globals.css +49 -0
  60. package/templates/bases/next/app-router/js/src/app/layout.js +25 -0
  61. package/templates/bases/next/app-router/js/src/app/loading.js +15 -0
  62. package/templates/bases/next/app-router/js/src/app/not-found.js +29 -0
  63. package/templates/bases/next/app-router/js/src/app/page.js +69 -0
  64. package/templates/bases/next/app-router/js/src/app/page.module.css +150 -0
  65. package/templates/bases/next/app-router/ts/.provenance.json +19 -0
  66. package/templates/bases/next/app-router/ts/README.md +36 -0
  67. package/templates/bases/next/app-router/ts/next.config.ts +7 -0
  68. package/templates/bases/next/app-router/ts/package.json +21 -0
  69. package/templates/bases/next/app-router/ts/public/file.svg +1 -0
  70. package/templates/bases/next/app-router/ts/public/globe.svg +1 -0
  71. package/templates/bases/next/app-router/ts/public/next.svg +1 -0
  72. package/templates/bases/next/app-router/ts/public/vercel.svg +1 -0
  73. package/templates/bases/next/app-router/ts/public/window.svg +1 -0
  74. package/templates/bases/next/app-router/ts/src/app/api/hello/route.ts +5 -0
  75. package/templates/bases/next/app-router/ts/src/app/blog/[slug]/page.tsx +38 -0
  76. package/templates/bases/next/app-router/ts/src/app/favicon.ico +0 -0
  77. package/templates/bases/next/app-router/ts/src/app/globals.css +49 -0
  78. package/templates/bases/next/app-router/ts/src/app/layout.tsx +30 -0
  79. package/templates/bases/next/app-router/ts/src/app/loading.tsx +15 -0
  80. package/templates/bases/next/app-router/ts/src/app/not-found.tsx +29 -0
  81. package/templates/bases/next/app-router/ts/src/app/page.module.css +150 -0
  82. package/templates/bases/next/app-router/ts/src/app/page.tsx +69 -0
  83. package/templates/bases/next/app-router/ts/tsconfig.json +34 -0
  84. package/templates/bases/next/pages-router/js/.provenance.json +19 -0
  85. package/templates/bases/next/pages-router/js/README.md +40 -0
  86. package/templates/bases/next/pages-router/js/jsconfig.json +7 -0
  87. package/templates/bases/next/pages-router/js/next.config.mjs +7 -0
  88. package/templates/bases/next/pages-router/js/package.json +15 -0
  89. package/templates/bases/next/pages-router/js/public/favicon.ico +0 -0
  90. package/templates/bases/next/pages-router/js/public/file.svg +1 -0
  91. package/templates/bases/next/pages-router/js/public/globe.svg +1 -0
  92. package/templates/bases/next/pages-router/js/public/next.svg +1 -0
  93. package/templates/bases/next/pages-router/js/public/vercel.svg +1 -0
  94. package/templates/bases/next/pages-router/js/public/window.svg +1 -0
  95. package/templates/bases/next/pages-router/js/src/pages/404.js +35 -0
  96. package/templates/bases/next/pages-router/js/src/pages/500.js +35 -0
  97. package/templates/bases/next/pages-router/js/src/pages/_app.js +20 -0
  98. package/templates/bases/next/pages-router/js/src/pages/_document.js +15 -0
  99. package/templates/bases/next/pages-router/js/src/pages/api/hello.js +5 -0
  100. package/templates/bases/next/pages-router/js/src/pages/blog/[slug].js +41 -0
  101. package/templates/bases/next/pages-router/js/src/pages/index.js +77 -0
  102. package/templates/bases/next/pages-router/js/src/styles/Home.module.css +149 -0
  103. package/templates/bases/next/pages-router/js/src/styles/globals.css +42 -0
  104. package/templates/bases/next/pages-router/ts/.provenance.json +19 -0
  105. package/templates/bases/next/pages-router/ts/README.md +40 -0
  106. package/templates/bases/next/pages-router/ts/next.config.ts +8 -0
  107. package/templates/bases/next/pages-router/ts/package.json +21 -0
  108. package/templates/bases/next/pages-router/ts/public/favicon.ico +0 -0
  109. package/templates/bases/next/pages-router/ts/public/file.svg +1 -0
  110. package/templates/bases/next/pages-router/ts/public/globe.svg +1 -0
  111. package/templates/bases/next/pages-router/ts/public/next.svg +1 -0
  112. package/templates/bases/next/pages-router/ts/public/vercel.svg +1 -0
  113. package/templates/bases/next/pages-router/ts/public/window.svg +1 -0
  114. package/templates/bases/next/pages-router/ts/src/pages/404.tsx +35 -0
  115. package/templates/bases/next/pages-router/ts/src/pages/500.tsx +35 -0
  116. package/templates/bases/next/pages-router/ts/src/pages/_app.tsx +21 -0
  117. package/templates/bases/next/pages-router/ts/src/pages/_document.tsx +15 -0
  118. package/templates/bases/next/pages-router/ts/src/pages/api/hello.ts +13 -0
  119. package/templates/bases/next/pages-router/ts/src/pages/blog/[slug].tsx +46 -0
  120. package/templates/bases/next/pages-router/ts/src/pages/index.tsx +77 -0
  121. package/templates/bases/next/pages-router/ts/src/styles/Home.module.css +149 -0
  122. package/templates/bases/next/pages-router/ts/src/styles/globals.css +42 -0
  123. package/templates/bases/next/pages-router/ts/tsconfig.json +29 -0
  124. package/templates/conditional/linting/biome/biome.json +31 -0
  125. package/templates/conditional/next/config/cloudflare/next.config.mjs +6 -0
  126. package/templates/conditional/next/config/cloudflare/next.config.ts +7 -0
  127. package/templates/conditional/next/config/node/next.config.mjs +6 -0
  128. package/templates/conditional/next/config/node/next.config.ts +7 -0
  129. package/templates/conditional/next/config/static/next.config.mjs +6 -0
  130. package/templates/conditional/next/config/static/next.config.ts +7 -0
  131. package/templates/conditional/next/config/turbopack/next.config.mjs +7 -0
  132. package/templates/conditional/next/config/turbopack/next.config.ts +8 -0
  133. package/templates/conditional/next/config/vercel/next.config.mjs +6 -0
  134. package/templates/conditional/next/config/vercel/next.config.ts +7 -0
  135. package/templates/conditional/next/config/webpack/next.config.mjs +9 -0
  136. package/templates/conditional/next/config/webpack/next.config.ts +10 -0
  137. package/templates/conditional/next/font/BUILD_SIZE_NOTE.md +17 -0
  138. package/templates/conditional/next/font/app-router/src/app/layout.js +25 -0
  139. package/templates/conditional/next/font/app-router/src/app/layout.tsx +30 -0
  140. package/templates/conditional/next/font/pages-router/src/pages/_app.js +20 -0
  141. package/templates/conditional/next/font/pages-router/src/pages/_app.tsx +21 -0
  142. package/templates/conditional/next/font/pages-router/src/pages/_document.js +18 -0
  143. package/templates/conditional/next/font/pages-router/src/pages/_document.tsx +18 -0
  144. package/templates/conditional/next/font/src/app/layout.js +25 -0
  145. package/templates/conditional/next/font/src/app/layout.tsx +30 -0
  146. package/templates/conditional/next/font/src/lib/fonts.js +11 -0
  147. package/templates/conditional/next/font/src/lib/fonts.ts +11 -0
  148. package/templates/conditional/next/font/src/pages/_app.js +20 -0
  149. package/templates/conditional/next/font/src/pages/_app.tsx +21 -0
  150. package/templates/conditional/next/font/src/pages/_document.js +18 -0
  151. package/templates/conditional/next/font/src/pages/_document.tsx +18 -0
  152. package/templates/conditional/next/image/BUILD_SIZE_NOTE.md +15 -0
  153. package/templates/conditional/next/image/app-router/src/components/ImageExample.jsx +34 -0
  154. package/templates/conditional/next/image/app-router/src/components/ImageExample.tsx +44 -0
  155. package/templates/conditional/next/image/pages-router/src/components/ImageExample.jsx +34 -0
  156. package/templates/conditional/next/image/pages-router/src/components/ImageExample.tsx +44 -0
  157. package/templates/conditional/next/image/src/components/ImageExample.jsx +44 -0
  158. package/templates/conditional/next/image/src/components/ImageExample.tsx +54 -0
  159. package/templates/conditional/next/image/src/components/image/index.js +1 -0
  160. package/templates/conditional/next/image/src/components/image/index.ts +2 -0
  161. package/templates/conditional/next/server-components/README.md +13 -0
  162. package/templates/conditional/next/server-components/eslint.config.mjs +47 -0
  163. package/templates/conditional/next/server-components/rules/no-server-imports-in-client.js +89 -0
  164. package/templates/conditional/next/server-components/rules/no-server-imports-in-client.mjs +88 -0
  165. package/templates/conditional/next/server-components/src/components/boundaries/ClientCounter.jsx +48 -0
  166. package/templates/conditional/next/server-components/src/components/boundaries/ClientCounter.tsx +53 -0
  167. package/templates/conditional/next/server-components/src/components/boundaries/ServerCard.jsx +41 -0
  168. package/templates/conditional/next/server-components/src/components/boundaries/ServerCard.tsx +46 -0
  169. package/templates/conditional/next/server-components/src/components/boundaries/index.js +2 -0
  170. package/templates/conditional/next/server-components/src/components/boundaries/index.ts +4 -0
  171. package/templates/conditional/testing/jest/hybrid/src/__tests__/App.test.jsx +11 -0
  172. package/templates/conditional/testing/jest/hybrid/src/__tests__/App.test.tsx +11 -0
  173. package/templates/conditional/testing/jest/none/src/__tests__/App.test.jsx +11 -0
  174. package/templates/conditional/testing/jest/none/src/__tests__/App.test.tsx +11 -0
  175. package/templates/conditional/testing/vitest/hybrid/src/__tests__/App.test.jsx +10 -0
  176. package/templates/conditional/testing/vitest/hybrid/src/__tests__/App.test.tsx +10 -0
  177. package/templates/conditional/testing/vitest/none/src/__tests__/App.test.jsx +10 -0
  178. package/templates/conditional/testing/vitest/none/src/__tests__/App.test.tsx +10 -0
  179. package/templates/css/tailwind/src/globals.css +10 -0
  180. package/templates/css/tailwind/src/themes.css +86 -4
  181. package/templates/ui/shadcn/lib/utils.js +6 -0
  182. package/templates/ui/shadcn/lib/utils.ts +6 -0
  183. package/templates/ui/shadcn/primitives/Button.jsx +48 -0
  184. package/templates/ui/shadcn/primitives/Button.tsx +59 -0
  185. package/templates/ui/shadcn/primitives/Card.jsx +55 -0
  186. package/templates/ui/shadcn/primitives/Card.tsx +73 -0
  187. package/templates/ui/shadcn/primitives/index.js +9 -0
  188. package/templates/ui/shadcn/primitives/index.ts +9 -0
  189. package/templates/css/bootstrap/src/themes.css +0 -14
  190. /package/templates/{css/bootstrap/src/globals.css → architectures/hybrid/src/features/.gitkeep} +0 -0
package/src/readme.js CHANGED
@@ -10,8 +10,6 @@ function buildBuiltWith(responses) {
10
10
 
11
11
  if (responses.cssFramework === "tailwind") {
12
12
  items.push("[Tailwind CSS](https://tailwindcss.com/)");
13
- } else if (responses.cssFramework === "bootstrap") {
14
- items.push("[Bootstrap](https://getbootstrap.com/)");
15
13
  }
16
14
 
17
15
  if (responses.router) {
@@ -119,6 +117,29 @@ ${nestedTree(appChildren)}
119
117
  ${nestedTree(shared)}`;
120
118
  }
121
119
 
120
+ if (responses.architecture === "hybrid") {
121
+ const shared = [
122
+ "components/ # Shared UI components",
123
+ "hooks/ # Shared custom hooks",
124
+ "layouts/ # High-level layout wrappers",
125
+ "stores/ # Global state stores",
126
+ `styles/ # ${responses.cssFramework === "none" ? "main.css (reset) + themes.css (CSS variables)" : "globals.css (framework directives) + themes.css"}`,
127
+ "types/ # Global type definitions",
128
+ "utils/ # Pure utility functions",
129
+ ];
130
+ return `src/
131
+ ├── features/ # Feature modules (domain boundaries)
132
+ └── shared/ # Reusable, business-agnostic resources
133
+ ${nestedTree(shared)}`;
134
+ }
135
+
136
+ if (responses.architecture === "none") {
137
+ return `src/
138
+ ├── App.${responses.language === "ts" ? "tsx" : "jsx"} # Root application component
139
+ ├── main.${responses.language === "ts" ? "tsx" : "jsx"} # Application entry point
140
+ └── styles/ # Stylesheets`;
141
+ }
142
+
122
143
  const rows = ["components/ # Reusable UI components (common, form)"];
123
144
  if (responses.apiClient !== "none") {
124
145
  rows.push("config/ # API configuration (axios/fetch)");
package/src/scaffold.js CHANGED
@@ -1,5 +1,7 @@
1
+ import { promises as fsp } from "fs";
1
2
  import path from "path";
2
3
  import { execa } from "execa";
4
+ import { copyDirRecursive } from "@/utils/fs.js";
3
5
  import { isYarnV1 } from "@/utils/yarn-v1.js";
4
6
 
5
7
  export async function runViteCreate(projectPath, projectName, pkg, language) {
@@ -27,3 +29,18 @@ export async function runBaseInstall(projectPath, pkg) {
27
29
  export async function runGitInit(projectPath) {
28
30
  await execa("git", ["init"], { stdio: "pipe", cwd: projectPath });
29
31
  }
32
+
33
+ export async function scaffoldBase(projectPath, provider, language, templatesDir) {
34
+ if (provider && typeof provider.getFilePlan === "function") {
35
+ const filePlan = provider.getFilePlan({ lang: language });
36
+ const baseDir = path.join(templatesDir, "..", filePlan);
37
+ try {
38
+ await fsp.access(baseDir);
39
+ await copyDirRecursive(baseDir, projectPath);
40
+ return true;
41
+ } catch {
42
+ // Base directory does not exist yet in templates/bases
43
+ }
44
+ }
45
+ return false;
46
+ }
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import App from "./App";
4
+ import "./shared/styles/globals.css";
5
+
6
+ ReactDOM.createRoot(document.getElementById("root")).render(
7
+ <React.StrictMode>
8
+ <App />
9
+ </React.StrictMode>
10
+ );
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import App from "./App";
4
+ import "./shared/styles/globals.css";
5
+
6
+ ReactDOM.createRoot(document.getElementById("root")!).render(
7
+ <React.StrictMode>
8
+ <App />
9
+ </React.StrictMode>
10
+ );
@@ -0,0 +1,20 @@
1
+ import { Button } from "@/shared/components/ui/Button";
2
+
3
+ export default function App() {
4
+ return (
5
+ <div
6
+ style={{
7
+ minHeight: "100vh",
8
+ display: "flex",
9
+ flexDirection: "column",
10
+ alignItems: "center",
11
+ justifyContent: "center",
12
+ backgroundColor: "var(--color-bg, #ffffff)",
13
+ }}
14
+ >
15
+ <h1>Welcome to Lumen</h1>
16
+ <p>Hybrid architecture (src/features + src/shared).</p>
17
+ <Button>Click me</Button>
18
+ </div>
19
+ );
20
+ }
@@ -0,0 +1,20 @@
1
+ import { Button } from "@/shared/components/ui/Button";
2
+
3
+ export default function App() {
4
+ return (
5
+ <div
6
+ style={{
7
+ minHeight: "100vh",
8
+ display: "flex",
9
+ flexDirection: "column",
10
+ alignItems: "center",
11
+ justifyContent: "center",
12
+ backgroundColor: "var(--color-bg, #ffffff)",
13
+ }}
14
+ >
15
+ <h1>Welcome to Lumen</h1>
16
+ <p>Hybrid architecture (src/features + src/shared).</p>
17
+ <Button>Click me</Button>
18
+ </div>
19
+ );
20
+ }
@@ -0,0 +1,31 @@
1
+ export function Button({
2
+ variant = "primary",
3
+ children,
4
+ className,
5
+ ...props
6
+ }) {
7
+ const styles = {
8
+ primary: { backgroundColor: "var(--color-primary)", color: "white" },
9
+ secondary: {
10
+ backgroundColor: "var(--color-border)",
11
+ color: "var(--color-fg)",
12
+ },
13
+ };
14
+
15
+ return (
16
+ <button
17
+ style={{
18
+ padding: "8px 16px",
19
+ borderRadius: "8px",
20
+ fontWeight: 500,
21
+ border: "none",
22
+ cursor: "pointer",
23
+ ...styles[variant],
24
+ }}
25
+ className={className}
26
+ {...props}
27
+ >
28
+ {children}
29
+ </button>
30
+ );
31
+ }
@@ -0,0 +1,36 @@
1
+ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
2
+ variant?: "primary" | "secondary";
3
+ children: React.ReactNode;
4
+ }
5
+
6
+ export function Button({
7
+ variant = "primary",
8
+ children,
9
+ className,
10
+ ...props
11
+ }: ButtonProps) {
12
+ const styles = {
13
+ primary: { backgroundColor: "var(--color-primary)", color: "white" },
14
+ secondary: {
15
+ backgroundColor: "var(--color-border)",
16
+ color: "var(--color-fg)",
17
+ },
18
+ };
19
+
20
+ return (
21
+ <button
22
+ style={{
23
+ padding: "8px 16px",
24
+ borderRadius: "8px",
25
+ fontWeight: 500,
26
+ border: "none",
27
+ cursor: "pointer",
28
+ ...styles[variant],
29
+ }}
30
+ className={className}
31
+ {...props}
32
+ >
33
+ {children}
34
+ </button>
35
+ );
36
+ }
@@ -0,0 +1 @@
1
+ export { Button } from "./Button";
@@ -0,0 +1 @@
1
+ export { Button } from "./Button";
@@ -0,0 +1,28 @@
1
+ import { useState, useCallback } from "react";
2
+
3
+ export function useLocalStorage(key, initialValue) {
4
+ const [storedValue, setStoredValue] = useState(() => {
5
+ try {
6
+ const item = window.localStorage.getItem(key);
7
+ return item ? JSON.parse(item) : initialValue;
8
+ } catch {
9
+ return initialValue;
10
+ }
11
+ });
12
+
13
+ const setValue = useCallback(
14
+ (value) => {
15
+ try {
16
+ const valueToStore =
17
+ value instanceof Function ? value(storedValue) : value;
18
+ setStoredValue(valueToStore);
19
+ window.localStorage.setItem(key, JSON.stringify(valueToStore));
20
+ } catch (error) {
21
+ console.error(error);
22
+ }
23
+ },
24
+ [key, storedValue]
25
+ );
26
+
27
+ return [storedValue, setValue];
28
+ }
@@ -0,0 +1,28 @@
1
+ import { useState, useCallback } from "react";
2
+
3
+ export function useLocalStorage<T>(key: string, initialValue: T) {
4
+ const [storedValue, setStoredValue] = useState<T>(() => {
5
+ try {
6
+ const item = window.localStorage.getItem(key);
7
+ return item ? (JSON.parse(item) as T) : initialValue;
8
+ } catch {
9
+ return initialValue;
10
+ }
11
+ });
12
+
13
+ const setValue = useCallback(
14
+ (value: T | ((prev: T) => T)) => {
15
+ try {
16
+ const valueToStore =
17
+ value instanceof Function ? value(storedValue) : value;
18
+ setStoredValue(valueToStore);
19
+ window.localStorage.setItem(key, JSON.stringify(valueToStore));
20
+ } catch (error) {
21
+ console.error(error);
22
+ }
23
+ },
24
+ [key, storedValue]
25
+ );
26
+
27
+ return [storedValue, setValue] as const;
28
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @typedef {Object} User
3
+ * @property {string} id
4
+ * @property {string} email
5
+ * @property {string} name
6
+ */
7
+
8
+ /**
9
+ * @typedef {Object} ApiResponse
10
+ * @property {*} data
11
+ * @property {string} message
12
+ * @property {boolean} success
13
+ */
14
+
15
+ /**
16
+ * @typedef {Object} CreateUserPayload
17
+ * @property {string} email
18
+ * @property {string} name
19
+ */
20
+ export {};
@@ -0,0 +1,16 @@
1
+ export interface User {
2
+ id: string;
3
+ email: string;
4
+ name: string;
5
+ }
6
+
7
+ export interface ApiResponse<T> {
8
+ data: T;
9
+ message: string;
10
+ success: boolean;
11
+ }
12
+
13
+ export interface CreateUserPayload {
14
+ email: string;
15
+ name: string;
16
+ }
@@ -0,0 +1,3 @@
1
+ export function cn(...inputs) {
2
+ return inputs.filter(Boolean).join(" ");
3
+ }
@@ -0,0 +1,5 @@
1
+ type ClassValue = string | false | null | undefined;
2
+
3
+ export function cn(...inputs: ClassValue[]): string {
4
+ return inputs.filter(Boolean).join(" ");
5
+ }
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import App from "./App";
4
+ import "./styles/globals.css";
5
+
6
+ ReactDOM.createRoot(document.getElementById("root")).render(
7
+ <React.StrictMode>
8
+ <App />
9
+ </React.StrictMode>
10
+ );
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import App from "./App";
4
+ import "./styles/globals.css";
5
+
6
+ ReactDOM.createRoot(document.getElementById("root")!).render(
7
+ <React.StrictMode>
8
+ <App />
9
+ </React.StrictMode>
10
+ );
@@ -0,0 +1,15 @@
1
+ export default function App() {
2
+ return (
3
+ <div
4
+ style={{
5
+ minHeight: "100vh",
6
+ display: "flex",
7
+ alignItems: "center",
8
+ justifyContent: "center",
9
+ backgroundColor: "var(--color-bg, #ffffff)",
10
+ }}
11
+ >
12
+ <h1>Welcome to Lumen</h1>
13
+ </div>
14
+ );
15
+ }
@@ -0,0 +1,15 @@
1
+ export default function App() {
2
+ return (
3
+ <div
4
+ style={{
5
+ minHeight: "100vh",
6
+ display: "flex",
7
+ alignItems: "center",
8
+ justifyContent: "center",
9
+ backgroundColor: "var(--color-bg, #ffffff)",
10
+ }}
11
+ >
12
+ <h1>Welcome to Lumen</h1>
13
+ </div>
14
+ );
15
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @typedef {Object} User
3
+ * @property {string} id
4
+ * @property {string} email
5
+ * @property {string} name
6
+ */
7
+
8
+ /**
9
+ * @typedef {Object} ApiResponse
10
+ * @property {*} data
11
+ * @property {string} message
12
+ * @property {boolean} success
13
+ */
14
+
15
+ /**
16
+ * @typedef {Object} CreateUserPayload
17
+ * @property {string} email
18
+ * @property {string} name
19
+ */
20
+ export {};
@@ -0,0 +1,16 @@
1
+ export interface User {
2
+ id: string;
3
+ email: string;
4
+ name: string;
5
+ }
6
+
7
+ export interface ApiResponse<T> {
8
+ data: T;
9
+ message: string;
10
+ success: boolean;
11
+ }
12
+
13
+ export interface CreateUserPayload {
14
+ email: string;
15
+ name: string;
16
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "cli": "create-next-app",
3
+ "source": "create-next-app",
4
+ "version": "16.3.8",
5
+ "flags": [
6
+ "--js",
7
+ "--app",
8
+ "--src-dir",
9
+ "--import-alias",
10
+ "@/*",
11
+ "--no-tailwind",
12
+ "--no-eslint",
13
+ "--skip-install",
14
+ "--disable-git",
15
+ "--no-agents-md",
16
+ "--no-react-compiler"
17
+ ],
18
+ "date": "2026-10-06"
19
+ }
@@ -0,0 +1,36 @@
1
+ This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
2
+
3
+ ## Getting Started
4
+
5
+ First, run the development server:
6
+
7
+ ```bash
8
+ npm run dev
9
+ # or
10
+ yarn dev
11
+ # or
12
+ pnpm dev
13
+ # or
14
+ bun dev
15
+ ```
16
+
17
+ Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
18
+
19
+ You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file.
20
+
21
+ This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
22
+
23
+ ## Learn More
24
+
25
+ To learn more about Next.js, take a look at the following resources:
26
+
27
+ - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
28
+ - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
29
+
30
+ You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
31
+
32
+ ## Deploy on Vercel
33
+
34
+ The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
35
+
36
+ Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
@@ -0,0 +1,7 @@
1
+ {
2
+ "compilerOptions": {
3
+ "paths": {
4
+ "@/*": ["./src/*"]
5
+ }
6
+ }
7
+ }
@@ -0,0 +1,6 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ /* config options here */
4
+ };
5
+
6
+ export default nextConfig;
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "next-app",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "next dev",
7
+ "build": "next build",
8
+ "start": "next start"
9
+ },
10
+ "dependencies": {
11
+ "next": "^16.0.0",
12
+ "react": "^19.0.0",
13
+ "react-dom": "^19.0.0"
14
+ }
15
+ }
@@ -0,0 +1 @@
1
+ <svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
@@ -0,0 +1 @@
1
+ <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
@@ -0,0 +1 @@
1
+ <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>
@@ -0,0 +1 @@
1
+ <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>
@@ -0,0 +1,5 @@
1
+ import { NextResponse } from "next/server";
2
+
3
+ export async function GET() {
4
+ return NextResponse.json({ hello: "lumen" });
5
+ }
@@ -0,0 +1,33 @@
1
+ import Link from "next/link";
2
+
3
+ export async function generateMetadata({ params }) {
4
+ const resolvedParams = await params;
5
+ const slug = resolvedParams?.slug || "";
6
+ return {
7
+ title: slug,
8
+ };
9
+ }
10
+
11
+ export default async function BlogPost({ params }) {
12
+ const resolvedParams = await params;
13
+ const slug = resolvedParams?.slug || "";
14
+
15
+ return (
16
+ <main
17
+ style={{
18
+ padding: "2rem",
19
+ fontFamily: "var(--font-geist-sans, sans-serif)",
20
+ maxWidth: "800px",
21
+ margin: "0 auto",
22
+ }}
23
+ >
24
+ <h1>{slug}</h1>
25
+ <p style={{ marginTop: "1rem" }}>Post slug: {slug}</p>
26
+ <p style={{ marginTop: "1.5rem" }}>
27
+ <Link href="/" style={{ textDecoration: "underline" }}>
28
+ Back to home
29
+ </Link>
30
+ </p>
31
+ </main>
32
+ );
33
+ }
@@ -0,0 +1,49 @@
1
+ :root {
2
+ --background: #ffffff;
3
+ --foreground: #171717;
4
+ }
5
+
6
+ @media (prefers-color-scheme: dark) {
7
+ :root {
8
+ --background: #0a0a0a;
9
+ --foreground: #ededed;
10
+ }
11
+ }
12
+
13
+ html {
14
+ height: 100%;
15
+ }
16
+
17
+ html,
18
+ body {
19
+ max-width: 100vw;
20
+ overflow-x: hidden;
21
+ }
22
+
23
+ body {
24
+ min-height: 100%;
25
+ display: flex;
26
+ flex-direction: column;
27
+ color: var(--foreground);
28
+ background: var(--background);
29
+ font-family: Arial, Helvetica, sans-serif;
30
+ -webkit-font-smoothing: antialiased;
31
+ -moz-osx-font-smoothing: grayscale;
32
+ }
33
+
34
+ * {
35
+ box-sizing: border-box;
36
+ padding: 0;
37
+ margin: 0;
38
+ }
39
+
40
+ a {
41
+ color: inherit;
42
+ text-decoration: none;
43
+ }
44
+
45
+ @media (prefers-color-scheme: dark) {
46
+ html {
47
+ color-scheme: dark;
48
+ }
49
+ }
@@ -0,0 +1,25 @@
1
+ import { Geist, Geist_Mono } from "next/font/google";
2
+ import "./globals.css";
3
+
4
+ const geistSans = Geist({
5
+ variable: "--font-geist-sans",
6
+ subsets: ["latin"],
7
+ });
8
+
9
+ const geistMono = Geist_Mono({
10
+ variable: "--font-geist-mono",
11
+ subsets: ["latin"],
12
+ });
13
+
14
+ export const metadata = {
15
+ title: "Create Next App",
16
+ description: "Generated by create next app",
17
+ };
18
+
19
+ export default function RootLayout({ children }) {
20
+ return (
21
+ <html lang="en" className={`${geistSans.variable} ${geistMono.variable}`}>
22
+ <body>{children}</body>
23
+ </html>
24
+ );
25
+ }