create-modern-react 1.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.
package/README.md ADDED
@@ -0,0 +1,113 @@
1
+ # create-modern-react
2
+
3
+ Create a modern React application with Vite, TypeScript, and your choice of modern libraries.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ npx create-modern-react my-app
9
+ cd my-app
10
+ npm run dev
11
+ ```
12
+
13
+ ## Features
14
+
15
+ 🚀 **Modern Stack**: Vite + React 18 + TypeScript
16
+ 📦 **Interactive Setup**: Choose your preferred libraries
17
+ 🎨 **UI Libraries**: Ant Design, Material-UI, Chakra UI support
18
+ 🎯 **State Management**: Redux Toolkit, Zustand, Jotai options
19
+ 🛣️ **Routing**: React Router or Wouter
20
+ 🔧 **Development Tools**: ESLint, Prettier, Storybook, Testing
21
+ 🎨 **Styling**: Tailwind CSS, CSS Modules, Styled Components
22
+ 📱 **PWA Ready**: Optional Progressive Web App support
23
+
24
+ ## Usage
25
+
26
+ ### Basic Usage
27
+
28
+ ```bash
29
+ npx create-modern-react my-project
30
+ ```
31
+
32
+ ### With Options
33
+
34
+ ```bash
35
+ npx create-modern-react my-project --skip-install --skip-git
36
+ ```
37
+
38
+ ## Interactive Prompts
39
+
40
+ The CLI will guide you through selecting:
41
+
42
+ - **Project Name**: Your project directory name
43
+ - **Package Manager**: npm, yarn, or pnpm
44
+ - **UI Library**: Ant Design, Material-UI, Chakra UI, or none
45
+ - **CSS Framework**: Tailwind CSS, CSS Modules, Styled Components, or plain CSS
46
+ - **State Management**: Redux Toolkit, Zustand, Jotai, or React state only
47
+ - **Data Fetching**: React Query, SWR, Apollo Client, or Fetch API
48
+ - **Routing**: React Router, Wouter, or none
49
+ - **Development Tools**: Storybook, ESLint/Prettier, Husky, Testing
50
+ - **Icons**: Lucide React, React Icons, Heroicons, or none
51
+ - **PWA**: Progressive Web App features
52
+ - **Git**: Initialize Git repository
53
+
54
+ ## Template Combinations
55
+
56
+ ### Minimal Setup
57
+
58
+ - Vite + React + TypeScript + Tailwind CSS
59
+
60
+ ### Enterprise Ready
61
+
62
+ - Vite + React + TypeScript + Ant Design + Redux Toolkit + React Query + React Router
63
+
64
+ ### Modern Stack
65
+
66
+ - Vite + React + TypeScript + Tailwind + Zustand + React Query + Wouter
67
+
68
+ ### Full Featured
69
+
70
+ - All libraries with Storybook, testing, and PWA support
71
+
72
+ ## CLI Options
73
+
74
+ - `--skip-install`: Skip automatic dependency installation
75
+ - `--skip-git`: Skip Git repository initialization
76
+ - `--template <name>`: Use a specific template (future feature)
77
+
78
+ ## Requirements
79
+
80
+ - Node.js 16.0.0 or higher
81
+ - npm, yarn, or pnpm
82
+
83
+ ## Generated Project Structure
84
+
85
+ ```
86
+ my-app/
87
+ ├── public/
88
+ ├── src/
89
+ │ ├── components/
90
+ │ ├── hooks/
91
+ │ ├── utils/
92
+ │ ├── types/
93
+ │ ├── styles/
94
+ │ ├── App.tsx
95
+ │ ├── main.tsx
96
+ │ └── index.css
97
+ ├── package.json
98
+ ├── vite.config.ts
99
+ ├── tsconfig.json
100
+ └── README.md
101
+ ```
102
+
103
+ ## Contributing
104
+
105
+ 1. Fork the repository
106
+ 2. Create your feature branch
107
+ 3. Commit your changes
108
+ 4. Push to the branch
109
+ 5. Create a Pull Request
110
+
111
+ ## License
112
+
113
+ MIT © [Your Name]
package/bin/index.js ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { program } = require("commander");
4
+ const chalk = require("chalk");
5
+ const { createProject } = require("../lib/prompts");
6
+
7
+ program
8
+ .name("create-modern-react")
9
+ .description(
10
+ "Create a modern React application with Vite, TypeScript, and your choice of modern libraries",
11
+ )
12
+ .version("1.0.0")
13
+ .argument("[project-name]", "name of the project")
14
+ .option("-t, --template <template>", "use a specific template")
15
+ .option("--skip-install", "skip dependency installation")
16
+ .option("--skip-git", "skip git initialization")
17
+ .action(async (projectName, options) => {
18
+ console.log(chalk.blue.bold("\n🚀 Welcome to create-modern-react!\n"));
19
+
20
+ try {
21
+ await createProject(projectName, options);
22
+ } catch (error) {
23
+ console.error(chalk.red("❌ Error creating project:"), error.message);
24
+ process.exit(1);
25
+ }
26
+ });
27
+
28
+ program.parse();
package/lib/install.js ADDED
@@ -0,0 +1,59 @@
1
+ const { spawn } = require("child_process");
2
+ const chalk = require("chalk");
3
+
4
+ function runCommand(command, args, cwd) {
5
+ return new Promise((resolve, reject) => {
6
+ const child = spawn(command, args, {
7
+ cwd,
8
+ stdio: "inherit",
9
+ shell: true,
10
+ });
11
+
12
+ child.on("close", (code) => {
13
+ if (code === 0) {
14
+ resolve();
15
+ } else {
16
+ reject(new Error(`Command failed with exit code ${code}`));
17
+ }
18
+ });
19
+
20
+ child.on("error", (error) => {
21
+ reject(error);
22
+ });
23
+ });
24
+ }
25
+
26
+ async function installDependencies(config) {
27
+ const { projectPath, packageManager } = config;
28
+
29
+ console.log(chalk.blue("\n📦 Installing dependencies..."));
30
+
31
+ try {
32
+ const installCommand =
33
+ packageManager === "yarn"
34
+ ? "yarn"
35
+ : packageManager === "pnpm"
36
+ ? "pnpm"
37
+ : "npm";
38
+ const installArgs =
39
+ packageManager === "npm"
40
+ ? ["install"]
41
+ : packageManager === "pnpm"
42
+ ? ["install"]
43
+ : [];
44
+
45
+ await runCommand(installCommand, installArgs, projectPath);
46
+
47
+ console.log(chalk.green("✅ Dependencies installed successfully!"));
48
+ } catch (error) {
49
+ console.error(
50
+ chalk.red("❌ Failed to install dependencies:"),
51
+ error.message,
52
+ );
53
+ console.log(chalk.yellow("You can install them manually by running:"));
54
+ console.log(chalk.gray(` cd ${config.projectName}`));
55
+ console.log(chalk.gray(` ${packageManager} install`));
56
+ }
57
+ }
58
+
59
+ module.exports = { installDependencies, runCommand };
package/lib/prompts.js ADDED
@@ -0,0 +1,235 @@
1
+ const inquirer = require("inquirer");
2
+ const chalk = require("chalk");
3
+ const path = require("path");
4
+ const fs = require("fs-extra");
5
+ const { installDependencies } = require("./install");
6
+ const { setupProject } = require("./setup");
7
+
8
+ async function createProject(projectName, options) {
9
+ // Get project name if not provided
10
+ if (!projectName) {
11
+ const nameAnswer = await inquirer.prompt([
12
+ {
13
+ type: "input",
14
+ name: "projectName",
15
+ message: "What is the name of your project?",
16
+ validate: (input) => {
17
+ if (!input.trim()) return "Project name is required";
18
+ if (!/^[a-zA-Z0-9-_]+$/.test(input))
19
+ return "Project name can only contain letters, numbers, hyphens, and underscores";
20
+ return true;
21
+ },
22
+ },
23
+ ]);
24
+ projectName = nameAnswer.projectName;
25
+ }
26
+
27
+ const projectPath = path.resolve(process.cwd(), projectName);
28
+
29
+ // Check if directory exists
30
+ if (fs.existsSync(projectPath)) {
31
+ const overwriteAnswer = await inquirer.prompt([
32
+ {
33
+ type: "confirm",
34
+ name: "overwrite",
35
+ message: `Directory ${projectName} already exists. Do you want to overwrite it?`,
36
+ default: false,
37
+ },
38
+ ]);
39
+
40
+ if (!overwriteAnswer.overwrite) {
41
+ console.log(chalk.yellow("Operation cancelled."));
42
+ return;
43
+ }
44
+
45
+ await fs.remove(projectPath);
46
+ }
47
+
48
+ // Package Manager Selection
49
+ const packageManagerAnswer = await inquirer.prompt([
50
+ {
51
+ type: "list",
52
+ name: "packageManager",
53
+ message: "Which package manager would you like to use?",
54
+ choices: [
55
+ { name: "npm", value: "npm" },
56
+ { name: "yarn", value: "yarn" },
57
+ { name: "pnpm", value: "pnpm" },
58
+ ],
59
+ },
60
+ ]);
61
+
62
+ // UI Library Selection
63
+ const uiLibraryAnswer = await inquirer.prompt([
64
+ {
65
+ type: "list",
66
+ name: "uiLibrary",
67
+ message: "Do you want to include a UI component library?",
68
+ choices: [
69
+ { name: "Ant Design v5 (with theme customization)", value: "antd" },
70
+ { name: "Material-UI (MUI)", value: "mui" },
71
+ { name: "Chakra UI", value: "chakra" },
72
+ { name: "None (custom components only)", value: "none" },
73
+ ],
74
+ },
75
+ ]);
76
+
77
+ // CSS Framework Selection
78
+ const cssFrameworkAnswer = await inquirer.prompt([
79
+ {
80
+ type: "list",
81
+ name: "cssFramework",
82
+ message: "Which CSS framework would you like to use?",
83
+ choices: [
84
+ { name: "Tailwind CSS (with custom config)", value: "tailwind" },
85
+ { name: "CSS Modules", value: "css-modules" },
86
+ { name: "Styled Components", value: "styled-components" },
87
+ { name: "Plain CSS only", value: "plain" },
88
+ ],
89
+ },
90
+ ]);
91
+
92
+ // State Management Selection
93
+ const stateManagementAnswer = await inquirer.prompt([
94
+ {
95
+ type: "list",
96
+ name: "stateManagement",
97
+ message: "Do you need state management?",
98
+ choices: [
99
+ { name: "Redux Toolkit (with Redux Persist)", value: "redux-toolkit" },
100
+ { name: "Zustand", value: "zustand" },
101
+ { name: "Jotai", value: "jotai" },
102
+ { name: "React state only", value: "none" },
103
+ ],
104
+ },
105
+ ]);
106
+
107
+ // Data Fetching Selection
108
+ const dataFetchingAnswer = await inquirer.prompt([
109
+ {
110
+ type: "list",
111
+ name: "dataFetching",
112
+ message: "Do you want to include data fetching libraries?",
113
+ choices: [
114
+ { name: "React Query (TanStack Query)", value: "react-query" },
115
+ { name: "SWR", value: "swr" },
116
+ { name: "Apollo Client (for GraphQL)", value: "apollo" },
117
+ { name: "Fetch API only", value: "none" },
118
+ ],
119
+ },
120
+ ]);
121
+
122
+ // Routing Selection
123
+ const routingAnswer = await inquirer.prompt([
124
+ {
125
+ type: "list",
126
+ name: "routing",
127
+ message: "Do you need client-side routing?",
128
+ choices: [
129
+ { name: "React Router v6", value: "react-router" },
130
+ { name: "Wouter (lightweight)", value: "wouter" },
131
+ { name: "No routing", value: "none" },
132
+ ],
133
+ },
134
+ ]);
135
+
136
+ // Development Tools Selection
137
+ const devToolsAnswer = await inquirer.prompt([
138
+ {
139
+ type: "checkbox",
140
+ name: "devTools",
141
+ message: "Which development tools would you like?",
142
+ choices: [
143
+ { name: "Storybook (component development)", value: "storybook" },
144
+ {
145
+ name: "ESLint + Prettier (code quality)",
146
+ value: "eslint-prettier",
147
+ checked: true,
148
+ },
149
+ {
150
+ name: "Husky + lint-staged (git hooks)",
151
+ value: "husky",
152
+ checked: true,
153
+ },
154
+ { name: "Jest + Testing Library (testing)", value: "testing" },
155
+ ],
156
+ },
157
+ ]);
158
+
159
+ // Icons Selection
160
+ const iconsAnswer = await inquirer.prompt([
161
+ {
162
+ type: "list",
163
+ name: "icons",
164
+ message: "Do you want icon libraries?",
165
+ choices: [
166
+ { name: "Lucide React", value: "lucide" },
167
+ { name: "React Icons", value: "react-icons" },
168
+ { name: "Heroicons", value: "heroicons" },
169
+ { name: "No icon library", value: "none" },
170
+ ],
171
+ },
172
+ ]);
173
+
174
+ // PWA Selection
175
+ const pwaAnswer = await inquirer.prompt([
176
+ {
177
+ type: "confirm",
178
+ name: "pwa",
179
+ message: "Make it a PWA?",
180
+ default: false,
181
+ },
182
+ ]);
183
+
184
+ // Git Selection
185
+ const gitAnswer = await inquirer.prompt([
186
+ {
187
+ type: "confirm",
188
+ name: "git",
189
+ message: "Initialize Git repository?",
190
+ default: true,
191
+ },
192
+ ]);
193
+
194
+ const config = {
195
+ projectName,
196
+ projectPath,
197
+ packageManager: packageManagerAnswer.packageManager,
198
+ uiLibrary: uiLibraryAnswer.uiLibrary,
199
+ cssFramework: cssFrameworkAnswer.cssFramework,
200
+ stateManagement: stateManagementAnswer.stateManagement,
201
+ dataFetching: dataFetchingAnswer.dataFetching,
202
+ routing: routingAnswer.routing,
203
+ devTools: devToolsAnswer.devTools,
204
+ icons: iconsAnswer.icons,
205
+ pwa: pwaAnswer.pwa,
206
+ git: gitAnswer.git,
207
+ skipInstall: options.skipInstall,
208
+ skipGit: options.skipGit,
209
+ };
210
+
211
+ console.log(
212
+ chalk.blue("\n📦 Creating project with the following configuration:"),
213
+ );
214
+ console.log(chalk.gray(JSON.stringify(config, null, 2)));
215
+
216
+ // Create project
217
+ await setupProject(config);
218
+
219
+ // Install dependencies
220
+ if (!options.skipInstall) {
221
+ await installDependencies(config);
222
+ }
223
+
224
+ console.log(
225
+ chalk.green.bold(`\n🎉 Project ${projectName} created successfully!`),
226
+ );
227
+ console.log(chalk.blue("\nNext steps:"));
228
+ console.log(chalk.gray(` cd ${projectName}`));
229
+ if (options.skipInstall) {
230
+ console.log(chalk.gray(` ${config.packageManager} install`));
231
+ }
232
+ console.log(chalk.gray(` ${config.packageManager} dev`));
233
+ }
234
+
235
+ module.exports = { createProject };
package/lib/setup.js ADDED
@@ -0,0 +1,228 @@
1
+ const fs = require("fs-extra");
2
+ const path = require("path");
3
+ const chalk = require("chalk");
4
+ const { runCommand } = require("./install");
5
+
6
+ async function setupProject(config) {
7
+ const { projectPath, projectName } = config;
8
+
9
+ console.log(chalk.blue("\n🏗️ Setting up project structure..."));
10
+
11
+ // Create project directory
12
+ await fs.ensureDir(projectPath);
13
+
14
+ // Copy base template
15
+ const templatePath = path.join(__dirname, "../templates/base");
16
+ await fs.copy(templatePath, projectPath);
17
+
18
+ // Update package.json with project name and selected dependencies
19
+ await updatePackageJson(config);
20
+
21
+ // Configure selected libraries
22
+ await configureLibraries(config);
23
+
24
+ // Initialize git if requested
25
+ if (config.git && !config.skipGit) {
26
+ await initializeGit(config);
27
+ }
28
+
29
+ console.log(chalk.green("✅ Project structure created successfully!"));
30
+ }
31
+
32
+ async function updatePackageJson(config) {
33
+ const packageJsonPath = path.join(config.projectPath, "package.json");
34
+ const packageJson = await fs.readJson(packageJsonPath);
35
+
36
+ // Update name
37
+ packageJson.name = config.projectName;
38
+
39
+ // Add dependencies based on configuration
40
+ const dependencies = { ...packageJson.dependencies };
41
+ const devDependencies = { ...packageJson.devDependencies };
42
+
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";
110
+ }
111
+
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";
117
+ }
118
+
119
+ if (config.devTools.includes("husky")) {
120
+ devDependencies["husky"] = "^9.0.0";
121
+ devDependencies["lint-staged"] = "^15.0.0";
122
+ }
123
+
124
+ // PWA dependencies
125
+ if (config.pwa) {
126
+ devDependencies["vite-plugin-pwa"] = "^0.20.0";
127
+ }
128
+
129
+ packageJson.dependencies = dependencies;
130
+ packageJson.devDependencies = devDependencies;
131
+
132
+ await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
133
+ }
134
+
135
+ async function configureLibraries(config) {
136
+ const { projectPath } = config;
137
+
138
+ // Configure Tailwind if selected
139
+ if (config.cssFramework === "tailwind") {
140
+ await configureTailwind(projectPath);
141
+ }
142
+
143
+ // Configure Vite plugins based on selections
144
+ await configureVite(config);
145
+
146
+ // Add configuration files for selected libraries
147
+ await addConfigFiles(config);
148
+ }
149
+
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
+ }`;
169
+
170
+ 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,
177
+ );
178
+
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;
184
+
185
+ `;
186
+
187
+ if (await fs.pathExists(cssPath)) {
188
+ const existingCss = await fs.readFile(cssPath, "utf8");
189
+ await fs.writeFile(cssPath, tailwindDirectives + existingCss);
190
+ } else {
191
+ await fs.writeFile(cssPath, tailwindDirectives);
192
+ }
193
+ }
194
+
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
198
+ }
199
+
200
+ async function addConfigFiles(config) {
201
+ // Add configuration files for selected tools
202
+ // This would add ESLint, Prettier, Jest configs, etc.
203
+ }
204
+
205
+ async function initializeGit(config) {
206
+ const { projectPath } = config;
207
+
208
+ try {
209
+ console.log(chalk.blue("🔧 Initializing Git repository..."));
210
+
211
+ await runCommand("git", ["init"], projectPath);
212
+ await runCommand("git", ["add", "."], projectPath);
213
+ await runCommand(
214
+ "git",
215
+ ["commit", "-m", "Initial commit from create-modern-react"],
216
+ projectPath,
217
+ );
218
+
219
+ console.log(chalk.green("✅ Git repository initialized!"));
220
+ } catch (error) {
221
+ console.warn(
222
+ chalk.yellow("⚠️ Could not initialize Git repository:"),
223
+ error.message,
224
+ );
225
+ }
226
+ }
227
+
228
+ module.exports = { setupProject };
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
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",
5
+ "main": "bin/index.js",
6
+ "bin": {
7
+ "create-modern-react": "./bin/index.js"
8
+ },
9
+ "engines": {
10
+ "node": ">=16.0.0"
11
+ },
12
+ "keywords": [
13
+ "react",
14
+ "vite",
15
+ "typescript",
16
+ "cli",
17
+ "boilerplate",
18
+ "template",
19
+ "modern",
20
+ "scaffold"
21
+ ],
22
+ "author": "Abhay Rana",
23
+ "license": "MIT",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/abhay-rana/create-modern-react.git"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/abhay-rana/create-modern-react/issues"
30
+ },
31
+ "homepage": "https://github.com/abhay-rana/create-modern-react#readme",
32
+ "files": [
33
+ "bin",
34
+ "lib",
35
+ "templates"
36
+ ],
37
+ "dependencies": {
38
+ "chalk": "^4.1.2",
39
+ "commander": "^11.0.0",
40
+ "fs-extra": "^11.0.0",
41
+ "inquirer": "^8.2.6"
42
+ },
43
+ "devDependencies": {
44
+ "@types/fs-extra": "^11.0.0",
45
+ "@types/inquirer": "^9.0.0",
46
+ "eslint": "^8.57.0",
47
+ "prettier": "^3.0.0"
48
+ },
49
+ "scripts": {
50
+ "test": "echo \"Error: no test specified\" && exit 1",
51
+ "lint": "eslint .",
52
+ "format": "prettier --write ."
53
+ }
54
+ }
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Modern React App</title>
8
+ </head>
9
+ <body>
10
+ <div id="root"></div>
11
+ <script type="module" src="/src/main.tsx"></script>
12
+ </body>
13
+ </html>
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "modern-react-app",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "tsc && vite build",
9
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10
+ "preview": "vite preview"
11
+ },
12
+ "dependencies": {
13
+ "react": "^18.2.0",
14
+ "react-dom": "^18.2.0"
15
+ },
16
+ "devDependencies": {
17
+ "@types/react": "^18.2.66",
18
+ "@types/react-dom": "^18.2.22",
19
+ "@typescript-eslint/eslint-plugin": "^7.2.0",
20
+ "@typescript-eslint/parser": "^7.2.0",
21
+ "@vitejs/plugin-react": "^4.2.1",
22
+ "eslint": "^8.57.0",
23
+ "eslint-plugin-react-hooks": "^4.6.0",
24
+ "eslint-plugin-react-refresh": "^0.4.6",
25
+ "typescript": "^5.2.2",
26
+ "vite": "^5.2.0"
27
+ }
28
+ }
@@ -0,0 +1,14 @@
1
+ #root {
2
+ max-width: 1280px;
3
+ margin: 0 auto;
4
+ padding: 2rem;
5
+ text-align: center;
6
+ }
7
+
8
+ .card {
9
+ padding: 2em;
10
+ }
11
+
12
+ .read-the-docs {
13
+ color: #888;
14
+ }
@@ -0,0 +1,25 @@
1
+ import { useState } from "react";
2
+ import "./App.css";
3
+
4
+ function App() {
5
+ const [count, setCount] = useState(0);
6
+
7
+ return (
8
+ <div className="App">
9
+ <div>
10
+ <h1>Modern React App</h1>
11
+ <div className="card">
12
+ <button onClick={() => setCount((count) => count + 1)}>
13
+ count is {count}
14
+ </button>
15
+ <p>
16
+ Edit <code>src/App.tsx</code> and save to test HMR
17
+ </p>
18
+ </div>
19
+ <p className="read-the-docs">Click on the React logo to learn more</p>
20
+ </div>
21
+ </div>
22
+ );
23
+ }
24
+
25
+ export default App;
@@ -0,0 +1,70 @@
1
+ :root {
2
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3
+ line-height: 1.5;
4
+ font-weight: 400;
5
+
6
+ color-scheme: light dark;
7
+ color: rgba(255, 255, 255, 0.87);
8
+ background-color: #242424;
9
+
10
+ font-synthesis: none;
11
+ text-rendering: optimizeLegibility;
12
+ -webkit-font-smoothing: antialiased;
13
+ -moz-osx-font-smoothing: grayscale;
14
+ -webkit-text-size-adjust: 100%;
15
+ }
16
+
17
+ a {
18
+ font-weight: 500;
19
+ color: #646cff;
20
+ text-decoration: inherit;
21
+ }
22
+ a:hover {
23
+ color: #535bf2;
24
+ }
25
+
26
+ body {
27
+ margin: 0;
28
+ display: flex;
29
+ place-items: center;
30
+ min-width: 320px;
31
+ min-height: 100vh;
32
+ }
33
+
34
+ h1 {
35
+ font-size: 3.2em;
36
+ line-height: 1.1;
37
+ }
38
+
39
+ button {
40
+ border-radius: 8px;
41
+ border: 1px solid transparent;
42
+ padding: 0.6em 1.2em;
43
+ font-size: 1em;
44
+ font-weight: 500;
45
+ font-family: inherit;
46
+ background-color: #1a1a1a;
47
+ color: inherit;
48
+ cursor: pointer;
49
+ transition: border-color 0.25s;
50
+ }
51
+ button:hover {
52
+ border-color: #646cff;
53
+ }
54
+ button:focus,
55
+ button:focus-visible {
56
+ outline: 4px auto -webkit-focus-ring-color;
57
+ }
58
+
59
+ @media (prefers-color-scheme: light) {
60
+ :root {
61
+ color: #213547;
62
+ background-color: #ffffff;
63
+ }
64
+ a:hover {
65
+ color: #747bff;
66
+ }
67
+ button {
68
+ background-color: #f9f9f9;
69
+ }
70
+ }
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import App from "./App.tsx";
4
+ import "./index.css";
5
+
6
+ ReactDOM.createRoot(document.getElementById("root")!).render(
7
+ <React.StrictMode>
8
+ <App />
9
+ </React.StrictMode>,
10
+ );
@@ -0,0 +1,31 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+
9
+ /* Bundler mode */
10
+ "moduleResolution": "bundler",
11
+ "allowImportingTsExtensions": true,
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "noEmit": true,
15
+ "jsx": "react-jsx",
16
+
17
+ /* Linting */
18
+ "strict": true,
19
+ "noUnusedLocals": true,
20
+ "noUnusedParameters": true,
21
+ "noFallthroughCasesInSwitch": true,
22
+
23
+ /* Path mapping */
24
+ "baseUrl": ".",
25
+ "paths": {
26
+ "~/*": ["src/*"]
27
+ }
28
+ },
29
+ "include": ["src"],
30
+ "references": [{ "path": "./tsconfig.node.json" }]
31
+ }
@@ -0,0 +1,12 @@
1
+ import { defineConfig } from "vite";
2
+ import react from "@vitejs/plugin-react";
3
+
4
+ // https://vitejs.dev/config/
5
+ export default defineConfig({
6
+ plugins: [react()],
7
+ resolve: {
8
+ alias: {
9
+ "~": "/src",
10
+ },
11
+ },
12
+ });