create-stackkit-app 0.3.0 → 0.4.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 (88) hide show
  1. package/README.md +12 -94
  2. package/dist/index.d.ts +0 -1
  3. package/dist/index.js +0 -1
  4. package/dist/lib/create-project.d.ts +0 -1
  5. package/dist/lib/create-project.js +124 -67
  6. package/dist/lib/template-composer.d.ts +0 -1
  7. package/dist/lib/template-composer.js +0 -2
  8. package/modules/auth/authjs-express/files/lib/auth.ts +40 -0
  9. package/modules/auth/authjs-express/files/routes/auth.ts +12 -0
  10. package/modules/auth/authjs-express/module.json +39 -0
  11. package/modules/auth/authjs-nextjs/files/lib/auth.ts +43 -0
  12. package/modules/auth/authjs-nextjs/module.json +38 -0
  13. package/modules/auth/better-auth-express/files/lib/auth.ts +16 -0
  14. package/modules/auth/better-auth-express/files/routes/auth.ts +12 -0
  15. package/modules/auth/better-auth-express/module.json +38 -0
  16. package/{templates/auth/better-auth-nextjs/app → modules/auth/better-auth-nextjs/files}/api/auth/[...all]/route.ts +1 -0
  17. package/modules/auth/better-auth-nextjs/files/lib/auth.ts +26 -0
  18. package/modules/auth/better-auth-nextjs/module.json +41 -0
  19. package/modules/auth/better-auth-react/files/lib/auth-client.ts +9 -0
  20. package/modules/auth/better-auth-react/module.json +26 -0
  21. package/modules/auth/clerk-express/files/lib/auth.ts +7 -0
  22. package/modules/auth/clerk-express/module.json +19 -0
  23. package/modules/auth/clerk-nextjs/files/lib/auth-provider.tsx +5 -0
  24. package/modules/auth/clerk-nextjs/files/middleware.ts +9 -0
  25. package/modules/auth/clerk-nextjs/module.json +27 -0
  26. package/modules/auth/clerk-react/files/lib/auth-provider.tsx +15 -0
  27. package/modules/auth/clerk-react/module.json +18 -0
  28. package/modules/auth/nextauth/files/app-router/api/auth/[...nextauth]/route.ts +6 -0
  29. package/modules/auth/nextauth/files/lib/auth.ts +82 -0
  30. package/modules/auth/nextauth/files/pages-router/api/auth/[...nextauth].ts +4 -0
  31. package/modules/auth/nextauth/module.json +50 -0
  32. package/modules/database/drizzle-postgresql/files/drizzle.config.ts +10 -0
  33. package/modules/database/drizzle-postgresql/files/lib/db.ts +7 -0
  34. package/modules/database/drizzle-postgresql/files/lib/schema.ts +8 -0
  35. package/modules/database/drizzle-postgresql/module.json +34 -0
  36. package/modules/database/mongoose-mongodb/files/lib/db.ts +40 -0
  37. package/modules/database/mongoose-mongodb/module.json +17 -0
  38. package/{templates/databases/prisma-mongodb → modules/database/prisma-mongodb/files}/lib/db.ts +2 -6
  39. package/{templates/databases/prisma-mongodb → modules/database/prisma-mongodb/files}/prisma/schema.prisma +1 -0
  40. package/modules/database/prisma-mongodb/module.json +36 -0
  41. package/{templates/databases/prisma-postgresql → modules/database/prisma-postgresql/files}/lib/db.ts +2 -6
  42. package/{templates/databases/prisma-postgresql → modules/database/prisma-postgresql/files}/prisma/schema.prisma +1 -0
  43. package/modules/database/prisma-postgresql/module.json +36 -0
  44. package/package.json +7 -5
  45. package/templates/bases/nextjs-base/README.md +36 -0
  46. package/templates/bases/nextjs-base/app/favicon.ico +0 -0
  47. package/templates/bases/nextjs-base/app/globals.css +26 -3
  48. package/templates/bases/nextjs-base/app/layout.tsx +21 -6
  49. package/templates/bases/nextjs-base/app/page.tsx +61 -4
  50. package/templates/bases/nextjs-base/eslint.config.mjs +18 -0
  51. package/templates/bases/nextjs-base/next.config.ts +4 -2
  52. package/templates/bases/nextjs-base/package-lock.json +6538 -0
  53. package/templates/bases/nextjs-base/package.json +12 -10
  54. package/templates/bases/nextjs-base/postcss.config.mjs +7 -0
  55. package/templates/bases/nextjs-base/public/file.svg +1 -0
  56. package/templates/bases/nextjs-base/public/globe.svg +1 -0
  57. package/templates/bases/nextjs-base/public/next.svg +1 -0
  58. package/templates/bases/nextjs-base/public/vercel.svg +1 -0
  59. package/templates/bases/nextjs-base/public/window.svg +1 -0
  60. package/templates/bases/nextjs-base/template.json +12 -1
  61. package/templates/bases/nextjs-base/tsconfig.json +9 -2
  62. package/templates/bases/react-vite-base/index.html +13 -0
  63. package/templates/bases/react-vite-base/package.json +27 -0
  64. package/templates/bases/react-vite-base/src/App.css +14 -0
  65. package/templates/bases/react-vite-base/src/App.tsx +23 -0
  66. package/templates/bases/react-vite-base/src/index.css +68 -0
  67. package/templates/bases/react-vite-base/src/main.tsx +10 -0
  68. package/templates/bases/react-vite-base/src/vite-env.d.ts +1 -0
  69. package/templates/bases/react-vite-base/template.json +5 -0
  70. package/templates/bases/react-vite-base/tsconfig.json +21 -0
  71. package/templates/bases/react-vite-base/vite.config.ts +7 -0
  72. package/dist/index.d.ts.map +0 -1
  73. package/dist/index.js.map +0 -1
  74. package/dist/lib/create-project.d.ts.map +0 -1
  75. package/dist/lib/create-project.js.map +0 -1
  76. package/dist/lib/template-composer.d.ts.map +0 -1
  77. package/dist/lib/template-composer.js.map +0 -1
  78. package/templates/auth/better-auth-express/config.json +0 -18
  79. package/templates/auth/better-auth-express/src/lib/auth.ts +0 -12
  80. package/templates/auth/better-auth-express/src/routes/auth.ts +0 -10
  81. package/templates/auth/better-auth-nextjs/config.json +0 -18
  82. package/templates/auth/better-auth-nextjs/lib/auth.ts +0 -14
  83. package/templates/auth/nextauth/config.json +0 -18
  84. package/templates/auth/nextauth/lib/auth.ts +0 -31
  85. package/templates/bases/nextjs-base/.eslintrc.json +0 -3
  86. package/templates/databases/prisma-mongodb/config.json +0 -21
  87. package/templates/databases/prisma-postgresql/config.json +0 -22
  88. /package/{templates/auth/nextauth/app → modules/auth/authjs-nextjs/files}/api/auth/[...nextauth]/route.ts +0 -0
package/README.md CHANGED
@@ -1,107 +1,25 @@
1
1
  # create-stackkit-app
2
2
 
3
- Production-ready project generator with interactive wizard setup.
4
-
5
- [![npm](https://img.shields.io/npm/v/create-stackkit-app)](https://www.npmjs.com/package/create-stackkit-app)
3
+ Create production-ready projects with one command.
6
4
 
7
5
  ## Usage
8
6
 
9
7
  ```bash
10
- # npm
11
- npx create-stackkit-app@latest my-app
12
-
13
- # pnpm
14
- pnpm dlx create-stackkit-app@latest my-app
15
-
16
- # yarn
17
- yarn dlx create-stackkit-app@latest my-app
18
-
19
- # bun
20
- bunx create-stackkit-app@latest my-app
21
- ```
22
-
23
- ## Interactive Wizard
24
-
25
- The wizard guides you through project setup:
26
-
27
- 1. **Framework Selection**
28
- - Next.js
29
- - Express.js
30
- - React (Vite)
31
- - Astro
32
-
33
- 2. **Database/ORM**
34
- - Prisma + PostgreSQL
35
- - Prisma + MongoDB
36
- - Mongoose + MongoDB
37
- - Drizzle + PostgreSQL
38
- - None
39
-
40
- 3. **Authentication**
41
- - Auth.js (NextAuth)
42
- - Better Auth
43
- - Clerk
44
- - None
45
-
46
- 4. **Language**
47
- - TypeScript *(recommended)*
48
- - JavaScript
49
-
50
- 5. **Package Manager**
51
- - pnpm *(recommended)*
52
- - npm
53
- - yarn
54
-
55
- ## Automatic Setup
56
-
57
- After answering questions, the tool automatically:
58
-
59
- ✅ Creates project files
60
- ✅ Installs dependencies
61
- ✅ Initializes git repository
62
-
63
- No manual `npm install` or `git init` needed.
64
-
65
- ## What's Included
66
-
67
- Default Next.js + Prisma + PostgreSQL template:
68
-
69
- - ⚡ Next.js 15 with App Router
70
- - 🛡️ TypeScript
71
- - 🗄️ Prisma ORM + PostgreSQL
72
- - 🎨 shadcn/ui components
73
- - 💅 Tailwind CSS
74
- - ✅ Zod validation
75
- - 🔧 ESLint + Prettier
76
-
77
- ## Next Steps
78
-
79
- After creating your project:
80
-
81
- ```bash
82
- cd my-app
83
- pnpm dev
8
+ npx create-stackkit-app my-app
84
9
  ```
85
10
 
86
- Add modules to existing projects:
11
+ Interactive wizard for:
12
+ - **Framework**: Next.js, Express, React (Vite)
13
+ - **Database**: Prisma, Drizzle, Mongoose, or none
14
+ - **Auth**: Auth.js, Better Auth, Clerk, or none
15
+ - **Language**: TypeScript or JavaScript
87
16
 
88
- ```bash
89
- npx stackkit-cli add auth
90
- ```
91
-
92
- ## Full CLI
93
-
94
- For advanced features:
17
+ ## Development
95
18
 
96
19
  ```bash
97
- npm install -g stackkit-cli
98
-
99
- stackkit list # View all templates/modules
100
- stackkit add auth
20
+ pnpm install
21
+ pnpm build
22
+ npx . test-app
101
23
  ```
102
24
 
103
- See [stackkit-cli](https://www.npmjs.com/package/stackkit-cli) for details.
104
-
105
- ## License
106
-
107
- MIT
25
+ See [main README](../../README.md) for full documentation.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,2 @@
1
1
  #!/usr/bin/env node
2
2
  export {};
3
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -14,4 +14,3 @@ async function main() {
14
14
  }
15
15
  }
16
16
  main();
17
- //# sourceMappingURL=index.js.map
@@ -1,2 +1 @@
1
1
  export declare function createProject(projectName?: string): Promise<void>;
2
- //# sourceMappingURL=create-project.d.ts.map
@@ -54,13 +54,13 @@ async function getProjectConfig(projectName) {
54
54
  { name: 'Next.js', value: 'nextjs' },
55
55
  { name: 'Express.js', value: 'express' },
56
56
  { name: 'React (Vite)', value: 'react-vite' },
57
- { name: 'Astro', value: 'astro' },
58
57
  ],
59
58
  },
60
59
  {
61
60
  type: 'list',
62
61
  name: 'database',
63
62
  message: 'Select database/ORM:',
63
+ when: (answers) => answers.framework !== 'react-vite',
64
64
  choices: [
65
65
  { name: 'Prisma + PostgreSQL', value: 'prisma-postgresql' },
66
66
  { name: 'Prisma + MongoDB', value: 'prisma-mongodb' },
@@ -74,22 +74,34 @@ async function getProjectConfig(projectName) {
74
74
  name: 'auth',
75
75
  message: 'Select authentication:',
76
76
  choices: (answers) => {
77
- const baseChoices = [
78
- { name: 'Auth.js (NextAuth)', value: 'nextauth' },
79
- { name: 'Better Auth', value: 'better-auth' },
80
- { name: 'Clerk', value: 'clerk' },
81
- { name: 'None', value: 'none' },
82
- ];
83
- // Filter choices based on framework compatibility
84
- if (answers.framework === 'nextjs') {
85
- return baseChoices;
77
+ if (answers.framework === 'react-vite') {
78
+ return [
79
+ { name: 'Better Auth', value: 'better-auth-react' },
80
+ { name: 'Clerk', value: 'clerk-react' },
81
+ { name: 'None', value: 'none' },
82
+ ];
86
83
  }
87
- else if (answers.framework === 'express') {
88
- return baseChoices.filter((c) => ['better-auth', 'none'].includes(c.value));
84
+ // Next.js apps
85
+ if (answers.framework === 'nextjs') {
86
+ return [
87
+ { name: 'Auth.js v5', value: 'authjs-nextjs' },
88
+ { name: 'NextAuth.js', value: 'nextauth' },
89
+ { name: 'Better Auth', value: 'better-auth-nextjs' },
90
+ { name: 'Clerk', value: 'clerk-nextjs' },
91
+ { name: 'None', value: 'none' },
92
+ ];
89
93
  }
90
- else {
91
- return [{ name: 'None', value: 'none' }];
94
+ // Express apps
95
+ if (answers.framework === 'express') {
96
+ return [
97
+ { name: 'Auth.js', value: 'authjs-express' },
98
+ { name: 'Better Auth', value: 'better-auth-express' },
99
+ { name: 'Clerk', value: 'clerk-express' },
100
+ { name: 'None', value: 'none' },
101
+ ];
92
102
  }
103
+ // Default - no auth
104
+ return [{ name: 'None', value: 'none' }];
93
105
  },
94
106
  },
95
107
  {
@@ -113,7 +125,7 @@ async function getProjectConfig(projectName) {
113
125
  return {
114
126
  projectName: projectName || answers.projectName,
115
127
  framework: answers.framework,
116
- database: answers.database,
128
+ database: answers.framework === 'react-vite' ? 'none' : answers.database,
117
129
  auth: answers.auth,
118
130
  language: answers.language,
119
131
  packageManager: answers.packageManager,
@@ -189,73 +201,119 @@ async function copyBaseFramework(templatesDir, targetDir, framework) {
189
201
  });
190
202
  }
191
203
  async function mergeDatabaseConfig(templatesDir, targetDir, database) {
192
- const dbDir = path_1.default.join(templatesDir, 'databases', database);
193
- if (!(await fs_extra_1.default.pathExists(dbDir))) {
194
- console.warn(`Database template not found: ${database}`);
204
+ // Use modules directory (sibling to templates)
205
+ const modulesDir = path_1.default.join(templatesDir, '..', 'modules');
206
+ const dbModulePath = path_1.default.join(modulesDir, 'database', database);
207
+ if (!(await fs_extra_1.default.pathExists(dbModulePath))) {
208
+ console.warn(`Database module not found: ${database}`);
195
209
  return;
196
210
  }
197
- // Read config
198
- const configPath = path_1.default.join(dbDir, 'config.json');
199
- if (!(await fs_extra_1.default.pathExists(configPath))) {
211
+ // Read module.json
212
+ const moduleJsonPath = path_1.default.join(dbModulePath, 'module.json');
213
+ if (!(await fs_extra_1.default.pathExists(moduleJsonPath))) {
200
214
  return;
201
215
  }
202
- const config = await fs_extra_1.default.readJson(configPath);
203
- // Copy database files
204
- const entries = await fs_extra_1.default.readdir(dbDir, { withFileTypes: true });
205
- for (const entry of entries) {
206
- if (entry.name === 'config.json')
207
- continue;
208
- const sourcePath = path_1.default.join(dbDir, entry.name);
209
- const destPath = path_1.default.join(targetDir, entry.name);
210
- if (entry.isDirectory()) {
211
- await fs_extra_1.default.copy(sourcePath, destPath, { overwrite: false });
212
- }
213
- else {
214
- await fs_extra_1.default.copy(sourcePath, destPath, { overwrite: false });
216
+ const moduleData = await fs_extra_1.default.readJson(moduleJsonPath);
217
+ // Copy files from module
218
+ const filesDir = path_1.default.join(dbModulePath, 'files');
219
+ if (await fs_extra_1.default.pathExists(filesDir)) {
220
+ // Copy files based on patches in module.json
221
+ for (const patch of moduleData.patches || []) {
222
+ if (patch.type === 'create-file') {
223
+ const sourceFile = path_1.default.join(filesDir, patch.source);
224
+ let destFile = path_1.default.join(targetDir, patch.destination);
225
+ // Simple placeholder replacement for lib
226
+ destFile = destFile.replace('{{lib}}', 'lib').replace('{{src}}', 'src');
227
+ if (await fs_extra_1.default.pathExists(sourceFile)) {
228
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(destFile));
229
+ await fs_extra_1.default.copy(sourceFile, destFile, { overwrite: false });
230
+ }
231
+ }
215
232
  }
216
233
  }
217
- // Merge package.json
218
- await mergePackageJson(targetDir, config);
219
- // Merge .env
220
- await mergeEnvFile(targetDir, config.env || {});
234
+ // Merge package.json with module dependencies
235
+ await mergePackageJson(targetDir, {
236
+ dependencies: moduleData.dependencies,
237
+ devDependencies: moduleData.devDependencies,
238
+ });
239
+ // Merge .env with module envVars
240
+ const envVars = {};
241
+ for (const envVar of moduleData.envVars || []) {
242
+ envVars[envVar.key] = envVar.value;
243
+ }
244
+ await mergeEnvFile(targetDir, envVars);
221
245
  }
222
246
  async function mergeAuthConfig(templatesDir, targetDir, framework, auth) {
223
- // Map auth selection to template directory
247
+ // Use modules directory (sibling to templates)
248
+ const modulesDir = path_1.default.join(templatesDir, '..', 'modules');
249
+ // Auth modules are now named with framework suffix
250
+ // e.g., better-auth-nextjs, authjs-express, better-auth-react
251
+ // If auth already has framework suffix, use it directly
252
+ // Otherwise, map old names to new ones
224
253
  const authMap = {
225
- 'nextjs-nextauth': 'nextauth',
226
- 'nextjs-better-auth': 'better-auth-nextjs',
227
- 'express-better-auth': 'better-auth-express',
254
+ nextauth: 'nextauth',
255
+ 'better-auth': framework === 'nextjs' ? 'better-auth-nextjs' : 'better-auth-express',
256
+ clerk: framework === 'nextjs'
257
+ ? 'clerk-nextjs'
258
+ : framework === 'react-vite'
259
+ ? 'clerk-react'
260
+ : 'clerk-express',
228
261
  };
229
- const authKey = authMap[`${framework}-${auth}`] || auth;
230
- const authDir = path_1.default.join(templatesDir, 'auth', authKey);
231
- if (!(await fs_extra_1.default.pathExists(authDir))) {
232
- console.warn(`Auth template not found: ${authKey}`);
262
+ const authKey = auth.includes('-') ? auth : authMap[auth] || auth;
263
+ const authModulePath = path_1.default.join(modulesDir, 'auth', authKey);
264
+ if (!(await fs_extra_1.default.pathExists(authModulePath))) {
265
+ console.warn(`Auth module not found: ${authKey}`);
233
266
  return;
234
267
  }
235
- // Read config
236
- const configPath = path_1.default.join(authDir, 'config.json');
237
- if (!(await fs_extra_1.default.pathExists(configPath))) {
268
+ // Read module.json
269
+ const moduleJsonPath = path_1.default.join(authModulePath, 'module.json');
270
+ if (!(await fs_extra_1.default.pathExists(moduleJsonPath))) {
238
271
  return;
239
272
  }
240
- const config = await fs_extra_1.default.readJson(configPath);
241
- // Copy auth files
242
- const entries = await fs_extra_1.default.readdir(authDir, { withFileTypes: true });
243
- for (const entry of entries) {
244
- if (entry.name === 'config.json')
245
- continue;
246
- const sourcePath = path_1.default.join(authDir, entry.name);
247
- const destPath = path_1.default.join(targetDir, entry.name);
248
- if (entry.isDirectory()) {
249
- await fs_extra_1.default.copy(sourcePath, destPath, { overwrite: false });
250
- }
251
- else {
252
- await fs_extra_1.default.copy(sourcePath, destPath, { overwrite: false });
273
+ const moduleData = await fs_extra_1.default.readJson(moduleJsonPath);
274
+ // Copy files from module
275
+ const filesDir = path_1.default.join(authModulePath, 'files');
276
+ if (await fs_extra_1.default.pathExists(filesDir)) {
277
+ // Determine path replacements based on framework
278
+ const getReplacements = () => {
279
+ if (framework === 'nextjs') {
280
+ return { lib: 'lib', router: 'app' };
281
+ }
282
+ else if (framework === 'express') {
283
+ return { lib: 'src', router: 'src' };
284
+ }
285
+ else {
286
+ return { lib: 'src', router: 'src' };
287
+ }
288
+ };
289
+ const replacements = getReplacements();
290
+ // Copy files based on patches in module.json
291
+ for (const patch of moduleData.patches || []) {
292
+ if (patch.type === 'create-file') {
293
+ const sourceFile = path_1.default.join(filesDir, patch.source);
294
+ let destFile = path_1.default.join(targetDir, patch.destination);
295
+ // Replace placeholders
296
+ destFile = destFile
297
+ .replace('{{lib}}', replacements.lib)
298
+ .replace('{{router}}', replacements.router);
299
+ if (await fs_extra_1.default.pathExists(sourceFile)) {
300
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(destFile));
301
+ await fs_extra_1.default.copy(sourceFile, destFile, { overwrite: false });
302
+ }
303
+ }
253
304
  }
254
305
  }
255
- // Merge package.json
256
- await mergePackageJson(targetDir, config);
257
- // Merge .env
258
- await mergeEnvFile(targetDir, config.env || {});
306
+ // Merge package.json with module dependencies
307
+ await mergePackageJson(targetDir, {
308
+ dependencies: moduleData.dependencies,
309
+ devDependencies: moduleData.devDependencies,
310
+ });
311
+ // Merge .env with module envVars
312
+ const envVars = {};
313
+ for (const envVar of moduleData.envVars || []) {
314
+ envVars[envVar.key] = envVar.value;
315
+ }
316
+ await mergeEnvFile(targetDir, envVars);
259
317
  }
260
318
  async function mergePackageJson(targetDir, config) {
261
319
  const pkgPath = path_1.default.join(targetDir, 'package.json');
@@ -377,4 +435,3 @@ function showNextSteps(config) {
377
435
  console.log(chalk_1.default.cyan(` cd ${config.projectName}`));
378
436
  console.log(chalk_1.default.cyan(` ${config.packageManager}${config.packageManager === 'npm' ? ' run' : ''} dev\n`));
379
437
  }
380
- //# sourceMappingURL=create-project.js.map
@@ -14,4 +14,3 @@ export declare class TemplateComposer {
14
14
  private writeEnvFile;
15
15
  private getAuthKey;
16
16
  }
17
- //# sourceMappingURL=template-composer.d.ts.map
@@ -7,7 +7,6 @@ exports.TemplateComposer = void 0;
7
7
  const fs_extra_1 = __importDefault(require("fs-extra"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  class TemplateComposer {
10
- templatesDir;
11
10
  constructor(templatesDir) {
12
11
  this.templatesDir = templatesDir;
13
12
  }
@@ -196,4 +195,3 @@ class TemplateComposer {
196
195
  }
197
196
  }
198
197
  exports.TemplateComposer = TemplateComposer;
199
- //# sourceMappingURL=template-composer.js.map
@@ -0,0 +1,40 @@
1
+ import Credentials from '@auth/core/providers/credentials';
2
+
3
+ export const authConfig = {
4
+ secret: process.env.AUTH_SECRET,
5
+ trustHost: true,
6
+ providers: [
7
+ // GitHub OAuth Provider
8
+ // Uncomment and add GITHUB_ID and GITHUB_SECRET to .env
9
+ // GitHub({
10
+ // clientId: process.env.GITHUB_ID!,
11
+ // clientSecret: process.env.GITHUB_SECRET!,
12
+ // }),
13
+
14
+ // Google OAuth Provider
15
+ // Uncomment and add GOOGLE_ID and GOOGLE_SECRET to .env
16
+ // Google({
17
+ // clientId: process.env.GOOGLE_ID!,
18
+ // clientSecret: process.env.GOOGLE_SECRET!,
19
+ // }),
20
+
21
+ // Credentials Provider (email/password)
22
+ Credentials({
23
+ credentials: {
24
+ email: { label: 'Email', type: 'email' },
25
+ password: { label: 'Password', type: 'password' },
26
+ },
27
+ authorize: async (credentials) => {
28
+ // Add your own authentication logic here
29
+ if (credentials?.email === 'demo@example.com' && credentials?.password === 'demo') {
30
+ return {
31
+ id: '1',
32
+ name: 'Demo User',
33
+ email: 'demo@example.com',
34
+ };
35
+ }
36
+ return null;
37
+ },
38
+ }),
39
+ ],
40
+ };
@@ -0,0 +1,12 @@
1
+ import { Auth } from '@auth/core';
2
+ import { Router } from 'express';
3
+ import { authConfig } from '../lib/auth';
4
+
5
+ const router = Router();
6
+
7
+ router.all('/auth/*', async (req, res) => {
8
+ const response = await Auth(req, authConfig);
9
+ return res.status(response.status).json(response.body);
10
+ });
11
+
12
+ export default router;
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "auth",
3
+ "displayName": "Auth.js (Express)",
4
+ "description": "Authentication with Auth.js for Express",
5
+ "category": "auth",
6
+ "supportedFrameworks": ["express"],
7
+ "dependencies": {
8
+ "@auth/express": "^0.7.6",
9
+ "@auth/core": "^0.37.4"
10
+ },
11
+ "envVars": [
12
+ {
13
+ "key": "AUTH_SECRET",
14
+ "value": "",
15
+ "description": "Secret for encrypting tokens. Generate with: openssl rand -base64 32",
16
+ "required": true
17
+ },
18
+ {
19
+ "key": "AUTH_TRUST_HOST",
20
+ "value": "true",
21
+ "description": "Trust the host header (required for Express)",
22
+ "required": true
23
+ }
24
+ ],
25
+ "patches": [
26
+ {
27
+ "type": "create-file",
28
+ "description": "Create Auth.js configuration",
29
+ "source": "lib/auth.ts",
30
+ "destination": "src/lib/auth.ts"
31
+ },
32
+ {
33
+ "type": "create-file",
34
+ "description": "Create auth routes",
35
+ "source": "routes/auth.ts",
36
+ "destination": "src/routes/auth.ts"
37
+ }
38
+ ]
39
+ }
@@ -0,0 +1,43 @@
1
+ import NextAuth from 'next-auth';
2
+ import Credentials from 'next-auth/providers/credentials';
3
+
4
+ export const { handlers, signIn, signOut, auth } = NextAuth({
5
+ providers: [
6
+ // GitHub OAuth Provider
7
+ // Uncomment and add GITHUB_ID and GITHUB_SECRET to .env
8
+ // GitHub({
9
+ // clientId: process.env.GITHUB_ID!,
10
+ // clientSecret: process.env.GITHUB_SECRET!,
11
+ // }),
12
+
13
+ // Google OAuth Provider
14
+ // Uncomment and add GOOGLE_ID and GOOGLE_SECRET to .env
15
+ // Google({
16
+ // clientId: process.env.GOOGLE_ID!,
17
+ // clientSecret: process.env.GOOGLE_SECRET!,
18
+ // }),
19
+
20
+ // Credentials Provider (email/password)
21
+ Credentials({
22
+ credentials: {
23
+ email: { label: 'Email', type: 'email' },
24
+ password: { label: 'Password', type: 'password' },
25
+ },
26
+ authorize: async (credentials) => {
27
+ // Add your own authentication logic here
28
+ // This is just a demo - DO NOT use in production
29
+ if (credentials?.email === 'demo@example.com' && credentials?.password === 'demo') {
30
+ return {
31
+ id: '1',
32
+ name: 'Demo User',
33
+ email: 'demo@example.com',
34
+ };
35
+ }
36
+ return null;
37
+ },
38
+ }),
39
+ ],
40
+ pages: {
41
+ signIn: '/auth/signin',
42
+ },
43
+ });
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "auth",
3
+ "displayName": "Auth.js v5 (Next.js)",
4
+ "description": "Modern authentication with Auth.js v5 (NextAuth successor)",
5
+ "category": "auth",
6
+ "supportedFrameworks": ["nextjs"],
7
+ "dependencies": {
8
+ "next-auth": "^5.0.0-beta.25"
9
+ },
10
+ "envVars": [
11
+ {
12
+ "key": "AUTH_SECRET",
13
+ "value": "",
14
+ "description": "Secret for encrypting tokens. Generate with: openssl rand -base64 32",
15
+ "required": true
16
+ },
17
+ {
18
+ "key": "AUTH_URL",
19
+ "value": "http://localhost:3000",
20
+ "description": "Canonical URL of your site (change in production)",
21
+ "required": false
22
+ }
23
+ ],
24
+ "patches": [
25
+ {
26
+ "type": "create-file",
27
+ "description": "Create Auth.js configuration",
28
+ "source": "lib/auth.ts",
29
+ "destination": "{{lib}}/auth.ts"
30
+ },
31
+ {
32
+ "type": "create-file",
33
+ "description": "Create Auth.js API route",
34
+ "source": "api/auth/[...nextauth]/route.ts",
35
+ "destination": "{{router}}/api/auth/[...nextauth]/route.ts"
36
+ }
37
+ ]
38
+ }
@@ -0,0 +1,16 @@
1
+ import { betterAuth } from 'better-auth';
2
+
3
+ export const auth = betterAuth({
4
+ secret: process.env.BETTER_AUTH_SECRET!,
5
+ baseURL: process.env.BETTER_AUTH_URL!,
6
+
7
+ emailAndPassword: {
8
+ enabled: true,
9
+ },
10
+
11
+ // Uncomment to add database adapter
12
+ // database: {
13
+ // provider: "pg", // or "mongodb", "mysql"
14
+ // url: process.env.DATABASE_URL!,
15
+ // },
16
+ });
@@ -0,0 +1,12 @@
1
+ import { Router } from 'express';
2
+ import { auth } from '../lib/auth';
3
+
4
+ const router = Router();
5
+
6
+ // Mount Better Auth handlers
7
+ router.all('/auth/*', async (req, res) => {
8
+ const response = await auth.handler(req);
9
+ return res.status(response.status).json(response.body);
10
+ });
11
+
12
+ export default router;
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "auth",
3
+ "displayName": "Better Auth (Express)",
4
+ "description": "Modern authentication with Better Auth for Express",
5
+ "category": "auth",
6
+ "supportedFrameworks": ["express"],
7
+ "dependencies": {
8
+ "better-auth": "^1.0.0"
9
+ },
10
+ "envVars": [
11
+ {
12
+ "key": "BETTER_AUTH_SECRET",
13
+ "value": "",
14
+ "description": "Secret key for Better Auth. Generate with: openssl rand -base64 32",
15
+ "required": true
16
+ },
17
+ {
18
+ "key": "BETTER_AUTH_URL",
19
+ "value": "http://localhost:3000",
20
+ "description": "Base URL of your application (change in production)",
21
+ "required": true
22
+ }
23
+ ],
24
+ "patches": [
25
+ {
26
+ "type": "create-file",
27
+ "description": "Create Better Auth configuration",
28
+ "source": "lib/auth.ts",
29
+ "destination": "src/lib/auth.ts"
30
+ },
31
+ {
32
+ "type": "create-file",
33
+ "description": "Create auth routes",
34
+ "source": "routes/auth.ts",
35
+ "destination": "src/routes/auth.ts"
36
+ }
37
+ ]
38
+ }
@@ -2,3 +2,4 @@ import { auth } from '@/lib/auth';
2
2
  import { toNextJsHandler } from 'better-auth/next-js';
3
3
 
4
4
  export const { GET, POST } = toNextJsHandler(auth);
5
+