diff --git a/index.js b/index.js index 2e4aad6..8e340d4 100644 --- a/index.js +++ b/index.js @@ -2,10 +2,15 @@ import { input, select, confirm, checkbox } from "@inquirer/prompts" import { select as selectPro } from 'inquirer-select-pro'; import path from "path"; -import { run, createFolder, deleteFile } from './lib/utils.js'; -import { initializePWA } from './lib/pwa.js'; -import { setupCSSFramework } from './lib/css-frameworks.js'; -import { createAxiosSetup, createAppComponent, createPWAReadme } from './lib/templates.js'; +import { run, createFolder, deleteFile } from "./lib/utils.js"; +import { initializePWA } from "./lib/pwa.js"; +import { setupCSSFramework } from "./lib/css-frameworks.js"; +import { + createAxiosSetup, + createAppComponent, + setupRouterMain, + createPWAReadme, +} from "./lib/templates.js"; import { setupRoutingFramework } from "./lib/router-setup.js"; const getExtraPackages = async (input) => { @@ -25,132 +30,143 @@ const getExtraPackages = async (input) => { }; (async () => { - // 1. Collect user inputs - const projectName = await input({ message: "Enter project name:", required: true }); - const cssFramework = await select({ - message: "Choose a CSS framework:", - choices: ["Tailwind", "Bootstrap (CDN)", "React Bootstrap", "MUI"] - }); - const routingFramework = await select({ - message: "Choose a routing framework:", - choices: ["React Router", "Tanstack Router",] - }) - const isPWA = await confirm({ message: "Do you want to make this a Progressive Web App (PWA)?", default: false }); - - const packages = await checkbox({ - message: "Select optional packages:", - choices: [ - { name: "Axios", value: "axios" }, - { name: "React Icons", value: "react-icons" }, - { name: "React Hook Form", value: "react-hook-form" }, - { name: "Yup", value: "yup" }, - { name: "Formik", value: "formik" }, - { name: "Moment.js", value: "moment" } - ] - }); - - const extraPackages = await selectPro({ - message: 'Search extra packages to add', - multiple: true, - clearInputWhenSelected: true, - pageSize: 10, - options: getExtraPackages, - theme: { - style: { - renderSelectedOptions: (selectedOptions) => { - return selectedOptions.map(option => option.value).join(', '); - } - } - } - }); - - let selectedExtraPackages = []; - if (extraPackages.length > 0) { - selectedExtraPackages = await checkbox({ - message: "These extra packages will be installed:", - choices: extraPackages.map(pkg => ({ - name: pkg, - value: pkg, - checked: true, - })), - }) + // 1. Collect user inputs + const answers = await inquirer.prompt([ + { + type: "input", + name: "projectName", + message: "Enter project name:", + }, + { + type: "list", + name: "cssFramework", + message: "Choose a CSS framework:", + choices: ["Tailwind", "Bootstrap (CDN)", "React Bootstrap", "MUI"], + }, + { + type: "list", + name: "routingFramework", + message: "Choose a routing framework:", + choices: ["React Router", "Tanstack Router"], + }, + { + type: "confirm", + name: "isPWA", + message: "Do you want to make this a Progressive Web App (PWA)?", + default: false, + }, + { + type: "checkbox", + name: "packages", + message: "Select optional packages:", + choices: [ + { name: "Axios", value: "axios" }, + { name: "React Icons", value: "react-icons" }, + { name: "React Hook Form", value: "react-hook-form" }, + { name: "Yup", value: "yup" }, + { name: "Formik", value: "formik" }, + { name: "Moment.js", value: "moment" }, + { name: "ReduxJs/Toolkit", value: "@reduxjs/toolkit" }, + { name: "React Bindings (React-Redux)", value: "react-redux" } + ], + }, + { + type: "checkbox", + name: "devPackages", + message: "Select dev packages to install:", + choices: [{ name: "Jest", value: "jest" }], + }, + ]); + + const { projectName, cssFramework, routingFramework, isPWA, packages, devPackages } = answers; + const projectPath = path.join(process.cwd(), projectName); + + console.log( + `\nš Creating ${projectName}${isPWA ? " with PWA capabilities" : ""}...` + ); + + // 2. Create Vite project + run(`npm create vite@latest ${projectName} -- --template react`); + + // 3. Create all necessary folder structure first + const folders = ["components", "pages", "hooks", "store", "utils", "assets"]; + const routingConfig = { + "Tanstack Router": { + folders: ["routes"], + packages: ["@tanstack/react-router", "@tanstack/react-router-devtools"], + devPackages: ["@tanstack/router-plugin"] + }, + "React Router": { + folders: [], + packages: ["react-router-dom"], + devPackages: [] } + }; + const config = routingConfig[routingFramework] || { folders: [], packages: [], devPackages: [] }; + folders.push(...config.folders); + folders.forEach((folder) => { + createFolder(path.join(projectPath, "src", folder)); + }); + + // 4. Install packages + const allPackages = [...config.packages, ...packages]; + if (allPackages.length > 0) { + run(`npm install ${allPackages.join(" ")}`, projectPath); + } + if (devPackages.length > 0 || config.devPackages.length > 0) { + run(`npm install --save-dev ${[...devPackages, ...config.devPackages].join(" ")}`, projectPath); + } + + // 5. Setup PWA if selected (after folder structure is created) + if (isPWA) { + initializePWA(projectPath, projectName); + } + + // 6. Setup CSS framework + setupCSSFramework(cssFramework, projectPath); + + // 7. Setup Axios if selected + if (packages.includes("axios")) { + createAxiosSetup(projectPath); + } + + // 8. Clean up default boilerplate files + deleteFile(path.join(projectPath, "src", "App.css")); + if (cssFramework !== "Tailwind") { + deleteFile(path.join(projectPath, "src", "index.css")); + } + + // 9. Generate clean templates + createAppComponent(projectPath, projectName, isPWA); + setupRouterMain(projectPath, cssFramework); + + // 10. Create comprehensive README + createPWAReadme(projectPath, projectName, cssFramework, packages, isPWA); + + // 11. Success message + console.log("\nā Setup complete!"); + if (isPWA) { + console.log( + "š± PWA features enabled - your app can be installed on mobile devices!" + ); + console.log( + "ā ļø Important: Replace placeholder SVG icons with proper PNG icons for production" + ); + } + console.log( + `\nNext steps:\n cd ${projectName}\n npm install\n npm run dev` + ); + + if (isPWA) { + console.log( + `\nš± To test PWA:\n npm run build\n npm run preview\n Open http://localhost:5173 and test install/offline features` + ); + } - const projectPath = path.join(process.cwd(), projectName); - - console.log(`\nš Creating ${projectName}${isPWA ? ' with PWA capabilities' : ''}...`); - - // 2. Create Vite project - run(`npm create vite@latest ${projectName} -- --template react`); - - // 3. Create all necessary folder structure first - const folders = ["components", "pages", "hooks", "store", "utils", "assets"]; - - // Create the routes folder (for tanstack router) and the necessary packages for Router setup - const routingConfig = { - "Tanstack Router": { - folders: ["routes"], - packages: ["@tanstack/react-router", "@tanstack/react-router-devtools"], - devPackages: ["@tanstack/router-plugin"] - }, - "React Router": { - folders: [], - packages: ["react-router"], - devPackages: [] - } - }; - - const config = routingConfig[routingFramework] || { folders: [], packages: [], devPackages: [] }; - folders.push(...config.folders); - const routingPackages = config.packages; - folders.forEach((folder) => { - createFolder(path.join(projectPath, "src", folder)); - }); - - // 4. Install packages - const allPackages = [...routingPackages, ...packages, ...selectedExtraPackages]; - if (allPackages.length > 0) { - run(`npm install ${allPackages.join(" ")}`, projectPath); - if (config.devPackages.length > 0) { - run(`npm i -D ${config.devPackages.join(" ")}`, projectPath); - } - } - - // 5. Setup PWA if selected (after folder structure is created) - if (isPWA) { - initializePWA(projectPath, projectName); - } - - // 6. Setup CSS framework - setupCSSFramework(cssFramework, projectPath); - - // 7. Setup Axios if selected - if (packages.includes("axios")) { - createAxiosSetup(projectPath); - } - - // 8. Clean up default boilerplate files - deleteFile(path.join(projectPath, "src", "App.css")); - if (cssFramework !== "Tailwind") { - deleteFile(path.join(projectPath, "src", "index.css")); - } - - // 9. Generate clean templates - createAppComponent(projectPath, projectName, isPWA); - setupRoutingFramework(projectPath, routingFramework, cssFramework); - - // 10. Create comprehensive README - createPWAReadme(projectPath, projectName, cssFramework, packages, isPWA); - - // 11. Success message - console.log("\nā Setup complete!"); - if (isPWA) { - console.log("š± PWA features enabled - your app can be installed on mobile devices!"); - console.log("ā ļø Important: Replace placeholder SVG icons with proper PNG icons for production"); - } - console.log(`\nNext steps:\n cd ${projectName}\n npm install\n npm run dev`); - - if (isPWA) { - console.log(`\nš± To test PWA:\n npm run build\n npm run preview\n Open http://localhost:5173 and test install/offline features`); - } -})(); + if (devPackages.includes("jest")) { + console.log( + "Setting up Jest configuration... \n Add the following to your package.json:" + ); + console.log(`\n "scripts": {\n "test": "jest"\n }`); + } +})(); \ No newline at end of file diff --git a/test/test-react/.gitignore b/test/test-react/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/test/test-react/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/test/test-react/README.md b/test/test-react/README.md new file mode 100644 index 0000000..dbb4249 --- /dev/null +++ b/test/test-react/README.md @@ -0,0 +1,127 @@ +# test-react + +A modern React application built with Vite. + +## š Features + +- ā” **Vite** - Fast build tool and development server +- āļø **React 18** - Latest React with modern hooks +- šØ **Tailwind** - Styling framework +- š£ļø **React Router** - Client-side routing + +- š¦ **Additional Packages**: axios, react-icons, formik, @reduxjs/toolkit, react-redux + +## š Prerequisites + +- Node.js (v16 or higher) +- npm or yarn + +## š ļø Installation + +1. Navigate to the project directory: + ```bash + cd test-react + ``` + +2. Install dependencies: + ```bash + npm install + ``` + +## šāāļø Running the Application + +### Development Mode +```bash +npm run dev +``` +The app will be available at `http://localhost:5173` + +### Production Build +```bash +npm run build +``` + +### Preview Production Build +```bash +npm run preview +``` + +## š Project Structure + +``` +test-react/ +āāā public/ +āāā src/ +ā āāā components/ # Reusable components +ā āāā pages/ # Page components +ā āāā hooks/ # Custom React hooks +ā āāā store/ # State management +ā āāā utils/ # Utility functions +ā ā āāā axiosInstance.js # Axios configuration +ā āāā assets/ # Static assets +ā āāā App.jsx # Main App component +ā āāā main.jsx # Entry point +āāā vite.config.js # Vite configuration +āāā package.json +``` + +## šØ Styling + +This project uses **Tailwind** for styling: + +- Classes are available globally +- Configuration in `vite.config.js` +- Customize in `src/index.css` + +## š API Integration + +Axios is pre-configured in `src/utils/axiosInstance.js`: + +```javascript +import { api } from './utils/axiosInstance'; + +// GET request +const data = await api.get('/users'); + +// POST request +const response = await api.post('/users', { name: 'John' }); +``` + +### Environment Variables +Create a `.env` file: +``` +VITE_API_URL=https://your-api-url.com +``` + +## š§ Available Scripts + +- `npm run dev` - Start development server +- `npm run build` - Build for production +- `npm run preview` - Preview production build +- `npm run lint` - Run ESLint (if configured) + +## š Deployment + +### Vercel +```bash +npm install -g vercel +vercel --prod +``` + +### Netlify +```bash +npm run build +# Upload dist/ folder to Netlify +``` + +## šÆ Next Steps + +1. **Add Components**: Start building your app components +2. **Set up Routing**: Add more routes in main.jsx +3. **Configure API**: Set up your API endpoints if using Axios +4. **Add State Management**: Implement Redux/Zustand if needed +5. **Deploy**: Deploy to your preferred hosting service + +--- + +Built with ā¤ļø by harsh & Sameer using React + Vite diff --git a/test/test-react/eslint.config.js b/test/test-react/eslint.config.js new file mode 100644 index 0000000..cee1e2c --- /dev/null +++ b/test/test-react/eslint.config.js @@ -0,0 +1,29 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import { defineConfig, globalIgnores } from 'eslint/config' + +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{js,jsx}'], + extends: [ + js.configs.recommended, + reactHooks.configs['recommended-latest'], + reactRefresh.configs.vite, + ], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + parserOptions: { + ecmaVersion: 'latest', + ecmaFeatures: { jsx: true }, + sourceType: 'module', + }, + }, + rules: { + 'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }], + }, + }, +]) diff --git a/test/test-react/index.html b/test/test-react/index.html new file mode 100644 index 0000000..0c589ec --- /dev/null +++ b/test/test-react/index.html @@ -0,0 +1,13 @@ + + +
+ + + ++ Your project is ready. Start building amazing things! +
+ + +