initkit 1.2.0 → 1.2.2
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.
- package/README.md +137 -117
- package/package.json +6 -5
- package/src/commands/create.js +0 -111
- package/src/prompts/questions.js +0 -1
- package/src/utils/addonInstaller.js +161 -10
- package/src/utils/frameworkBootstrap.js +2 -2
- package/src/utils/templateGenerator.js +1 -1
- package/src/utils/versionFetcher.js +3 -3
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ Built with ES Modules | TypeScript Ready | Zero Config Required | Fully Document
|
|
|
23
23
|
|
|
24
24
|

|
|
25
25
|
|
|
26
|
-
_Creating a
|
|
26
|
+
_Creating a production-ready React application with InitKit_
|
|
27
27
|
|
|
28
28
|
</div>
|
|
29
29
|
|
|
@@ -35,11 +35,11 @@ InitKit eliminates the tedious project setup process by providing intelligent sc
|
|
|
35
35
|
|
|
36
36
|
**Key Benefits:**
|
|
37
37
|
|
|
38
|
-
- **
|
|
38
|
+
- **CLI-First Architecture** - Uses official framework CLIs (create-next-app, create-vite, create-vue, express-generator)
|
|
39
39
|
- **Smart Validation** - Real-time npm package name validation with helpful suggestions and colored feedback
|
|
40
40
|
- **Enhanced CLI UX** - Beautiful formatted help text with colors, boxes, and comprehensive examples
|
|
41
|
-
- **
|
|
42
|
-
- **
|
|
41
|
+
- **Always Up-to-Date** - Leverages official CLIs to ensure latest best practices and configurations
|
|
42
|
+
- **Non-Interactive Mode** - Properly configured for CI/CD with no hanging prompts
|
|
43
43
|
- **Flexible Architecture** - Feature-based, type-based, domain-driven, clean architecture structures
|
|
44
44
|
- **Docker Ready** - Complete Docker orchestration with multi-stage builds and docker-compose
|
|
45
45
|
- **API Integration** - Seamless frontend-backend communication with axios interceptors
|
|
@@ -110,32 +110,30 @@ Want to contribute or add a custom template?
|
|
|
110
110
|
|
|
111
111
|
### 🎯 Project Types
|
|
112
112
|
|
|
113
|
-
| Type | Description
|
|
114
|
-
| ------------------- |
|
|
115
|
-
| **Frontend Only** | Single-page applications
|
|
116
|
-
| **Backend Only** | REST APIs and services
|
|
117
|
-
| **
|
|
118
|
-
| **Node.js Library** | Publishable npm packages | Reusable modules and utilities |
|
|
113
|
+
| Type | Description | Use Case |
|
|
114
|
+
| ------------------- | ------------------------ | -------------------------------- |
|
|
115
|
+
| **Frontend Only** | Single-page applications | React, Vue, Next.js apps |
|
|
116
|
+
| **Backend Only** | REST APIs and services | Express, NestJS, Fastify servers |
|
|
117
|
+
| **Node.js Library** | Publishable npm packages | Reusable modules and utilities |
|
|
119
118
|
|
|
120
119
|
### 🎨 Framework Support
|
|
121
120
|
|
|
122
121
|
**Frontend Frameworks:**
|
|
123
122
|
|
|
124
|
-
- React (
|
|
125
|
-
-
|
|
126
|
-
-
|
|
127
|
-
- Svelte (SvelteKit)
|
|
128
|
-
- Next.js (App Router & Pages Router)
|
|
129
|
-
- Nuxt.js (Vue 3)
|
|
130
|
-
- Vanilla JavaScript (Modern ES6+)
|
|
123
|
+
- React + Vite (Fast HMR, modern build tool)
|
|
124
|
+
- Next.js (App Router with TypeScript)
|
|
125
|
+
- Vue.js + Vite (Progressive framework)
|
|
131
126
|
|
|
132
127
|
**Backend Frameworks:**
|
|
133
128
|
|
|
134
129
|
- Express.js (Minimalist & flexible)
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
-
|
|
130
|
+
|
|
131
|
+
**Coming Soon:**
|
|
132
|
+
|
|
133
|
+
- NestJS (Enterprise TypeScript) - Code ready, testing in progress
|
|
134
|
+
- Fastify (High performance) - Code ready, testing in progress
|
|
135
|
+
- Nuxt.js (Vue 3) - Code ready, testing in progress
|
|
136
|
+
- Svelte (Modern reactivity) - Code ready, testing in progress
|
|
139
137
|
|
|
140
138
|
**Databases:**
|
|
141
139
|
|
|
@@ -168,31 +166,7 @@ Want to contribute or add a custom template?
|
|
|
168
166
|
- Environment variables (.env setup)
|
|
169
167
|
- Turborepo (monorepo build system)
|
|
170
168
|
|
|
171
|
-
###
|
|
172
|
-
|
|
173
|
-
**Monorepo (Turborepo):**
|
|
174
|
-
|
|
175
|
-
- Shared packages (types, UI components)
|
|
176
|
-
- Unified workspace management
|
|
177
|
-
- Optimized build pipeline
|
|
178
|
-
- Consistent tooling across apps
|
|
179
|
-
|
|
180
|
-
**Traditional Stack Options:**
|
|
181
|
-
|
|
182
|
-
- **MERN** - MongoDB + Express + React + Node
|
|
183
|
-
- **PERN** - PostgreSQL + Express + React + Node
|
|
184
|
-
- **Next.js + Express** - Full-stack React with API
|
|
185
|
-
- **Laravel + React** - PHP backend with React frontend
|
|
186
|
-
|
|
187
|
-
**Features:**
|
|
188
|
-
|
|
189
|
-
- API integration (Vite proxy, Next.js rewrites)
|
|
190
|
-
- Docker orchestration (frontend + backend + database)
|
|
191
|
-
- Environment configuration
|
|
192
|
-
- Shared TypeScript types
|
|
193
|
-
- Reusable UI components
|
|
194
|
-
|
|
195
|
-
### 🎨 Styling Solutions
|
|
169
|
+
### Styling Solutions
|
|
196
170
|
|
|
197
171
|
| Solution | Description | Best For |
|
|
198
172
|
| --------------------- | ------------------------------- | ------------------------------ |
|
|
@@ -341,90 +315,98 @@ my-react-app/
|
|
|
341
315
|
└── package.json
|
|
342
316
|
```
|
|
343
317
|
|
|
344
|
-
### Example 2:
|
|
318
|
+
### Example 2: Next.js with TypeScript
|
|
345
319
|
|
|
346
320
|
```bash
|
|
347
|
-
initkit
|
|
348
|
-
# Select:
|
|
321
|
+
initkit nextjs-app
|
|
322
|
+
# Select: Frontend Only → Next.js → TypeScript → Tailwind CSS
|
|
349
323
|
```
|
|
350
324
|
|
|
351
325
|
**Generated Structure:**
|
|
352
326
|
|
|
353
327
|
```
|
|
354
|
-
|
|
355
|
-
├──
|
|
356
|
-
│ ├──
|
|
357
|
-
│ │ ├──
|
|
358
|
-
│ │
|
|
359
|
-
│
|
|
360
|
-
│ ├──
|
|
361
|
-
│ └──
|
|
362
|
-
├──
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
│ └── package.json
|
|
369
|
-
├── docker-compose.yml # MongoDB + Frontend + Backend
|
|
370
|
-
└── README.md
|
|
328
|
+
nextjs-app/
|
|
329
|
+
├── src/
|
|
330
|
+
│ ├── app/
|
|
331
|
+
│ │ ├── page.tsx
|
|
332
|
+
│ │ └── layout.tsx
|
|
333
|
+
│ ├── components/
|
|
334
|
+
│ ├── features/
|
|
335
|
+
│ └── lib/
|
|
336
|
+
├── public/
|
|
337
|
+
├── .eslintrc.json
|
|
338
|
+
├── next.config.js
|
|
339
|
+
├── tsconfig.json
|
|
340
|
+
├── tailwind.config.js
|
|
341
|
+
└── package.json
|
|
371
342
|
```
|
|
372
343
|
|
|
373
|
-
### Example 3:
|
|
344
|
+
### Example 3: Vue with TypeScript
|
|
374
345
|
|
|
375
346
|
```bash
|
|
376
|
-
initkit
|
|
377
|
-
# Select:
|
|
347
|
+
initkit vue-app
|
|
348
|
+
# Select: Frontend Only → Vue → TypeScript → Tailwind CSS
|
|
378
349
|
```
|
|
379
350
|
|
|
380
351
|
**Generated Structure:**
|
|
381
352
|
|
|
382
353
|
```
|
|
383
|
-
|
|
384
|
-
├──
|
|
385
|
-
│ ├──
|
|
386
|
-
│
|
|
387
|
-
├──
|
|
388
|
-
│ ├──
|
|
389
|
-
│
|
|
390
|
-
├──
|
|
391
|
-
|
|
354
|
+
vue-app/
|
|
355
|
+
├── src/
|
|
356
|
+
│ ├── components/
|
|
357
|
+
│ ├── features/
|
|
358
|
+
│ ├── composables/
|
|
359
|
+
│ ├── stores/
|
|
360
|
+
│ ├── router/
|
|
361
|
+
│ ├── App.vue
|
|
362
|
+
│ └── main.ts
|
|
363
|
+
├── public/
|
|
364
|
+
├── vite.config.ts
|
|
365
|
+
├── tsconfig.json
|
|
392
366
|
└── package.json
|
|
393
367
|
```
|
|
394
368
|
|
|
395
|
-
### Example 4: Express API
|
|
369
|
+
### Example 4: Express Backend API
|
|
396
370
|
|
|
397
371
|
```bash
|
|
398
372
|
initkit api-server
|
|
399
|
-
# Select: Backend Only → Express →
|
|
373
|
+
# Select: Backend Only → Express → JavaScript → MVC structure
|
|
400
374
|
```
|
|
401
375
|
|
|
402
|
-
**
|
|
376
|
+
**Generated Structure:**
|
|
403
377
|
|
|
404
|
-
|
|
405
|
-
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
378
|
+
```
|
|
379
|
+
api-server/
|
|
380
|
+
├── models/
|
|
381
|
+
├── controllers/
|
|
382
|
+
├── routes/
|
|
383
|
+
│ ├── index.js
|
|
384
|
+
│ └── users.js
|
|
385
|
+
├── middlewares/
|
|
386
|
+
├── services/
|
|
387
|
+
├── .env.example
|
|
388
|
+
├── app.js
|
|
389
|
+
└── package.json
|
|
390
|
+
```
|
|
409
391
|
|
|
410
392
|
### Example 5: Quick Start with Defaults
|
|
411
393
|
|
|
412
394
|
```bash
|
|
413
395
|
initkit quick-app --yes
|
|
414
|
-
# Creates a
|
|
396
|
+
# Creates a React + Vite app with TypeScript + Tailwind CSS
|
|
415
397
|
```
|
|
416
398
|
|
|
417
399
|
---
|
|
418
400
|
|
|
419
401
|
## Interactive Prompt Flow
|
|
420
402
|
|
|
421
|
-
InitKit uses an intelligent
|
|
403
|
+
InitKit uses an intelligent question flow that adapts based on your project type:
|
|
422
404
|
|
|
423
|
-
1. **Project Type** - Frontend, Backend,
|
|
405
|
+
1. **Project Type** - Frontend, Backend, or Library
|
|
424
406
|
2. **Project Name** - With real-time validation and suggestions
|
|
425
|
-
3. **Frontend Framework** - Shown for Frontend
|
|
426
|
-
4. **Backend Framework** - Shown for Backend
|
|
427
|
-
5. **Database** - Shown for Backend
|
|
407
|
+
3. **Frontend Framework** - Shown for Frontend projects
|
|
408
|
+
4. **Backend Framework** - Shown for Backend projects
|
|
409
|
+
5. **Database/ORM** - Shown for Backend projects
|
|
428
410
|
6. **Language** - TypeScript (recommended) or JavaScript
|
|
429
411
|
7. **Folder Structure** - Feature-based, Type-based, Domain-driven, or Flat
|
|
430
412
|
8. **TypeScript Strictness** - Strict, Moderate, or Relaxed (if TS selected)
|
|
@@ -444,12 +426,12 @@ See [QUESTION_FLOW.md](./QUESTION_FLOW.md) for the complete decision tree.
|
|
|
444
426
|
|
|
445
427
|
Unlike other scaffolding tools, InitKit generates **truly production-ready** projects:
|
|
446
428
|
|
|
447
|
-
- **
|
|
448
|
-
- **
|
|
449
|
-
- **
|
|
450
|
-
- **
|
|
451
|
-
- **
|
|
452
|
-
- **
|
|
429
|
+
- **Official CLIs** - Uses create-next-app, create-vite, create-vue, express-generator for best practices
|
|
430
|
+
- **Always Current** - Leverages framework maintainers' latest configurations
|
|
431
|
+
- **No Hanging** - Properly configured non-interactive mode for CI/CD pipelines
|
|
432
|
+
- **TypeScript First** - Full TypeScript support with proper configurations
|
|
433
|
+
- **Best Practices Built-in** - ESLint, Prettier, proper folder structures
|
|
434
|
+
- **Package Manager Choice** - Full support for npm, yarn, pnpm, and bun
|
|
453
435
|
|
|
454
436
|
### 🚀 Developer Experience
|
|
455
437
|
|
|
@@ -729,33 +711,71 @@ initkit my-app --verbose
|
|
|
729
711
|
|
|
730
712
|
## Recent Updates
|
|
731
713
|
|
|
732
|
-
### Version 1.
|
|
714
|
+
### Version 1.2.0 (Latest) 🚀
|
|
715
|
+
|
|
716
|
+
**🎉 BREAKING CHANGES:**
|
|
717
|
+
|
|
718
|
+
- **Removed fullstack project type** - Simplified to focus on stable frontend and backend options
|
|
719
|
+
- **Migrated to CLI-first architecture** - Now uses official framework CLIs exclusively
|
|
733
720
|
|
|
734
|
-
|
|
721
|
+
**✨ Major Features:**
|
|
735
722
|
|
|
736
|
-
-
|
|
737
|
-
-
|
|
738
|
-
-
|
|
739
|
-
-
|
|
740
|
-
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
- ShadCN UI (component library)
|
|
744
|
-
- 📦 **Bun Support** - Added bun as a package manager option
|
|
723
|
+
- **CLI-First Architecture** - Uses official CLIs for all frameworks:
|
|
724
|
+
- `create-next-app` for Next.js projects
|
|
725
|
+
- `create-vite@5.1.0` for React (pinned for stability)
|
|
726
|
+
- `create-vue` with `--typescript --default` for Vue
|
|
727
|
+
- `express-generator` for Express backends
|
|
728
|
+
- **Enhanced Logging** - Emoji-based progress indicators (📦) with detailed command visibility
|
|
729
|
+
- **Non-Interactive Mode** - All frameworks properly configured for CI/CD (no hanging prompts)
|
|
745
730
|
|
|
746
731
|
**🐛 Bug Fixes:**
|
|
747
732
|
|
|
748
|
-
- Fixed
|
|
749
|
-
- Fixed
|
|
750
|
-
- Fixed
|
|
751
|
-
- Fixed
|
|
733
|
+
- Fixed package manager override bug (CLI default removed)
|
|
734
|
+
- Fixed create-vite@8.x hanging (pinned to stable v5.1.0)
|
|
735
|
+
- Fixed create-vue prompting (added --default flag)
|
|
736
|
+
- Fixed CI environment variable for non-interactive execution
|
|
752
737
|
|
|
753
738
|
**🔧 Improvements:**
|
|
754
739
|
|
|
755
|
-
-
|
|
756
|
-
-
|
|
757
|
-
-
|
|
758
|
-
-
|
|
740
|
+
- Always uses latest framework configurations from official CLIs
|
|
741
|
+
- Better error messages and rollback handling
|
|
742
|
+
- Cleaner codebase with removed legacy template files
|
|
743
|
+
- All tests passing (48/48)
|
|
744
|
+
|
|
745
|
+
**📊 Test Results:**
|
|
746
|
+
|
|
747
|
+
- React + Vite: ✅ 16.5s (218 packages)
|
|
748
|
+
- Next.js: ✅ 26.9s (347 packages)
|
|
749
|
+
- Vue: ✅ 16.2s (153 packages)
|
|
750
|
+
- Express: ✅ 12.3s (53 packages)
|
|
751
|
+
|
|
752
|
+
---
|
|
753
|
+
|
|
754
|
+
## Recent Updates
|
|
755
|
+
|
|
756
|
+
### Version 1.2.2 (January 2026)
|
|
757
|
+
|
|
758
|
+
**Critical Bug Fixes:**
|
|
759
|
+
|
|
760
|
+
- ✅ **Fixed Tailwind CSS installation** - Resolved issue where styling was not installed if no other addons were selected
|
|
761
|
+
- ✅ **Fixed package manager compatibility** - All 4 package managers (npm, yarn, pnpm, bun) now work correctly with Tailwind CSS
|
|
762
|
+
- ✅ **Fixed Next.js duplicate configs** - Prevents duplicate Tailwind config files in Next.js projects
|
|
763
|
+
- ✅ **Improved file creation** - Uses proper fs-extra methods for reliable config file generation
|
|
764
|
+
|
|
765
|
+
**What's Fixed:**
|
|
766
|
+
|
|
767
|
+
- `hasAddons()` function now properly checks for styling configuration
|
|
768
|
+
- Changed from unreliable `npx tailwindcss init` to direct config file creation
|
|
769
|
+
- All package managers tested and verified working
|
|
770
|
+
- Next.js now uses built-in Tailwind setup (no duplicates)
|
|
771
|
+
|
|
772
|
+
**Testing:**
|
|
773
|
+
|
|
774
|
+
- ✅ 4/4 package managers passing tests (npm, yarn, pnpm, bun)
|
|
775
|
+
- ✅ Verified across React+Vite, Next.js, and Vue.js
|
|
776
|
+
- ✅ No duplicate configuration files
|
|
777
|
+
|
|
778
|
+
[View Full Changelog](./docs/CHANGELOG.md)
|
|
759
779
|
|
|
760
780
|
---
|
|
761
781
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "initkit",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A modern CLI tool for scaffolding production-ready web projects with live npm version fetching, multiple frameworks, and best practices built-in",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -61,16 +61,17 @@
|
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"chalk": "^5.3.0",
|
|
63
63
|
"commander": "^12.0.0",
|
|
64
|
+
"ejs": "^3.1.9",
|
|
65
|
+
"fs-extra": "^11.2.0",
|
|
66
|
+
"initkit": "^1.2.1",
|
|
64
67
|
"inquirer": "^9.2.15",
|
|
65
68
|
"ora": "^8.0.1",
|
|
66
|
-
"fs-extra": "^11.2.0",
|
|
67
|
-
"ejs": "^3.1.9",
|
|
68
69
|
"validate-npm-package-name": "^5.0.0"
|
|
69
70
|
},
|
|
70
71
|
"devDependencies": {
|
|
72
|
+
"@types/node": "^20.11.5",
|
|
71
73
|
"eslint": "^8.56.0",
|
|
72
|
-
"prettier": "^3.2.4",
|
|
73
74
|
"jest": "^29.7.0",
|
|
74
|
-
"
|
|
75
|
+
"prettier": "^3.2.4"
|
|
75
76
|
}
|
|
76
77
|
}
|
package/src/commands/create.js
CHANGED
|
@@ -239,115 +239,4 @@ function getInstallCommand(packageManager) {
|
|
|
239
239
|
return commands[packageManager] || 'npm install';
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
-
/** * Display comprehensive success summary after project creation (LEGACY - DEPRECATED)
|
|
243
|
-
* This function is kept for backward compatibility but is no longer used
|
|
244
|
-
* @deprecated Use displaySuccessMessage instead
|
|
245
|
-
*/
|
|
246
|
-
function displaySuccessSummary(answers, projectPath, _verbose = false) {
|
|
247
|
-
console.log('');
|
|
248
|
-
console.log(chalk.green('╔════════════════════════════════════════════════════════════╗'));
|
|
249
|
-
console.log(
|
|
250
|
-
chalk.green('║') +
|
|
251
|
-
chalk.green.bold(' ✨ Project Created Successfully! ✨ ') +
|
|
252
|
-
chalk.green('║')
|
|
253
|
-
);
|
|
254
|
-
console.log(chalk.green('╚════════════════════════════════════════════════════════════╝'));
|
|
255
|
-
console.log('');
|
|
256
|
-
|
|
257
|
-
// Project info section
|
|
258
|
-
console.log(chalk.cyan.bold(' 📦 Project Information'));
|
|
259
|
-
console.log(chalk.white(` ${chalk.gray('Name:')} ${chalk.bold(answers.projectName)}`));
|
|
260
|
-
console.log(chalk.white(` ${chalk.gray('Type:')} ${answers.projectType}`));
|
|
261
|
-
console.log(
|
|
262
|
-
chalk.white(` ${chalk.gray('Language:')} ${answers.language || 'JavaScript'}`)
|
|
263
|
-
);
|
|
264
|
-
|
|
265
|
-
if (answers.frontend) {
|
|
266
|
-
console.log(chalk.white(` ${chalk.gray('Frontend:')} ${answers.frontend}`));
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
if (answers.backend) {
|
|
270
|
-
console.log(chalk.white(` ${chalk.gray('Backend:')} ${answers.backend}`));
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
if (answers.database && answers.database !== 'none') {
|
|
274
|
-
console.log(chalk.white(` ${chalk.gray('Database:')} ${answers.database}`));
|
|
275
|
-
}
|
|
276
|
-
console.log('');
|
|
277
|
-
|
|
278
|
-
// Location section
|
|
279
|
-
console.log(chalk.cyan.bold(' 📁 Project Location'));
|
|
280
|
-
console.log(chalk.white(` ${projectPath}`));
|
|
281
|
-
console.log('');
|
|
282
|
-
|
|
283
|
-
// Features section
|
|
284
|
-
if (answers.features && answers.features.length > 0) {
|
|
285
|
-
console.log(chalk.cyan.bold(' ⚙️ Configured Features'));
|
|
286
|
-
answers.features.forEach((feature) => {
|
|
287
|
-
console.log(chalk.white(` ${chalk.green('✓')} ${feature}`));
|
|
288
|
-
});
|
|
289
|
-
console.log('');
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// Additional libraries
|
|
293
|
-
if (answers.additionalLibraries && answers.additionalLibraries.length > 0) {
|
|
294
|
-
console.log(chalk.cyan.bold(' 📚 Additional Libraries'));
|
|
295
|
-
answers.additionalLibraries.slice(0, 5).forEach((lib) => {
|
|
296
|
-
console.log(chalk.white(` ${chalk.green('✓')} ${lib}`));
|
|
297
|
-
});
|
|
298
|
-
if (answers.additionalLibraries.length > 5) {
|
|
299
|
-
console.log(chalk.gray(` ... and ${answers.additionalLibraries.length - 5} more`));
|
|
300
|
-
}
|
|
301
|
-
console.log('');
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// Package manager info
|
|
305
|
-
const packagesInstalled = answers.installDependencies !== false;
|
|
306
|
-
if (packagesInstalled) {
|
|
307
|
-
console.log(chalk.cyan.bold(' 📦 Dependencies'));
|
|
308
|
-
console.log(chalk.white(` ${chalk.green('✓')} Installed with ${answers.packageManager}`));
|
|
309
|
-
console.log('');
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// Next steps
|
|
313
|
-
console.log(chalk.cyan.bold(' 🚀 Next Steps'));
|
|
314
|
-
console.log('');
|
|
315
|
-
console.log(chalk.white(` ${chalk.yellow('1.')} Navigate to your project:`));
|
|
316
|
-
console.log(chalk.gray(` cd ${answers.projectName}`));
|
|
317
|
-
console.log('');
|
|
318
|
-
|
|
319
|
-
if (!packagesInstalled) {
|
|
320
|
-
console.log(chalk.white(` ${chalk.yellow('2.')} Install dependencies:`));
|
|
321
|
-
console.log(chalk.gray(` ${answers.packageManager} install`));
|
|
322
|
-
console.log('');
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
const stepNum = packagesInstalled ? 2 : 3;
|
|
326
|
-
console.log(chalk.white(` ${chalk.yellow(stepNum + '.')} Start development server:`));
|
|
327
|
-
console.log(
|
|
328
|
-
chalk.gray(
|
|
329
|
-
` ${answers.packageManager} ${answers.packageManager === 'npm' ? 'run ' : ''}dev`
|
|
330
|
-
)
|
|
331
|
-
);
|
|
332
|
-
console.log('');
|
|
333
|
-
|
|
334
|
-
console.log(
|
|
335
|
-
chalk.white(` ${chalk.yellow(stepNum + 1 + '.')} Read the README for more info:`)
|
|
336
|
-
);
|
|
337
|
-
console.log(chalk.gray(` cat README.md`));
|
|
338
|
-
console.log('');
|
|
339
|
-
|
|
340
|
-
// Documentation link
|
|
341
|
-
console.log(chalk.cyan.bold(' 📚 Documentation'));
|
|
342
|
-
console.log(chalk.white(` Check out the README.md in your project folder`));
|
|
343
|
-
console.log(chalk.white(` for setup instructions and best practices.`));
|
|
344
|
-
console.log('');
|
|
345
|
-
|
|
346
|
-
// Footer
|
|
347
|
-
console.log(chalk.green(' ─────────────────────────────────────────────────────────────'));
|
|
348
|
-
console.log(chalk.green.bold(' 🎉 Happy coding! Your project is ready! 🎉'));
|
|
349
|
-
console.log(chalk.green(' ─────────────────────────────────────────────────────────────'));
|
|
350
|
-
console.log('');
|
|
351
|
-
}
|
|
352
|
-
|
|
353
242
|
export { createProject };
|
package/src/prompts/questions.js
CHANGED
|
@@ -24,13 +24,19 @@ export async function installAddons(projectPath, config) {
|
|
|
24
24
|
additionalLibraries = [],
|
|
25
25
|
} = config;
|
|
26
26
|
|
|
27
|
+
// Styling (MUST be installed before UI libraries like shadcn)
|
|
28
|
+
if (styling && styling !== 'none' && styling !== 'css') {
|
|
29
|
+
console.log(chalk.cyan('\n🎨 Installing styling solution...'));
|
|
30
|
+
await installStyling(projectPath, styling, config);
|
|
31
|
+
}
|
|
32
|
+
|
|
27
33
|
// State Management
|
|
28
34
|
if (stateManagement && stateManagement !== 'none') {
|
|
29
35
|
console.log(chalk.cyan('\n📦 Installing state management...'));
|
|
30
36
|
await installStateManagement(projectPath, stateManagement, config);
|
|
31
37
|
}
|
|
32
38
|
|
|
33
|
-
// UI Library
|
|
39
|
+
// UI Library (must come AFTER styling, especially for shadcn which needs Tailwind)
|
|
34
40
|
if (uiLibrary && uiLibrary !== 'none') {
|
|
35
41
|
console.log(chalk.cyan('\n🎨 Installing UI library...'));
|
|
36
42
|
await installUILibrary(projectPath, uiLibrary, config);
|
|
@@ -104,20 +110,143 @@ async function installStateManagement(projectPath, library, config) {
|
|
|
104
110
|
}
|
|
105
111
|
}
|
|
106
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Install styling solution
|
|
115
|
+
*/
|
|
116
|
+
async function installStyling(projectPath, styling, config) {
|
|
117
|
+
const { packageManager, frontend } = config;
|
|
118
|
+
const installCmd = getInstallCommand(packageManager);
|
|
119
|
+
|
|
120
|
+
switch (styling) {
|
|
121
|
+
case 'tailwind': {
|
|
122
|
+
// Next.js already includes Tailwind CSS when --tailwind flag is used
|
|
123
|
+
if (frontend === 'nextjs') {
|
|
124
|
+
console.log(chalk.dim(' Tailwind CSS already configured by Next.js'));
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
console.log(chalk.dim(' Installing Tailwind CSS...'));
|
|
129
|
+
await execCommand(`${installCmd} -D tailwindcss postcss autoprefixer`, {
|
|
130
|
+
cwd: projectPath,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Create Tailwind config files directly (more reliable than running init command)
|
|
134
|
+
console.log(chalk.dim(' Initializing Tailwind configuration...'));
|
|
135
|
+
const fs = await import('fs-extra');
|
|
136
|
+
const path = await import('path');
|
|
137
|
+
|
|
138
|
+
// Create tailwind.config.js with proper content paths
|
|
139
|
+
const tailwindConfigPath = path.join(projectPath, 'tailwind.config.js');
|
|
140
|
+
const tailwindConfig = `/** @type {import('tailwindcss').Config} */
|
|
141
|
+
export default {
|
|
142
|
+
content: [
|
|
143
|
+
"./index.html",
|
|
144
|
+
"./src/**/*.{js,ts,jsx,tsx}",
|
|
145
|
+
],
|
|
146
|
+
theme: {
|
|
147
|
+
extend: {},
|
|
148
|
+
},
|
|
149
|
+
plugins: [],
|
|
150
|
+
}`;
|
|
151
|
+
await fs.outputFile(tailwindConfigPath, tailwindConfig);
|
|
152
|
+
|
|
153
|
+
// Create postcss.config.js
|
|
154
|
+
const postcssConfigPath = path.join(projectPath, 'postcss.config.js');
|
|
155
|
+
const postcssConfig = `export default {
|
|
156
|
+
plugins: {
|
|
157
|
+
tailwindcss: {},
|
|
158
|
+
autoprefixer: {},
|
|
159
|
+
},
|
|
160
|
+
}`;
|
|
161
|
+
await fs.outputFile(postcssConfigPath, postcssConfig);
|
|
162
|
+
|
|
163
|
+
// For Vite projects, update the main CSS file
|
|
164
|
+
if (frontend === 'react' || frontend === 'vue') {
|
|
165
|
+
// Create/update main CSS file with Tailwind directives
|
|
166
|
+
const cssPath = path.join(projectPath, 'src', 'index.css');
|
|
167
|
+
const tailwindDirectives = `@tailwind base;
|
|
168
|
+
@tailwind components;
|
|
169
|
+
@tailwind utilities;
|
|
170
|
+
`;
|
|
171
|
+
await fs.outputFile(cssPath, tailwindDirectives);
|
|
172
|
+
}
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
case 'scss':
|
|
177
|
+
case 'sass':
|
|
178
|
+
console.log(chalk.dim(' Installing Sass...'));
|
|
179
|
+
await execCommand(`${installCmd} -D sass`, { cwd: projectPath });
|
|
180
|
+
break;
|
|
181
|
+
|
|
182
|
+
case 'styled-components':
|
|
183
|
+
console.log(chalk.dim(' Installing Styled Components...'));
|
|
184
|
+
await execCommand(`${installCmd} styled-components`, { cwd: projectPath });
|
|
185
|
+
if (config.language === 'typescript') {
|
|
186
|
+
await execCommand(`${installCmd} -D @types/styled-components`, {
|
|
187
|
+
cwd: projectPath,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
break;
|
|
191
|
+
|
|
192
|
+
case 'emotion':
|
|
193
|
+
console.log(chalk.dim(' Installing Emotion...'));
|
|
194
|
+
await execCommand(`${installCmd} @emotion/react @emotion/styled`, {
|
|
195
|
+
cwd: projectPath,
|
|
196
|
+
});
|
|
197
|
+
break;
|
|
198
|
+
|
|
199
|
+
case 'css-modules':
|
|
200
|
+
// CSS Modules are built into Vite and Next.js, no installation needed
|
|
201
|
+
console.log(chalk.dim(' CSS Modules are built-in, no installation needed'));
|
|
202
|
+
break;
|
|
203
|
+
|
|
204
|
+
default:
|
|
205
|
+
console.log(chalk.yellow(` Unknown styling solution: ${styling}`));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
107
209
|
/**
|
|
108
210
|
* Install UI library (some have their own CLIs!)
|
|
109
211
|
*/
|
|
110
212
|
async function installUILibrary(projectPath, library, config) {
|
|
111
|
-
const { packageManager
|
|
213
|
+
const { packageManager } = config;
|
|
112
214
|
const installCmd = getInstallCommand(packageManager);
|
|
113
215
|
|
|
114
216
|
switch (library) {
|
|
115
217
|
case 'shadcn':
|
|
116
|
-
case 'shadcn-ui':
|
|
218
|
+
case 'shadcn-ui': {
|
|
117
219
|
console.log(chalk.dim(' Running shadcn-ui init...'));
|
|
118
|
-
|
|
119
|
-
|
|
220
|
+
|
|
221
|
+
// Ensure tsconfig has path aliases for shadcn
|
|
222
|
+
const fs = await import('fs-extra');
|
|
223
|
+
const path = await import('path');
|
|
224
|
+
const tsconfigPath = path.join(projectPath, 'tsconfig.json');
|
|
225
|
+
|
|
226
|
+
if (await fs.pathExists(tsconfigPath)) {
|
|
227
|
+
const tsconfig = await fs.readJson(tsconfigPath);
|
|
228
|
+
if (!tsconfig.compilerOptions) tsconfig.compilerOptions = {};
|
|
229
|
+
if (!tsconfig.compilerOptions.baseUrl) tsconfig.compilerOptions.baseUrl = '.';
|
|
230
|
+
if (!tsconfig.compilerOptions.paths) tsconfig.compilerOptions.paths = {};
|
|
231
|
+
tsconfig.compilerOptions.paths['@/*'] = ['./src/*'];
|
|
232
|
+
await fs.writeJson(tsconfigPath, tsconfig, { spaces: 2 });
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// shadcn has its own CLI! Use package manager's binary runner
|
|
236
|
+
const { packageManager } = config;
|
|
237
|
+
const execCmd =
|
|
238
|
+
packageManager === 'npm'
|
|
239
|
+
? 'npx'
|
|
240
|
+
: packageManager === 'yarn'
|
|
241
|
+
? 'yarn dlx'
|
|
242
|
+
: packageManager === 'pnpm'
|
|
243
|
+
? 'pnpm dlx'
|
|
244
|
+
: packageManager === 'bun'
|
|
245
|
+
? 'bunx'
|
|
246
|
+
: 'npx';
|
|
247
|
+
await execCommand(`${execCmd} shadcn@latest init -y`, { cwd: projectPath });
|
|
120
248
|
break;
|
|
249
|
+
}
|
|
121
250
|
|
|
122
251
|
case 'mui':
|
|
123
252
|
case 'material-ui':
|
|
@@ -175,10 +304,20 @@ async function installORM(projectPath, orm, database, config) {
|
|
|
175
304
|
await execCommand(`${installCmd} -D prisma`, { cwd: projectPath });
|
|
176
305
|
await execCommand(`${installCmd} @prisma/client`, { cwd: projectPath });
|
|
177
306
|
|
|
178
|
-
// Initialize Prisma with database
|
|
307
|
+
// Initialize Prisma with database using package manager's binary runner
|
|
179
308
|
const datasource = getDatasourceForPrisma(database);
|
|
180
309
|
console.log(chalk.dim(` Initializing Prisma with ${datasource}...`));
|
|
181
|
-
|
|
310
|
+
const execCmd =
|
|
311
|
+
packageManager === 'npm'
|
|
312
|
+
? 'npx'
|
|
313
|
+
: packageManager === 'yarn'
|
|
314
|
+
? 'yarn'
|
|
315
|
+
: packageManager === 'pnpm'
|
|
316
|
+
? 'pnpm exec'
|
|
317
|
+
: packageManager === 'bun'
|
|
318
|
+
? 'bunx'
|
|
319
|
+
: 'npx';
|
|
320
|
+
await execCommand(`${execCmd} prisma init --datasource-provider ${datasource}`, {
|
|
182
321
|
cwd: projectPath,
|
|
183
322
|
});
|
|
184
323
|
break;
|
|
@@ -295,11 +434,22 @@ async function installTesting(projectPath, testingLibs, config) {
|
|
|
295
434
|
});
|
|
296
435
|
break;
|
|
297
436
|
|
|
298
|
-
case 'playwright':
|
|
437
|
+
case 'playwright': {
|
|
299
438
|
console.log(chalk.dim(' Installing Playwright...'));
|
|
300
|
-
// Playwright has its own init CLI!
|
|
301
|
-
|
|
439
|
+
// Playwright has its own init CLI! Use package manager's create command
|
|
440
|
+
const initCmd =
|
|
441
|
+
packageManager === 'npm'
|
|
442
|
+
? 'npm init'
|
|
443
|
+
: packageManager === 'yarn'
|
|
444
|
+
? 'yarn create'
|
|
445
|
+
: packageManager === 'pnpm'
|
|
446
|
+
? 'pnpm create'
|
|
447
|
+
: packageManager === 'bun'
|
|
448
|
+
? 'bun create'
|
|
449
|
+
: 'npm init';
|
|
450
|
+
await execCommand(`${initCmd} playwright@latest`, { cwd: projectPath });
|
|
302
451
|
break;
|
|
452
|
+
}
|
|
303
453
|
|
|
304
454
|
case 'cypress':
|
|
305
455
|
console.log(chalk.dim(' Installing Cypress...'));
|
|
@@ -392,6 +542,7 @@ function getDriverForTypeORM(database) {
|
|
|
392
542
|
*/
|
|
393
543
|
export function hasAddons(config) {
|
|
394
544
|
return !!(
|
|
545
|
+
(config.styling && config.styling !== 'none' && config.styling !== 'css') ||
|
|
395
546
|
(config.stateManagement && config.stateManagement !== 'none') ||
|
|
396
547
|
(config.uiLibrary && config.uiLibrary !== 'none') ||
|
|
397
548
|
(config.orm && config.orm !== 'none') ||
|
|
@@ -14,7 +14,7 @@ import chalk from 'chalk';
|
|
|
14
14
|
* @returns {Promise<void>}
|
|
15
15
|
*/
|
|
16
16
|
export async function bootstrapWithOfficialCLI(projectPath, config) {
|
|
17
|
-
const { projectType, frontend, backend } = config;
|
|
17
|
+
const { projectType, frontend: _frontend, backend: _backend } = config;
|
|
18
18
|
|
|
19
19
|
switch (projectType) {
|
|
20
20
|
case 'frontend':
|
|
@@ -239,7 +239,7 @@ export async function bootstrapSvelte(projectPath, config) {
|
|
|
239
239
|
* @param {Object} config - Configuration object
|
|
240
240
|
*/
|
|
241
241
|
export async function bootstrapExpress(projectPath, config) {
|
|
242
|
-
const { language
|
|
242
|
+
const { language } = config;
|
|
243
243
|
const projectName = path.basename(projectPath);
|
|
244
244
|
const parentDir = path.dirname(projectPath);
|
|
245
245
|
|
|
@@ -109,7 +109,7 @@ async function createFeatureBasedStructure(srcPath, config) {
|
|
|
109
109
|
/**
|
|
110
110
|
* Create component-based folder structure
|
|
111
111
|
*/
|
|
112
|
-
async function createComponentBasedStructure(srcPath,
|
|
112
|
+
async function createComponentBasedStructure(srcPath, _config) {
|
|
113
113
|
await fs.ensureDir(path.join(srcPath, 'components', 'ui'));
|
|
114
114
|
await fs.ensureDir(path.join(srcPath, 'components', 'layout'));
|
|
115
115
|
await fs.ensureDir(path.join(srcPath, 'components', 'forms'));
|
|
@@ -6,7 +6,7 @@ import https from 'https';
|
|
|
6
6
|
* @returns {Promise<string>} Latest version number
|
|
7
7
|
*/
|
|
8
8
|
export async function getLatestVersion(packageName) {
|
|
9
|
-
return new Promise((resolve
|
|
9
|
+
return new Promise((resolve) => {
|
|
10
10
|
const url = `https://registry.npmjs.org/${packageName}/latest`;
|
|
11
11
|
|
|
12
12
|
https
|
|
@@ -21,13 +21,13 @@ export async function getLatestVersion(packageName) {
|
|
|
21
21
|
try {
|
|
22
22
|
const json = JSON.parse(data);
|
|
23
23
|
resolve(json.version || 'latest');
|
|
24
|
-
} catch (
|
|
24
|
+
} catch (_error) {
|
|
25
25
|
// If parsing fails, return 'latest' as fallback
|
|
26
26
|
resolve('latest');
|
|
27
27
|
}
|
|
28
28
|
});
|
|
29
29
|
})
|
|
30
|
-
.on('error', (
|
|
30
|
+
.on('error', () => {
|
|
31
31
|
// On network error, return 'latest' as fallback
|
|
32
32
|
console.warn(`Warning: Could not fetch version for ${packageName}, using 'latest'`);
|
|
33
33
|
resolve('latest');
|