UNPKG

create-react-fast-app

Version:

Instantly create a React + Vite + Tailwind + ShadCN app

223 lines (190 loc) 5.79 kB
#!/usr/bin/env node import enquirer from "enquirer"; import chalk from "chalk"; import { execa } from "execa"; import ora from "ora"; import degit from "degit"; import path from "path"; import fs from "fs"; import boxen from "boxen"; const { prompt } = enquirer; const { Input, Select } = enquirer; import open from "open"; import readline from "readline"; import { fileURLToPath } from "url"; const args = process.argv.slice(2); // Default values let projectNameArg = null; let langArg = null; // Parse CLI args args.forEach((arg) => { if (arg === "--js") langArg = "JavaScript"; else if (arg === "--ts") langArg = "TypeScript"; else if (!arg.startsWith("--")) projectNameArg = arg; }); // Step 0: Give Credit console.log(); console.log( chalk.greenBright("✨ Thank You for using", chalk.italic("react-fast-app"))); console.log( chalk.dim("This will creat a react app with Tailwind CSS and shadcn UI") ); // Step 1: Ask for project name console.log(); // const { projectName } = await prompt({ // type: "input", // name: "projectName", // message: chalk.cyan("Project name?\n", chalk.gray.italic(("use '.' for current folder:\n")), // ), // initial: "fast-react-app-by-satendra", // }); const projectName = projectNameArg || ( await prompt({ type: "input", name: "projectName", message: chalk.cyan("Project name?\n", chalk.gray.italic("use '.' for current folder:\n")), initial: "fast-react-app-by-satendra", }) ).projectName; const targetDir = projectName === "." ? "." : path.join(process.cwd(), projectName); // Step 2: Ask for language preference console.log(); // const { language } = await prompt({ // type: "select", // name: "language", // message: chalk.cyan("Choose your language:"), // choices: [ // { // name: "JavaScript", // message: chalk.yellow("JavaScript"), // value: "JavaScript", // }, // { // name: "TypeScript", // message: chalk.blue("TypeScript"), // value: "TypeScript", // }, // ], // }); const language = langArg || ( await prompt({ type: "select", name: "language", message: chalk.cyan("Choose your language:"), choices: [ { name: "JavaScript", message: chalk.yellow("JavaScript"), value: "JavaScript", }, { name: "TypeScript", message: chalk.blue("TypeScript"), value: "TypeScript", }, ], }) ).language; // Step 3: Ask for UI library (currently only shadcn) // console.log(); // const { uiLib } = await prompt({ // type: "select", // name: "uiLib", // message: chalk.cyan("Choose your UI library:"), // choices: [ // { // name: "shadcn", // message: chalk.white.bgBlackBright('Shadcn UI'), // value: "shadcn", // }, // { // name: "magic-ui", // message: chalk.hex('#FEAACA')("Magic UI"), // value: "magic-ui", // }, // { // name: "miui", // message: chalk.hex('#0073E6')("MIUI"), // value: "miui", // }, // { // name: "aceternity-ui", // message: chalk.white.bgBlack("Aceternity UI"), // value: "aceternity-ui", // }, // ], // }); const langSuffix = language === "JavaScript" ? "js" : "ts"; const repoFolder = `tailwind-shadcn-${langSuffix}`; // Step 4: Clone the template const repo = `satendra03/react-fast-app/${repoFolder}`; const emitter = degit(repo, { force: true, verbose: true }); console.log(); const spinner = ora("Creating your Fast React app...").start(); try { await emitter.clone(targetDir); spinner.succeed(chalk.green("Project created successfully!")); } catch (err) { spinner.fail(chalk.red("Failed to create project.")); console.error(err); process.exit(1); } // Step 5: Install dependencies if (projectName !== ".") process.chdir(projectName); console.log(chalk.cyan("\nInstalling dependencies...\n")); const installSpinner = ora("Running npm install...").start(); try { await execa("npm", ["install"], { stdio: "inherit" }); installSpinner.succeed("Dependencies installed."); } catch (e) { installSpinner.fail("Failed to install dependencies."); process.exit(1); } const actualProjectName = projectName === "." ? path.basename(process.cwd()) : projectName; console.clear(); console.log(chalk.greenBright("\n✅ All done!\n")); // console.log(chalk.blueBright(` cd ${actualProjectName}`)); // console.log(chalk.blueBright(` npm run dev\n`)); console.log(chalk.cyan("✨ Happy Development!\n")); const credit = chalk.greenBright("✨ Created with ❤️ by Satendra Parteti") + "\n" + chalk.cyan("🔗 GitHub: ") + chalk.underline.blue("https://github.com/satendra03"); console.log(); console.log( boxen(credit, { padding: 1, borderColor: "cyan", borderStyle: "round", align: "center", }) ); console.log(); const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const projectPath = process.cwd(); // Start dev server and listen to its stdout const devProcess = execa("npm", ["run", "dev"], { cwd: projectPath, stdout: "pipe", stderr: "inherit", }); // Read stdout line by line const rl = readline.createInterface({ input: devProcess.stdout, }); let opened = false; rl.on("line", (line) => { console.log(line); // mirror the dev output to CLI // Detect and open the local server URL const match = line.match(/http:\/\/localhost:\d+/); if (match && !opened) { open(match[0]); opened = true; } }); // Wait for the dev process to exit await devProcess;