Add Todo button to homepage when examples are included

Add project creation time display in success message
This commit is contained in:
Aman Varshney
2025-03-24 01:38:53 +05:30
parent df0aa04503
commit b5f47fc23b
8 changed files with 47 additions and 113 deletions

View File

@@ -0,0 +1,5 @@
---
"create-better-t-stack": patch
---
Add Todo button to homepage when examples are included

View File

@@ -22,10 +22,7 @@
"test": "vitest run",
"prepublishOnly": "npm run build"
},
"files": [
"dist",
"template"
],
"files": ["dist", "template"],
"dependencies": {
"@clack/prompts": "^0.10.0",
"commander": "^13.1.0",

View File

@@ -48,6 +48,7 @@ async function setupTodoExample(
}
await updateHeaderWithTodoLink(projectDir, auth);
await addTodoButtonToHomepage(projectDir);
}
}
@@ -128,3 +129,28 @@ async function updateRouterIndex(projectDir: string): Promise<void> {
await fs.writeFile(routerFile, routerContent);
}
}
async function addTodoButtonToHomepage(projectDir: string): Promise<void> {
const indexPath = path.join(
projectDir,
"packages/client/src/routes/index.tsx",
);
if (await fs.pathExists(indexPath)) {
let indexContent = await fs.readFile(indexPath, "utf8");
indexContent = indexContent.replace(
/<div id="buttons"><\/div>/,
`<div id="buttons" className="mt-4 flex flex-col gap-4 sm:flex-row sm:items-center">
<Button asChild>
<Link to="/todos" className="flex items-center">
View Todo Demo
<ArrowRight className="ml-1 h-4 w-4" />
</Link>
</Button>
</div>`,
);
await fs.writeFile(indexPath, indexContent);
}
}

View File

@@ -19,6 +19,8 @@ process.on("SIGINT", () => {
const program = new Command();
async function main() {
const startTime = Date.now();
program
.name("create-better-t-stack")
.description("Create a new Better-T Stack project")
@@ -169,7 +171,12 @@ async function main() {
),
);
outro(pc.magenta("Project created successfully!"));
const elapsedTimeInSeconds = ((Date.now() - startTime) / 1000).toFixed(2);
outro(
pc.magenta(
`Project created successfully in ${pc.bold(elapsedTimeInSeconds)} seconds!`,
),
);
} catch (error) {
s.stop(pc.red("Failed"));
if (error instanceof Error) {

View File

@@ -50,7 +50,8 @@ export async function gatherConfig(
? getTursoSetupChoice(flags.turso)
: Promise.resolve(false),
addons: () => getAddonsChoice(flags.addons),
examples: () => getExamplesChoice(flags.examples),
examples: ({ results }) =>
getExamplesChoice(flags.examples, results.database),
git: () => getGitChoice(flags.git),
packageManager: () => getPackageManagerChoice(flags.packageManager),
noInstall: () => getNoInstallChoice(flags.noInstall),

View File

@@ -1,13 +1,16 @@
import { cancel, isCancel, multiselect } from "@clack/prompts";
import pc from "picocolors";
import { DEFAULT_CONFIG } from "../constants";
import type { ProjectExamples } from "../types";
import type { ProjectDatabase, ProjectExamples } from "../types";
export async function getExamplesChoice(
examples?: ProjectExamples[],
database?: ProjectDatabase,
): Promise<ProjectExamples[]> {
if (examples !== undefined) return examples;
if (database === "none") return [];
const response = await multiselect<ProjectExamples>({
message: "Which examples would you like to include?",
options: [

View File

@@ -67,15 +67,7 @@ function HomeComponent() {
/>
</ul>
</section>
<div className="mt-4 flex flex-col gap-4 sm:flex-row sm:items-center">
<Button asChild>
<Link to="/todos" className="flex items-center">
View Todo Demo
<ArrowRight className="ml-1 h-4 w-4" />
</Link>
</Button>
</div>
<div id="buttons"></div>
</div>
</div>
);

View File

@@ -1,97 +0,0 @@
import { Button } from "@/components/ui/button";
import { trpc } from "@/utils/trpc";
import { Link, createFileRoute } from "@tanstack/react-router";
import { ArrowRight } from "lucide-react";
export const Route = createFileRoute("/")({
component: HomeComponent,
});
const TITLE_TEXT = `
██████╗ ███████╗████████╗████████╗███████╗██████╗
██╔══██╗██╔════╝╚══██╔══╝╚══██╔══╝██╔════╝██╔══██╗
██████╔╝█████╗ ██║ ██║ █████╗ ██████╔╝
██╔══██╗██╔══╝ ██║ ██║ ██╔══╝ ██╔══██╗
██████╔╝███████╗ ██║ ██║ ███████╗██║ ██║
╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝
████████╗ ███████╗████████╗ █████╗ ██████╗██╗ ██╗
╚══██╔══╝ ██╔════╝╚══██╔══╝██╔══██╗██╔════╝██║ ██╔╝
██║ ███████╗ ██║ ███████║██║ █████╔╝
██║ ╚════██║ ██║ ██╔══██║██║ ██╔═██╗
██║ ███████║ ██║ ██║ ██║╚██████╗██║ ██╗
╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
`;
function HomeComponent() {
const healthCheck = trpc.healthCheck.useQuery();
return (
<div className="container mx-auto max-w-3xl px-4 py-2">
<pre className="overflow-x-auto font-mono text-sm">{TITLE_TEXT}</pre>
<div className="grid gap-6">
<section className="rounded-lg border p-4">
<h2 className="mb-2 font-medium">API Status</h2>
<div className="flex items-center gap-2">
<div
className={`h-2 w-2 rounded-full ${healthCheck.data ? "bg-green-500" : "bg-red-500"}`}
/>
<span className="text-sm text-muted-foreground">
{healthCheck.isLoading
? "Checking..."
: healthCheck.data
? "Connected"
: "Disconnected"}
</span>
</div>
</section>
<section>
<h2 className="mb-3 font-medium">Core Features</h2>
<ul className="grid grid-cols-2 gap-3">
<FeatureItem
title="Type-Safe API"
description="End-to-end type safety with tRPC"
/>
<FeatureItem
title="Modern React"
description="TanStack Router + TanStack Query"
/>
<FeatureItem
title="Fast Backend"
description="Lightweight Hono server"
/>
<FeatureItem
title="Beautiful UI"
description="TailwindCSS + shadcn/ui components"
/>
</ul>
</section>
<div className="mt-4 flex flex-col gap-4 sm:flex-row sm:items-center">
<Button asChild>
<Link to="/todos" className="flex items-center">
View Todo Demo
<ArrowRight className="ml-1 h-4 w-4" />
</Link>
</Button>
</div>
</div>
</div>
);
}
function FeatureItem({
title,
description,
}: {
title: string;
description: string;
}) {
return (
<li className="border-l-2 border-primary py-1 pl-3">
<h3 className="font-medium">{title}</h3>
<p className="text-sm text-muted-foreground">{description}</p>
</li>
);
}