create-modern-react 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +270 -72
  2. package/bin/index.js +13 -13
  3. package/lib/install.js +103 -32
  4. package/lib/prompts.js +152 -179
  5. package/lib/setup.js +267 -159
  6. package/package.json +17 -8
  7. package/templates/base/.env.example +9 -0
  8. package/templates/base/.eslintrc.cjs +37 -0
  9. package/templates/base/.prettierrc +11 -0
  10. package/templates/base/components.json +17 -0
  11. package/templates/base/index.html +2 -1
  12. package/templates/base/package.json +33 -14
  13. package/templates/base/postcss.config.js +6 -0
  14. package/templates/base/src/App.tsx +5 -18
  15. package/templates/base/src/components/layout/error-boundary.tsx +60 -0
  16. package/templates/base/src/components/layout/index.ts +2 -0
  17. package/templates/base/src/components/layout/root-layout.tsx +36 -0
  18. package/templates/base/src/components/ui/button.tsx +55 -0
  19. package/templates/base/src/components/ui/card.tsx +85 -0
  20. package/templates/base/src/components/ui/index.ts +12 -0
  21. package/templates/base/src/components/ui/input.tsx +24 -0
  22. package/templates/base/src/components/ui/separator.tsx +29 -0
  23. package/templates/base/src/components/ui/skeleton.tsx +15 -0
  24. package/templates/base/src/hooks/index.ts +3 -0
  25. package/templates/base/src/hooks/use-cancel-token.ts +63 -0
  26. package/templates/base/src/hooks/use-debounce.ts +29 -0
  27. package/templates/base/src/hooks/use-loader.ts +39 -0
  28. package/templates/base/src/index.css +73 -60
  29. package/templates/base/src/lib/utils.ts +14 -0
  30. package/templates/base/src/main.tsx +6 -6
  31. package/templates/base/src/providers/index.tsx +27 -0
  32. package/templates/base/src/providers/theme-provider.tsx +92 -0
  33. package/templates/base/src/routes/index.tsx +40 -0
  34. package/templates/base/src/routes/routes.ts +36 -0
  35. package/templates/base/src/screens/home/index.tsx +132 -0
  36. package/templates/base/src/screens/not-found/index.tsx +29 -0
  37. package/templates/base/src/services/alertify-services.ts +133 -0
  38. package/templates/base/src/services/api/api-helpers.ts +130 -0
  39. package/templates/base/src/services/api/axios-instance.ts +77 -0
  40. package/templates/base/src/services/api/index.ts +9 -0
  41. package/templates/base/src/services/index.ts +2 -0
  42. package/templates/base/src/types/index.ts +55 -0
  43. package/templates/base/src/vite-env.d.ts +31 -0
  44. package/templates/base/tailwind.config.js +77 -0
  45. package/templates/base/tsconfig.json +4 -3
  46. package/templates/base/tsconfig.node.json +22 -0
  47. package/templates/base/vite.config.ts +65 -4
  48. package/templates/optional/antd/config-provider.tsx +33 -0
  49. package/templates/optional/antd/index.ts +2 -0
  50. package/templates/optional/antd/styles/antd-overrides.css +104 -0
  51. package/templates/optional/antd/theme.ts +75 -0
  52. package/templates/optional/husky/.husky/pre-commit +1 -0
  53. package/templates/optional/husky/.lintstagedrc.json +6 -0
  54. package/templates/optional/redux/hooks.ts +17 -0
  55. package/templates/optional/redux/index.ts +13 -0
  56. package/templates/optional/redux/provider.tsx +33 -0
  57. package/templates/optional/redux/store/index.ts +45 -0
  58. package/templates/optional/redux/store/slices/app-slice.ts +62 -0
  59. package/templates/base/src/App.css +0 -14
package/lib/setup.js CHANGED
@@ -1,228 +1,336 @@
1
- const fs = require("fs-extra");
2
- const path = require("path");
3
- const chalk = require("chalk");
4
- const { runCommand } = require("./install");
5
-
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+ const { runCommand } = require('./install');
5
+
6
+ /**
7
+ * Main setup function - orchestrates the entire project generation
8
+ */
6
9
  async function setupProject(config) {
7
10
  const { projectPath, projectName } = config;
8
11
 
9
- console.log(chalk.blue("\nšŸ—ļø Setting up project structure..."));
12
+ console.log(chalk.blue('\nšŸ—ļø Setting up project structure...\n'));
10
13
 
11
- // Create project directory
14
+ // Step 1: Create project directory
12
15
  await fs.ensureDir(projectPath);
13
16
 
14
- // Copy base template
15
- const templatePath = path.join(__dirname, "../templates/base");
17
+ // Step 2: Copy base template
18
+ console.log(chalk.gray(' Copying base template...'));
19
+ const templatePath = path.join(__dirname, '../templates/base');
16
20
  await fs.copy(templatePath, projectPath);
17
21
 
18
- // Update package.json with project name and selected dependencies
19
- await updatePackageJson(config);
22
+ // Step 3: Handle Antd vs Shadcn/ui
23
+ if (config.useAntd) {
24
+ console.log(chalk.gray(' Configuring Ant Design (removing Shadcn/ui)...'));
25
+ await removeDirectory(path.join(projectPath, 'src/components/ui'));
26
+ await fs.remove(path.join(projectPath, 'components.json'));
27
+ await copyOptionalTemplate('antd', projectPath);
28
+ await updateProvidersForAntd(projectPath);
29
+ }
30
+
31
+ // Step 4: Copy optional feature templates
32
+ if (config.useRedux) {
33
+ console.log(chalk.gray(' Adding Redux Toolkit + Redux Persist...'));
34
+ await copyOptionalTemplate('redux', projectPath);
35
+ await updateProvidersForRedux(projectPath, config.useAntd);
36
+ }
37
+
38
+ if (config.useHusky) {
39
+ console.log(chalk.gray(' Adding Husky + lint-staged...'));
40
+ await copyOptionalTemplate('husky', projectPath);
41
+ }
20
42
 
21
- // Configure selected libraries
22
- await configureLibraries(config);
43
+ // Step 5: Update package.json
44
+ console.log(chalk.gray(' Configuring package.json...'));
45
+ await updatePackageJson(config);
23
46
 
24
- // Initialize git if requested
25
- if (config.git && !config.skipGit) {
47
+ // Step 6: Initialize git if requested
48
+ if (config.initGit) {
26
49
  await initializeGit(config);
27
50
  }
28
51
 
29
- console.log(chalk.green("āœ… Project structure created successfully!"));
52
+ // Step 7: Setup Husky if selected
53
+ if (config.useHusky && config.initGit) {
54
+ await setupHusky(projectPath);
55
+ }
56
+
57
+ console.log(chalk.green('\nāœ… Project structure created successfully!\n'));
30
58
  }
31
59
 
60
+ /**
61
+ * Update package.json with project name and selected dependencies
62
+ */
32
63
  async function updatePackageJson(config) {
33
- const packageJsonPath = path.join(config.projectPath, "package.json");
64
+ const packageJsonPath = path.join(config.projectPath, 'package.json');
34
65
  const packageJson = await fs.readJson(packageJsonPath);
35
66
 
36
67
  // Update name
37
68
  packageJson.name = config.projectName;
38
69
 
39
- // Add dependencies based on configuration
70
+ // Add optional dependencies
40
71
  const dependencies = { ...packageJson.dependencies };
41
72
  const devDependencies = { ...packageJson.devDependencies };
42
73
 
43
- // UI Library dependencies
44
- if (config.uiLibrary === "antd") {
45
- dependencies["antd"] = "^5.0.0";
46
- } else if (config.uiLibrary === "mui") {
47
- dependencies["@mui/material"] = "^5.0.0";
48
- dependencies["@emotion/react"] = "^11.0.0";
49
- dependencies["@emotion/styled"] = "^11.0.0";
50
- } else if (config.uiLibrary === "chakra") {
51
- dependencies["@chakra-ui/react"] = "^2.0.0";
52
- dependencies["@emotion/react"] = "^11.0.0";
53
- dependencies["@emotion/styled"] = "^11.0.0";
54
- dependencies["framer-motion"] = "^6.0.0";
55
- }
56
-
57
- // CSS Framework dependencies
58
- if (config.cssFramework === "tailwind") {
59
- devDependencies["tailwindcss"] = "^3.0.0";
60
- devDependencies["postcss"] = "^8.0.0";
61
- devDependencies["autoprefixer"] = "^10.0.0";
62
- } else if (config.cssFramework === "styled-components") {
63
- dependencies["styled-components"] = "^6.0.0";
64
- devDependencies["@types/styled-components"] = "^5.1.0";
65
- }
66
-
67
- // State Management dependencies
68
- if (config.stateManagement === "redux-toolkit") {
69
- dependencies["@reduxjs/toolkit"] = "^2.0.0";
70
- dependencies["react-redux"] = "^9.0.0";
71
- dependencies["redux-persist"] = "^6.0.0";
72
- } else if (config.stateManagement === "zustand") {
73
- dependencies["zustand"] = "^4.0.0";
74
- } else if (config.stateManagement === "jotai") {
75
- dependencies["jotai"] = "^2.0.0";
76
- }
77
-
78
- // Data Fetching dependencies
79
- if (config.dataFetching === "react-query") {
80
- dependencies["@tanstack/react-query"] = "^5.0.0";
81
- dependencies["@tanstack/react-query-devtools"] = "^5.0.0";
82
- } else if (config.dataFetching === "swr") {
83
- dependencies["swr"] = "^2.0.0";
84
- } else if (config.dataFetching === "apollo") {
85
- dependencies["@apollo/client"] = "^3.0.0";
86
- dependencies["graphql"] = "^16.0.0";
87
- }
88
-
89
- // Routing dependencies
90
- if (config.routing === "react-router") {
91
- dependencies["react-router-dom"] = "^6.0.0";
92
- } else if (config.routing === "wouter") {
93
- dependencies["wouter"] = "^3.0.0";
94
- }
95
-
96
- // Icon dependencies
97
- if (config.icons === "lucide") {
98
- dependencies["lucide-react"] = "^0.400.0";
99
- } else if (config.icons === "react-icons") {
100
- dependencies["react-icons"] = "^5.0.0";
101
- } else if (config.icons === "heroicons") {
102
- dependencies["@heroicons/react"] = "^2.0.0";
103
- }
104
-
105
- // Development Tools dependencies
106
- if (config.devTools.includes("storybook")) {
107
- devDependencies["@storybook/react-vite"] = "^8.0.0";
108
- devDependencies["@storybook/addon-essentials"] = "^8.0.0";
109
- devDependencies["storybook"] = "^8.0.0";
74
+ // Redux dependencies
75
+ if (config.useRedux) {
76
+ dependencies['@reduxjs/toolkit'] = '^2.2.0';
77
+ dependencies['react-redux'] = '^9.1.0';
78
+ dependencies['redux-persist'] = '^6.0.0';
110
79
  }
111
80
 
112
- if (config.devTools.includes("testing")) {
113
- devDependencies["jest"] = "^29.0.0";
114
- devDependencies["@testing-library/react"] = "^14.0.0";
115
- devDependencies["@testing-library/jest-dom"] = "^6.0.0";
116
- devDependencies["@testing-library/user-event"] = "^14.0.0";
81
+ // Ant Design dependencies (replaces Shadcn)
82
+ if (config.useAntd) {
83
+ dependencies['antd'] = '^5.20.0';
84
+ dependencies['@ant-design/icons'] = '^5.4.0';
85
+ // Remove Radix dependency when using Antd
86
+ delete dependencies['@radix-ui/react-slot'];
117
87
  }
118
88
 
119
- if (config.devTools.includes("husky")) {
120
- devDependencies["husky"] = "^9.0.0";
121
- devDependencies["lint-staged"] = "^15.0.0";
122
- }
89
+ // Husky dependencies
90
+ if (config.useHusky) {
91
+ devDependencies['husky'] = '^9.1.0';
92
+ devDependencies['lint-staged'] = '^15.2.0';
123
93
 
124
- // PWA dependencies
125
- if (config.pwa) {
126
- devDependencies["vite-plugin-pwa"] = "^0.20.0";
94
+ // Add prepare script for husky
95
+ packageJson.scripts = packageJson.scripts || {};
96
+ packageJson.scripts.prepare = 'husky';
127
97
  }
128
98
 
129
- packageJson.dependencies = dependencies;
130
- packageJson.devDependencies = devDependencies;
99
+ packageJson.dependencies = sortObjectKeys(dependencies);
100
+ packageJson.devDependencies = sortObjectKeys(devDependencies);
131
101
 
132
102
  await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
133
103
  }
134
104
 
135
- async function configureLibraries(config) {
136
- const { projectPath } = config;
105
+ /**
106
+ * Copy an optional template to the project
107
+ */
108
+ async function copyOptionalTemplate(templateName, projectPath) {
109
+ const optionalTemplatePath = path.join(
110
+ __dirname,
111
+ '../templates/optional',
112
+ templateName
113
+ );
137
114
 
138
- // Configure Tailwind if selected
139
- if (config.cssFramework === "tailwind") {
140
- await configureTailwind(projectPath);
115
+ if (await fs.pathExists(optionalTemplatePath)) {
116
+ // For redux and antd, copy to src directory
117
+ if (templateName === 'redux') {
118
+ await fs.copy(optionalTemplatePath, path.join(projectPath, 'src/redux'));
119
+ } else if (templateName === 'antd') {
120
+ await fs.copy(optionalTemplatePath, path.join(projectPath, 'src/antd'));
121
+ // Also copy the styles file to src/styles
122
+ const stylesFile = path.join(optionalTemplatePath, 'styles/antd-overrides.css');
123
+ if (await fs.pathExists(stylesFile)) {
124
+ await fs.ensureDir(path.join(projectPath, 'src/styles'));
125
+ await fs.copy(
126
+ stylesFile,
127
+ path.join(projectPath, 'src/styles/antd-overrides.css')
128
+ );
129
+ }
130
+ } else if (templateName === 'husky') {
131
+ // Copy husky files to root
132
+ await fs.copy(
133
+ path.join(optionalTemplatePath, '.husky'),
134
+ path.join(projectPath, '.husky')
135
+ );
136
+ await fs.copy(
137
+ path.join(optionalTemplatePath, '.lintstagedrc.json'),
138
+ path.join(projectPath, '.lintstagedrc.json')
139
+ );
140
+ }
141
141
  }
142
+ }
142
143
 
143
- // Configure Vite plugins based on selections
144
- await configureVite(config);
144
+ /**
145
+ * Update providers/index.tsx to include Antd ConfigProvider
146
+ */
147
+ async function updateProvidersForAntd(projectPath) {
148
+ const providersContent = `import { type ReactNode } from 'react';
149
+ import { ThemeProvider } from './theme-provider';
150
+ import { RootLayout } from '~/components/layout';
151
+ import { ErrorBoundary } from '~/components/layout';
152
+ import { AntdConfigProvider } from '~/antd';
153
+ import '~/styles/antd-overrides.css';
154
+
155
+ interface ProvidersProps {
156
+ children: ReactNode;
157
+ }
145
158
 
146
- // Add configuration files for selected libraries
147
- await addConfigFiles(config);
159
+ /**
160
+ * Application providers composition
161
+ * Wraps the app with all necessary context providers
162
+ */
163
+ export function Providers({ children }: ProvidersProps) {
164
+ return (
165
+ <ErrorBoundary>
166
+ <ThemeProvider defaultTheme="system" storageKey="app-theme">
167
+ <AntdConfigProvider>
168
+ <RootLayout>{children}</RootLayout>
169
+ </AntdConfigProvider>
170
+ </ThemeProvider>
171
+ </ErrorBoundary>
172
+ );
148
173
  }
149
174
 
150
- async function configureTailwind(projectPath) {
151
- const tailwindConfig = `/** @type {import('tailwindcss').Config} */
152
- export default {
153
- content: [
154
- "./index.html",
155
- "./src/**/*.{js,ts,jsx,tsx}",
156
- ],
157
- theme: {
158
- extend: {},
159
- },
160
- plugins: [],
161
- }`;
162
-
163
- const postcssConfig = `export default {
164
- plugins: {
165
- tailwindcss: {},
166
- autoprefixer: {},
167
- },
168
- }`;
175
+ export { ThemeProvider, useTheme } from './theme-provider';
176
+ `;
169
177
 
170
178
  await fs.writeFile(
171
- path.join(projectPath, "tailwind.config.js"),
172
- tailwindConfig,
173
- );
174
- await fs.writeFile(
175
- path.join(projectPath, "postcss.config.js"),
176
- postcssConfig,
179
+ path.join(projectPath, 'src/providers/index.tsx'),
180
+ providersContent
177
181
  );
178
182
 
179
- // Add Tailwind directives to CSS
180
- const cssPath = path.join(projectPath, "src/index.css");
181
- const tailwindDirectives = `@tailwind base;
182
- @tailwind components;
183
- @tailwind utilities;
183
+ // Create styles directory if it doesn't exist
184
+ await fs.ensureDir(path.join(projectPath, 'src/styles'));
185
+ }
184
186
 
185
- `;
187
+ /**
188
+ * Update providers/index.tsx to include Redux Provider
189
+ */
190
+ async function updateProvidersForRedux(projectPath, hasAntd) {
191
+ let providersContent;
192
+
193
+ if (hasAntd) {
194
+ providersContent = `import { type ReactNode } from 'react';
195
+ import { ThemeProvider } from './theme-provider';
196
+ import { RootLayout } from '~/components/layout';
197
+ import { ErrorBoundary } from '~/components/layout';
198
+ import { AntdConfigProvider } from '~/antd';
199
+ import { ReduxProvider } from '~/redux';
200
+ import '~/styles/antd-overrides.css';
201
+
202
+ interface ProvidersProps {
203
+ children: ReactNode;
204
+ }
186
205
 
187
- if (await fs.pathExists(cssPath)) {
188
- const existingCss = await fs.readFile(cssPath, "utf8");
189
- await fs.writeFile(cssPath, tailwindDirectives + existingCss);
206
+ /**
207
+ * Application providers composition
208
+ * Wraps the app with all necessary context providers
209
+ *
210
+ * Order: ErrorBoundary > Redux > Theme > Antd > Layout
211
+ */
212
+ export function Providers({ children }: ProvidersProps) {
213
+ return (
214
+ <ErrorBoundary>
215
+ <ReduxProvider>
216
+ <ThemeProvider defaultTheme="system" storageKey="app-theme">
217
+ <AntdConfigProvider>
218
+ <RootLayout>{children}</RootLayout>
219
+ </AntdConfigProvider>
220
+ </ThemeProvider>
221
+ </ReduxProvider>
222
+ </ErrorBoundary>
223
+ );
224
+ }
225
+
226
+ export { ThemeProvider, useTheme } from './theme-provider';
227
+ `;
190
228
  } else {
191
- await fs.writeFile(cssPath, tailwindDirectives);
192
- }
229
+ providersContent = `import { type ReactNode } from 'react';
230
+ import { ThemeProvider } from './theme-provider';
231
+ import { RootLayout } from '~/components/layout';
232
+ import { ErrorBoundary } from '~/components/layout';
233
+ import { ReduxProvider } from '~/redux';
234
+
235
+ interface ProvidersProps {
236
+ children: ReactNode;
193
237
  }
194
238
 
195
- async function configureVite(config) {
196
- // This would configure vite.config.ts based on selected options
197
- // For now, we'll use the existing base template configuration
239
+ /**
240
+ * Application providers composition
241
+ * Wraps the app with all necessary context providers
242
+ *
243
+ * Order: ErrorBoundary > Redux > Theme > Layout
244
+ */
245
+ export function Providers({ children }: ProvidersProps) {
246
+ return (
247
+ <ErrorBoundary>
248
+ <ReduxProvider>
249
+ <ThemeProvider defaultTheme="system" storageKey="app-theme">
250
+ <RootLayout>{children}</RootLayout>
251
+ </ThemeProvider>
252
+ </ReduxProvider>
253
+ </ErrorBoundary>
254
+ );
198
255
  }
199
256
 
200
- async function addConfigFiles(config) {
201
- // Add configuration files for selected tools
202
- // This would add ESLint, Prettier, Jest configs, etc.
257
+ export { ThemeProvider, useTheme } from './theme-provider';
258
+ `;
259
+ }
260
+
261
+ await fs.writeFile(
262
+ path.join(projectPath, 'src/providers/index.tsx'),
263
+ providersContent
264
+ );
203
265
  }
204
266
 
267
+ /**
268
+ * Remove a directory and all its contents
269
+ */
270
+ async function removeDirectory(dirPath) {
271
+ if (await fs.pathExists(dirPath)) {
272
+ await fs.remove(dirPath);
273
+ }
274
+ }
275
+
276
+ /**
277
+ * Initialize git repository
278
+ */
205
279
  async function initializeGit(config) {
206
280
  const { projectPath } = config;
207
281
 
208
282
  try {
209
- console.log(chalk.blue("šŸ”§ Initializing Git repository..."));
283
+ console.log(chalk.gray(' Initializing Git repository...'));
210
284
 
211
- await runCommand("git", ["init"], projectPath);
212
- await runCommand("git", ["add", "."], projectPath);
285
+ await runCommand('git', ['init'], projectPath);
286
+ await runCommand('git', ['add', '.'], projectPath);
213
287
  await runCommand(
214
- "git",
215
- ["commit", "-m", "Initial commit from create-modern-react"],
216
- projectPath,
288
+ 'git',
289
+ ['commit', '-m', 'Initial commit from create-modern-react'],
290
+ projectPath
291
+ );
292
+
293
+ console.log(chalk.green(' āœ… Git repository initialized!'));
294
+ } catch (error) {
295
+ console.warn(
296
+ chalk.yellow(' āš ļø Could not initialize Git repository:'),
297
+ error.message
217
298
  );
299
+ }
300
+ }
301
+
302
+ /**
303
+ * Setup Husky hooks after git init
304
+ */
305
+ async function setupHusky(projectPath) {
306
+ try {
307
+ console.log(chalk.gray(' Setting up Husky git hooks...'));
218
308
 
219
- console.log(chalk.green("āœ… Git repository initialized!"));
309
+ // Make pre-commit hook executable
310
+ const preCommitPath = path.join(projectPath, '.husky/pre-commit');
311
+ if (await fs.pathExists(preCommitPath)) {
312
+ await fs.chmod(preCommitPath, '755');
313
+ }
314
+
315
+ console.log(chalk.green(' āœ… Husky configured!'));
220
316
  } catch (error) {
221
317
  console.warn(
222
- chalk.yellow("āš ļø Could not initialize Git repository:"),
223
- error.message,
318
+ chalk.yellow(' āš ļø Could not setup Husky:'),
319
+ error.message
224
320
  );
225
321
  }
226
322
  }
227
323
 
324
+ /**
325
+ * Sort object keys alphabetically
326
+ */
327
+ function sortObjectKeys(obj) {
328
+ return Object.keys(obj)
329
+ .sort()
330
+ .reduce((sorted, key) => {
331
+ sorted[key] = obj[key];
332
+ return sorted;
333
+ }, {});
334
+ }
335
+
228
336
  module.exports = { setupProject };
package/package.json CHANGED
@@ -1,29 +1,38 @@
1
1
  {
2
2
  "name": "create-modern-react",
3
- "version": "1.0.0",
4
- "description": "Create a modern React application with Vite, TypeScript, and your choice of modern libraries",
3
+ "version": "2.0.0",
4
+ "description": "Create production-ready React + TypeScript + Tailwind applications in seconds",
5
5
  "main": "bin/index.js",
6
6
  "bin": {
7
7
  "create-modern-react": "./bin/index.js"
8
8
  },
9
9
  "engines": {
10
- "node": ">=16.0.0"
10
+ "node": ">=18.0.0"
11
11
  },
12
12
  "keywords": [
13
13
  "react",
14
- "vite",
15
14
  "typescript",
15
+ "vite",
16
+ "tailwindcss",
16
17
  "cli",
18
+ "scaffold",
17
19
  "boilerplate",
18
- "template",
19
- "modern",
20
- "scaffold"
20
+ "create-react-app",
21
+ "starter-kit",
22
+ "shadcn-ui",
23
+ "react-starter",
24
+ "vite-template",
25
+ "react-boilerplate",
26
+ "npx",
27
+ "frontend",
28
+ "antd",
29
+ "redux"
21
30
  ],
22
31
  "author": "Abhay Rana",
23
32
  "license": "MIT",
24
33
  "repository": {
25
34
  "type": "git",
26
- "url": "https://github.com/abhay-rana/create-modern-react.git"
35
+ "url": "git+https://github.com/abhay-rana/create-modern-react.git"
27
36
  },
28
37
  "bugs": {
29
38
  "url": "https://github.com/abhay-rana/create-modern-react/issues"
@@ -0,0 +1,9 @@
1
+ # API Configuration
2
+ VITE_API_URL=http://localhost:8000/api
3
+
4
+ # App Configuration
5
+ VITE_APP_NAME=Modern React App
6
+ VITE_APP_VERSION=1.0.0
7
+
8
+ # Feature Flags
9
+ VITE_ENABLE_DEVTOOLS=true
@@ -0,0 +1,37 @@
1
+ module.exports = {
2
+ root: true,
3
+ env: { browser: true, es2020: true },
4
+ extends: [
5
+ 'eslint:recommended',
6
+ 'plugin:@typescript-eslint/recommended',
7
+ 'plugin:react-hooks/recommended',
8
+ ],
9
+ ignorePatterns: ['dist', '.eslintrc.cjs'],
10
+ parser: '@typescript-eslint/parser',
11
+ plugins: ['react-refresh', 'unused-imports'],
12
+ rules: {
13
+ 'react-refresh/only-export-components': [
14
+ 'warn',
15
+ { allowConstantExport: true },
16
+ ],
17
+ // Unused imports
18
+ 'unused-imports/no-unused-imports': 'error',
19
+ 'unused-imports/no-unused-vars': [
20
+ 'warn',
21
+ {
22
+ vars: 'all',
23
+ varsIgnorePattern: '^_',
24
+ args: 'after-used',
25
+ argsIgnorePattern: '^_',
26
+ },
27
+ ],
28
+ // TypeScript
29
+ '@typescript-eslint/no-unused-vars': 'off', // Handled by unused-imports
30
+ '@typescript-eslint/no-explicit-any': 'warn',
31
+ '@typescript-eslint/prefer-as-const': 'error',
32
+ // General
33
+ 'no-console': ['warn', { allow: ['warn', 'error'] }],
34
+ 'prefer-const': 'error',
35
+ 'no-var': 'error',
36
+ },
37
+ };
@@ -0,0 +1,11 @@
1
+ {
2
+ "semi": true,
3
+ "singleQuote": true,
4
+ "tabWidth": 2,
5
+ "trailingComma": "es5",
6
+ "printWidth": 80,
7
+ "bracketSpacing": true,
8
+ "arrowParens": "always",
9
+ "endOfLine": "lf",
10
+ "plugins": ["prettier-plugin-tailwindcss"]
11
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema.json",
3
+ "style": "default",
4
+ "rsc": false,
5
+ "tsx": true,
6
+ "tailwind": {
7
+ "config": "tailwind.config.js",
8
+ "css": "src/index.css",
9
+ "baseColor": "slate",
10
+ "cssVariables": true,
11
+ "prefix": ""
12
+ },
13
+ "aliases": {
14
+ "components": "~/components",
15
+ "utils": "~/lib/utils"
16
+ }
17
+ }
@@ -1,9 +1,10 @@
1
1
  <!doctype html>
2
- <html lang="en">
2
+ <html lang="en" class="light">
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
5
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <meta name="description" content="Modern React application built with create-modern-react" />
7
8
  <title>Modern React App</title>
8
9
  </head>
9
10
  <body>