Files
create-better-t-stack/apps/cli/src/helpers/create-readme.ts
2025-04-01 01:02:32 +05:30

194 lines
5.1 KiB
TypeScript

import path from "node:path";
import fs from "fs-extra";
import type {
ProjectAddons,
ProjectConfig,
ProjectDatabase,
ProjectOrm,
ProjectRuntime,
} from "../types";
export async function createReadme(projectDir: string, options: ProjectConfig) {
const readmePath = path.join(projectDir, "README.md");
const content = generateReadmeContent(options);
try {
await fs.writeFile(readmePath, content);
} catch (error) {
console.error("Failed to create README.md file:", error);
}
}
function generateReadmeContent(options: ProjectConfig): string {
const {
projectName,
packageManager,
database,
auth,
addons = [],
orm = "drizzle",
runtime = "bun",
} = options;
const packageManagerRunCmd =
packageManager === "npm" ? "npm run" : packageManager;
return `# ${projectName}
This project was created with [Better-T-Stack](https://github.com/better-t-stack/Better-T-Stack), a modern TypeScript stack that combines React, TanStack Router, Hono, tRPC, and more.
## Features
${generateFeaturesList(database, auth, addons, orm, runtime)}
## Getting Started
First, install the dependencies:
\`\`\`bash
${packageManager} install
\`\`\`
${generateDatabaseSetup(database, auth, packageManagerRunCmd, orm)}
Then, run the development server:
\`\`\`bash
${packageManagerRunCmd} dev
\`\`\`
Open [http://localhost:3001](http://localhost:3001) in your browser to see the web application.
The API is running at [http://localhost:3000](http://localhost:3000).
## Project Structure
\`\`\`
${projectName}/
├── apps/
│ ├── web/ # Frontend application (React, TanStack Router)
│ └── server/ # Backend API (Hono, tRPC)
\`\`\`
## Available Scripts
${generateScriptsList(packageManagerRunCmd, database, orm, auth)}
`;
}
function generateFeaturesList(
database: ProjectDatabase,
auth: boolean,
addons: ProjectAddons[],
orm: ProjectOrm,
runtime: ProjectRuntime,
): string {
const addonsList = [
"- **TypeScript** - For type safety and improved developer experience",
"- **TanStack Router** - File-based routing with full type safety",
"- **TailwindCSS** - Utility-first CSS for rapid UI development",
"- **shadcn/ui** - Reusable UI components",
"- **Hono** - Lightweight, performant server framework",
"- **tRPC** - End-to-end type-safe APIs",
`- **${runtime === "bun" ? "Bun" : "Node.js"}** - Runtime environment`,
];
if (database !== "none") {
addonsList.push(
`- **${orm === "drizzle" ? "Drizzle" : "Prisma"}** - TypeScript-first ORM`,
`- **${database === "sqlite" ? "SQLite/Turso" : "PostgreSQL"}** - Database engine`,
);
}
if (auth) {
addonsList.push(
"- **Authentication** - Email & password authentication with Better Auth",
);
}
for (const addon of addons) {
if (addon === "pwa") {
addonsList.push("- **PWA** - Progressive Web App support");
} else if (addon === "tauri") {
addonsList.push("- **Tauri** - Build native desktop applications");
} else if (addon === "biome") {
addonsList.push("- **Biome** - Linting and formatting");
} else if (addon === "husky") {
addonsList.push("- **Husky** - Git hooks for code quality");
}
}
return addonsList.join("\n");
}
function generateDatabaseSetup(
database: ProjectDatabase,
auth: boolean,
packageManagerRunCmd: string,
orm: ProjectOrm,
): string {
if (database === "none") {
return "";
}
let setup = "## Database Setup\n\n";
if (database === "sqlite") {
setup += `This project uses SQLite${orm === "drizzle" ? " with Drizzle ORM" : " with Prisma"}.
1. Start the local SQLite database:
\`\`\`bash
cd apps/server && ${packageManagerRunCmd} db:local
\`\`\`
2. Update your \`.env\` file in the \`apps/server\` directory with the appropriate connection details if needed.
`;
} else if (database === "postgres") {
setup += `This project uses PostgreSQL${orm === "drizzle" ? " with Drizzle ORM" : " with Prisma"}.
1. Make sure you have a PostgreSQL database set up.
2. Update your \`apps/server/.env\` file with your PostgreSQL connection details.
`;
}
setup += `
${auth ? "4" : "3"}. ${
orm === "prisma"
? `Generate the Prisma client and push the schema:
\`\`\`bash
${packageManagerRunCmd} db:push
\`\`\``
: `Apply the schema to your database:
\`\`\`bash
${packageManagerRunCmd} db:push
\`\`\``
}
`;
return setup;
}
function generateScriptsList(
packageManagerRunCmd: string,
database: ProjectDatabase,
orm: ProjectOrm,
auth: boolean,
): string {
let scripts = `- \`${packageManagerRunCmd} dev\`: Start both web and server in development mode
- \`${packageManagerRunCmd} build\`: Build both web and server
- \`${packageManagerRunCmd} dev:web\`: Start only the web application
- \`${packageManagerRunCmd} dev:server\`: Start only the server
- \`${packageManagerRunCmd} check-types\`: Check TypeScript types across all apps`;
if (database !== "none") {
scripts += `
- \`${packageManagerRunCmd} db:push\`: Push schema changes to database
- \`${packageManagerRunCmd} db:studio\`: Open database studio UI`;
if (database === "sqlite" && orm === "drizzle") {
scripts += `\n- \`cd apps/server && ${packageManagerRunCmd} db:local\`: Start the local SQLite database`;
}
}
return scripts;
}