@nynrathod/react-quick-starter
Version:
A quick React + Vite starter template
167 lines (147 loc) • 4.6 kB
JavaScript
const { program } = require("commander");
const { execSync } = require("child_process");
const path = require("path");
const fs = require("fs");
const chalk = require("chalk");
const inquirer = require("inquirer");
const ora = require("ora").default;
// Predefined versions fallback
const versions = require("./versions");
program
.command("create <app-name...>")
.description("Create a new React project with Vite")
.option("--latest", "Use latest package versions from npm")
.action(async (appNameParts, cmdObj) => {
const appName = appNameParts.join("_");
const useLatest = cmdObj.latest;
try {
const answers = await inquirer.prompt([
{
type: "confirm",
name: "typescript",
message: "Do you want TypeScript?",
default: true,
},
{
type: "confirm",
name: "tailwind",
message: "Do you want Tailwind CSS?",
default: false,
},
]);
const projectPath = path.resolve(process.cwd(), appName);
const template = answers.typescript ? "react-ts" : "react";
console.log(chalk.blue("Creating Vite project skeleton..."));
const spinner = ora("Creating Vite project...").start();
try {
execSync(
`yarn create vite ${appName} --template ${template} --no-install`,
{ stdio: "pipe" }
);
spinner.succeed("Vite project created!");
} catch (err) {
spinner.fail("Failed to create Vite project");
console.error(err);
}
process.chdir(projectPath);
// Read package.json
const pkgPath = path.join(projectPath, "package.json");
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
pkg.dependencies = pkg.dependencies || {};
pkg.devDependencies = pkg.devDependencies || {};
// Helper to get version (latest or predefined)
const getVersion = (pkgName, predefined) => {
if (useLatest) {
try {
const version = execSync(`npm view ${pkgName} version`)
.toString()
.trim();
return `^${version}`;
} catch {
return `^${predefined}`;
}
}
return `^${predefined}`;
};
// Add required packages
pkg.dependencies["react-router-dom"] = getVersion(
"react-router-dom",
versions.reactRouterDom
);
pkg.devDependencies["prettier"] = getVersion(
"prettier",
versions.prettier
);
if (answers.tailwind) {
pkg.devDependencies["tailwindcss"] = getVersion(
"tailwindcss",
versions.tailwindcss
);
pkg.devDependencies["@tailwindcss/vite"] = getVersion(
"@tailwindcss/vite",
versions.tailwindPluginVite
);
pkg.devDependencies["prettier-plugin-tailwindcss"] = getVersion(
"prettier-plugin-tailwindcss",
versions.prettierPluginTailwind
);
}
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2), "utf-8");
// Tailwind scaffolding
if (answers.tailwind) {
const tailwindSpinner = ora(
"Scaffolding Tailwind CSS..."
).start();
try {
// index.css
fs.writeFileSync(
path.join(projectPath, "src/index.css"),
"@tailwind base;\n@tailwind components;\n@tailwind utilities;\n",
"utf-8"
);
// vite.config.js
const viteConfigContent = `import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [react(), tailwindcss()],
})
`;
fs.writeFileSync(
path.join(projectPath, "vite.config.js"),
viteConfigContent,
"utf-8"
);
// tailwind.config.js
const tailwindConfig = `module.exports = {
content: ["./index.html","./src/**/*.{js,ts,jsx,tsx}"],
theme: { extend: {} },
plugins: [],
};
`;
fs.writeFileSync(
path.join(projectPath, "tailwind.config.js"),
tailwindConfig,
"utf-8"
);
tailwindSpinner.succeed(
"Tailwind CSS scaffolding completed!"
);
} catch (err) {
tailwindSpinner.fail("Failed to scaffold Tailwind CSS");
console.error(err);
}
}
console.log(
chalk.green(`Project ${appName} scaffolded successfully!`)
);
console.log(chalk.yellow("Next steps:"));
console.log(` cd ${appName}`);
console.log(" yarn install # to install dependencies");
console.log(" yarn dev # to start development server");
} catch (err) {
console.error(chalk.red("Error creating project:", err));
}
});
program.parse(process.argv);