initkit 1.1.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.
@@ -0,0 +1,1236 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import ora from 'ora';
4
+ import chalk from 'chalk';
5
+ import { getLatestVersion } from '../utils/versionFetcher.js';
6
+ import { generateNextjsTemplate } from './nextjs.js';
7
+ import { generateReactTemplate } from './react.js';
8
+ import { generateExpressTemplate } from './express.js';
9
+
10
+ async function fetchVersion(packageName, fallback = 'latest') {
11
+ try {
12
+ const version = await getLatestVersion(packageName);
13
+ return `^${version}`;
14
+ } catch {
15
+ return fallback;
16
+ }
17
+ }
18
+
19
+ /**
20
+ * Generate Full-Stack project with integrated frontend and backend
21
+ *
22
+ * Creates a complete full-stack application supporting:
23
+ * - **Monorepo Structure**: Turborepo with apps/ and packages/ workspaces
24
+ * - **Traditional Structure**: Separate client/ and server/ directories
25
+ * - **Popular Stacks**: MERN, PERN, T3 Stack, Next.js + Express, etc.
26
+ * - **Shared Packages**: Common types, UI components, utilities
27
+ * - **API Integration**: Pre-configured frontend-backend communication
28
+ * - **Database Setup**: Models, migrations, seeders
29
+ * - **Docker Compose**: Complete orchestration for all services
30
+ *
31
+ * Generated project includes:
32
+ * - Frontend application (React, Next.js, Vue, etc.)
33
+ * - Backend API (Express, NestJS, etc.)
34
+ * - Shared TypeScript types package
35
+ * - UI components library (optional)
36
+ * - Root configuration (Turborepo, Docker Compose, etc.)
37
+ * - Environment configuration for all services
38
+ * - Comprehensive README with setup instructions
39
+ *
40
+ * @param {string} projectPath - Absolute path to the project directory
41
+ * @param {Object} config - User configuration object
42
+ * @param {string} config.projectName - Name of the project
43
+ * @param {string} config.language - Programming language ('typescript'|'javascript')
44
+ * @param {string} config.fullstackType - Project structure type
45
+ * - 'monorepo': Turborepo with workspaces (recommended for large projects)
46
+ * - 'traditional': Separate client/ and server/ folders
47
+ * @param {string} config.stack - Technology stack selection
48
+ * - 'MERN': MongoDB + Express + React + Node.js
49
+ * - 'PERN': PostgreSQL + Express + React + Node.js
50
+ * - 'T3': Next.js + tRPC + Prisma + NextAuth
51
+ * - 'Next.js + Express': Next.js frontend with Express backend
52
+ * - 'Vue + Express': Vue.js frontend with Express backend
53
+ * @param {string} [config.frontend] - Frontend framework (derived from stack)
54
+ * @param {string} [config.backend] - Backend framework (derived from stack)
55
+ * @param {string} [config.database] - Database choice (derived from stack)
56
+ * @param {string} config.packageManager - Package manager to use
57
+ *
58
+ * @returns {Promise<void>}
59
+ *
60
+ * @example
61
+ * // Create MERN stack monorepo with Turborepo
62
+ * await generateFullStackTemplate('/path/to/project', {
63
+ * projectName: 'my-fullstack-app',
64
+ * language: 'typescript',
65
+ * fullstackType: 'monorepo',
66
+ * stack: 'MERN',
67
+ * packageManager: 'pnpm'
68
+ * });
69
+ *
70
+ * @example
71
+ * // Create T3 Stack (Next.js + tRPC + Prisma)
72
+ * await generateFullStackTemplate('/path/to/project', {
73
+ * projectName: 'my-t3-app',
74
+ * language: 'typescript',
75
+ * fullstackType: 'monorepo',
76
+ * stack: 'T3',
77
+ * packageManager: 'pnpm'
78
+ * });
79
+ */
80
+ export async function generateFullStackTemplate(projectPath, config) {
81
+ const { fullstackType, stack } = config;
82
+
83
+ if (fullstackType === 'monorepo') {
84
+ await generateMonorepoStructure(projectPath, config);
85
+ } else {
86
+ await generateTraditionalFullStack(projectPath, config);
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Generate Monorepo Structure with Turborepo
92
+ */
93
+ async function generateMonorepoStructure(projectPath, config) {
94
+ const { stack } = config;
95
+
96
+ // Create monorepo folder structure
97
+ await fs.ensureDir(path.join(projectPath, 'apps', 'frontend'));
98
+ await fs.ensureDir(path.join(projectPath, 'apps', 'backend'));
99
+ await fs.ensureDir(path.join(projectPath, 'packages', 'shared-types'));
100
+ await fs.ensureDir(path.join(projectPath, 'packages', 'ui-components'));
101
+
102
+ // Generate root package.json with workspaces
103
+ await fs.writeFile(
104
+ path.join(projectPath, 'package.json'),
105
+ await generateMonorepoPackageJson(config)
106
+ );
107
+
108
+ // Generate turbo.json
109
+ await fs.writeFile(path.join(projectPath, 'turbo.json'), generateTurboConfig());
110
+
111
+ // Generate frontend in apps/frontend
112
+ const frontendPath = path.join(projectPath, 'apps', 'frontend');
113
+ const frontendConfig = {
114
+ ...config,
115
+ projectName: 'frontend',
116
+ frontend: stack.includes('Next.js') ? 'nextjs' : 'react',
117
+ };
118
+
119
+ if (stack.includes('Next.js')) {
120
+ await generateNextjsTemplate(frontendPath, frontendConfig);
121
+ } else {
122
+ await generateReactTemplate(frontendPath, frontendConfig);
123
+ }
124
+
125
+ // Generate backend in apps/backend
126
+ const backendPath = path.join(projectPath, 'apps', 'backend');
127
+ const backendConfig = {
128
+ ...config,
129
+ projectName: 'backend',
130
+ backend: 'express',
131
+ database: stack.includes('MongoDB')
132
+ ? 'mongodb'
133
+ : stack.includes('PostgreSQL')
134
+ ? 'prisma'
135
+ : 'none',
136
+ };
137
+ await generateExpressTemplate(backendPath, backendConfig);
138
+
139
+ // Generate shared packages
140
+ await generateSharedTypes(path.join(projectPath, 'packages', 'shared-types'));
141
+ await generateUIComponents(path.join(projectPath, 'packages', 'ui-components'), config);
142
+
143
+ // Generate root-level configs
144
+ await generateMonorepoRootFiles(projectPath, config);
145
+
146
+ // Generate Docker setup for monorepo
147
+ await generateMonorepoDockerSetup(projectPath, config);
148
+
149
+ // Generate README
150
+ await generateMonorepoReadme(projectPath, config);
151
+ }
152
+
153
+ /**
154
+ * Generate Traditional Full-Stack Structure
155
+ */
156
+ async function generateTraditionalFullStack(projectPath, config) {
157
+ const { stack } = config;
158
+
159
+ if (stack === 'MERN') {
160
+ await generateMERNStack(projectPath, config);
161
+ } else if (stack === 'PERN') {
162
+ await generatePERNStack(projectPath, config);
163
+ } else if (stack === 'Next.js + Express') {
164
+ await generateNextExpressStack(projectPath, config);
165
+ } else if (stack === 'Laravel + React') {
166
+ await generateLaravelReactStack(projectPath, config);
167
+ }
168
+ }
169
+
170
+ /**
171
+ * MERN Stack (MongoDB, Express, React, Node)
172
+ */
173
+ async function generateMERNStack(projectPath, config) {
174
+ // Create folder structure
175
+ await fs.ensureDir(path.join(projectPath, 'client'));
176
+ await fs.ensureDir(path.join(projectPath, 'server'));
177
+
178
+ // Generate React frontend in client/
179
+ const clientConfig = {
180
+ ...config,
181
+ projectName: 'client',
182
+ frontend: 'react',
183
+ additionalLibraries: ['react-router', 'axios'],
184
+ };
185
+ await generateReactTemplate(path.join(projectPath, 'client'), clientConfig);
186
+
187
+ // Generate Express backend in server/
188
+ const serverConfig = {
189
+ ...config,
190
+ projectName: 'server',
191
+ backend: 'express',
192
+ database: 'mongodb',
193
+ folderStructure: 'mvc',
194
+ };
195
+ await generateExpressTemplate(path.join(projectPath, 'server'), serverConfig);
196
+
197
+ // Generate root package.json
198
+ await fs.writeFile(
199
+ path.join(projectPath, 'package.json'),
200
+ await generateRootPackageJson(config, 'MERN')
201
+ );
202
+
203
+ // Generate Docker setup
204
+ await generateDockerSetup(projectPath, config, 'MERN');
205
+
206
+ // Generate API proxy config
207
+ await generateAPIConfig(projectPath, config, 'MERN');
208
+
209
+ // Generate environment files
210
+ await generateFullStackEnv(projectPath, config, 'MERN');
211
+
212
+ // Generate README
213
+ await generateFullStackReadme(projectPath, config, 'MERN');
214
+ }
215
+
216
+ /**
217
+ * PERN Stack (PostgreSQL, Express, React, Node)
218
+ */
219
+ async function generatePERNStack(projectPath, config) {
220
+ // Create folder structure
221
+ await fs.ensureDir(path.join(projectPath, 'client'));
222
+ await fs.ensureDir(path.join(projectPath, 'server'));
223
+
224
+ // Generate React frontend
225
+ const clientConfig = {
226
+ ...config,
227
+ projectName: 'client',
228
+ frontend: 'react',
229
+ additionalLibraries: ['react-router', 'axios'],
230
+ };
231
+ await generateReactTemplate(path.join(projectPath, 'client'), clientConfig);
232
+
233
+ // Generate Express backend with Prisma
234
+ const serverConfig = {
235
+ ...config,
236
+ projectName: 'server',
237
+ backend: 'express',
238
+ database: 'prisma',
239
+ folderStructure: 'layered',
240
+ };
241
+ await generateExpressTemplate(path.join(projectPath, 'server'), serverConfig);
242
+
243
+ // Generate root package.json
244
+ await fs.writeFile(
245
+ path.join(projectPath, 'package.json'),
246
+ await generateRootPackageJson(config, 'PERN')
247
+ );
248
+
249
+ // Generate Docker setup with PostgreSQL
250
+ await generateDockerSetup(projectPath, config, 'PERN');
251
+
252
+ // Generate API config
253
+ await generateAPIConfig(projectPath, config, 'PERN');
254
+
255
+ // Generate environment files
256
+ await generateFullStackEnv(projectPath, config, 'PERN');
257
+
258
+ // Generate README
259
+ await generateFullStackReadme(projectPath, config, 'PERN');
260
+ }
261
+
262
+ /**
263
+ * Next.js + Express Stack
264
+ */
265
+ async function generateNextExpressStack(projectPath, config) {
266
+ // Create folder structure
267
+ await fs.ensureDir(path.join(projectPath, 'frontend'));
268
+ await fs.ensureDir(path.join(projectPath, 'backend'));
269
+
270
+ // Generate Next.js frontend
271
+ const frontendConfig = {
272
+ ...config,
273
+ projectName: 'frontend',
274
+ frontend: 'nextjs',
275
+ };
276
+ await generateNextjsTemplate(path.join(projectPath, 'frontend'), frontendConfig);
277
+
278
+ // Generate Express backend
279
+ const backendConfig = {
280
+ ...config,
281
+ projectName: 'backend',
282
+ backend: 'express',
283
+ database: config.database || 'prisma',
284
+ folderStructure: 'clean-architecture',
285
+ };
286
+ await generateExpressTemplate(path.join(projectPath, 'backend'), backendConfig);
287
+
288
+ // Generate root package.json
289
+ await fs.writeFile(
290
+ path.join(projectPath, 'package.json'),
291
+ await generateRootPackageJson(config, 'Next.js + Express')
292
+ );
293
+
294
+ // Generate Docker setup
295
+ await generateDockerSetup(projectPath, config, 'Next.js + Express');
296
+
297
+ // Generate Next.js API proxy config
298
+ await generateNextjsProxyConfig(path.join(projectPath, 'frontend'));
299
+
300
+ // Generate environment files
301
+ await generateFullStackEnv(projectPath, config, 'Next.js + Express');
302
+
303
+ // Generate README
304
+ await generateFullStackReadme(projectPath, config, 'Next.js + Express');
305
+ }
306
+
307
+ /**
308
+ * Laravel + React Stack (Scaffolding only)
309
+ */
310
+ async function generateLaravelReactStack(projectPath, config) {
311
+ // Create folder structure
312
+ await fs.ensureDir(path.join(projectPath, 'client'));
313
+
314
+ // Generate React frontend
315
+ const clientConfig = {
316
+ ...config,
317
+ projectName: 'client',
318
+ frontend: 'react',
319
+ additionalLibraries: ['react-router', 'axios'],
320
+ };
321
+ await generateReactTemplate(path.join(projectPath, 'client'), clientConfig);
322
+
323
+ // Create Laravel backend placeholder
324
+ await fs.ensureDir(path.join(projectPath, 'server'));
325
+ await fs.writeFile(
326
+ path.join(projectPath, 'server', 'README.md'),
327
+ `# Laravel Backend
328
+
329
+ ## Setup Instructions
330
+
331
+ 1. Install Laravel:
332
+ \`\`\`bash
333
+ composer create-project laravel/laravel .
334
+ \`\`\`
335
+
336
+ 2. Configure database in \`.env\`
337
+
338
+ 3. Run migrations:
339
+ \`\`\`bash
340
+ php artisan migrate
341
+ \`\`\`
342
+
343
+ 4. Start server:
344
+ \`\`\`bash
345
+ php artisan serve
346
+ \`\`\`
347
+
348
+ ## API Routes
349
+
350
+ Add your API routes in \`routes/api.php\`
351
+ `
352
+ );
353
+
354
+ // Generate root README
355
+ await fs.writeFile(path.join(projectPath, 'README.md'), generateLaravelReactReadme(config));
356
+ }
357
+
358
+ // ==================== Helper Functions ====================
359
+
360
+ async function generateMonorepoPackageJson(config) {
361
+ const spinner = ora('Fetching latest package versions...').start();
362
+
363
+ try {
364
+ const turboVer = await fetchVersion('turbo');
365
+ spinner.succeed(chalk.green('Fetched latest versions'));
366
+
367
+ return JSON.stringify(
368
+ {
369
+ name: config.projectName || 'my-monorepo',
370
+ version: '1.0.0',
371
+ private: true,
372
+ workspaces: ['apps/*', 'packages/*'],
373
+ scripts: {
374
+ dev: 'turbo run dev',
375
+ build: 'turbo run build',
376
+ lint: 'turbo run lint',
377
+ clean: 'turbo run clean',
378
+ 'dev:frontend': 'turbo run dev --filter=frontend',
379
+ 'dev:backend': 'turbo run dev --filter=backend',
380
+ },
381
+ devDependencies: {
382
+ turbo: turboVer,
383
+ },
384
+ },
385
+ null,
386
+ 2
387
+ );
388
+ } catch (error) {
389
+ spinner.fail(chalk.yellow('Could not fetch versions, using fallbacks'));
390
+ return JSON.stringify(
391
+ {
392
+ name: config.projectName || 'my-monorepo',
393
+ version: '1.0.0',
394
+ private: true,
395
+ workspaces: ['apps/*', 'packages/*'],
396
+ scripts: {
397
+ dev: 'turbo run dev',
398
+ build: 'turbo run build',
399
+ lint: 'turbo run lint',
400
+ clean: 'turbo run clean',
401
+ 'dev:frontend': 'turbo run dev --filter=frontend',
402
+ 'dev:backend': 'turbo run dev --filter=backend',
403
+ },
404
+ devDependencies: { turbo: 'latest' },
405
+ },
406
+ null,
407
+ 2
408
+ );
409
+ }
410
+ }
411
+
412
+ function generateTurboConfig() {
413
+ return JSON.stringify(
414
+ {
415
+ $schema: 'https://turbo.build/schema.json',
416
+ pipeline: {
417
+ build: {
418
+ dependsOn: ['^build'],
419
+ outputs: ['dist/**', '.next/**'],
420
+ },
421
+ dev: {
422
+ cache: false,
423
+ persistent: true,
424
+ },
425
+ lint: {},
426
+ clean: {
427
+ cache: false,
428
+ },
429
+ },
430
+ },
431
+ null,
432
+ 2
433
+ );
434
+ }
435
+
436
+ async function generateSharedTypes(typesPath) {
437
+ await fs.writeFile(
438
+ path.join(typesPath, 'package.json'),
439
+ JSON.stringify(
440
+ {
441
+ name: 'shared-types',
442
+ version: '1.0.0',
443
+ main: './src/index.ts',
444
+ types: './src/index.ts',
445
+ },
446
+ null,
447
+ 2
448
+ )
449
+ );
450
+
451
+ await fs.ensureDir(path.join(typesPath, 'src'));
452
+ await fs.writeFile(
453
+ path.join(typesPath, 'src', 'index.ts'),
454
+ `// Shared TypeScript types and interfaces
455
+
456
+ export interface User {
457
+ id: string;
458
+ email: string;
459
+ name: string;
460
+ createdAt: Date;
461
+ }
462
+
463
+ export interface ApiResponse<T = any> {
464
+ success: boolean;
465
+ data?: T;
466
+ message?: string;
467
+ error?: string;
468
+ }
469
+
470
+ // Add your shared types here
471
+ `
472
+ );
473
+
474
+ await fs.writeFile(
475
+ path.join(typesPath, 'tsconfig.json'),
476
+ JSON.stringify(
477
+ {
478
+ compilerOptions: {
479
+ target: 'ES2020',
480
+ module: 'ESNext',
481
+ moduleResolution: 'node',
482
+ declaration: true,
483
+ outDir: './dist',
484
+ strict: true,
485
+ esModuleInterop: true,
486
+ },
487
+ include: ['src/**/*'],
488
+ exclude: ['node_modules', 'dist'],
489
+ },
490
+ null,
491
+ 2
492
+ )
493
+ );
494
+ }
495
+
496
+ async function generateUIComponents(uiPath, config) {
497
+ const isNextjs = config.stack?.includes('Next.js');
498
+
499
+ await fs.writeFile(
500
+ path.join(uiPath, 'package.json'),
501
+ JSON.stringify(
502
+ {
503
+ name: 'ui-components',
504
+ version: '1.0.0',
505
+ main: './src/index.ts',
506
+ dependencies: {
507
+ react: '^19.0.0',
508
+ ...(isNextjs && { next: '^15.1.4' }),
509
+ },
510
+ },
511
+ null,
512
+ 2
513
+ )
514
+ );
515
+
516
+ await fs.ensureDir(path.join(uiPath, 'src'));
517
+ await fs.writeFile(
518
+ path.join(uiPath, 'src', 'Button.tsx'),
519
+ `import React from 'react';
520
+
521
+ interface ButtonProps {
522
+ children: React.ReactNode;
523
+ onClick?: () => void;
524
+ variant?: 'primary' | 'secondary';
525
+ }
526
+
527
+ export const Button: React.FC<ButtonProps> = ({
528
+ children,
529
+ onClick,
530
+ variant = 'primary'
531
+ }) => {
532
+ return (
533
+ <button
534
+ onClick={onClick}
535
+ className={\`btn btn-\${variant}\`}
536
+ >
537
+ {children}
538
+ </button>
539
+ );
540
+ };
541
+ `
542
+ );
543
+
544
+ await fs.writeFile(
545
+ path.join(uiPath, 'src', 'index.ts'),
546
+ `export { Button } from './Button';
547
+ // Export more components here
548
+ `
549
+ );
550
+ }
551
+
552
+ async function generateMonorepoRootFiles(projectPath, config) {
553
+ // Root .gitignore
554
+ await fs.writeFile(
555
+ path.join(projectPath, '.gitignore'),
556
+ `# Dependencies
557
+ node_modules/
558
+ .pnp
559
+ .pnp.js
560
+
561
+ # Build outputs
562
+ dist/
563
+ .next/
564
+ build/
565
+
566
+ # Environment
567
+ .env
568
+ .env*.local
569
+
570
+ # Logs
571
+ *.log
572
+
573
+ # OS
574
+ .DS_Store
575
+ Thumbs.db
576
+
577
+ # IDE
578
+ .vscode/
579
+ .idea/
580
+ *.swp
581
+ *.swo
582
+ `
583
+ );
584
+
585
+ // Root .env.example
586
+ await fs.writeFile(
587
+ path.join(projectPath, '.env.example'),
588
+ `# Environment Configuration
589
+
590
+ # Frontend
591
+ NEXT_PUBLIC_API_URL=http://localhost:3001/api
592
+
593
+ # Backend
594
+ PORT=3001
595
+ NODE_ENV=development
596
+ DATABASE_URL=
597
+
598
+ # Add your environment variables here
599
+ `
600
+ );
601
+ }
602
+
603
+ async function generateMonorepoDockerSetup(projectPath, config) {
604
+ // Docker Compose for monorepo
605
+ await fs.writeFile(
606
+ path.join(projectPath, 'docker-compose.yml'),
607
+ `version: '3.8'
608
+
609
+ services:
610
+ frontend:
611
+ build:
612
+ context: ./apps/frontend
613
+ dockerfile: Dockerfile
614
+ ports:
615
+ - "3000:3000"
616
+ environment:
617
+ - NEXT_PUBLIC_API_URL=http://backend:3001/api
618
+ depends_on:
619
+ - backend
620
+ volumes:
621
+ - ./apps/frontend:/app
622
+ - /app/node_modules
623
+
624
+ backend:
625
+ build:
626
+ context: ./apps/backend
627
+ dockerfile: Dockerfile
628
+ ports:
629
+ - "3001:3001"
630
+ environment:
631
+ - NODE_ENV=development
632
+ - PORT=3001
633
+ volumes:
634
+ - ./apps/backend:/app
635
+ - /app/node_modules
636
+
637
+ ${
638
+ config.stack?.includes('MongoDB')
639
+ ? `mongo:
640
+ image: mongo:7
641
+ ports:
642
+ - "27017:27017"
643
+ volumes:
644
+ - mongo_data:/data/db`
645
+ : ''
646
+ }
647
+
648
+ ${
649
+ config.stack?.includes('PostgreSQL')
650
+ ? `postgres:
651
+ image: postgres:15-alpine
652
+ ports:
653
+ - "5432:5432"
654
+ environment:
655
+ - POSTGRES_USER=postgres
656
+ - POSTGRES_PASSWORD=postgres
657
+ - POSTGRES_DB=mydb
658
+ volumes:
659
+ - postgres_data:/var/lib/postgresql/data`
660
+ : ''
661
+ }
662
+
663
+ ${
664
+ config.stack?.includes('MongoDB') || config.stack?.includes('PostgreSQL')
665
+ ? `volumes:
666
+ ${config.stack?.includes('MongoDB') ? 'mongo_data:' : ''}
667
+ ${config.stack?.includes('PostgreSQL') ? 'postgres_data:' : ''}`
668
+ : ''
669
+ }
670
+ `
671
+ );
672
+ }
673
+
674
+ function generateMonorepoReadme(projectPath, config) {
675
+ return fs.writeFile(
676
+ path.join(projectPath, 'README.md'),
677
+ `# ${config.projectName || 'My Monorepo'}
678
+
679
+ Full-stack monorepo with ${config.stack}
680
+
681
+ ## 📁 Structure
682
+
683
+ \`\`\`
684
+ ${config.projectName}/
685
+ ├── apps/
686
+ │ ├── frontend/ # ${config.stack?.includes('Next.js') ? 'Next.js' : 'React'} application
687
+ │ └── backend/ # Express.js API
688
+ ├── packages/
689
+ │ ├── shared-types/ # Shared TypeScript types
690
+ │ └── ui-components/# Shared UI components
691
+ ├── package.json # Root workspace config
692
+ └── turbo.json # Turborepo configuration
693
+ \`\`\`
694
+
695
+ ## 🚀 Getting Started
696
+
697
+ ### Prerequisites
698
+
699
+ - Node.js 18+
700
+ - pnpm (recommended) or npm
701
+
702
+ ### Installation
703
+
704
+ \`\`\`bash
705
+ # Install dependencies
706
+ npm install
707
+
708
+ # Or with pnpm
709
+ pnpm install
710
+ \`\`\`
711
+
712
+ ### Development
713
+
714
+ \`\`\`bash
715
+ # Run all apps
716
+ npm run dev
717
+
718
+ # Run frontend only
719
+ npm run dev:frontend
720
+
721
+ # Run backend only
722
+ npm run dev:backend
723
+ \`\`\`
724
+
725
+ ### Build
726
+
727
+ \`\`\`bash
728
+ npm run build
729
+ \`\`\`
730
+
731
+ ## 🐳 Docker
732
+
733
+ \`\`\`bash
734
+ # Start all services
735
+ docker-compose up
736
+
737
+ # Build and start
738
+ docker-compose up --build
739
+ \`\`\`
740
+
741
+ ## 📦 Packages
742
+
743
+ - **shared-types**: Common TypeScript interfaces
744
+ - **ui-components**: Reusable UI components
745
+
746
+ ## 📝 License
747
+
748
+ MIT
749
+ `
750
+ );
751
+ }
752
+
753
+ async function generateRootPackageJson(config, stackType) {
754
+ const spinner = ora('Fetching latest package versions...').start();
755
+
756
+ try {
757
+ const concurrentlyVer = await fetchVersion('concurrently');
758
+ spinner.succeed(chalk.green('Fetched latest versions'));
759
+
760
+ const scripts = {
761
+ dev: 'concurrently "npm run dev:client" "npm run dev:server"',
762
+ 'dev:client':
763
+ stackType === 'Next.js + Express'
764
+ ? 'cd frontend && npm run dev'
765
+ : 'cd client && npm run dev',
766
+ 'dev:server':
767
+ stackType === 'Next.js + Express'
768
+ ? 'cd backend && npm run dev'
769
+ : 'cd server && npm run dev',
770
+ build: 'npm run build:client && npm run build:server',
771
+ 'build:client':
772
+ stackType === 'Next.js + Express'
773
+ ? 'cd frontend && npm run build'
774
+ : 'cd client && npm run build',
775
+ 'build:server':
776
+ stackType === 'Next.js + Express'
777
+ ? 'cd backend && npm run build'
778
+ : 'cd server && npm run build',
779
+ 'install:all':
780
+ stackType === 'Next.js + Express'
781
+ ? 'npm install && cd frontend && npm install && cd ../backend && npm install'
782
+ : 'npm install && cd client && npm install && cd ../server && npm install',
783
+ };
784
+
785
+ return JSON.stringify(
786
+ {
787
+ name: config.projectName || 'my-fullstack-app',
788
+ version: '1.0.0',
789
+ description: `${stackType} full-stack application`,
790
+ scripts,
791
+ devDependencies: {
792
+ concurrently: concurrentlyVer,
793
+ },
794
+ },
795
+ null,
796
+ 2
797
+ );
798
+ } catch (error) {
799
+ spinner.fail(chalk.yellow('Could not fetch versions, using fallbacks'));
800
+ const scripts = {
801
+ dev: 'concurrently "npm run dev:client" "npm run dev:server"',
802
+ 'dev:client':
803
+ stackType === 'Next.js + Express'
804
+ ? 'cd frontend && npm run dev'
805
+ : 'cd client && npm run dev',
806
+ 'dev:server':
807
+ stackType === 'Next.js + Express'
808
+ ? 'cd backend && npm run dev'
809
+ : 'cd server && npm run dev',
810
+ build: 'npm run build:client && npm run build:server',
811
+ 'build:client':
812
+ stackType === 'Next.js + Express'
813
+ ? 'cd frontend && npm run build'
814
+ : 'cd client && npm run build',
815
+ 'build:server':
816
+ stackType === 'Next.js + Express'
817
+ ? 'cd backend && npm run build'
818
+ : 'cd server && npm run build',
819
+ 'install:all':
820
+ stackType === 'Next.js + Express'
821
+ ? 'npm install && cd frontend && npm install && cd ../backend && npm install'
822
+ : 'npm install && cd client && npm install && cd ../server && npm install',
823
+ };
824
+ return JSON.stringify(
825
+ {
826
+ name: config.projectName || 'my-fullstack-app',
827
+ version: '1.0.0',
828
+ description: `${stackType} full-stack application`,
829
+ scripts,
830
+ devDependencies: { concurrently: 'latest' },
831
+ },
832
+ null,
833
+ 2
834
+ );
835
+ }
836
+ }
837
+
838
+ async function generateDockerSetup(projectPath, config, stackType) {
839
+ const frontendDir = stackType === 'Next.js + Express' ? 'frontend' : 'client';
840
+ const backendDir = stackType === 'Next.js + Express' ? 'backend' : 'server';
841
+
842
+ // Docker Compose
843
+ const dbService =
844
+ stackType === 'MERN'
845
+ ? ` mongo:
846
+ image: mongo:7
847
+ ports:
848
+ - "27017:27017"
849
+ volumes:
850
+ - mongo_data:/data/db
851
+ environment:
852
+ - MONGO_INITDB_DATABASE=mydb`
853
+ : stackType === 'PERN' || stackType === 'Next.js + Express'
854
+ ? ` postgres:
855
+ image: postgres:15-alpine
856
+ ports:
857
+ - "5432:5432"
858
+ environment:
859
+ - POSTGRES_USER=postgres
860
+ - POSTGRES_PASSWORD=postgres
861
+ - POSTGRES_DB=mydb
862
+ volumes:
863
+ - postgres_data:/var/lib/postgresql/data`
864
+ : '';
865
+
866
+ await fs.writeFile(
867
+ path.join(projectPath, 'docker-compose.yml'),
868
+ `version: '3.8'
869
+
870
+ services:
871
+ frontend:
872
+ build:
873
+ context: ./${frontendDir}
874
+ dockerfile: Dockerfile
875
+ ports:
876
+ - "${stackType.includes('Next.js') ? '3000:3000' : '5173:5173'}"
877
+ environment:
878
+ - ${stackType.includes('Next.js') ? 'NEXT_PUBLIC_API_URL' : 'VITE_API_URL'}=http://backend:3001/api
879
+ depends_on:
880
+ - backend
881
+ volumes:
882
+ - ./${frontendDir}:/app
883
+ - /app/node_modules
884
+
885
+ backend:
886
+ build:
887
+ context: ./${backendDir}
888
+ dockerfile: Dockerfile
889
+ ports:
890
+ - "3001:3001"
891
+ environment:
892
+ - NODE_ENV=development
893
+ - PORT=3001
894
+ ${stackType === 'MERN' ? '- MONGODB_URI=mongodb://mongo:27017/mydb' : ''}
895
+ ${stackType === 'PERN' || stackType === 'Next.js + Express' ? '- DATABASE_URL=postgresql://postgres:postgres@postgres:5432/mydb' : ''}
896
+ depends_on:
897
+ ${stackType !== 'MERN' && stackType !== 'PERN' && !stackType.includes('Next.js') ? '' : '- ' + (stackType === 'MERN' ? 'mongo' : 'postgres')}
898
+ volumes:
899
+ - ./${backendDir}:/app
900
+ - /app/node_modules
901
+
902
+ ${dbService}
903
+
904
+ ${
905
+ dbService
906
+ ? `volumes:
907
+ ${stackType === 'MERN' ? 'mongo_data:' : 'postgres_data:'}`
908
+ : ''
909
+ }
910
+ `
911
+ );
912
+
913
+ // Frontend Dockerfile
914
+ const frontendDockerfile = stackType.includes('Next.js')
915
+ ? `FROM node:18-alpine AS base
916
+
917
+ FROM base AS deps
918
+ WORKDIR /app
919
+ COPY package*.json ./
920
+ RUN npm ci
921
+
922
+ FROM base AS builder
923
+ WORKDIR /app
924
+ COPY --from=deps /app/node_modules ./node_modules
925
+ COPY . .
926
+ RUN npm run build
927
+
928
+ FROM base AS runner
929
+ WORKDIR /app
930
+ ENV NODE_ENV production
931
+ COPY --from=builder /app/public ./public
932
+ COPY --from=builder /app/.next/standalone ./
933
+ COPY --from=builder /app/.next/static ./.next/static
934
+
935
+ EXPOSE 3000
936
+ CMD ["node", "server.js"]`
937
+ : `FROM node:18-alpine
938
+ WORKDIR /app
939
+ COPY package*.json ./
940
+ RUN npm install
941
+ COPY . .
942
+ EXPOSE 5173
943
+ CMD ["npm", "run", "dev", "--", "--host"]`;
944
+
945
+ await fs.writeFile(path.join(projectPath, frontendDir, 'Dockerfile'), frontendDockerfile);
946
+
947
+ // Backend Dockerfile
948
+ await fs.writeFile(
949
+ path.join(projectPath, backendDir, 'Dockerfile'),
950
+ `FROM node:18-alpine
951
+ WORKDIR /app
952
+ COPY package*.json ./
953
+ RUN npm install
954
+ COPY . .
955
+ ${config.language === 'typescript' ? 'RUN npm run build' : ''}
956
+ EXPOSE 3001
957
+ CMD ["npm", "start"]`
958
+ );
959
+ }
960
+
961
+ async function generateAPIConfig(projectPath, config, stackType) {
962
+ const frontendDir = stackType === 'Next.js + Express' ? 'frontend' : 'client';
963
+
964
+ if (stackType.includes('Next.js')) {
965
+ return; // Next.js uses rewrites in next.config.js
966
+ }
967
+
968
+ // Vite proxy config for React
969
+ const viteConfig = `import { defineConfig } from 'vite';
970
+ import react from '@vitejs/plugin-react';
971
+
972
+ export default defineConfig({
973
+ plugins: [react()],
974
+ server: {
975
+ proxy: {
976
+ '/api': {
977
+ target: 'http://localhost:3001',
978
+ changeOrigin: true,
979
+ },
980
+ },
981
+ },
982
+ });
983
+ `;
984
+
985
+ await fs.writeFile(path.join(projectPath, frontendDir, 'vite.config.js'), viteConfig);
986
+
987
+ // API client wrapper
988
+ await fs.ensureDir(path.join(projectPath, frontendDir, 'src', 'lib'));
989
+ await fs.writeFile(
990
+ path.join(projectPath, frontendDir, 'src', 'lib', 'api.js'),
991
+ `import axios from 'axios';
992
+
993
+ const api = axios.create({
994
+ baseURL: import.meta.env.VITE_API_URL || '/api',
995
+ headers: {
996
+ 'Content-Type': 'application/json',
997
+ },
998
+ });
999
+
1000
+ // Add interceptors for auth tokens if needed
1001
+ api.interceptors.request.use((config) => {
1002
+ const token = localStorage.getItem('token');
1003
+ if (token) {
1004
+ config.headers.Authorization = \`Bearer \${token}\`;
1005
+ }
1006
+ return config;
1007
+ });
1008
+
1009
+ export default api;
1010
+ `
1011
+ );
1012
+ }
1013
+
1014
+ async function generateNextjsProxyConfig(frontendPath) {
1015
+ // Add API rewrite to next.config.js
1016
+ const nextConfigPath = path.join(frontendPath, 'next.config.js');
1017
+
1018
+ // Read existing config or create new one
1019
+ let configContent = `/** @type {import('next').NextConfig} */
1020
+ const nextConfig = {
1021
+ async rewrites() {
1022
+ return [
1023
+ {
1024
+ source: '/api/:path*',
1025
+ destination: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001/api/:path*',
1026
+ },
1027
+ ];
1028
+ },
1029
+ };
1030
+
1031
+ export default nextConfig;
1032
+ `;
1033
+
1034
+ await fs.writeFile(nextConfigPath, configContent);
1035
+ }
1036
+
1037
+ async function generateFullStackEnv(projectPath, config, stackType) {
1038
+ const frontendDir = stackType === 'Next.js + Express' ? 'frontend' : 'client';
1039
+ const backendDir = stackType === 'Next.js + Express' ? 'backend' : 'server';
1040
+
1041
+ // Root .env.example
1042
+ await fs.writeFile(
1043
+ path.join(projectPath, '.env.example'),
1044
+ `# Full Stack Environment Variables
1045
+
1046
+ # Frontend
1047
+ ${stackType.includes('Next.js') ? 'NEXT_PUBLIC_API_URL' : 'VITE_API_URL'}=http://localhost:3001/api
1048
+
1049
+ # Backend
1050
+ PORT=3001
1051
+ NODE_ENV=development
1052
+ ${stackType === 'MERN' ? 'MONGODB_URI=mongodb://localhost:27017/mydb' : ''}
1053
+ ${stackType === 'PERN' || stackType === 'Next.js + Express' ? 'DATABASE_URL=postgresql://postgres:postgres@localhost:5432/mydb' : ''}
1054
+ `
1055
+ );
1056
+ }
1057
+
1058
+ function generateFullStackReadme(projectPath, config, stackType) {
1059
+ const frontendDir = stackType === 'Next.js + Express' ? 'frontend' : 'client';
1060
+ const backendDir = stackType === 'Next.js + Express' ? 'backend' : 'server';
1061
+
1062
+ const frontend = stackType.includes('Next.js') ? 'Next.js' : 'React';
1063
+ const backend = 'Express.js';
1064
+ const database =
1065
+ stackType === 'MERN' ? 'MongoDB' : stackType === 'PERN' ? 'PostgreSQL' : 'PostgreSQL';
1066
+
1067
+ return fs.writeFile(
1068
+ path.join(projectPath, 'README.md'),
1069
+ `# ${config.projectName || 'Full Stack Application'}
1070
+
1071
+ ${stackType} full-stack application
1072
+
1073
+ ## 🛠️ Tech Stack
1074
+
1075
+ - **Frontend**: ${frontend}
1076
+ - **Backend**: ${backend}
1077
+ - **Database**: ${database}
1078
+
1079
+ ## 📁 Project Structure
1080
+
1081
+ \`\`\`
1082
+ ${config.projectName}/
1083
+ ├── ${frontendDir}/ # Frontend application
1084
+ ├── ${backendDir}/ # Backend API
1085
+ ├── docker-compose.yml # Docker setup
1086
+ └── package.json # Root scripts
1087
+ \`\`\`
1088
+
1089
+ ## 🚀 Getting Started
1090
+
1091
+ ### Prerequisites
1092
+
1093
+ - Node.js 18+
1094
+ ${stackType === 'MERN' ? '- MongoDB' : ''}
1095
+ ${stackType === 'PERN' || stackType === 'Next.js + Express' ? '- PostgreSQL' : ''}
1096
+
1097
+ ### Installation
1098
+
1099
+ \`\`\`bash
1100
+ # Install all dependencies
1101
+ npm run install:all
1102
+ \`\`\`
1103
+
1104
+ ### Environment Variables
1105
+
1106
+ Copy \`.env.example\` to \`.env\` in both frontend and backend directories and configure:
1107
+
1108
+ \`\`\`bash
1109
+ cp .env.example .env
1110
+ \`\`\`
1111
+
1112
+ ### Development
1113
+
1114
+ \`\`\`bash
1115
+ # Run both frontend and backend
1116
+ npm run dev
1117
+
1118
+ # Or run separately:
1119
+ npm run dev:client # Frontend only
1120
+ npm run dev:server # Backend only
1121
+ \`\`\`
1122
+
1123
+ Frontend: http://localhost:${stackType.includes('Next.js') ? '3000' : '5173'}
1124
+ Backend: http://localhost:3001
1125
+
1126
+ ### Build
1127
+
1128
+ \`\`\`bash
1129
+ npm run build
1130
+ \`\`\`
1131
+
1132
+ ## 🐳 Docker
1133
+
1134
+ \`\`\`bash
1135
+ # Start all services with Docker
1136
+ docker-compose up
1137
+
1138
+ # Build and start
1139
+ docker-compose up --build
1140
+
1141
+ # Stop services
1142
+ docker-compose down
1143
+ \`\`\`
1144
+
1145
+ ## 📡 API Integration
1146
+
1147
+ The frontend is configured to proxy API requests to the backend:
1148
+ - **Endpoint**: \`/api/*\`
1149
+ - **Target**: \`http://localhost:3001/api\`
1150
+
1151
+ ## 📝 License
1152
+
1153
+ MIT
1154
+ `
1155
+ );
1156
+ }
1157
+
1158
+ function generateLaravelReactReadme(config) {
1159
+ return `# ${config.projectName || 'Laravel + React Application'}
1160
+
1161
+ Full-stack application with Laravel backend and React frontend
1162
+
1163
+ ## 🛠️ Tech Stack
1164
+
1165
+ - **Frontend**: React + Vite
1166
+ - **Backend**: Laravel
1167
+ - **Database**: MySQL/PostgreSQL
1168
+
1169
+ ## 📁 Project Structure
1170
+
1171
+ \`\`\`
1172
+ ${config.projectName}/
1173
+ ├── client/ # React frontend
1174
+ └── server/ # Laravel backend
1175
+ \`\`\`
1176
+
1177
+ ## 🚀 Getting Started
1178
+
1179
+ ### Prerequisites
1180
+
1181
+ - Node.js 18+
1182
+ - PHP 8.1+
1183
+ - Composer
1184
+ - MySQL or PostgreSQL
1185
+
1186
+ ### Backend Setup
1187
+
1188
+ \`\`\`bash
1189
+ cd server
1190
+
1191
+ # Install Laravel
1192
+ composer create-project laravel/laravel .
1193
+
1194
+ # Configure .env file
1195
+ cp .env.example .env
1196
+
1197
+ # Generate application key
1198
+ php artisan key:generate
1199
+
1200
+ # Run migrations
1201
+ php artisan migrate
1202
+
1203
+ # Start server
1204
+ php artisan serve
1205
+ \`\`\`
1206
+
1207
+ ### Frontend Setup
1208
+
1209
+ \`\`\`bash
1210
+ cd client
1211
+
1212
+ # Install dependencies
1213
+ npm install
1214
+
1215
+ # Start development server
1216
+ npm run dev
1217
+ \`\`\`
1218
+
1219
+ Frontend: http://localhost:5173
1220
+ Backend: http://localhost:8000
1221
+
1222
+ ## 📡 API Integration
1223
+
1224
+ Configure API URL in \`client/.env\`:
1225
+
1226
+ \`\`\`
1227
+ VITE_API_URL=http://localhost:8000/api
1228
+ \`\`\`
1229
+
1230
+ ## 📝 License
1231
+
1232
+ MIT
1233
+ `;
1234
+ }
1235
+
1236
+ export default generateFullStackTemplate;