initkit 1.1.0 → 1.2.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.
- package/package.json +2 -5
- package/src/cli.js +77 -34
- package/src/commands/create.js +173 -84
- package/src/prompts/questions.js +95 -39
- package/src/utils/addonInstaller.js +402 -0
- package/src/utils/cliRunner.js +146 -0
- package/src/utils/frameworkBootstrap.js +304 -0
- package/src/utils/templateGenerator.js +191 -171
- package/src/templates/express.js +0 -915
- package/src/templates/fullstack.js +0 -1236
- package/src/templates/nextjs.js +0 -620
- package/src/templates/react.js +0 -586
- package/src/templates/vue.js +0 -545
package/src/templates/react.js
DELETED
|
@@ -1,586 +0,0 @@
|
|
|
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
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Fetch latest version with fallback
|
|
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 React + Vite project with modern build tooling
|
|
21
|
-
*
|
|
22
|
-
* Creates a React single-page application using Vite for:
|
|
23
|
-
* - Fast HMR (Hot Module Replacement)
|
|
24
|
-
* - Optimized production builds
|
|
25
|
-
* - TypeScript or JavaScript support
|
|
26
|
-
* - Multiple folder structure patterns
|
|
27
|
-
*
|
|
28
|
-
* Generated project includes:
|
|
29
|
-
* - Vite configuration with React plugin
|
|
30
|
-
* - Folder structure based on preference
|
|
31
|
-
* - Package.json with React 18+ and Vite dependencies
|
|
32
|
-
* - README with getting started instructions
|
|
33
|
-
*
|
|
34
|
-
* @param {string} projectPath - Absolute path to the project directory
|
|
35
|
-
* @param {Object} config - User configuration object
|
|
36
|
-
* @param {string} config.projectName - Name of the project
|
|
37
|
-
* @param {string} config.language - Programming language ('typescript'|'javascript')
|
|
38
|
-
* @param {string} [config.folderStructure='feature-based'] - Folder organization pattern
|
|
39
|
-
* - 'feature-based': Organize by features/modules (recommended)
|
|
40
|
-
* - 'component-based': Organize by component types (pages, components, layouts)
|
|
41
|
-
* - 'type-based': Organize by file type (components, hooks, utils, services)
|
|
42
|
-
* @param {string} config.packageManager - Package manager to use
|
|
43
|
-
*
|
|
44
|
-
* @returns {Promise<void>}
|
|
45
|
-
*
|
|
46
|
-
* @example
|
|
47
|
-
* // Create React + Vite project with feature-based structure
|
|
48
|
-
* await generateReactTemplate('/path/to/project', {
|
|
49
|
-
* projectName: 'my-react-app',
|
|
50
|
-
* language: 'typescript',
|
|
51
|
-
* folderStructure: 'feature-based',
|
|
52
|
-
* packageManager: 'npm'
|
|
53
|
-
* });
|
|
54
|
-
*/
|
|
55
|
-
export async function generateReactTemplate(projectPath, config) {
|
|
56
|
-
// Create folder structure only
|
|
57
|
-
await createReactFolderStructure(projectPath, config);
|
|
58
|
-
|
|
59
|
-
// Generate package.json
|
|
60
|
-
await generateReactPackageJson(projectPath, config);
|
|
61
|
-
|
|
62
|
-
// Generate essential files (App.jsx, main.jsx, index.css, vite.config)
|
|
63
|
-
await generateReactEssentialFiles(projectPath, config);
|
|
64
|
-
|
|
65
|
-
// Generate README
|
|
66
|
-
await generateReactReadme(projectPath, config);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async function createReactFolderStructure(projectPath, config) {
|
|
70
|
-
const srcPath = path.join(projectPath, 'src');
|
|
71
|
-
const folderStructure = config.folderStructure || 'feature-based';
|
|
72
|
-
|
|
73
|
-
if (folderStructure === 'feature-based') {
|
|
74
|
-
// Feature-based structure
|
|
75
|
-
const features = ['auth', 'dashboard', 'users'];
|
|
76
|
-
for (const feature of features) {
|
|
77
|
-
await fs.ensureDir(path.join(srcPath, 'features', feature, 'components'));
|
|
78
|
-
await fs.ensureDir(path.join(srcPath, 'features', feature, 'hooks'));
|
|
79
|
-
await fs.ensureDir(path.join(srcPath, 'features', feature, 'services'));
|
|
80
|
-
await fs.ensureDir(path.join(srcPath, 'features', feature, 'types'));
|
|
81
|
-
|
|
82
|
-
// Barrel export
|
|
83
|
-
await fs.writeFile(
|
|
84
|
-
path.join(srcPath, 'features', feature, 'index.ts'),
|
|
85
|
-
generateFeatureExport(feature)
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Shared directory
|
|
90
|
-
await fs.ensureDir(path.join(srcPath, 'shared', 'components', 'ui'));
|
|
91
|
-
await fs.ensureDir(path.join(srcPath, 'shared', 'components', 'layout'));
|
|
92
|
-
await fs.ensureDir(path.join(srcPath, 'shared', 'hooks'));
|
|
93
|
-
await fs.ensureDir(path.join(srcPath, 'shared', 'utils'));
|
|
94
|
-
await fs.ensureDir(path.join(srcPath, 'shared', 'types'));
|
|
95
|
-
|
|
96
|
-
await fs.writeFile(
|
|
97
|
-
path.join(srcPath, 'shared', 'components', 'index.ts'),
|
|
98
|
-
`// Export shared components\n// TODO: Add your shared components here\n`
|
|
99
|
-
);
|
|
100
|
-
} else if (folderStructure === 'component-based') {
|
|
101
|
-
// Component-based structure
|
|
102
|
-
await fs.ensureDir(path.join(srcPath, 'components', 'ui'));
|
|
103
|
-
await fs.ensureDir(path.join(srcPath, 'components', 'layout'));
|
|
104
|
-
await fs.ensureDir(path.join(srcPath, 'components', 'forms'));
|
|
105
|
-
await fs.ensureDir(path.join(srcPath, 'hooks'));
|
|
106
|
-
await fs.ensureDir(path.join(srcPath, 'services'));
|
|
107
|
-
await fs.ensureDir(path.join(srcPath, 'utils'));
|
|
108
|
-
await fs.ensureDir(path.join(srcPath, 'types'));
|
|
109
|
-
} else if (folderStructure === 'atomic') {
|
|
110
|
-
// Atomic design structure
|
|
111
|
-
await fs.ensureDir(path.join(srcPath, 'components', 'atoms'));
|
|
112
|
-
await fs.ensureDir(path.join(srcPath, 'components', 'molecules'));
|
|
113
|
-
await fs.ensureDir(path.join(srcPath, 'components', 'organisms'));
|
|
114
|
-
await fs.ensureDir(path.join(srcPath, 'components', 'templates'));
|
|
115
|
-
await fs.ensureDir(path.join(srcPath, 'pages'));
|
|
116
|
-
await fs.ensureDir(path.join(srcPath, 'hooks'));
|
|
117
|
-
await fs.ensureDir(path.join(srcPath, 'services'));
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Common directories
|
|
121
|
-
await fs.ensureDir(path.join(srcPath, 'routes'));
|
|
122
|
-
await fs.ensureDir(path.join(srcPath, 'lib'));
|
|
123
|
-
await fs.ensureDir(path.join(projectPath, 'public'));
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
async function generateReactPackageJson(projectPath, config) {
|
|
127
|
-
const { language, styling, additionalLibraries = [] } = config;
|
|
128
|
-
const isTypeScript = language === 'typescript';
|
|
129
|
-
|
|
130
|
-
const spinner = ora('Fetching latest package versions...').start();
|
|
131
|
-
|
|
132
|
-
try {
|
|
133
|
-
// Fetch core dependencies
|
|
134
|
-
const [reactVer, reactDomVer, viteVer, pluginVer] = await Promise.all([
|
|
135
|
-
fetchVersion('react'),
|
|
136
|
-
fetchVersion('react-dom'),
|
|
137
|
-
fetchVersion('vite'),
|
|
138
|
-
fetchVersion('@vitejs/plugin-react'),
|
|
139
|
-
]);
|
|
140
|
-
|
|
141
|
-
const dependencies = {
|
|
142
|
-
react: reactVer,
|
|
143
|
-
'react-dom': reactDomVer,
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
const devDependencies = {
|
|
147
|
-
'@vitejs/plugin-react': pluginVer,
|
|
148
|
-
vite: viteVer,
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
// TypeScript dependencies
|
|
152
|
-
if (isTypeScript) {
|
|
153
|
-
const [tsVer, typesReactVer, typesReactDomVer] = await Promise.all([
|
|
154
|
-
fetchVersion('typescript'),
|
|
155
|
-
fetchVersion('@types/react'),
|
|
156
|
-
fetchVersion('@types/react-dom'),
|
|
157
|
-
]);
|
|
158
|
-
devDependencies['typescript'] = tsVer;
|
|
159
|
-
devDependencies['@types/react'] = typesReactVer;
|
|
160
|
-
devDependencies['@types/react-dom'] = typesReactDomVer;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Add router
|
|
164
|
-
if (additionalLibraries.includes('react-router')) {
|
|
165
|
-
dependencies['react-router-dom'] = await fetchVersion('react-router-dom');
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Add Tailwind
|
|
169
|
-
if (styling === 'tailwind') {
|
|
170
|
-
devDependencies['tailwindcss'] = await fetchVersion('tailwindcss');
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// Add libraries
|
|
174
|
-
if (additionalLibraries.includes('tanstack-query')) {
|
|
175
|
-
dependencies['@tanstack/react-query'] = await fetchVersion('@tanstack/react-query');
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (additionalLibraries.includes('redux-toolkit')) {
|
|
179
|
-
const [reduxVer, reactReduxVer] = await Promise.all([
|
|
180
|
-
fetchVersion('@reduxjs/toolkit'),
|
|
181
|
-
fetchVersion('react-redux'),
|
|
182
|
-
]);
|
|
183
|
-
dependencies['@reduxjs/toolkit'] = reduxVer;
|
|
184
|
-
dependencies['react-redux'] = reactReduxVer;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (additionalLibraries.includes('zustand')) {
|
|
188
|
-
dependencies['zustand'] = await fetchVersion('zustand');
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (additionalLibraries.includes('jotai')) {
|
|
192
|
-
dependencies['jotai'] = await fetchVersion('jotai');
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
if (additionalLibraries.includes('axios')) {
|
|
196
|
-
dependencies['axios'] = await fetchVersion('axios');
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
if (additionalLibraries.includes('zod')) {
|
|
200
|
-
dependencies['zod'] = await fetchVersion('zod');
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if (additionalLibraries.includes('react-hook-form')) {
|
|
204
|
-
const [formVer, resolversVer] = await Promise.all([
|
|
205
|
-
fetchVersion('react-hook-form'),
|
|
206
|
-
fetchVersion('@hookform/resolvers'),
|
|
207
|
-
]);
|
|
208
|
-
dependencies['react-hook-form'] = formVer;
|
|
209
|
-
dependencies['@hookform/resolvers'] = resolversVer;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
if (additionalLibraries.includes('framer-motion')) {
|
|
213
|
-
dependencies['framer-motion'] = await fetchVersion('framer-motion');
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (additionalLibraries.includes('react-icons')) {
|
|
217
|
-
dependencies['react-icons'] = await fetchVersion('react-icons');
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
if (additionalLibraries.includes('radix-ui')) {
|
|
221
|
-
const [dialogVer, dropdownVer, selectVer, slotVer] = await Promise.all([
|
|
222
|
-
fetchVersion('@radix-ui/react-dialog'),
|
|
223
|
-
fetchVersion('@radix-ui/react-dropdown-menu'),
|
|
224
|
-
fetchVersion('@radix-ui/react-select'),
|
|
225
|
-
fetchVersion('@radix-ui/react-slot'),
|
|
226
|
-
]);
|
|
227
|
-
Object.assign(dependencies, {
|
|
228
|
-
'@radix-ui/react-dialog': dialogVer,
|
|
229
|
-
'@radix-ui/react-dropdown-menu': dropdownVer,
|
|
230
|
-
'@radix-ui/react-select': selectVer,
|
|
231
|
-
'@radix-ui/react-slot': slotVer,
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
spinner.succeed(chalk.green('Fetched latest versions'));
|
|
236
|
-
|
|
237
|
-
const packageJson = {
|
|
238
|
-
name: config.projectName,
|
|
239
|
-
private: true,
|
|
240
|
-
version: '0.1.0',
|
|
241
|
-
type: 'module',
|
|
242
|
-
scripts: {
|
|
243
|
-
dev: 'vite',
|
|
244
|
-
build: isTypeScript ? 'tsc && vite build' : 'vite build',
|
|
245
|
-
preview: 'vite preview',
|
|
246
|
-
},
|
|
247
|
-
dependencies,
|
|
248
|
-
devDependencies,
|
|
249
|
-
};
|
|
250
|
-
|
|
251
|
-
await fs.writeJSON(path.join(projectPath, 'package.json'), packageJson, { spaces: 2 });
|
|
252
|
-
} catch (error) {
|
|
253
|
-
spinner.fail(chalk.yellow('Could not fetch versions, using fallbacks'));
|
|
254
|
-
|
|
255
|
-
// Fallback with latest tag
|
|
256
|
-
const dependencies = { react: 'latest', 'react-dom': 'latest' };
|
|
257
|
-
const devDependencies = {
|
|
258
|
-
'@vitejs/plugin-react': 'latest',
|
|
259
|
-
vite: 'latest',
|
|
260
|
-
...(isTypeScript && {
|
|
261
|
-
typescript: 'latest',
|
|
262
|
-
'@types/react': 'latest',
|
|
263
|
-
'@types/react-dom': 'latest',
|
|
264
|
-
}),
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
const packageJson = {
|
|
268
|
-
name: config.projectName,
|
|
269
|
-
private: true,
|
|
270
|
-
version: '0.1.0',
|
|
271
|
-
type: 'module',
|
|
272
|
-
scripts: {
|
|
273
|
-
dev: 'vite',
|
|
274
|
-
build: isTypeScript ? 'tsc && vite build' : 'vite build',
|
|
275
|
-
preview: 'vite preview',
|
|
276
|
-
},
|
|
277
|
-
dependencies,
|
|
278
|
-
devDependencies,
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
await fs.writeJSON(path.join(projectPath, 'package.json'), packageJson, { spaces: 2 });
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
async function generateReactEssentialFiles(projectPath, config) {
|
|
286
|
-
const { language } = config;
|
|
287
|
-
const isTypeScript = language === 'typescript';
|
|
288
|
-
const ext = isTypeScript ? 'tsx' : 'jsx';
|
|
289
|
-
const srcPath = path.join(projectPath, 'src');
|
|
290
|
-
|
|
291
|
-
// Create App component
|
|
292
|
-
const appContent = `import { useState } from 'react'
|
|
293
|
-
import './App.css'
|
|
294
|
-
|
|
295
|
-
function App() {
|
|
296
|
-
const [count, setCount] = useState(0)
|
|
297
|
-
|
|
298
|
-
return (
|
|
299
|
-
<>
|
|
300
|
-
<div>
|
|
301
|
-
<h1>Welcome to ${config.projectName}</h1>
|
|
302
|
-
<div className="card">
|
|
303
|
-
<button onClick={() => setCount((count) => count + 1)}>
|
|
304
|
-
count is {count}
|
|
305
|
-
</button>
|
|
306
|
-
<p>
|
|
307
|
-
Edit <code>src/App.${ext}</code> and save to test HMR
|
|
308
|
-
</p>
|
|
309
|
-
</div>
|
|
310
|
-
<p className="read-the-docs">
|
|
311
|
-
Click on the Vite and React logos to learn more
|
|
312
|
-
</p>
|
|
313
|
-
</div>
|
|
314
|
-
</>
|
|
315
|
-
)
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
export default App
|
|
319
|
-
`;
|
|
320
|
-
|
|
321
|
-
await fs.writeFile(path.join(srcPath, `App.${ext}`), appContent);
|
|
322
|
-
|
|
323
|
-
// Create main entry point
|
|
324
|
-
const mainContent = `import { StrictMode } from 'react'
|
|
325
|
-
import { createRoot } from 'react-dom/client'
|
|
326
|
-
import './index.css'
|
|
327
|
-
import App from './App.${ext}'
|
|
328
|
-
|
|
329
|
-
createRoot(document.getElementById('root')${isTypeScript ? '!' : ''}).render(
|
|
330
|
-
<StrictMode>
|
|
331
|
-
<App />
|
|
332
|
-
</StrictMode>,
|
|
333
|
-
)
|
|
334
|
-
`;
|
|
335
|
-
|
|
336
|
-
await fs.writeFile(path.join(srcPath, `main.${ext}`), mainContent);
|
|
337
|
-
|
|
338
|
-
// Create index.css
|
|
339
|
-
const indexCssContent = `:root {
|
|
340
|
-
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
341
|
-
line-height: 1.5;
|
|
342
|
-
font-weight: 400;
|
|
343
|
-
|
|
344
|
-
color-scheme: light dark;
|
|
345
|
-
color: rgba(255, 255, 255, 0.87);
|
|
346
|
-
background-color: #242424;
|
|
347
|
-
|
|
348
|
-
font-synthesis: none;
|
|
349
|
-
text-rendering: optimizeLegibility;
|
|
350
|
-
-webkit-font-smoothing: antialiased;
|
|
351
|
-
-moz-osx-font-smoothing: grayscale;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
a {
|
|
355
|
-
font-weight: 500;
|
|
356
|
-
color: #646cff;
|
|
357
|
-
text-decoration: inherit;
|
|
358
|
-
}
|
|
359
|
-
a:hover {
|
|
360
|
-
color: #535bf2;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
body {
|
|
364
|
-
margin: 0;
|
|
365
|
-
display: flex;
|
|
366
|
-
place-items: center;
|
|
367
|
-
min-width: 320px;
|
|
368
|
-
min-height: 100vh;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
h1 {
|
|
372
|
-
font-size: 3.2em;
|
|
373
|
-
line-height: 1.1;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
button {
|
|
377
|
-
border-radius: 8px;
|
|
378
|
-
border: 1px solid transparent;
|
|
379
|
-
padding: 0.6em 1.2em;
|
|
380
|
-
font-size: 1em;
|
|
381
|
-
font-weight: 500;
|
|
382
|
-
font-family: inherit;
|
|
383
|
-
background-color: #1a1a1a;
|
|
384
|
-
cursor: pointer;
|
|
385
|
-
transition: border-color 0.25s;
|
|
386
|
-
}
|
|
387
|
-
button:hover {
|
|
388
|
-
border-color: #646cff;
|
|
389
|
-
}
|
|
390
|
-
button:focus,
|
|
391
|
-
button:focus-visible {
|
|
392
|
-
outline: 4px auto -webkit-focus-ring-color;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
@media (prefers-color-scheme: light) {
|
|
396
|
-
:root {
|
|
397
|
-
color: #213547;
|
|
398
|
-
background-color: #ffffff;
|
|
399
|
-
}
|
|
400
|
-
a:hover {
|
|
401
|
-
color: #747bff;
|
|
402
|
-
}
|
|
403
|
-
button {
|
|
404
|
-
background-color: #f9f9f9;
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
`;
|
|
408
|
-
|
|
409
|
-
await fs.writeFile(path.join(srcPath, 'index.css'), indexCssContent);
|
|
410
|
-
|
|
411
|
-
// Create App.css
|
|
412
|
-
const appCssContent = `#root {
|
|
413
|
-
max-width: 1280px;
|
|
414
|
-
margin: 0 auto;
|
|
415
|
-
padding: 2rem;
|
|
416
|
-
text-align: center;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
.card {
|
|
420
|
-
padding: 2em;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
.read-the-docs {
|
|
424
|
-
color: #888;
|
|
425
|
-
}
|
|
426
|
-
`;
|
|
427
|
-
|
|
428
|
-
await fs.writeFile(path.join(srcPath, 'App.css'), appCssContent);
|
|
429
|
-
|
|
430
|
-
// Create vite.config
|
|
431
|
-
const viteConfigContent = isTypeScript
|
|
432
|
-
? `import { defineConfig } from 'vite'
|
|
433
|
-
import react from '@vitejs/plugin-react'
|
|
434
|
-
|
|
435
|
-
// https://vite.dev/config/
|
|
436
|
-
export default defineConfig({
|
|
437
|
-
plugins: [react()],
|
|
438
|
-
})
|
|
439
|
-
`
|
|
440
|
-
: `import { defineConfig } from 'vite'
|
|
441
|
-
import react from '@vitejs/plugin-react'
|
|
442
|
-
|
|
443
|
-
// https://vite.dev/config/
|
|
444
|
-
export default defineConfig({
|
|
445
|
-
plugins: [react()],
|
|
446
|
-
})
|
|
447
|
-
`;
|
|
448
|
-
|
|
449
|
-
await fs.writeFile(
|
|
450
|
-
path.join(projectPath, `vite.config.${isTypeScript ? 'ts' : 'js'}`),
|
|
451
|
-
viteConfigContent
|
|
452
|
-
);
|
|
453
|
-
|
|
454
|
-
// Create index.html in project root
|
|
455
|
-
const indexHtmlContent = `<!doctype html>
|
|
456
|
-
<html lang="en">
|
|
457
|
-
<head>
|
|
458
|
-
<meta charset="UTF-8" />
|
|
459
|
-
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
460
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
461
|
-
<title>${config.projectName}</title>
|
|
462
|
-
</head>
|
|
463
|
-
<body>
|
|
464
|
-
<div id="root"></div>
|
|
465
|
-
<script type="module" src="/src/main.${ext}"></script>
|
|
466
|
-
</body>
|
|
467
|
-
</html>
|
|
468
|
-
`;
|
|
469
|
-
|
|
470
|
-
await fs.writeFile(path.join(projectPath, 'index.html'), indexHtmlContent);
|
|
471
|
-
|
|
472
|
-
// Create .gitignore
|
|
473
|
-
const gitignoreContent = `# Logs
|
|
474
|
-
logs
|
|
475
|
-
*.log
|
|
476
|
-
npm-debug.log*
|
|
477
|
-
yarn-debug.log*
|
|
478
|
-
yarn-error.log*
|
|
479
|
-
pnpm-debug.log*
|
|
480
|
-
lerna-debug.log*
|
|
481
|
-
|
|
482
|
-
node_modules
|
|
483
|
-
dist
|
|
484
|
-
dist-ssr
|
|
485
|
-
*.local
|
|
486
|
-
|
|
487
|
-
# Editor directories and files
|
|
488
|
-
.vscode/*
|
|
489
|
-
!.vscode/extensions.json
|
|
490
|
-
.idea
|
|
491
|
-
.DS_Store
|
|
492
|
-
*.suo
|
|
493
|
-
*.ntvs*
|
|
494
|
-
*.njsproj
|
|
495
|
-
*.sln
|
|
496
|
-
*.sw?
|
|
497
|
-
`;
|
|
498
|
-
|
|
499
|
-
await fs.writeFile(path.join(projectPath, '.gitignore'), gitignoreContent);
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
async function generateReactReadme(projectPath, config) {
|
|
503
|
-
const { projectName, folderStructure, language, styling, packageManager } = config;
|
|
504
|
-
|
|
505
|
-
const readme = `# ${projectName}
|
|
506
|
-
|
|
507
|
-
Created with InitKit CLI
|
|
508
|
-
|
|
509
|
-
## Setup
|
|
510
|
-
|
|
511
|
-
1. Install dependencies:
|
|
512
|
-
\`\`\`bash
|
|
513
|
-
${packageManager} install
|
|
514
|
-
\`\`\`
|
|
515
|
-
|
|
516
|
-
2. Run the development server:
|
|
517
|
-
\`\`\`bash
|
|
518
|
-
${packageManager} ${packageManager === 'npm' ? 'run ' : ''}dev
|
|
519
|
-
\`\`\`
|
|
520
|
-
|
|
521
|
-
3. Open [http://localhost:3000](http://localhost:3000)
|
|
522
|
-
|
|
523
|
-
## Tech Stack
|
|
524
|
-
|
|
525
|
-
- **React 18** - UI library
|
|
526
|
-
- **Vite 6** - Build tool${language === 'typescript' ? '\n- **TypeScript** - Type safety' : ''}${styling === 'tailwind' ? '\n- **Tailwind CSS v4** - Styling' : ''}
|
|
527
|
-
|
|
528
|
-
## Folder Structure
|
|
529
|
-
|
|
530
|
-
\`\`\`
|
|
531
|
-
src/
|
|
532
|
-
${
|
|
533
|
-
folderStructure === 'feature-based'
|
|
534
|
-
? `├── features/ # Feature modules
|
|
535
|
-
│ ├── auth/ # Authentication
|
|
536
|
-
│ ├── dashboard/ # Dashboard
|
|
537
|
-
│ └── users/ # Users
|
|
538
|
-
├── shared/ # Shared code`
|
|
539
|
-
: folderStructure === 'atomic'
|
|
540
|
-
? `├── components/ # Atomic design
|
|
541
|
-
│ ├── atoms/ # Basic UI elements
|
|
542
|
-
│ ├── molecules/ # Simple components
|
|
543
|
-
│ ├── organisms/ # Complex components
|
|
544
|
-
│ └── templates/ # Page templates
|
|
545
|
-
├── pages/ # Page components`
|
|
546
|
-
: `├── components/ # React components
|
|
547
|
-
│ ├── ui/ # UI components
|
|
548
|
-
│ └── layout/ # Layout components
|
|
549
|
-
├── hooks/ # Custom hooks
|
|
550
|
-
├── services/ # API services`
|
|
551
|
-
}
|
|
552
|
-
├── routes/ # Routing configuration
|
|
553
|
-
├── lib/ # Utilities
|
|
554
|
-
└── public/ # Static files
|
|
555
|
-
\`\`\`
|
|
556
|
-
|
|
557
|
-
## Next Steps
|
|
558
|
-
|
|
559
|
-
1. Run \`npm create vite@latest . -- --template react${language === 'typescript' ? '-ts' : ''}\` to initialize Vite${styling === 'tailwind' ? '\n2. Install Tailwind v4: `' + packageManager + (packageManager === 'npm' ? ' install' : ' add') + ' tailwindcss@next`' : ''}
|
|
560
|
-
3. Start building in \`src/features/\`
|
|
561
|
-
4. Add environment variables in \`.env\`
|
|
562
|
-
|
|
563
|
-
---
|
|
564
|
-
|
|
565
|
-
Built with InitKit
|
|
566
|
-
`;
|
|
567
|
-
|
|
568
|
-
await fs.writeFile(path.join(projectPath, 'README.md'), readme);
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
function generateFeatureExport(featureName) {
|
|
572
|
-
return `// ${featureName.toUpperCase()} Feature
|
|
573
|
-
|
|
574
|
-
// TODO: Export your components
|
|
575
|
-
// export { ${featureName.charAt(0).toUpperCase() + featureName.slice(1)}Component } from './components/${featureName.charAt(0).toUpperCase() + featureName.slice(1)}Component';
|
|
576
|
-
|
|
577
|
-
// TODO: Export your hooks
|
|
578
|
-
// export { use${featureName.charAt(0).toUpperCase() + featureName.slice(1)} } from './hooks/use${featureName.charAt(0).toUpperCase() + featureName.slice(1)}';
|
|
579
|
-
|
|
580
|
-
// TODO: Export your services
|
|
581
|
-
// export * from './services/${featureName}Service';
|
|
582
|
-
|
|
583
|
-
// TODO: Export your types
|
|
584
|
-
// export type * from './types/${featureName}.types';
|
|
585
|
-
`;
|
|
586
|
-
}
|