initkit 1.2.1 → 1.2.3

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 CHANGED
@@ -751,6 +751,34 @@ initkit my-app --verbose
751
751
 
752
752
  ---
753
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)
779
+
780
+ ---
781
+
754
782
  ## Contributing
755
783
 
756
784
  We welcome contributions! InitKit has comprehensive documentation to help you get started.
@@ -823,7 +851,7 @@ MIT © [Shirish Shrestha](https://github.com/shirishshrestha)
823
851
  - **Issues**: [GitHub Issues](https://github.com/shirishshrestha/initkit/issues)
824
852
  - **Discussions**: [GitHub Discussions](https://github.com/shirishshrestha/initkit/discussions)
825
853
  - **Documentation**: [Full Documentation](./docs/QUICK_START.md)
826
- - **Email**: your.email@example.com
854
+ - **Email**: shirish.shrestha07@gmail.com
827
855
 
828
856
  ---
829
857
 
package/bin/index.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  /**
4
4
  * Entry point for the CLI application
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "initkit",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
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
- "@types/node": "^20.11.5"
75
+ "prettier": "^3.2.4"
75
76
  }
76
77
  }
@@ -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 };
@@ -1,5 +1,4 @@
1
1
  import chalk from 'chalk';
2
- import validateNpmName from 'validate-npm-package-name';
3
2
  import {
4
3
  validateProjectName,
5
4
  checkDirectoryExists,
@@ -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,147 @@ 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 fsExtra = await import('fs-extra');
136
+ const fs = fsExtra.default;
137
+ const pathModule = await import('path');
138
+ const path = pathModule.default;
139
+
140
+ // Create tailwind.config.js with proper content paths
141
+ const tailwindConfigPath = path.join(projectPath, 'tailwind.config.js');
142
+ const tailwindConfig = `/** @type {import('tailwindcss').Config} */
143
+ export default {
144
+ content: [
145
+ "./index.html",
146
+ "./src/**/*.{js,ts,jsx,tsx}",
147
+ ],
148
+ theme: {
149
+ extend: {},
150
+ },
151
+ plugins: [],
152
+ }`;
153
+ await fs.outputFile(tailwindConfigPath, tailwindConfig);
154
+
155
+ // Create postcss.config.js
156
+ const postcssConfigPath = path.join(projectPath, 'postcss.config.js');
157
+ const postcssConfig = `export default {
158
+ plugins: {
159
+ tailwindcss: {},
160
+ autoprefixer: {},
161
+ },
162
+ }`;
163
+ await fs.outputFile(postcssConfigPath, postcssConfig);
164
+
165
+ // For Vite projects, update the main CSS file
166
+ if (frontend === 'react' || frontend === 'vue') {
167
+ // Create/update main CSS file with Tailwind directives
168
+ const cssPath = path.join(projectPath, 'src', 'index.css');
169
+ const tailwindDirectives = `@tailwind base;
170
+ @tailwind components;
171
+ @tailwind utilities;
172
+ `;
173
+ await fs.outputFile(cssPath, tailwindDirectives);
174
+ }
175
+ break;
176
+ }
177
+
178
+ case 'scss':
179
+ case 'sass':
180
+ console.log(chalk.dim(' Installing Sass...'));
181
+ await execCommand(`${installCmd} -D sass`, { cwd: projectPath });
182
+ break;
183
+
184
+ case 'styled-components':
185
+ console.log(chalk.dim(' Installing Styled Components...'));
186
+ await execCommand(`${installCmd} styled-components`, { cwd: projectPath });
187
+ if (config.language === 'typescript') {
188
+ await execCommand(`${installCmd} -D @types/styled-components`, {
189
+ cwd: projectPath,
190
+ });
191
+ }
192
+ break;
193
+
194
+ case 'emotion':
195
+ console.log(chalk.dim(' Installing Emotion...'));
196
+ await execCommand(`${installCmd} @emotion/react @emotion/styled`, {
197
+ cwd: projectPath,
198
+ });
199
+ break;
200
+
201
+ case 'css-modules':
202
+ // CSS Modules are built into Vite and Next.js, no installation needed
203
+ console.log(chalk.dim(' CSS Modules are built-in, no installation needed'));
204
+ break;
205
+
206
+ default:
207
+ console.log(chalk.yellow(` Unknown styling solution: ${styling}`));
208
+ }
209
+ }
210
+
107
211
  /**
108
212
  * Install UI library (some have their own CLIs!)
109
213
  */
110
214
  async function installUILibrary(projectPath, library, config) {
111
- const { packageManager, language } = config;
215
+ const { packageManager } = config;
112
216
  const installCmd = getInstallCommand(packageManager);
113
217
 
114
218
  switch (library) {
115
219
  case 'shadcn':
116
- case 'shadcn-ui':
220
+ case 'shadcn-ui': {
117
221
  console.log(chalk.dim(' Running shadcn-ui init...'));
118
- // shadcn has its own CLI!
119
- await execCommand(`npx shadcn@latest init -y`, { cwd: projectPath });
222
+
223
+ // Ensure tsconfig has path aliases for shadcn
224
+ const fsExtra = await import('fs-extra');
225
+ const fs = fsExtra.default;
226
+ const pathModule = await import('path');
227
+ const path = pathModule.default;
228
+ const tsconfigPath = path.join(projectPath, 'tsconfig.json');
229
+
230
+ if (await fs.pathExists(tsconfigPath)) {
231
+ const tsconfig = await fs.readJson(tsconfigPath);
232
+ if (!tsconfig.compilerOptions) tsconfig.compilerOptions = {};
233
+ if (!tsconfig.compilerOptions.baseUrl) tsconfig.compilerOptions.baseUrl = '.';
234
+ if (!tsconfig.compilerOptions.paths) tsconfig.compilerOptions.paths = {};
235
+ tsconfig.compilerOptions.paths['@/*'] = ['./src/*'];
236
+ await fs.writeJson(tsconfigPath, tsconfig, { spaces: 2 });
237
+ }
238
+
239
+ // shadcn has its own CLI! Use package manager's binary runner
240
+ const { packageManager } = config;
241
+ const execCmd =
242
+ packageManager === 'npm'
243
+ ? 'npx'
244
+ : packageManager === 'yarn'
245
+ ? 'yarn dlx'
246
+ : packageManager === 'pnpm'
247
+ ? 'pnpm dlx'
248
+ : packageManager === 'bun'
249
+ ? 'bunx'
250
+ : 'npx';
251
+ await execCommand(`${execCmd} shadcn@latest init -y`, { cwd: projectPath });
120
252
  break;
253
+ }
121
254
 
122
255
  case 'mui':
123
256
  case 'material-ui':
@@ -175,10 +308,20 @@ async function installORM(projectPath, orm, database, config) {
175
308
  await execCommand(`${installCmd} -D prisma`, { cwd: projectPath });
176
309
  await execCommand(`${installCmd} @prisma/client`, { cwd: projectPath });
177
310
 
178
- // Initialize Prisma with database
311
+ // Initialize Prisma with database using package manager's binary runner
179
312
  const datasource = getDatasourceForPrisma(database);
180
313
  console.log(chalk.dim(` Initializing Prisma with ${datasource}...`));
181
- await execCommand(`npx prisma init --datasource-provider ${datasource}`, {
314
+ const execCmd =
315
+ packageManager === 'npm'
316
+ ? 'npx'
317
+ : packageManager === 'yarn'
318
+ ? 'yarn'
319
+ : packageManager === 'pnpm'
320
+ ? 'pnpm exec'
321
+ : packageManager === 'bun'
322
+ ? 'bunx'
323
+ : 'npx';
324
+ await execCommand(`${execCmd} prisma init --datasource-provider ${datasource}`, {
182
325
  cwd: projectPath,
183
326
  });
184
327
  break;
@@ -295,11 +438,22 @@ async function installTesting(projectPath, testingLibs, config) {
295
438
  });
296
439
  break;
297
440
 
298
- case 'playwright':
441
+ case 'playwright': {
299
442
  console.log(chalk.dim(' Installing Playwright...'));
300
- // Playwright has its own init CLI!
301
- await execCommand(`npm init playwright@latest`, { cwd: projectPath });
443
+ // Playwright has its own init CLI! Use package manager's create command
444
+ const initCmd =
445
+ packageManager === 'npm'
446
+ ? 'npm init'
447
+ : packageManager === 'yarn'
448
+ ? 'yarn create'
449
+ : packageManager === 'pnpm'
450
+ ? 'pnpm create'
451
+ : packageManager === 'bun'
452
+ ? 'bun create'
453
+ : 'npm init';
454
+ await execCommand(`${initCmd} playwright@latest`, { cwd: projectPath });
302
455
  break;
456
+ }
303
457
 
304
458
  case 'cypress':
305
459
  console.log(chalk.dim(' Installing Cypress...'));
@@ -392,6 +546,7 @@ function getDriverForTypeORM(database) {
392
546
  */
393
547
  export function hasAddons(config) {
394
548
  return !!(
549
+ (config.styling && config.styling !== 'none' && config.styling !== 'css') ||
395
550
  (config.stateManagement && config.stateManagement !== 'none') ||
396
551
  (config.uiLibrary && config.uiLibrary !== 'none') ||
397
552
  (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, packageManager = 'npm' } = config;
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, config) {
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, reject) => {
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 (error) {
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', (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');