add starlight docs addon

This commit is contained in:
Aman Varshney
2025-04-10 20:35:15 +05:30
parent 6847603b5c
commit aac6a7d267
11 changed files with 118 additions and 20 deletions

View File

@@ -0,0 +1,5 @@
---
"create-better-t-stack": minor
---
add starlight docs addon

View File

@@ -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 <type> Database type (none, sqlite, postgres, mongodb)
--database <type> Database type (none, sqlite, postgres, mysql, mongodb)
--orm <type> ORM type (none, drizzle, prisma)
--auth Include authentication
--no-auth Exclude authentication
--frontend <types...> Frontend types (tanstack-router, react-router, tanstack-start, native, none)
--addons <types...> Additional addons (pwa, tauri, biome, husky, none)
--addons <types...> Additional addons (pwa, tauri, starlight, biome, husky, none)
--examples <types...> 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
```

View File

@@ -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(

View File

@@ -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")) {

View File

@@ -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`;
}

View File

@@ -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<void> {
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;
}
}

View File

@@ -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 <types...>",
"Additional addons (pwa, tauri, biome, husky, none)",
"Additional addons (pwa, tauri, starlight, biome, husky, none)",
)
.option("--examples <types...>", "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"];

View File

@@ -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",

View File

@@ -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),

View File

@@ -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";

View File

@@ -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",