diff --git a/.changeset/slimy-ideas-do.md b/.changeset/slimy-ideas-do.md new file mode 100644 index 0000000..ecc282e --- /dev/null +++ b/.changeset/slimy-ideas-do.md @@ -0,0 +1,5 @@ +--- +"create-better-t-stack": minor +--- + +add starlight docs addon diff --git a/apps/cli/README.md b/apps/cli/README.md index 9117d5c..6b938d8 100644 --- a/apps/cli/README.md +++ b/apps/cli/README.md @@ -32,6 +32,7 @@ Follow the prompts to configure your project or use the `--yes` flag for default - **Authentication**: Optional auth setup with Better-Auth - **Progressive Web App**: Add PWA support with service workers and installable apps - **Desktop Apps**: Build native desktop apps with Tauri integration +- **Documentation**: Add an Astro Starlight documentation site to your project - **Code Quality**: Biome for linting and formatting - **Git Hooks**: Husky with lint-staged for pre-commit checks - **Examples**: Todo app with full CRUD functionality, AI Chat using AI SDK @@ -45,12 +46,12 @@ Usage: create-better-t-stack [project-directory] [options] Options: -V, --version Output the version number -y, --yes Use default configuration - --database Database type (none, sqlite, postgres, mongodb) + --database Database type (none, sqlite, postgres, mysql, mongodb) --orm ORM type (none, drizzle, prisma) --auth Include authentication --no-auth Exclude authentication --frontend Frontend types (tanstack-router, react-router, tanstack-start, native, none) - --addons Additional addons (pwa, tauri, biome, husky, none) + --addons Additional addons (pwa, tauri, starlight, biome, husky, none) --examples Examples to include (todo, ai) --no-examples Skip all examples --git Initialize git repository @@ -95,3 +96,8 @@ Create a project with Turso database setup: ```bash npx create-better-t-stack my-app --db-setup turso ``` + +Create a project with documentation site: +```bash +npx create-better-t-stack my-app --addons starlight +``` diff --git a/apps/cli/src/helpers/addons-setup.ts b/apps/cli/src/helpers/addons-setup.ts index acadec7..072c11e 100644 --- a/apps/cli/src/helpers/addons-setup.ts +++ b/apps/cli/src/helpers/addons-setup.ts @@ -7,6 +7,7 @@ import type { ProjectPackageManager, } from "../types"; import { addPackageDependency } from "../utils/add-package-deps"; +import { setupStarlight } from "./starlight-setup"; import { setupTauri } from "./tauri-setup"; export async function setupAddons( @@ -30,6 +31,9 @@ export async function setupAddons( if (addons.includes("husky")) { await setupHusky(projectDir); } + if (addons.includes("starlight")) { + await setupStarlight(projectDir, packageManager); + } } export function getWebAppDir( diff --git a/apps/cli/src/helpers/mongodb-atlas-setup.ts b/apps/cli/src/helpers/mongodb-atlas-setup.ts index f4ae0df..712f06a 100644 --- a/apps/cli/src/helpers/mongodb-atlas-setup.ts +++ b/apps/cli/src/helpers/mongodb-atlas-setup.ts @@ -36,10 +36,9 @@ async function initMongoDBAtlas( stdio: "inherit", }); - log.info(pc.yellow("Please enter your connection string")); - const connectionString = await text({ message: "Paste your complete MongoDB connection string:", + placeholder: "mongodb://USERNAME:PASSWORD@HOST/DATABASE", validate(value) { if (!value) return "Please enter a connection string"; if (!value.startsWith("mongodb")) { diff --git a/apps/cli/src/helpers/post-installation.ts b/apps/cli/src/helpers/post-installation.ts index 0b629c1..604e1e6 100644 --- a/apps/cli/src/helpers/post-installation.ts +++ b/apps/cli/src/helpers/post-installation.ts @@ -43,6 +43,9 @@ export function displayPostInstallInstructions( addons?.includes("pwa") && frontends?.includes("react-router") ? getPwaInstructions() : ""; + const starlightInstructions = addons?.includes("starlight") + ? getStarlightInstructions(runCmd) + : ""; const hasTanstackRouter = frontends?.includes("tanstack-router"); const hasTanstackStart = frontends?.includes("tanstack-start"); @@ -64,7 +67,7 @@ ${ ? `${hasWebFrontend ? `${pc.cyan("•")} Frontend: http://localhost:${webPort}\n` : ""}` : `${pc.yellow("NOTE:")} You are creating a backend-only app (no frontend selected)\n` }${pc.cyan("•")} API: http://localhost:3000 -${nativeInstructions ? `\n${nativeInstructions.trim()}` : ""}${databaseInstructions ? `\n${databaseInstructions.trim()}` : ""}${tauriInstructions ? `\n${tauriInstructions.trim()}` : ""}${lintingInstructions ? `\n${lintingInstructions.trim()}` : ""}${pwaInstructions ? `\n${pwaInstructions.trim()}` : ""} +${addons?.includes("starlight") ? `${pc.cyan("•")} Docs: http://localhost:4321\n` : ""}${nativeInstructions ? `\n${nativeInstructions.trim()}` : ""}${databaseInstructions ? `\n${databaseInstructions.trim()}` : ""}${tauriInstructions ? `\n${tauriInstructions.trim()}` : ""}${lintingInstructions ? `\n${lintingInstructions.trim()}` : ""}${pwaInstructions ? `\n${pwaInstructions.trim()}` : ""}${starlightInstructions ? `\n${starlightInstructions.trim()}` : ""} \n${pc.bold("Like Better-T Stack?")} Please consider giving us a star on GitHub: ${pc.cyan("https://github.com/AmanVarshney01/create-better-t-stack")}`, "Next steps", @@ -120,3 +123,7 @@ function getTauriInstructions(runCmd?: string): string { function getPwaInstructions(): string { return `${pc.bold("PWA with React Router v7:")}\n${pc.yellow("NOTE:")} There is a known compatibility issue between VitePWA and React Router v7.\nSee: https://github.com/vite-pwa/vite-plugin-pwa/issues/809\n`; } + +function getStarlightInstructions(runCmd?: string): string { + return `${pc.bold("Documentation with Starlight:")}\n${pc.cyan("•")} Start docs site: ${`cd apps/docs && ${runCmd} dev`}\n${pc.cyan("•")} Build docs site: ${`cd apps/docs && ${runCmd} build`}\n`; +} diff --git a/apps/cli/src/helpers/starlight-setup.ts b/apps/cli/src/helpers/starlight-setup.ts new file mode 100644 index 0000000..f9d0328 --- /dev/null +++ b/apps/cli/src/helpers/starlight-setup.ts @@ -0,0 +1,64 @@ +import path from "node:path"; +import { log, spinner } from "@clack/prompts"; +import { execa } from "execa"; +import pc from "picocolors"; +import type { ProjectPackageManager } from "../types"; + +export async function setupStarlight( + projectDir: string, + packageManager: ProjectPackageManager, +): Promise { + const s = spinner(); + + try { + s.start("Setting up Starlight documentation site..."); + + let cmd: string; + let args: string[]; + + switch (packageManager) { + case "npm": + cmd = "npx"; + args = ["create-astro@latest"]; + break; + case "pnpm": + cmd = "pnpm"; + args = ["dlx", "create-astro@latest"]; + break; + case "bun": + cmd = "bunx"; + args = ["create-astro@latest"]; + break; + default: + cmd = "npx"; + args = ["create-astro@latest"]; + } + + args = [ + ...args, + "docs", + "--template", + "starlight", + "--no-install", + "--add", + "tailwind", + "--no-git", + "--skip-houston", + ]; + + await execa(cmd, args, { + cwd: path.join(projectDir, "apps"), + env: { + CI: "true", + }, + }); + + s.stop("Starlight documentation site setup successfully!"); + } catch (error) { + s.stop(pc.red("Failed to set up Starlight documentation site")); + if (error instanceof Error) { + log.error(pc.red(error.message)); + } + throw error; + } +} diff --git a/apps/cli/src/index.ts b/apps/cli/src/index.ts index b6ed581..cedd094 100644 --- a/apps/cli/src/index.ts +++ b/apps/cli/src/index.ts @@ -22,10 +22,9 @@ import { generateReproducibleCommand } from "./utils/generate-reproducible-comma import { getLatestCLIVersion } from "./utils/get-latest-cli-version"; import { renderTitle } from "./utils/render-title"; -process.on("SIGINT", () => { - log.error(pc.red("Operation cancelled")); - process.exit(0); -}); +const exit = () => process.exit(0); +process.on("SIGINT", exit); +process.on("SIGTERM", exit); const program = new Command(); @@ -51,7 +50,7 @@ async function main() { ) .option( "--addons ", - "Additional addons (pwa, tauri, biome, husky, none)", + "Additional addons (pwa, tauri, starlight, biome, husky, none)", ) .option("--examples ", "Examples to include (todo, ai)") .option("--no-examples", "Skip all examples") @@ -354,7 +353,7 @@ function processAndValidateFlags( } if (options.addons && options.addons.length > 0) { - const validAddons = ["pwa", "tauri", "biome", "husky", "none"]; + const validAddons = ["pwa", "tauri", "biome", "husky", "starlight", "none"]; const invalidAddons = options.addons.filter( (addon: string) => !validAddons.includes(addon), ); @@ -380,7 +379,8 @@ function processAndValidateFlags( addon === "pwa" || addon === "tauri" || addon === "biome" || - addon === "husky", + addon === "husky" || + addon === "starlight", ); const webSpecificAddons = ["pwa", "tauri"]; diff --git a/apps/cli/src/prompts/addons.ts b/apps/cli/src/prompts/addons.ts index 5b92671..53679e6 100644 --- a/apps/cli/src/prompts/addons.ts +++ b/apps/cli/src/prompts/addons.ts @@ -14,6 +14,11 @@ export async function getAddonsChoice( frontends?.includes("tanstack-router"); const addonOptions = [ + { + value: "starlight" as const, + label: "Starlight", + hint: "Add Astro Starlight documentation site", + }, { value: "biome" as const, label: "Biome", diff --git a/apps/cli/src/prompts/config-prompts.ts b/apps/cli/src/prompts/config-prompts.ts index 2516cea..bf2a8ca 100644 --- a/apps/cli/src/prompts/config-prompts.ts +++ b/apps/cli/src/prompts/config-prompts.ts @@ -62,12 +62,6 @@ export async function gatherConfig( results.database !== "none", results.frontend, ), - dbSetup: ({ results }) => - getDBSetupChoice( - results.database ?? "none", - flags.dbSetup, - results.orm, - ), addons: ({ results }) => getAddonsChoice(flags.addons, results.frontend), examples: ({ results }) => getExamplesChoice( @@ -76,6 +70,12 @@ export async function gatherConfig( results.frontend, results.backend, ), + dbSetup: ({ results }) => + getDBSetupChoice( + results.database ?? "none", + flags.dbSetup, + results.orm, + ), git: () => getGitChoice(flags.git), packageManager: () => getPackageManagerChoice(flags.packageManager), noInstall: () => getNoInstallChoice(flags.noInstall), diff --git a/apps/cli/src/types.ts b/apps/cli/src/types.ts index c2725fd..b010ce5 100644 --- a/apps/cli/src/types.ts +++ b/apps/cli/src/types.ts @@ -6,7 +6,7 @@ export type ProjectDatabase = | "none"; export type ProjectOrm = "drizzle" | "prisma" | "none"; export type ProjectPackageManager = "npm" | "pnpm" | "bun"; -export type ProjectAddons = "pwa" | "biome" | "tauri" | "husky"; +export type ProjectAddons = "pwa" | "biome" | "tauri" | "husky" | "starlight"; export type ProjectBackend = "hono" | "elysia" | "express"; export type ProjectRuntime = "node" | "bun"; export type ProjectExamples = "todo" | "ai"; diff --git a/apps/web/src/lib/constant.ts b/apps/web/src/lib/constant.ts index 3896f5d..1e27ba1 100644 --- a/apps/web/src/lib/constant.ts +++ b/apps/web/src/lib/constant.ts @@ -233,6 +233,14 @@ export const TECH_OPTIONS = { color: "from-amber-500 to-amber-700", default: false, }, + { + id: "starlight", + name: "Starlight", + description: "Documentation site with Astro", + icon: "📚", + color: "from-teal-500 to-teal-700", + default: false, + }, { id: "biome", name: "Biome", @@ -379,7 +387,7 @@ export const PRESET_TEMPLATES = [ dbSetup: "turso", auth: "true", packageManager: "bun", - addons: ["pwa", "biome", "husky", "tauri"], + addons: ["pwa", "biome", "husky", "tauri", "starlight"], examples: ["todo", "ai"], git: "true", install: "true",