From 1f94a41d7f0d77b368dd25003e0b17915b692bd6 Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Fri, 8 Aug 2025 01:29:46 +0530 Subject: [PATCH 1/8] ok --- apps/cli/src/constants.ts | 11 +- apps/cli/src/prompts/api.ts | 59 ++- apps/cli/src/prompts/examples.ts | 16 +- apps/cli/src/prompts/frontend.ts | 10 +- apps/cli/src/prompts/project-name.ts | 14 +- apps/cli/src/prompts/web-deploy.ts | 3 +- apps/cli/src/types.ts | 6 +- apps/cli/src/utils/compatibility-rules.ts | 315 ++++++++++++++++ apps/cli/src/utils/compatibility.ts | 12 + .../utils/generate-reproducible-command.ts | 8 +- apps/cli/src/validation.ts | 355 ++---------------- 11 files changed, 423 insertions(+), 386 deletions(-) create mode 100644 apps/cli/src/utils/compatibility-rules.ts create mode 100644 apps/cli/src/utils/compatibility.ts diff --git a/apps/cli/src/constants.ts b/apps/cli/src/constants.ts index cdd55111..e8a8cf5b 100644 --- a/apps/cli/src/constants.ts +++ b/apps/cli/src/constants.ts @@ -140,13 +140,4 @@ export const ADDON_COMPATIBILITY: Record = { none: [], } as const; -// TODO: need to refactor this -export const WEB_FRAMEWORKS: readonly Frontend[] = [ - "tanstack-router", - "react-router", - "tanstack-start", - "next", - "nuxt", - "svelte", - "solid", -]; +// WEB_FRAMEWORKS moved to utils/compatibility for centralized use diff --git a/apps/cli/src/prompts/api.ts b/apps/cli/src/prompts/api.ts index 48d12b3b..5ca001c0 100644 --- a/apps/cli/src/prompts/api.ts +++ b/apps/cli/src/prompts/api.ts @@ -1,6 +1,7 @@ import { cancel, isCancel, select } from "@clack/prompts"; import pc from "picocolors"; import type { API, Backend, Frontend } from "../types"; +import { allowedApisForFrontends } from "../utils/compatibility-rules"; export async function getApiChoice( Api?: API | undefined, @@ -13,44 +14,26 @@ export async function getApiChoice( if (Api) return Api; - const includesNuxt = frontend?.includes("nuxt"); - const includesSvelte = frontend?.includes("svelte"); - const includesSolid = frontend?.includes("solid"); - - let apiOptions = [ - { - value: "trpc" as const, - label: "tRPC", - hint: "End-to-end typesafe APIs made easy", - }, - { - value: "orpc" as const, - label: "oRPC", - hint: "End-to-end type-safe APIs that adhere to OpenAPI standards", - }, - { - value: "none" as const, - label: "None", - hint: "No API layer (e.g. for full-stack frameworks like Next.js with Route Handlers)", - }, - ]; - - if (includesNuxt || includesSvelte || includesSolid) { - apiOptions = [ - { - value: "orpc" as const, - label: "oRPC", - hint: `End-to-end type-safe APIs (Recommended for ${ - includesNuxt ? "Nuxt" : includesSvelte ? "Svelte" : "Solid" - } frontend)`, - }, - { - value: "none" as const, - label: "None", - hint: "No API layer", - }, - ]; - } + const allowed = allowedApisForFrontends(frontend ?? []); + const apiOptions = allowed.map((a) => + a === "trpc" + ? { + value: "trpc" as const, + label: "tRPC", + hint: "End-to-end typesafe APIs made easy", + } + : a === "orpc" + ? { + value: "orpc" as const, + label: "oRPC", + hint: "End-to-end type-safe APIs that adhere to OpenAPI standards", + } + : { + value: "none" as const, + label: "None", + hint: "No API layer (e.g. for full-stack frameworks like Next.js with Route Handlers)", + }, + ); const apiType = await select({ message: "Select API type", diff --git a/apps/cli/src/prompts/examples.ts b/apps/cli/src/prompts/examples.ts index 3d39ada8..bb0c2da3 100644 --- a/apps/cli/src/prompts/examples.ts +++ b/apps/cli/src/prompts/examples.ts @@ -2,6 +2,10 @@ import { cancel, isCancel, multiselect } from "@clack/prompts"; import pc from "picocolors"; import { DEFAULT_CONFIG } from "../constants"; import type { API, Backend, Database, Examples, Frontend } from "../types"; +import { + isExampleAIAllowed, + isExampleTodoAllowed, +} from "../utils/compatibility-rules"; export async function getExamplesChoice( examples?: Examples[], @@ -30,15 +34,17 @@ export async function getExamplesChoice( if (noFrontendSelected) return []; let response: Examples[] | symbol = []; - const options: { value: Examples; label: string; hint: string }[] = [ - { + const options: { value: Examples; label: string; hint: string }[] = []; + + if (isExampleTodoAllowed(backend, database)) { + options.push({ value: "todo" as const, label: "Todo App", hint: "A simple CRUD example app", - }, - ]; + }); + } - if (backend !== "elysia" && !frontends?.includes("solid")) { + if (isExampleAIAllowed(backend, frontends ?? [])) { options.push({ value: "ai" as const, label: "AI Chat", diff --git a/apps/cli/src/prompts/frontend.ts b/apps/cli/src/prompts/frontend.ts index e4eb9c08..c337ada0 100644 --- a/apps/cli/src/prompts/frontend.ts +++ b/apps/cli/src/prompts/frontend.ts @@ -2,6 +2,7 @@ import { cancel, isCancel, multiselect, select } from "@clack/prompts"; import pc from "picocolors"; import { DEFAULT_CONFIG } from "../constants"; import type { Backend, Frontend } from "../types"; +import { isFrontendAllowedWithBackend } from "../utils/compatibility-rules"; export async function getFrontendChoice( frontendOptions?: Frontend[], @@ -73,12 +74,9 @@ export async function getFrontendChoice( }, ]; - const webOptions = allWebOptions.filter((option) => { - if (backend === "convex") { - return option.value !== "solid"; - } - return true; - }); + const webOptions = allWebOptions.filter((option) => + isFrontendAllowedWithBackend(option.value, backend), + ); const webFramework = await select({ message: "Choose web", diff --git a/apps/cli/src/prompts/project-name.ts b/apps/cli/src/prompts/project-name.ts index 0b5be852..eeae2a9f 100644 --- a/apps/cli/src/prompts/project-name.ts +++ b/apps/cli/src/prompts/project-name.ts @@ -5,6 +5,12 @@ import pc from "picocolors"; import { DEFAULT_CONFIG } from "../constants"; import { ProjectNameSchema } from "../types"; +function isPathWithinCwd(targetPath: string): boolean { + const resolved = path.resolve(targetPath); + const rel = path.relative(process.cwd(), resolved); + return !rel.startsWith("..") && !path.isAbsolute(rel); +} + function validateDirectoryName(name: string): string | undefined { if (name === ".") return undefined; @@ -23,7 +29,11 @@ export async function getProjectName(initialName?: string): Promise { const finalDirName = path.basename(initialName); const validationError = validateDirectoryName(finalDirName); if (!validationError) { - return initialName; + const projectDir = path.resolve(process.cwd(), initialName); + if (!isPathWithinCwd(projectDir)) { + } else { + return initialName; + } } } @@ -56,7 +66,7 @@ export async function getProjectName(initialName?: string): Promise { if (nameToUse !== ".") { const projectDir = path.resolve(process.cwd(), nameToUse); - if (!projectDir.startsWith(process.cwd())) { + if (!isPathWithinCwd(projectDir)) { return "Project path must be within current directory"; } } diff --git a/apps/cli/src/prompts/web-deploy.ts b/apps/cli/src/prompts/web-deploy.ts index 8622556f..e948758a 100644 --- a/apps/cli/src/prompts/web-deploy.ts +++ b/apps/cli/src/prompts/web-deploy.ts @@ -1,7 +1,8 @@ import { cancel, isCancel, select } from "@clack/prompts"; import pc from "picocolors"; -import { DEFAULT_CONFIG, WEB_FRAMEWORKS } from "../constants"; +import { DEFAULT_CONFIG } from "../constants"; import type { Backend, Frontend, Runtime, WebDeploy } from "../types"; +import { WEB_FRAMEWORKS } from "../utils/compatibility"; function hasWebFrontend(frontends: Frontend[]): boolean { return frontends.some((f) => WEB_FRAMEWORKS.includes(f)); diff --git a/apps/cli/src/types.ts b/apps/cli/src/types.ts index 536a1748..4997ceb4 100644 --- a/apps/cli/src/types.ts +++ b/apps/cli/src/types.ts @@ -17,9 +17,7 @@ export type Backend = z.infer; export const RuntimeSchema = z .enum(["bun", "node", "workers", "none"]) - .describe( - "Runtime environment (workers only available with hono backend and drizzle orm)", - ); + .describe("Runtime environment"); export type Runtime = z.infer; export const FrontendSchema = z @@ -176,5 +174,3 @@ export interface BetterTStackConfig { api: API; webDeploy: WebDeploy; } - -export type AvailablePackageManagers = "npm" | "pnpm" | "bun"; diff --git a/apps/cli/src/utils/compatibility-rules.ts b/apps/cli/src/utils/compatibility-rules.ts new file mode 100644 index 00000000..9b21a863 --- /dev/null +++ b/apps/cli/src/utils/compatibility-rules.ts @@ -0,0 +1,315 @@ +import { consola } from "consola"; +import type { + Addons, + API, + CLIInput, + Frontend, + ProjectConfig, + WebDeploy, +} from "../types"; +import { validateAddonCompatibility } from "./addon-compatibility"; +import { WEB_FRAMEWORKS } from "./compatibility"; + +export function isWebFrontend(value: Frontend): boolean { + return WEB_FRAMEWORKS.includes(value); +} + +export function splitFrontends(values: Frontend[] = []): { + web: Frontend[]; + native: Frontend[]; +} { + const web = values.filter((f) => isWebFrontend(f)); + const native = values.filter( + (f) => f === "native-nativewind" || f === "native-unistyles", + ); + return { web, native }; +} + +export function ensureSingleWebAndNative(frontends: Frontend[]) { + const { web, native } = splitFrontends(frontends); + if (web.length > 1) { + consola.fatal( + "Cannot select multiple web frameworks. Choose only one of: tanstack-router, tanstack-start, react-router, next, nuxt, svelte, solid", + ); + process.exit(1); + } + if (native.length > 1) { + consola.fatal( + "Cannot select multiple native frameworks. Choose only one of: native-nativewind, native-unistyles", + ); + process.exit(1); + } +} + +export function validateWorkersCompatibility( + providedFlags: Set, + options: CLIInput, + config: Partial, +) { + if ( + providedFlags.has("runtime") && + options.runtime === "workers" && + config.backend && + config.backend !== "hono" + ) { + consola.fatal( + `Cloudflare Workers runtime (--runtime workers) is only supported with Hono backend (--backend hono). Current backend: ${config.backend}. Please use '--backend hono' or choose a different runtime.`, + ); + process.exit(1); + } + + if ( + providedFlags.has("backend") && + config.backend && + config.backend !== "hono" && + config.runtime === "workers" + ) { + consola.fatal( + `Backend '${config.backend}' is not compatible with Cloudflare Workers runtime. Cloudflare Workers runtime is only supported with Hono backend. Please use '--backend hono' or choose a different runtime.`, + ); + process.exit(1); + } + + if ( + providedFlags.has("runtime") && + options.runtime === "workers" && + config.orm && + config.orm !== "drizzle" && + config.orm !== "none" + ) { + consola.fatal( + `Cloudflare Workers runtime (--runtime workers) is only supported with Drizzle ORM (--orm drizzle) or no ORM (--orm none). Current ORM: ${config.orm}. Please use '--orm drizzle', '--orm none', or choose a different runtime.`, + ); + process.exit(1); + } + + if ( + providedFlags.has("orm") && + config.orm && + config.orm !== "drizzle" && + config.orm !== "none" && + config.runtime === "workers" + ) { + consola.fatal( + `ORM '${config.orm}' is not compatible with Cloudflare Workers runtime. Cloudflare Workers runtime is only supported with Drizzle ORM or no ORM. Please use '--orm drizzle', '--orm none', or choose a different runtime.`, + ); + process.exit(1); + } + + if ( + providedFlags.has("runtime") && + options.runtime === "workers" && + config.database === "mongodb" + ) { + consola.fatal( + "Cloudflare Workers runtime (--runtime workers) is not compatible with MongoDB database. MongoDB requires Prisma or Mongoose ORM, but Workers runtime only supports Drizzle ORM. Please use a different database or runtime.", + ); + process.exit(1); + } + + if ( + providedFlags.has("runtime") && + options.runtime === "workers" && + config.dbSetup === "docker" + ) { + consola.fatal( + "Cloudflare Workers runtime (--runtime workers) is not compatible with Docker setup. Workers runtime uses serverless databases (D1) and doesn't support local Docker containers. Please use '--db-setup d1' for SQLite or choose a different runtime.", + ); + process.exit(1); + } + + if ( + providedFlags.has("database") && + config.database === "mongodb" && + config.runtime === "workers" + ) { + consola.fatal( + "MongoDB database is not compatible with Cloudflare Workers runtime. MongoDB requires Prisma or Mongoose ORM, but Workers runtime only supports Drizzle ORM. Please use a different database or runtime.", + ); + process.exit(1); + } + + if ( + providedFlags.has("db-setup") && + options.dbSetup === "docker" && + config.runtime === "workers" + ) { + consola.fatal( + "Docker setup (--db-setup docker) is not compatible with Cloudflare Workers runtime. Workers runtime uses serverless databases (D1) and doesn't support local Docker containers. Please use '--db-setup d1' for SQLite or choose a different runtime.", + ); + process.exit(1); + } +} + +export function coerceBackendPresets(config: Partial) { + if (config.backend === "convex") { + config.auth = false; + config.database = "none"; + config.orm = "none"; + config.api = "none"; + config.runtime = "none"; + config.dbSetup = "none"; + config.examples = ["todo"] as ProjectConfig["examples"]; + } + if (config.backend === "none") { + config.auth = false; + config.database = "none"; + config.orm = "none"; + config.api = "none"; + config.runtime = "none"; + config.dbSetup = "none"; + config.examples = [] as ProjectConfig["examples"]; + } +} + +export function incompatibleFlagsForBackend( + backend: ProjectConfig["backend"] | undefined, + providedFlags: Set, + options: CLIInput, +): string[] { + const list: string[] = []; + if (backend === "convex") { + if (providedFlags.has("auth") && options.auth === true) list.push("--auth"); + if (providedFlags.has("database") && options.database !== "none") + list.push(`--database ${options.database}`); + if (providedFlags.has("orm") && options.orm !== "none") + list.push(`--orm ${options.orm}`); + if (providedFlags.has("api") && options.api !== "none") + list.push(`--api ${options.api}`); + if (providedFlags.has("runtime") && options.runtime !== "none") + list.push(`--runtime ${options.runtime}`); + if (providedFlags.has("dbSetup") && options.dbSetup !== "none") + list.push(`--db-setup ${options.dbSetup}`); + } + if (backend === "none") { + if (providedFlags.has("auth") && options.auth === true) list.push("--auth"); + if (providedFlags.has("database") && options.database !== "none") + list.push(`--database ${options.database}`); + if (providedFlags.has("orm") && options.orm !== "none") + list.push(`--orm ${options.orm}`); + if (providedFlags.has("api") && options.api !== "none") + list.push(`--api ${options.api}`); + if (providedFlags.has("runtime") && options.runtime !== "none") + list.push(`--runtime ${options.runtime}`); + if (providedFlags.has("dbSetup") && options.dbSetup !== "none") + list.push(`--db-setup ${options.dbSetup}`); + if (providedFlags.has("examples") && options.examples) { + const hasNonNoneExamples = options.examples.some((ex) => ex !== "none"); + if (hasNonNoneExamples) list.push("--examples"); + } + } + return list; +} + +export function validateApiFrontendCompatibility( + api: API | undefined, + frontends: Frontend[] = [], +) { + const includesNuxt = frontends.includes("nuxt"); + const includesSvelte = frontends.includes("svelte"); + const includesSolid = frontends.includes("solid"); + if ((includesNuxt || includesSvelte || includesSolid) && api === "trpc") { + consola.fatal( + `tRPC API is not supported with '${includesNuxt ? "nuxt" : includesSvelte ? "svelte" : "solid"}' frontend. Please use --api orpc or --api none or remove '${includesNuxt ? "nuxt" : includesSvelte ? "svelte" : "solid"}' from --frontend.`, + ); + process.exit(1); + } +} + +export function isFrontendAllowedWithBackend( + frontend: Frontend, + backend?: ProjectConfig["backend"], +) { + if (backend === "convex" && frontend === "solid") return false; + return true; +} + +export function allowedApisForFrontends(frontends: Frontend[] = []): API[] { + const includesNuxt = frontends.includes("nuxt"); + const includesSvelte = frontends.includes("svelte"); + const includesSolid = frontends.includes("solid"); + const base: API[] = ["trpc", "orpc", "none"]; + if (includesNuxt || includesSvelte || includesSolid) { + return ["orpc", "none"]; + } + return base; +} + +export function isExampleTodoAllowed( + backend?: ProjectConfig["backend"], + database?: ProjectConfig["database"], +) { + return !(backend !== "convex" && backend !== "none" && database === "none"); +} + +export function isExampleAIAllowed( + backend?: ProjectConfig["backend"], + frontends: Frontend[] = [], +) { + const includesSolid = frontends.includes("solid"); + if (backend === "elysia") return false; + if (includesSolid) return false; + return true; +} + +export function validateWebDeployRequiresWebFrontend( + webDeploy: WebDeploy | undefined, + hasWebFrontendFlag: boolean, +) { + if (webDeploy && webDeploy !== "none" && !hasWebFrontendFlag) { + consola.fatal( + "'--web-deploy' requires a web frontend. Please select a web frontend or set '--web-deploy none'.", + ); + process.exit(1); + } +} + +export function validateAddonsAgainstFrontends( + addons: Addons[] = [], + frontends: Frontend[] = [], +) { + for (const addon of addons) { + if (addon === "none") continue; + const { isCompatible, reason } = validateAddonCompatibility( + addon, + frontends, + ); + if (!isCompatible) { + consola.fatal(`Incompatible addon/frontend combination: ${reason}`); + process.exit(1); + } + } +} + +export function validateExamplesCompatibility( + examples: string[] | undefined, + backend: ProjectConfig["backend"] | undefined, + database: ProjectConfig["database"] | undefined, + frontend?: Frontend[], +) { + const examplesArr = examples ?? []; + if (examplesArr.length === 0 || examplesArr.includes("none")) return; + if ( + examplesArr.includes("todo") && + backend !== "convex" && + backend !== "none" && + database === "none" + ) { + consola.fatal( + "The 'todo' example requires a database if a backend (other than Convex) is present. Cannot use --examples todo when database is 'none' and a backend is selected.", + ); + process.exit(1); + } + if (examplesArr.includes("ai") && backend === "elysia") { + consola.fatal( + "The 'ai' example is not compatible with the Elysia backend.", + ); + process.exit(1); + } + if (examplesArr.includes("ai") && (frontend ?? []).includes("solid")) { + consola.fatal( + "The 'ai' example is not compatible with the Solid frontend.", + ); + process.exit(1); + } +} diff --git a/apps/cli/src/utils/compatibility.ts b/apps/cli/src/utils/compatibility.ts new file mode 100644 index 00000000..b597ea2e --- /dev/null +++ b/apps/cli/src/utils/compatibility.ts @@ -0,0 +1,12 @@ +import type { Frontend } from "../types"; + +// Central list of web frontends used across the CLI +export const WEB_FRAMEWORKS: readonly Frontend[] = [ + "tanstack-router", + "react-router", + "tanstack-start", + "next", + "nuxt", + "svelte", + "solid", +] as const; diff --git a/apps/cli/src/utils/generate-reproducible-command.ts b/apps/cli/src/utils/generate-reproducible-command.ts index 36d06e7a..99e0c190 100644 --- a/apps/cli/src/utils/generate-reproducible-command.ts +++ b/apps/cli/src/utils/generate-reproducible-command.ts @@ -37,12 +37,12 @@ export function generateReproducibleCommand(config: ProjectConfig): string { let baseCommand = ""; const pkgManager = config.packageManager; - if (pkgManager === "npm") { - baseCommand = "npx create-better-t-stack@latest"; + if (pkgManager === "bun") { + baseCommand = "bun create better-t-stack@latest"; } else if (pkgManager === "pnpm") { baseCommand = "pnpm create better-t-stack@latest"; - } else if (pkgManager === "bun") { - baseCommand = "bun create better-t-stack@latest"; + } else if (pkgManager === "npm") { + baseCommand = "npx create-better-t-stack@latest"; } const projectPathArg = config.relativePath ? ` ${config.relativePath}` : ""; diff --git a/apps/cli/src/validation.ts b/apps/cli/src/validation.ts index 10db63bf..9d2324c9 100644 --- a/apps/cli/src/validation.ts +++ b/apps/cli/src/validation.ts @@ -1,6 +1,5 @@ import path from "node:path"; import { consola } from "consola"; -import { WEB_FRAMEWORKS } from "./constants"; import { type Addons, type API, @@ -17,6 +16,17 @@ import { type Runtime, type WebDeploy, } from "./types"; +import { + coerceBackendPresets, + ensureSingleWebAndNative, + incompatibleFlagsForBackend, + isWebFrontend, + validateAddonsAgainstFrontends, + validateApiFrontendCompatibility, + validateExamplesCompatibility, + validateWebDeployRequiresWebFrontend, + validateWorkersCompatibility, +} from "./utils/compatibility-rules"; export function processAndValidateFlags( options: CLIInput, @@ -126,25 +136,7 @@ export function processAndValidateFlags( const validOptions = options.frontend.filter( (f): f is Frontend => f !== "none", ); - const webFrontends = validOptions.filter((f) => - WEB_FRAMEWORKS.includes(f), - ); - const nativeFrontends = validOptions.filter( - (f) => f === "native-nativewind" || f === "native-unistyles", - ); - - if (webFrontends.length > 1) { - consola.fatal( - "Cannot select multiple web frameworks. Choose only one of: tanstack-router, tanstack-start, react-router, next, nuxt, svelte, solid", - ); - process.exit(1); - } - if (nativeFrontends.length > 1) { - consola.fatal( - "Cannot select multiple native frameworks. Choose only one of: native-nativewind, native-unistyles", - ); - process.exit(1); - } + ensureSingleWebAndNative(validOptions); config.frontend = validOptions; } } @@ -178,32 +170,26 @@ export function processAndValidateFlags( } } - if (config.backend === "convex") { - const incompatibleFlags: string[] = []; - - if (providedFlags.has("auth") && options.auth === true) - incompatibleFlags.push("--auth"); - if (providedFlags.has("database") && options.database !== "none") - incompatibleFlags.push(`--database ${options.database}`); - if (providedFlags.has("orm") && options.orm !== "none") - incompatibleFlags.push(`--orm ${options.orm}`); - if (providedFlags.has("api") && options.api !== "none") - incompatibleFlags.push(`--api ${options.api}`); - if (providedFlags.has("runtime") && options.runtime !== "none") - incompatibleFlags.push(`--runtime ${options.runtime}`); - if (providedFlags.has("dbSetup") && options.dbSetup !== "none") - incompatibleFlags.push(`--db-setup ${options.dbSetup}`); - + if (config.backend === "convex" || config.backend === "none") { + const incompatibleFlags = incompatibleFlagsForBackend( + config.backend, + providedFlags, + options, + ); if (incompatibleFlags.length > 0) { consola.fatal( - `The following flags are incompatible with '--backend convex': ${incompatibleFlags.join( + `The following flags are incompatible with '--backend ${config.backend}': ${incompatibleFlags.join( ", ", )}. Please remove them.`, ); process.exit(1); } - if (providedFlags.has("frontend") && options.frontend) { + if ( + config.backend === "convex" && + providedFlags.has("frontend") && + options.frontend + ) { const incompatibleFrontends = options.frontend.filter( (f) => f === "solid", ); @@ -217,51 +203,7 @@ export function processAndValidateFlags( } } - config.auth = false; - config.database = "none"; - config.orm = "none"; - config.api = "none"; - config.runtime = "none"; - config.dbSetup = "none"; - config.examples = ["todo"]; - } else if (config.backend === "none") { - const incompatibleFlags: string[] = []; - - if (providedFlags.has("auth") && options.auth === true) - incompatibleFlags.push("--auth"); - if (providedFlags.has("database") && options.database !== "none") - incompatibleFlags.push(`--database ${options.database}`); - if (providedFlags.has("orm") && options.orm !== "none") - incompatibleFlags.push(`--orm ${options.orm}`); - if (providedFlags.has("api") && options.api !== "none") - incompatibleFlags.push(`--api ${options.api}`); - if (providedFlags.has("runtime") && options.runtime !== "none") - incompatibleFlags.push(`--runtime ${options.runtime}`); - if (providedFlags.has("dbSetup") && options.dbSetup !== "none") - incompatibleFlags.push(`--db-setup ${options.dbSetup}`); - if (providedFlags.has("examples") && options.examples) { - const hasNonNoneExamples = options.examples.some((ex) => ex !== "none"); - if (hasNonNoneExamples) { - incompatibleFlags.push("--examples"); - } - } - - if (incompatibleFlags.length > 0) { - consola.fatal( - `The following flags are incompatible with '--backend none': ${incompatibleFlags.join( - ", ", - )}. Please remove them.`, - ); - process.exit(1); - } - - config.auth = false; - config.database = "none"; - config.orm = "none"; - config.api = "none"; - config.runtime = "none"; - config.dbSetup = "none"; - config.examples = []; + coerceBackendPresets(config); } if (config.orm === "mongoose" && config.database !== "mongodb") { @@ -387,114 +329,13 @@ export function processAndValidateFlags( process.exit(1); } - if ( - providedFlags.has("runtime") && - options.runtime === "workers" && - config.backend && - config.backend !== "hono" - ) { - consola.fatal( - `Cloudflare Workers runtime (--runtime workers) is only supported with Hono backend (--backend hono). Current backend: ${config.backend}. Please use '--backend hono' or choose a different runtime.`, - ); - process.exit(1); - } - - if ( - providedFlags.has("backend") && - config.backend && - config.backend !== "hono" && - config.runtime === "workers" - ) { - consola.fatal( - `Backend '${config.backend}' is not compatible with Cloudflare Workers runtime. Cloudflare Workers runtime is only supported with Hono backend. Please use '--backend hono' or choose a different runtime.`, - ); - process.exit(1); - } - - if ( - providedFlags.has("runtime") && - options.runtime === "workers" && - config.orm && - config.orm !== "drizzle" && - config.orm !== "none" - ) { - consola.fatal( - `Cloudflare Workers runtime (--runtime workers) is only supported with Drizzle ORM (--orm drizzle) or no ORM (--orm none). Current ORM: ${config.orm}. Please use '--orm drizzle', '--orm none', or choose a different runtime.`, - ); - process.exit(1); - } - - if ( - providedFlags.has("orm") && - config.orm && - config.orm !== "drizzle" && - config.orm !== "none" && - config.runtime === "workers" - ) { - consola.fatal( - `ORM '${config.orm}' is not compatible with Cloudflare Workers runtime. Cloudflare Workers runtime is only supported with Drizzle ORM or no ORM. Please use '--orm drizzle', '--orm none', or choose a different runtime.`, - ); - process.exit(1); - } - - if ( - providedFlags.has("runtime") && - options.runtime === "workers" && - config.database === "mongodb" - ) { - consola.fatal( - "Cloudflare Workers runtime (--runtime workers) is not compatible with MongoDB database. MongoDB requires Prisma or Mongoose ORM, but Workers runtime only supports Drizzle ORM. Please use a different database or runtime.", - ); - process.exit(1); - } - - if ( - providedFlags.has("runtime") && - options.runtime === "workers" && - config.dbSetup === "docker" - ) { - consola.fatal( - "Cloudflare Workers runtime (--runtime workers) is not compatible with Docker setup. Workers runtime uses serverless databases (D1) and doesn't support local Docker containers. Please use '--db-setup d1' for SQLite or choose a different runtime.", - ); - process.exit(1); - } - - if ( - providedFlags.has("database") && - config.database === "mongodb" && - config.runtime === "workers" - ) { - consola.fatal( - "MongoDB database is not compatible with Cloudflare Workers runtime. MongoDB requires Prisma or Mongoose ORM, but Workers runtime only supports Drizzle ORM. Please use a different database or runtime.", - ); - process.exit(1); - } - - if ( - providedFlags.has("db-setup") && - options.dbSetup === "docker" && - config.runtime === "workers" - ) { - consola.fatal( - "Docker setup (--db-setup docker) is not compatible with Cloudflare Workers runtime. Workers runtime uses serverless databases (D1) and doesn't support local Docker containers. Please use '--db-setup d1' for SQLite or choose a different runtime.", - ); - process.exit(1); - } + validateWorkersCompatibility(providedFlags, options, config); const hasWebFrontendFlag = (config.frontend ?? []).some((f) => - WEB_FRAMEWORKS.includes(f), + isWebFrontend(f), ); - - if ( - config.webDeploy && - config.webDeploy !== "none" && - !hasWebFrontendFlag && - providedFlags.has("frontend") - ) { - consola.fatal( - "'--web-deploy' requires a web frontend. Please select a web frontend or set '--web-deploy none'.", - ); - process.exit(1); + if (providedFlags.has("frontend")) { + validateWebDeployRequiresWebFrontend(config.webDeploy, hasWebFrontendFlag); } return config; @@ -505,140 +346,24 @@ export function validateConfigCompatibility(config: Partial) { const effectiveBackend = config.backend; const effectiveFrontend = config.frontend; const effectiveApi = config.api; - const effectiveRuntime = config.runtime; + // effectiveRuntime currently unused after centralizing checks, keep for future consolidation + // const effectiveRuntime = config.runtime; - if (effectiveRuntime === "workers" && effectiveBackend !== "hono") { - consola.fatal( - `Cloudflare Workers runtime is only supported with Hono backend. Current backend: ${effectiveBackend}. Please use a different runtime or change to Hono backend.`, - ); - process.exit(1); - } - - const effectiveOrm = config.orm; - if ( - effectiveRuntime === "workers" && - effectiveOrm !== "drizzle" && - effectiveOrm !== "none" - ) { - consola.fatal( - `Cloudflare Workers runtime is only supported with Drizzle ORM or no ORM. Current ORM: ${effectiveOrm}. Please use a different runtime or change to Drizzle ORM or no ORM.`, - ); - process.exit(1); - } - - if (effectiveRuntime === "workers" && effectiveDatabase === "mongodb") { - consola.fatal( - "Cloudflare Workers runtime is not compatible with MongoDB database. MongoDB requires Prisma or Mongoose ORM, but Workers runtime only supports Drizzle ORM. Please use a different database or runtime.", - ); - process.exit(1); - } - - if (effectiveRuntime === "workers" && config.dbSetup === "docker") { - consola.fatal( - "Cloudflare Workers runtime is not compatible with Docker setup. Workers runtime uses serverless databases (D1) and doesn't support local Docker containers. Please use a different runtime or change to D1 database setup.", - ); - process.exit(1); - } + // Workers-related compatibility is validated during flag processing. - const includesNuxt = effectiveFrontend?.includes("nuxt"); - const includesSvelte = effectiveFrontend?.includes("svelte"); - const includesSolid = effectiveFrontend?.includes("solid"); - - if ( - (includesNuxt || includesSvelte || includesSolid) && - effectiveApi === "trpc" - ) { - consola.fatal( - `tRPC API is not supported with '${ - includesNuxt ? "nuxt" : includesSvelte ? "svelte" : "solid" - }' frontend. Please use --api orpc or --api none or remove '${ - includesNuxt ? "nuxt" : includesSvelte ? "svelte" : "solid" - }' from --frontend.`, - ); - process.exit(1); - } + validateApiFrontendCompatibility(effectiveApi, effectiveFrontend); if (config.addons && config.addons.length > 0) { - const webSpecificAddons = ["pwa", "tauri"]; - const hasWebSpecificAddons = config.addons.some((addon) => - webSpecificAddons.includes(addon), - ); - const hasCompatibleWebFrontend = effectiveFrontend?.some((f) => { - const isPwaCompatible = - f === "tanstack-router" || - f === "react-router" || - f === "solid" || - f === "next"; - const isTauriCompatible = - f === "tanstack-router" || - f === "react-router" || - f === "nuxt" || - f === "svelte" || - f === "solid" || - f === "next"; - - if (config.addons?.includes("pwa") && config.addons?.includes("tauri")) { - return isPwaCompatible && isTauriCompatible; - } - if (config.addons?.includes("pwa")) { - return isPwaCompatible; - } - if (config.addons?.includes("tauri")) { - return isTauriCompatible; - } - return true; - }); - - if (hasWebSpecificAddons && !hasCompatibleWebFrontend) { - let incompatibleReason = "Selected frontend is not compatible."; - if (config.addons.includes("pwa")) { - incompatibleReason = - "PWA requires tanstack-router, react-router, next, or solid."; - } - if (config.addons.includes("tauri")) { - incompatibleReason = - "Tauri requires tanstack-router, react-router, nuxt, svelte, solid, or next."; - } - consola.fatal( - `Incompatible addon/frontend combination: ${incompatibleReason}`, - ); - process.exit(1); - } - + validateAddonsAgainstFrontends(config.addons, effectiveFrontend); config.addons = [...new Set(config.addons)]; } - if ( - config.examples && - config.examples.length > 0 && - !config.examples.includes("none") - ) { - if ( - config.examples.includes("todo") && - effectiveBackend !== "convex" && - effectiveBackend !== "none" && - effectiveDatabase === "none" - ) { - consola.fatal( - "The 'todo' example requires a database if a backend (other than Convex) is present. Cannot use --examples todo when database is 'none' and a backend is selected.", - ); - process.exit(1); - } - - if (config.examples.includes("ai") && effectiveBackend === "elysia") { - consola.fatal( - "The 'ai' example is not compatible with the Elysia backend.", - ); - process.exit(1); - } - - if (config.examples.includes("ai") && includesSolid) { - consola.fatal( - "The 'ai' example is not compatible with the Solid frontend.", - ); - process.exit(1); - } - } + validateExamplesCompatibility( + config.examples ?? [], + effectiveBackend, + effectiveDatabase, + effectiveFrontend ?? [], + ); } export function getProvidedFlags(options: CLIInput): Set { From 7f3603ebaae4c022004890a8e63b863d6be86484 Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Fri, 8 Aug 2025 13:51:02 +0530 Subject: [PATCH 2/8] feat(web): improve docs --- apps/cli/src/constants.ts | 2 - apps/cli/src/utils/compatibility.ts | 1 - apps/cli/src/validation.ts | 4 - apps/web/content/docs/bts-config.mdx | 54 ++++ apps/web/content/docs/cli-commands.mdx | 225 ++++++++++--- apps/web/content/docs/cli/add.mdx | 35 ++ apps/web/content/docs/cli/builder.mdx | 25 ++ apps/web/content/docs/cli/docs.mdx | 25 ++ apps/web/content/docs/cli/index.mdx | 23 ++ apps/web/content/docs/cli/init.mdx | 35 ++ apps/web/content/docs/cli/meta.json | 13 + apps/web/content/docs/cli/sponsors.mdx | 25 ++ apps/web/content/docs/compatibility.mdx | 29 ++ apps/web/content/docs/contributing.mdx | 94 ++++++ apps/web/content/docs/faq.mdx | 342 ++------------------ apps/web/content/docs/index.mdx | 181 ++++++----- apps/web/content/docs/installation.mdx | 236 -------------- apps/web/content/docs/meta.json | 30 +- apps/web/content/docs/project-structure.mdx | 60 ++++ apps/web/src/app/docs/layout.tsx | 4 - bun.lock | 2 +- 21 files changed, 725 insertions(+), 720 deletions(-) create mode 100644 apps/web/content/docs/bts-config.mdx create mode 100644 apps/web/content/docs/cli/add.mdx create mode 100644 apps/web/content/docs/cli/builder.mdx create mode 100644 apps/web/content/docs/cli/docs.mdx create mode 100644 apps/web/content/docs/cli/index.mdx create mode 100644 apps/web/content/docs/cli/init.mdx create mode 100644 apps/web/content/docs/cli/meta.json create mode 100644 apps/web/content/docs/cli/sponsors.mdx create mode 100644 apps/web/content/docs/compatibility.mdx create mode 100644 apps/web/content/docs/contributing.mdx delete mode 100644 apps/web/content/docs/installation.mdx create mode 100644 apps/web/content/docs/project-structure.mdx diff --git a/apps/cli/src/constants.ts b/apps/cli/src/constants.ts index e8a8cf5b..2130559c 100644 --- a/apps/cli/src/constants.ts +++ b/apps/cli/src/constants.ts @@ -139,5 +139,3 @@ export const ADDON_COMPATIBILITY: Record = { fumadocs: [], none: [], } as const; - -// WEB_FRAMEWORKS moved to utils/compatibility for centralized use diff --git a/apps/cli/src/utils/compatibility.ts b/apps/cli/src/utils/compatibility.ts index b597ea2e..3f488d4c 100644 --- a/apps/cli/src/utils/compatibility.ts +++ b/apps/cli/src/utils/compatibility.ts @@ -1,6 +1,5 @@ import type { Frontend } from "../types"; -// Central list of web frontends used across the CLI export const WEB_FRAMEWORKS: readonly Frontend[] = [ "tanstack-router", "react-router", diff --git a/apps/cli/src/validation.ts b/apps/cli/src/validation.ts index 9d2324c9..64a4fbc9 100644 --- a/apps/cli/src/validation.ts +++ b/apps/cli/src/validation.ts @@ -346,10 +346,6 @@ export function validateConfigCompatibility(config: Partial) { const effectiveBackend = config.backend; const effectiveFrontend = config.frontend; const effectiveApi = config.api; - // effectiveRuntime currently unused after centralizing checks, keep for future consolidation - // const effectiveRuntime = config.runtime; - - // Workers-related compatibility is validated during flag processing. validateApiFrontendCompatibility(effectiveApi, effectiveFrontend); diff --git a/apps/web/content/docs/bts-config.mdx b/apps/web/content/docs/bts-config.mdx new file mode 100644 index 00000000..ab2c4361 --- /dev/null +++ b/apps/web/content/docs/bts-config.mdx @@ -0,0 +1,54 @@ +--- +title: bts.jsonc +description: What bts.jsonc does and why it matters +--- + +## What is it? + +`bts.jsonc` is a small config file written to your project root when you create a project. It captures the stack choices you selected (frontend, backend, API, DB/ORM, auth, addons, etc.). The file uses JSONC (JSON with comments) and includes a schema for editor hints. + +Where: `./bts.jsonc` + +## Why it exists + +- Required for the `add` command to detect your current stack +- Helps validate compatibility and pre‑fill sensible defaults + +If `bts.jsonc` is missing, the `add` command cannot run because the project cannot be detected. + +## Safe to delete (with a caveat) + +It’s safe to delete for normal development; the generated code in `apps/*` and `packages/*` remains the source of truth. However, if you plan to use the `add` command later, you must keep `bts.jsonc` (or recreate it) so the CLI can detect your project. + +## Format + +The file is JSONC with comments enabled and includes a `$schema` URL for tooling. + +```jsonc +// Better-T-Stack configuration file +// safe to delete +{ + "$schema": "https://r2.better-t-stack.dev/schema.json", + "version": "x.y.z", + "createdAt": "2025-01-01T00:00:00.000Z", + "frontend": ["tanstack-router"], + "backend": "hono", + "runtime": "bun", + "database": "sqlite", + "orm": "drizzle", + "api": "trpc", + "auth": true, + "addons": ["turborepo"], + "examples": [], + "dbSetup": "none", + "webDeploy": "none", + "packageManager": "bun" +} +``` + +Notes: +- Values mirror what you selected during project creation +- The file may be updated when you run `add` (e.g., addons or webDeploy) + +See also: [`add` command](/docs/cli/add) + diff --git a/apps/web/content/docs/cli-commands.mdx b/apps/web/content/docs/cli-commands.mdx index 8c075d84..408a6cbc 100644 --- a/apps/web/content/docs/cli-commands.mdx +++ b/apps/web/content/docs/cli-commands.mdx @@ -3,6 +3,32 @@ title: CLI Commands description: Complete reference for all Better-T-Stack CLI commands and options --- +## Quick Usage + + + + ```bash + # Interactive setup + bun create better-t-stack@latest + + # With project name + bun create better-t-stack@latest my-project + ``` + + + ```bash + pnpm create better-t-stack@latest + pnpm create better-t-stack@latest my-project + ``` + + + ```bash + npx create-better-t-stack@latest + npx create-better-t-stack@latest my-project + ``` + + + ## Commands Overview | Command | Description | @@ -21,19 +47,39 @@ The primary command for creating new Better-T-Stack projects. ### Basic Usage -```bash -# Interactive setup -npx create-better-t-stack@latest - -# With project name -npx create-better-t-stack@latest my-project - -# With specific directory -npx create-better-t-stack@latest ./path/to/project - -# Use current directory -npx create-better-t-stack@latest . -``` + + + ```bash + # Interactive setup + bun create better-t-stack@latest + + # With project name + bun create better-t-stack@latest my-project + + # With specific directory + bun create better-t-stack@latest ./path/to/project + + # Use current directory + bun create better-t-stack@latest . + ``` + + + ```bash + pnpm create better-t-stack@latest + pnpm create better-t-stack@latest my-project + pnpm create better-t-stack@latest ./path/to/project + pnpm create better-t-stack@latest . + ``` + + + ```bash + npx create-better-t-stack@latest + npx create-better-t-stack@latest my-project + npx create-better-t-stack@latest ./path/to/project + npx create-better-t-stack@latest . + ``` + + ### Flags Reference @@ -71,13 +117,13 @@ npx create-better-t-stack@latest . # Web + Mobile --frontend tanstack-router native-nativewind -# Multiple frontends ---frontend next solid - # No frontend (API-only) --frontend none ``` +Note: Select at most one web frontend (one of: tanstack-router, react-router, tanstack-start, next, nuxt, svelte, solid) and at most one native frontend (one of: native-nativewind, native-unistyles). +Do not combine `none` with other frontend values. + #### Backend Options | Flag | Values | Default | Description | @@ -200,8 +246,13 @@ npx create-better-t-stack@latest . - `biome` - Biome linter/formatter - `husky` - Git hooks with Husky - `starlight` - Documentation site + - `fumadocs` - Fumadocs docs site + - `ultracite` - Markdown/MDX processing + - `oxlint` - Fast linter - `none` - No addons +Note: Do not combine `none` with other addon values. + **Examples:** ```bash --addons turborepo pwa @@ -227,6 +278,8 @@ npx create-better-t-stack@latest . --examples none ``` +Note: Do not combine `none` with other example values. + #### Database Setup Options | Flag | Values | Default | Description | @@ -295,19 +348,39 @@ Add addons or deployment configurations to existing Better-T-Stack projects. ### Usage -```bash -# Interactive addon selection -npx create-better-t-stack@latest add - -# Add specific addons -npx create-better-t-stack@latest add --addons pwa tauri - -# Add deployment -npx create-better-t-stack@latest add --web-deploy workers - -# Add both -npx create-better-t-stack@latest add --addons biome --web-deploy workers -``` + + + ```bash + # Interactive addon selection + bun create better-t-stack@latest add + + # Add specific addons + bun create better-t-stack@latest add --addons pwa tauri + + # Add deployment + bun create better-t-stack@latest add --web-deploy workers + + # Add both + bun create better-t-stack@latest add --addons biome --web-deploy workers + ``` + + + ```bash + pnpm create better-t-stack@latest add + pnpm create better-t-stack@latest add --addons pwa tauri + pnpm create better-t-stack@latest add --web-deploy workers + pnpm create better-t-stack@latest add --addons biome --web-deploy workers + ``` + + + ```bash + npx create-better-t-stack@latest add + npx create-better-t-stack@latest add --addons pwa tauri + npx create-better-t-stack@latest add --web-deploy workers + npx create-better-t-stack@latest add --addons biome --web-deploy workers + ``` + + ### Flags @@ -341,9 +414,23 @@ Display Better-T-Stack project sponsors. ### Usage -```bash -npx create-better-t-stack@latest sponsors -``` + + + ```bash + bun create better-t-stack@latest sponsors + ``` + + + ```bash + pnpm create better-t-stack@latest sponsors + ``` + + + ```bash + npx create-better-t-stack@latest sponsors + ``` + + Shows a list of project sponsors with their GitHub profiles and websites. @@ -355,9 +442,23 @@ Open Better-T-Stack documentation in your default browser. ### Usage -```bash -npx create-better-t-stack@latest docs -``` + + + ```bash + bun create better-t-stack@latest docs + ``` + + + ```bash + pnpm create better-t-stack@latest docs + ``` + + + ```bash + npx create-better-t-stack@latest docs + ``` + + Opens: https://better-t-stack.dev/docs @@ -369,9 +470,23 @@ Open the web-based interactive stack builder. ### Usage -```bash -npx create-better-t-stack@latest builder -``` + + + ```bash + bun create better-t-stack@latest builder + ``` + + + ```bash + pnpm create better-t-stack@latest builder + ``` + + + ```bash + npx create-better-t-stack@latest builder + ``` + + Opens: https://better-t-stack.dev/new @@ -384,7 +499,7 @@ The web builder provides a visual interface for configuring your stack and gener ### Full-Stack Web Application ```bash -npx create-better-t-stack@latest my-webapp \ +bun create better-t-stack@latest my-webapp \ --frontend tanstack-router \ --backend hono \ --runtime bun \ @@ -400,7 +515,7 @@ npx create-better-t-stack@latest my-webapp \ ### Mobile + Web Application ```bash -npx create-better-t-stack@latest my-mobile-app \ +bun create better-t-stack@latest my-mobile-app \ --frontend tanstack-router native-nativewind \ --backend hono \ --database sqlite \ @@ -413,7 +528,7 @@ npx create-better-t-stack@latest my-mobile-app \ ### Cloudflare Workers Project ```bash -npx create-better-t-stack@latest my-workers-app \ +bun create better-t-stack@latest my-workers-app \ --frontend tanstack-router \ --backend hono \ --runtime workers \ @@ -426,7 +541,7 @@ npx create-better-t-stack@latest my-workers-app \ ### API-Only Project ```bash -npx create-better-t-stack@latest my-api \ +bun create better-t-stack@latest my-api \ --frontend none \ --backend fastify \ --runtime node \ @@ -440,10 +555,10 @@ npx create-better-t-stack@latest my-api \ ```bash # Use all defaults with immediate setup -npx create-better-t-stack@latest my-project --yes +bun create better-t-stack@latest my-project --yes # Convex full-stack (automatically configures compatible options) -npx create-better-t-stack@latest my-convex-app --backend convex +bun create better-t-stack@latest my-convex-app --backend convex ``` --- @@ -452,11 +567,29 @@ npx create-better-t-stack@latest my-convex-app --backend convex Some options have compatibility requirements: -- **Cloudflare Workers**: Only with `--backend hono`, `--orm drizzle`, `--runtime workers` +- **Cloudflare Workers**: Only with `--backend hono`, `--orm drizzle` or `--orm none`, `--runtime workers` - **MongoDB**: Requires `--orm mongoose` or `--orm prisma` -- **Convex**: Incompatible with custom database/ORM/API options +- **Convex**: Forces `--no-auth`, `--database none`, `--orm none`, `--api none`, `--runtime none`, `--db-setup none`; sets `--examples todo`; Solid frontend is not supported with Convex - **PWA**: Requires compatible web frontend - **Tauri**: Requires compatible web frontend - **AI Examples**: Not compatible with `--backend elysia` or `--frontend solid` +- **tRPC + Nuxt/Svelte/Solid**: Use `--api orpc` (tRPC is not supported with `nuxt`, `svelte`, or `solid`) +- **Todo Example**: Requires a database when a backend (other than Convex) is selected +- **Web Deploy**: `--web-deploy workers` requires selecting a web frontend +- **Examples with `--api none`**: Cannot select examples when `--api none` (unless `--backend convex`) +- **Runtime `none`**: Only allowed with `--backend convex` or `--backend none` +- **Mongoose ORM**: Requires `--database mongodb` +- **Drizzle ORM**: Not compatible with `--database mongodb` +- **Database requires ORM**: Selecting a database requires a non-`none` ORM +- **ORM requires database**: Selecting a non-`none` ORM requires a database +- **Auth requires database**: `--auth` requires a non-`none` database +- **DB Setup constraints**: + - `--db-setup turso` → requires `--database sqlite` + - `--db-setup neon` → requires `--database postgres` + - `--db-setup prisma-postgres` → requires `--database postgres` + - `--db-setup mongodb-atlas` → requires `--database mongodb` + - `--db-setup supabase` → requires `--database postgres` + - `--db-setup d1` → requires `--database sqlite` and `--runtime workers` + - `--db-setup docker` → not compatible with `--database sqlite` or `--runtime workers` The CLI will validate compatibility and show helpful error messages for invalid combinations. diff --git a/apps/web/content/docs/cli/add.mdx b/apps/web/content/docs/cli/add.mdx new file mode 100644 index 00000000..292f2f11 --- /dev/null +++ b/apps/web/content/docs/cli/add.mdx @@ -0,0 +1,35 @@ +--- +title: add +description: Add addons or deployment to an existing project +--- + +## Usage + + + + ```bash + bun create better-t-stack@latest add [options] + ``` + + + ```bash + pnpm create better-t-stack@latest add [options] + ``` + + + ```bash + npx create-better-t-stack@latest add [options] + ``` + + + +### Options + +- `--addons` Multiple values +- `--web-deploy` One of: `workers`, `none` +- `--project-dir` Path +- `--install` / `--no-install` +- `--package-manager` One of: `bun`, `pnpm`, `npm` + +See also: [Compatibility](/docs/compatibility) + diff --git a/apps/web/content/docs/cli/builder.mdx b/apps/web/content/docs/cli/builder.mdx new file mode 100644 index 00000000..39df6b0a --- /dev/null +++ b/apps/web/content/docs/cli/builder.mdx @@ -0,0 +1,25 @@ +--- +title: builder +description: Open the web-based stack builder +--- + +## Usage + + + + ```bash + bun create better-t-stack@latest builder + ``` + + + ```bash + pnpm create better-t-stack@latest builder + ``` + + + ```bash + npx create-better-t-stack@latest builder + ``` + + + diff --git a/apps/web/content/docs/cli/docs.mdx b/apps/web/content/docs/cli/docs.mdx new file mode 100644 index 00000000..f5902b2e --- /dev/null +++ b/apps/web/content/docs/cli/docs.mdx @@ -0,0 +1,25 @@ +--- +title: docs +description: Open the documentation +--- + +## Usage + + + + ```bash + bun create better-t-stack@latest docs + ``` + + + ```bash + pnpm create better-t-stack@latest docs + ``` + + + ```bash + npx create-better-t-stack@latest docs + ``` + + + diff --git a/apps/web/content/docs/cli/index.mdx b/apps/web/content/docs/cli/index.mdx new file mode 100644 index 00000000..94774e6b --- /dev/null +++ b/apps/web/content/docs/cli/index.mdx @@ -0,0 +1,23 @@ +--- +title: CLI +description: Command reference index +--- + + + + Create a new Better‑T‑Stack project (prompts or --yes) + + + Add addons or deployment to an existing project + + + Open the web-based Stack Builder + + + Open documentation + + + View project sponsors + + + diff --git a/apps/web/content/docs/cli/init.mdx b/apps/web/content/docs/cli/init.mdx new file mode 100644 index 00000000..eb6bd22e --- /dev/null +++ b/apps/web/content/docs/cli/init.mdx @@ -0,0 +1,35 @@ +--- +title: init +description: Create a new Better-T-Stack project +--- + +## Usage + + + + ```bash + bun create better-t-stack@latest [project-directory] + ``` + + + ```bash + pnpm create better-t-stack@latest [project-directory] + ``` + + + ```bash + npx create-better-t-stack@latest [project-directory] + ``` + + + +You can pass `.` to use the current directory. + +### Skip prompts + +```bash +bun create better-t-stack@latest my-app --yes +``` + +See also: [Compatibility](/docs/compatibility) + diff --git a/apps/web/content/docs/cli/meta.json b/apps/web/content/docs/cli/meta.json new file mode 100644 index 00000000..a32f0751 --- /dev/null +++ b/apps/web/content/docs/cli/meta.json @@ -0,0 +1,13 @@ +{ + "title": "CLI", + "defaultOpen": true, + "pages": [ + "index", + "init", + "add", + "builder", + "docs", + "sponsors" + ] +} + diff --git a/apps/web/content/docs/cli/sponsors.mdx b/apps/web/content/docs/cli/sponsors.mdx new file mode 100644 index 00000000..b44f1cc7 --- /dev/null +++ b/apps/web/content/docs/cli/sponsors.mdx @@ -0,0 +1,25 @@ +--- +title: sponsors +description: View project sponsors +--- + +## Usage + + + + ```bash + bun create better-t-stack@latest sponsors + ``` + + + ```bash + pnpm create better-t-stack@latest sponsors + ``` + + + ```bash + npx create-better-t-stack@latest sponsors + ``` + + + diff --git a/apps/web/content/docs/compatibility.mdx b/apps/web/content/docs/compatibility.mdx new file mode 100644 index 00000000..4eddcfe8 --- /dev/null +++ b/apps/web/content/docs/compatibility.mdx @@ -0,0 +1,29 @@ +--- +title: Compatibility +description: Valid and invalid combinations across frontend, backend, runtime, database, and addons +--- + +## Rules + +- **Convex backend**: Disables authentication, database, ORM, and API options +- **Backend `none`**: Forces API, ORM, database, authentication, and runtime to `none`; disables examples +- **Frontend `none`**: Backend-only project; PWA/Tauri/examples may be disabled +- **API `none`**: No tRPC/oRPC setup; use framework-native APIs +- **Database `none`**: Disables ORM and authentication +- **ORM `none`**: No ORM setup; manage DB manually +- **Runtime `none`**: Only with Convex backend or when backend is `none` + +## Cloudflare Workers + +- Backend: `hono` only +- Database: `sqlite` with Cloudflare D1 +- ORM: `drizzle` (or none) +- Not compatible with MongoDB + +## Framework Notes + +- SvelteKit, Nuxt, and SolidJS frontends are only compatible with `orpc` API layer +- PWA addon requires React (TanStack Router/React Router) or SolidJS +- Tauri addon requires React (TanStack Router/React Router), Nuxt, SvelteKit, SolidJS, or Next.js +- AI example is not compatible with Elysia backend or SolidJS frontend + diff --git a/apps/web/content/docs/contributing.mdx b/apps/web/content/docs/contributing.mdx new file mode 100644 index 00000000..7ffdcd97 --- /dev/null +++ b/apps/web/content/docs/contributing.mdx @@ -0,0 +1,94 @@ +--- +title: Contributing +description: How to set up your environment and contribute changes +--- + +## Overview + +This project is a monorepo with two main apps: + +- CLI: `apps/cli` +- Documentation site: `apps/web` + +> Note: Planning to add a new feature? Please open an issue first to confirm it aligns with the project's future goals. We don't want you to spend time on work that might not land. + +## Setup + +### Prerequisites + +- Node.js 20+ +- Bun (recommended) +- Git + +### Install + +```bash +git clone https://github.com/better-t-stack/create-better-t-stack.git +cd create-better-t-stack +bun install +``` + +## Develop the CLI + +```bash +cd apps/cli +# optional global link for testing anywhere +bun link +# run in watch mode +bun dev:cli +``` + +## Develop the Docs + +```bash +# from repo root +bun dev:web +``` + +## Contribution Flow + +1. Open an issue/discussion before starting major work +2. Create a feature branch +3. Make changes following existing code style +4. Update docs as needed +5. Test and format + +```bash +# CLI +cd apps/cli && bun dev:cli + +# Web +bun dev:web + +# Format +bun run format + +# Type checks +bun check +``` + +6. (CLI changes) Add a changeset + +```bash +bunx changeset select create-better-t-stack +# Choose 'patch' for small fixes, 'minor' for features +# Never choose 'major' +``` + +7. Commit and push + +```bash +git add . +git commit -m "feat(web): ..." # or fix(cli): ... +git push origin +``` + +8. Open a Pull Request and link any related issues + +## Help + +- Issues and Discussions on GitHub +- Discord: https://discord.gg/ZYsbjpDaM5 + +See full contributor guide in the repository: `.github/CONTRIBUTING.md`. + diff --git a/apps/web/content/docs/faq.mdx b/apps/web/content/docs/faq.mdx index d6d5e218..7b939524 100644 --- a/apps/web/content/docs/faq.mdx +++ b/apps/web/content/docs/faq.mdx @@ -1,334 +1,46 @@ --- title: Frequently Asked Questions -description: Common questions and answers about Better-T-Stack CLI +description: Short answers to common beginner questions --- -## General Questions +## General -### What is Better-T-Stack? +### What is Better‑T‑Stack? +An opinionated CLI that scaffolds full‑stack TypeScript projects (frontend, backend, API, DB/ORM, auth, addons) with a clean monorepo. See the Quick Start on the docs home. -Better-T-Stack is a modern CLI tool that helps you scaffold end-to-end type-safe TypeScript projects. It provides opinionated, production-ready configurations for full-stack applications with support for multiple frontend frameworks, backend frameworks, databases, and deployment options. +### Do I need to install anything globally? +No. Run the CLI directly with your package manager. See Quick Start and the per‑command pages under CLI. -### How is Better-T-Stack different from other scaffolding tools? +### Which package manager can I use? +`npm`, `pnpm`, or `bun` (all supported). -- **End-to-End Type Safety**: TypeScript across your entire stack with proper type sharing -- **Modern Stack Focus**: Latest versions of popular frameworks and tools -- **Production Ready**: Configurations used in real production applications -- **Highly Customizable**: Mix and match technologies based on your needs -- **Monorepo Structure**: Organized project structure with shared packages -- **Database Integration**: Built-in database setup and ORM configuration -- **Authentication**: Integrated auth with Better-Auth -- **Multi-Platform**: Web, mobile, and desktop app support in one project +### What Node.js version is required? +Node.js 18+ (LTS recommended). -### Is Better-T-Stack free to use? +### Can I use this with an existing project? +The CLI is for new projects. You can migrate gradually or use `add` to extend a Better‑T‑Stack project. -Yes, Better-T-Stack is completely free and open-source under the MIT license. You can use it for personal and commercial projects without any restrictions. +### Where do generated files live? +See Project Structure for high‑level layouts (server‑based vs. Convex, optional web/native). -### Do I need to know all these technologies to use Better-T-Stack? +## Choosing options -No! Better-T-Stack is designed to help you learn modern full-stack development. Each generated project includes: -- Comprehensive README with setup instructions -- Example code and patterns -- TypeScript for better developer experience -- Best practices and folder structure +### Does the CLI recommend a stack? +No. Pick what fits your needs. The CLI validates compatibility. See CLI (per command) and Compatibility for rules. ---- - -## Installation & Setup - -### Which package manager should I use? - -You can use any of the major package managers: -- **npm**: Most widely supported, comes with Node.js -- **pnpm**: Faster installs, better disk space efficiency -- **bun**: All-in-one runtime, extremely fast - -For monorepo projects, we recommend **pnpm** for its excellent workspace support. - -### Do I need to install the CLI globally? - -No, you can use npx to run the latest version without installation: - -```bash -npx create-better-t-stack@latest my-project -``` - -This ensures you always use the latest version with the newest features and bug fixes. - -### What Node.js version do I need? - -Better-T-Stack requires **Node.js 18 or higher**. We recommend using the latest LTS version for the best experience. - -### Can I use Better-T-Stack with existing projects? - -Better-T-Stack is designed for new projects. For existing projects, you can: -1. Create a new Better-T-Stack project -2. Gradually migrate your code -3. Use the `add` command to add specific features to existing Better-T-Stack projects - ---- - -## Configuration & Stack Choices - -### Can I change my stack choices after creating a project? - -Some changes are possible: -- **Easy**: Add addons, examples, or deployment configurations using the `add` command -- **Medium**: Switch between compatible ORMs or databases (requires manual migration) -- **Hard**: Change frontend/backend frameworks (requires significant refactoring) - -It's best to plan your stack carefully during initial setup. - -### What's the difference between tRPC and oRPC? - -- **tRPC**: End-to-end type safety with TypeScript inference, great for TypeScript-only projects -- **oRPC**: OpenAPI-compatible type-safe APIs, better for teams using multiple languages or requiring OpenAPI specs - -Both provide excellent type safety, choose based on your team's needs. - -### Should I use Drizzle or Prisma? - -- **Drizzle**: TypeScript-first, lightweight, great for edge deployments, SQL-like syntax -- **Prisma**: Feature-rich, mature ecosystem, great tooling, GraphQL-like schema - -Choose Drizzle for modern TypeScript projects and Prisma for feature-rich applications. - -### What's the recommended stack for beginners? - -For beginners, we recommend: -```bash -npx create-better-t-stack@latest my-first-project \ - --frontend tanstack-router \ - --backend hono \ - --database sqlite \ - --orm drizzle \ - --auth \ - --addons turborepo biome -``` - -This provides a simple but powerful full-stack setup that's easy to understand and deploy. - ---- - -## Compatibility Questions - -### Can I use MongoDB with Drizzle? - -No, Drizzle doesn't support MongoDB. For MongoDB, use: -- **Prisma ORM**: Full ORM support for MongoDB -- **Mongoose**: Traditional MongoDB object modeling - -### Why can't I use tRPC with Nuxt/SvelteKit/SolidJS? - -tRPC is primarily designed for React ecosystems. For these frameworks, use: -- **oRPC**: Provides similar type safety with broader framework support -- **None**: Use the framework's built-in API capabilities - -### Can I use Cloudflare Workers with any backend? - -Cloudflare Workers runtime only supports: -- **Backend**: Hono only -- **Database**: SQLite with Cloudflare D1 -- **ORM**: Drizzle only - -This is due to the serverless nature and limitations of the Workers environment. - -### Which addons work with which frontends? - -| Addon | Compatible Frontends | -|-------|---------------------| -| PWA | TanStack Router, React Router, SolidJS, Next.js | -| Tauri | TanStack Router, React Router, Nuxt, SvelteKit, SolidJS, Next.js | -| Turborepo | All frontends | -| Biome | All frontends | -| Husky | All frontends | -| Starlight | All frontends | - ---- - -## Database & Hosting - -### What database should I choose for production? - -**For small to medium applications:** -- **SQLite + Turso**: Excellent performance, easy scaling -- **PostgreSQL + Neon**: Serverless PostgreSQL, great for startups - -**For large applications:** -- **PostgreSQL + Supabase**: Full backend-as-a-service -- **MongoDB + Atlas**: NoSQL flexibility with managed hosting - -### Do I need Docker for development? - -Docker is optional and only required for: -- **Database Setup**: If you choose `--db-setup docker` -- **Local Development**: Some setups like Supabase local development - -Many database options (Turso, Neon, MongoDB Atlas) don't require Docker. - -### How do I deploy my Better-T-Stack application? - -Better-T-Stack projects are configured for easy deployment: +### I’m unsure between tRPC and oRPC / Drizzle and Prisma +See Compatibility for guidance and constraints. Both pairs work well; choose based on team and hosting needs. -**Frontend:** -- **Vercel**: Zero-config deployment for Next.js, React apps -- **Netlify**: Static site deployment -- **Cloudflare Workers**: Edge deployment with `--web-deploy workers` +## Common issues -**Backend:** -- **Railway**: Easy backend deployment -- **Fly.io**: Global application deployment -- **Cloudflare Workers**: Serverless edge deployment - ---- - -## Development & Troubleshooting - -### My project won't start after creation. What should I do? - -1. **Check Node.js version**: Ensure you're using Node.js 18+ -2. **Install dependencies**: Run `npm install` in the project directory -3. **Check environment variables**: Copy `.env.example` to `.env` and fill in values -4. **Database setup**: Run database migrations if using a database -5. **Check the README**: Each project includes detailed setup instructions - -### I'm getting TypeScript errors. How do I fix them? - -1. **Install dependencies**: Ensure all packages are installed -2. **Restart TypeScript server**: In VS Code, use Ctrl/Cmd + Shift + P → "TypeScript: Restart TS Server" -3. **Check imports**: Ensure all imports are correct and packages are installed -4. **Update types**: Run `npm run check-types` to see detailed errors - -### How do I update dependencies in my project? - -```bash -# Check for updates -npx taze -r - -# Update all dependencies -npm update - -# Or with other package managers -pnpm update -bun update -``` - -### Can I use Better-T-Stack with VS Code? - -Yes! Better-T-Stack projects work excellently with VS Code. We recommend these extensions: -- TypeScript and JavaScript Language Features (built-in) -- Tailwind CSS IntelliSense -- Prisma or Drizzle Kit extensions -- ESLint (if using Biome addon) - -### My mobile app won't connect to the backend. What's wrong? - -This is a common issue with Expo and local development: - -1. **Check environment variables**: Update `EXPO_PUBLIC_SERVER_URL` in `apps/native/.env` -2. **Use your local IP**: Replace `localhost` with your computer's IP address -3. **Check firewall**: Ensure your firewall allows connections on port 3000 -4. **Use tunnel**: Consider using `npx expo start --tunnel` - ---- - -## Advanced Usage - -### Can I customize the generated templates? - -Currently, Better-T-Stack doesn't support custom templates, but you can: -1. Fork the repository and modify templates -2. Create a feature request for specific customizations -3. Modify the generated project after creation - -### How do I contribute to Better-T-Stack? - -We welcome contributions! Here's how to get started: - -1. **Fork the repository** on GitHub -2. **Clone your fork** locally -3. **Install dependencies**: `pnpm install` -4. **Make your changes** and test them -5. **Submit a pull request** with a clear description - -### Can I use Better-T-Stack in my company/team? - -Absolutely! Better-T-Stack is perfect for: -- **Standardizing project structure** across teams -- **Onboarding new developers** with consistent setup -- **Rapid prototyping** and MVP development -- **Client projects** with proven, production-ready configurations +### My mobile app can’t connect to the backend (Expo) +Set `EXPO_PUBLIC_SERVER_URL` in `apps/native/.env` to your machine IP (not `localhost`), check firewall, or try `npx expo start --tunnel`. ### How do I disable telemetry? +Set `BTS_TELEMETRY_DISABLED=1` (shell env). For one run, prefix the command; to make it permanent, export it in your shell profile. -Better-T-Stack collects anonymous usage data to improve the tool. To disable: - -```bash -# Disable for single run -BTS_TELEMETRY_DISABLED=1 npx create-better-t-stack@latest my-app - -# Disable globally -export BTS_TELEMETRY_DISABLED=1 -``` - -Add the export to your shell profile (`.bashrc`, `.zshrc`, etc.) to make it permanent. - ---- - -## Getting Help - -### Where can I get help? - -- **Documentation**: Comprehensive guides at [better-t-stack.dev/docs](https://better-t-stack.dev/docs) -- **GitHub Issues**: Report bugs or request features -- **GitHub Discussions**: Community support and questions -- **Discord/Twitter**: Follow for updates and community discussion - -### How do I report a bug? - -1. **Search existing issues** to avoid duplicates -2. **Create a new issue** with: - - Clear description of the problem - - Steps to reproduce - - Your system information (OS, Node.js version, etc.) - - Generated project configuration - - Error messages or screenshots - -### How do I request a new feature? - -1. **Check existing feature requests** in GitHub Issues -2. **Create a new issue** with the "feature request" label -3. **Describe the feature** and its use case -4. **Explain why** it would benefit the community - -### Is there a community? - -Yes! You can connect with other Better-T-Stack users: -- **GitHub Discussions**: Ask questions and share projects -- **Twitter**: Follow [@AmanVarshney01](https://twitter.com/AmanVarshney01) for updates -- **Show your projects**: Tag us when you build something with Better-T-Stack! - ---- - -## Sponsorship & Support - -### How can I support Better-T-Stack? - -- **⭐ Star the repository** on GitHub -- **🐛 Report bugs** and suggest improvements -- **💰 Sponsor the project** on GitHub Sponsors -- **📢 Share with others** who might find it useful -- **🤝 Contribute code** or documentation - -### Who sponsors Better-T-Stack? - -View current sponsors by running: -```bash -npx create-better-t-stack@latest sponsors -``` - -Or visit: [github.com/sponsors/AmanVarshney01](https://github.com/sponsors/AmanVarshney01) - ---- +## Getting help -*Still have questions? Feel free to ask in [GitHub Discussions](https://github.com/AmanVarshney01/create-better-t-stack/discussions) or check our [documentation](https://better-t-stack.dev/docs).* +- Docs: Quick Start, CLI, Project Structure, Compatibility +- Ask/Report: GitHub Issues & Discussions +- Community: Discord diff --git a/apps/web/content/docs/index.mdx b/apps/web/content/docs/index.mdx index 45d9571e..05acb1ff 100644 --- a/apps/web/content/docs/index.mdx +++ b/apps/web/content/docs/index.mdx @@ -1,118 +1,127 @@ --- -title: Getting Started -description: A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations +title: Quick Start +description: Create your first Better-T-Stack project in minutes --- -> ⚠️ **Warning:** Documentation is a work in progress. +## Philosophy -## What is Better-T-Stack? +- With Better T Stack, you freely choose only the parts you want; nothing extra is added. +- Pick your frontend, backend, API layer, database, ORM, auth, addons — or skip any of them. Compatibility is enforced. +- No lock‑in: it’s a generator, not a framework fork. -Better-T-Stack is designed to eliminate the complexity of setting up modern TypeScript projects. Instead of spending hours configuring build tools, type systems, databases, and deployment pipelines, you can get a production-ready project structure in minutes. +## Get Started -### Key Features +### Stack Builder (UI) -- **🏗️ Full-Stack Ready**: Choose from multiple frontend and backend frameworks -- **🔒 End-to-End Type Safety**: TypeScript across your entire application stack -- **🗄️ Database Integration**: Support for SQLite, PostgreSQL, MySQL, and MongoDB -- **🔐 Built-in Authentication**: Email/password auth with Better-Auth -- **📱 Multi-Platform**: Web, mobile (React Native), and desktop (Tauri) support -- **☁️ Deployment Ready**: Configured for modern hosting platforms -- **⚡ Modern Tooling**: Latest versions of your favorite tools and frameworks +- Visit [/new](/new) to pick your stack and copy the generated command +- Or open it via: -### Supported Technologies +```bash +bun create better-t-stack@latest builder +``` -#### Frontend Frameworks -- **React** with TanStack Router or React Router -- **Next.js** - Full-stack React framework -- **SvelteKit** - Web framework for Svelte -- **Nuxt** - Vue.js framework -- **SolidJS** - Performant reactive framework -- **TanStack Start** - SSR with TanStack Router -- **React Native** - Mobile development with Expo +### CLI (prompts) -#### Backend Frameworks -- **Hono** - Lightweight, ultrafast web framework -- **Express** - Popular Node.js framework -- **Fastify** - Fast, low-overhead framework -- **Elysia** - Type-safe, high-performance framework -- **Convex** - Reactive backend-as-a-service -- **Next.js API Routes** - Full-stack React +```bash +bun create better-t-stack@latest +``` -#### Databases & ORMs -- **Databases**: SQLite/Turso, PostgreSQL, MySQL, MongoDB -- **ORMs**: Drizzle (TypeScript-first), Prisma (feature-rich), Mongoose -- **Hosting**: Neon, Supabase, MongoDB Atlas, Cloudflare D1 +Follow the interactive prompts to choose your frontend, backend, database, ORM, API layer, and addons. -#### API Layers -- **tRPC** - End-to-end type-safe APIs -- **oRPC** - OpenAPI-compatible type-safe APIs +Skip prompts and use the default stack: + +```bash +bun create better-t-stack@latest my-app --yes +``` -### Why Choose Better-T-Stack? +Prefer a visual flow? Use the Stack Builder at [/new](/new) to pick your stack and copy the generated command. You can also open it via: -#### Traditional Setup Problems -- ⏰ Hours of configuration and setup -- 🔧 Complex toolchain integration -- 📚 Overwhelming technology choices -- 🐛 Configuration bugs and compatibility issues -- 🏗️ Inconsistent project structures +```bash +bun create better-t-stack@latest builder +``` -#### Better-T-Stack Solutions -- ⚡ **Quick Setup**: Get started in under 2 minutes -- 🎯 **Curated Choices**: Pre-selected, compatible technology combinations -- 📋 **Best Practices**: Industry-standard configurations out of the box -- 🔄 **Consistent Structure**: Standardized monorepo organization -- 🧪 **Battle-Tested**: Configurations used in production applications +## Common Setups -## Quick Example +### Default Stack ```bash -# Create a new project -npx create-better-t-stack@latest my-app - -# Choose your stack interactively or use flags -npx create-better-t-stack@latest my-app \ +bun create better-t-stack@latest my-webapp \ --frontend tanstack-router \ --backend hono \ - --database postgres \ + --database sqlite \ --orm drizzle \ --auth \ - --addons pwa turborepo + --addons turborepo ``` -## Project Types - -Better-T-Stack supports various project configurations: - -### Full-Stack Web Applications -Perfect for modern web apps with React, Vue, or Svelte frontends backed by type-safe APIs. - -### Mobile Applications -Build React Native apps with Expo, sharing type definitions with your backend. +### Convex + React -### Desktop Applications -Create cross-platform desktop apps using Tauri with your web frontend. - -### API-Only Projects -Build standalone APIs and microservices with your preferred backend framework. +```bash +bun create better-t-stack@latest my-convex-app \ + --frontend tanstack-router \ + --backend convex +``` -### Monorepo Projects -Organize multiple applications (web, mobile, API) in a single repository with shared packages. +### API Only -## Who Should Use Better-T-Stack? +```bash +bun create better-t-stack@latest my-api \ + --frontend none \ + --backend fastify \ + --runtime node \ + --database postgres \ + --orm prisma \ + --api trpc +``` -- **Indie Developers**: Quickly prototype and build full-stack applications -- **Startups**: Get to market faster with production-ready project structure -- **Teams**: Standardize project setup across your organization -- **Students**: Learn modern full-stack development with best practices -- **Agencies**: Rapidly scaffold client projects with consistent quality +### Mobile App (Expo) -## What's Next? +```bash +bun create better-t-stack@latest my-native \ + --frontend native-nativewind \ + --backend hono \ + --database sqlite \ + --orm drizzle \ + --auth +``` -Ready to get started? Check out our [Quick Start Guide](/docs/quick-start) to create your first Better-T-Stack project, or explore the [Configuration Options](/docs/frontend) to learn about all available technologies and features. +### Empty Monorepo -### Need Help? +```bash +bun create better-t-stack@latest my-workspace \ + --frontend none \ + --backend none +``` -- 📖 **Documentation**: Comprehensive guides and references -- 🐛 **Issues**: Report bugs on [GitHub](https://github.com/AmanVarshney01/create-better-t-stack/issues) -- 💬 **Discussions**: Community support and questions -- 🌟 **Star us**: Show support on [GitHub](https://github.com/AmanVarshney01/create-better-t-stack) +## Flags Cheat Sheet + +See the full list in the [CLI Reference](/docs/cli). Key flags: + +- `--frontend`: tanstack-router, react-router, tanstack-start, next, nuxt, svelte, solid, native-nativewind, native-unistyles, none +- `--backend`: hono, express, fastify, elysia, next, convex, none +- `--runtime`: bun, node, workers, none +- `--database`: sqlite, postgres, mysql, mongodb, none +- `--orm`: drizzle, prisma, mongoose, none +- `--api`: trpc, orpc, none +- `--addons`: turborepo, pwa, tauri, biome, husky, starlight, none +- `--examples`: todo, ai, none + +## Next Steps + + + + Flags, usage, and examples for each command + + + See how web/server/native and Convex layouts are generated + + + Valid combinations for backend, runtime, database, ORM, API + + + Required for the add command; safe to delete if you don’t use add + + + Dev setup and contribution flow + + diff --git a/apps/web/content/docs/installation.mdx b/apps/web/content/docs/installation.mdx deleted file mode 100644 index 0dc06be2..00000000 --- a/apps/web/content/docs/installation.mdx +++ /dev/null @@ -1,236 +0,0 @@ ---- -title: Installation -description: How to install and set up Better-T-Stack CLI ---- - -## System Requirements - -Before installing Better-T-Stack, ensure your system meets these requirements: - -- **Node.js**: Version 18 or higher -- **Package Manager**: npm, pnpm, or bun -- **Git**: For repository initialization (optional but recommended) - -### Optional Dependencies - -Depending on your project configuration, you may need: - -- **Docker**: For local database development with Docker Compose -- **Rust & System Dependencies**: For Tauri desktop applications -- **Cloudflare CLI**: For Workers deployment - -## Quick Start (Recommended) - -The fastest way to get started is using npx, which runs the latest version without installation: - -```bash -npx create-better-t-stack@latest my-project -``` - -This command will: -1. Download the latest version of the CLI -2. Run the interactive setup wizard -3. Create your project in the `my-project` directory - -## Package Manager Specific Commands - -### npm - -```bash -# Run without installing -npx create-better-t-stack@latest my-project - -# Or install globally -npm install -g create-better-t-stack -create-better-t-stack my-project -``` - -### pnpm - -```bash -# Run without installing (recommended) -pnpm create better-t-stack@latest my-project - -# Or install globally -pnpm add -g create-better-t-stack -create-better-t-stack my-project -``` - -### bun - -```bash -# Run without installing (recommended) -bun create better-t-stack@latest my-project - -# Or install globally -bun add -g create-better-t-stack -create-better-t-stack my-project -``` - -## Global Installation - -If you frequently create new projects, you might want to install the CLI globally: - - - - ```bash - npm install -g create-better-t-stack - ``` - - - ```bash - pnpm add -g create-better-t-stack - ``` - - - ```bash - bun add -g create-better-t-stack - ``` - - - -After global installation, you can run: - -```bash -create-better-t-stack my-project -``` - -## Verification - -Verify your installation by checking the version: - -```bash -# If installed globally -create-better-t-stack --version - -# Or with npx -npx create-better-t-stack@latest --version -``` - -You should see output similar to: - -``` -2.26.3 -``` - -## Development Installation - -For contributing to Better-T-Stack or running the latest development version: - -```bash -# Clone the repository -git clone https://github.com/AmanVarshney01/create-better-t-stack.git -cd create-better-t-stack - -# Install dependencies -pnpm install - -# Build the CLI -cd apps/cli -pnpm build - -# Link for local development -pnpm link --global -``` - -## Troubleshooting - -### Common Issues - -#### Permission Errors (npm) - -If you encounter permission errors with npm global installation: - -```bash -# Use npx instead (recommended) -npx create-better-t-stack@latest my-project - -# Or configure npm to use a different directory -mkdir ~/.npm-global -npm config set prefix '~/.npm-global' -echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc -source ~/.bashrc -``` - -#### Node.js Version Issues - -Ensure you're using Node.js 18 or higher: - -```bash -node --version -``` - -If you need to upgrade Node.js: - -- **Using nvm**: `nvm install 18 && nvm use 18` -- **Using n**: `n 18` -- **Download**: Visit [nodejs.org](https://nodejs.org/) - -#### Package Manager Not Found - -If you prefer a specific package manager but it's not installed: - -```bash -# Install pnpm -npm install -g pnpm - -# Install bun -curl -fsSL https://bun.sh/install | bash -``` - -#### Network Issues - -If you experience network timeouts or connection issues: - -```bash -# Try with different registry -npm config set registry https://registry.npmjs.org/ - -# Or clear npm cache -npm cache clean --force -``` - -## Next Steps - -Once installed, you're ready to create your first project: - -1. **Quick Start**: Follow our [Quick Start Guide](/docs/quick-start) -2. **Configuration**: Learn about [Configuration Options](/docs/frontend) -3. **CLI Reference**: Explore all [CLI Commands](/docs/cli-commands) - -## Staying Updated - -To ensure you're always using the latest version with bug fixes and new features: - -### Using npx (Automatic) -When using `npx create-better-t-stack@latest`, you automatically get the latest version. - -### Global Installation Updates - -If you have it installed globally, update regularly: - - - - ```bash - npm update -g create-better-t-stack - ``` - - - ```bash - pnpm update -g create-better-t-stack - ``` - - - ```bash - bun update -g create-better-t-stack - ``` - - - -### Release Notes - -Stay informed about new features and changes: - -- **GitHub Releases**: [View releases](https://github.com/AmanVarshney01/create-better-t-stack/releases) -- **Changelog**: Check the repository for detailed changes -- **Breaking Changes**: Major version updates may include breaking changes diff --git a/apps/web/content/docs/meta.json b/apps/web/content/docs/meta.json index 1b834409..70231044 100644 --- a/apps/web/content/docs/meta.json +++ b/apps/web/content/docs/meta.json @@ -1,32 +1,12 @@ { "pages": [ "index", - "installation", - "quick-start", + "cli", "project-structure", - "---Configuration Options---", - "frontend", - "backend", - "database", - "orm", - "authentication", - "runtime", - "api-layer", - "---Addons & Features---", - "addons", - "examples", - "deployment", - "---Database Setup---", - "database-providers", - "---CLI Reference---", - "cli-commands", - "cli-flags", - "---Guides---", - "migration-guide", + "bts-config", + "contributing", + "compatibility", "troubleshooting", - "best-practices", - "---FAQ---", - "faq", - "compatibility" + "faq" ] } diff --git a/apps/web/content/docs/project-structure.mdx b/apps/web/content/docs/project-structure.mdx new file mode 100644 index 00000000..466dbc70 --- /dev/null +++ b/apps/web/content/docs/project-structure.mdx @@ -0,0 +1,60 @@ +--- +title: Project Structure +description: High-level overview of the generated monorepo layout +--- + +import { File, Folder, Files } from 'fumadocs-ui/components/files'; + +### Server-based projects + + + + + + + + + + + + + + + + +Notes: +- `apps/server` is present for backends like `hono`, `express`, `fastify`, `elysia`, `next`. +- `apps/web` and `apps/native` are optional; they appear only if you select a web or native frontend. + +### Convex-based projects + + + + + + + + + + + + + + + + + + +Notes: +- Convex replaces the server app; `packages/backend` is generated instead of `apps/server`. +- Auth, DB/ORM, and API scaffolding are disabled for Convex presets. + +### Where features land (high level) + +- API layer: merged into `apps/server` and `apps/web` when applicable. +- Database & ORM: merged into `apps/server` when both are selected. +- Authentication: merged into `apps/server`, `apps/web`, and `apps/native` when enabled and compatible. +- Addons: PWA merges into `apps/web`; others merge at the appropriate location. +- Web deployment (Workers): deployment files merge into `apps/web` per frontend. +- Runtime extras (Workers): Workers-specific files added at the repo root. + diff --git a/apps/web/src/app/docs/layout.tsx b/apps/web/src/app/docs/layout.tsx index 5020e9a6..1593f33e 100644 --- a/apps/web/src/app/docs/layout.tsx +++ b/apps/web/src/app/docs/layout.tsx @@ -1,4 +1,3 @@ -import { Banner } from "fumadocs-ui/components/banner"; import { DocsLayout, type DocsLayoutProps } from "fumadocs-ui/layouts/docs"; import type { ReactNode } from "react"; import { baseOptions } from "@/app/layout.config"; @@ -17,9 +16,6 @@ const docsOptions: DocsLayoutProps = { export default function Layout({ children }: { children: ReactNode }) { return ( <> - - ⚠️ WORK IN PROGRESS DONT TAKE REFERENCE!!! - {children} ); diff --git a/bun.lock b/bun.lock index 82ee4837..d4278b0d 100644 --- a/bun.lock +++ b/bun.lock @@ -14,7 +14,7 @@ }, "apps/cli": { "name": "create-better-t-stack", - "version": "2.29.2", + "version": "2.29.3", "bin": { "create-better-t-stack": "dist/index.js", }, From 74c2fa56d8935d6a3c946ce963a4f9c27ceffbc9 Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Fri, 8 Aug 2025 13:55:54 +0530 Subject: [PATCH 3/8] update readme --- README.md | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 68c6c25b..37aa5a86 100644 --- a/README.md +++ b/README.md @@ -25,27 +25,30 @@ pnpm create better-t-stack@latest ## Features -- **Zero-config setup** with interactive CLI wizard -- **End-to-end type safety** from database to frontend via tRPC -- **Modern stack** with React, Hono/Elysia, and TanStack libraries -- **Multi-platform** supporting web, mobile (Expo), and desktop applications -- **Database flexibility** with SQLite (Turso) or PostgreSQL options -- **ORM choice** between Drizzle or Prisma -- **Built-in authentication** with Better-Auth -- **Optional PWA support** for installable web applications -- **Desktop app capabilities** with Tauri integration -- **Monorepo architecture** powered by Turborepo +- Frontend: React (TanStack Router, React Router, TanStack Start), Next.js, Nuxt, Svelte, Solid, React Native (NativeWind/Unistyles), or none +- Backend: Hono, Express, Fastify, Elysia, Next API Routes, Convex, or none +- API: tRPC or oRPC (or none) +- Runtime: Bun, Node.js, or Cloudflare Workers +- Databases: SQLite, PostgreSQL, MySQL, MongoDB (or none) +- ORMs: Drizzle, Prisma, Mongoose (or none) +- Auth: Better-Auth (optional) +- Addons: Turborepo, PWA, Tauri, Biome, Husky, Starlight, Fumadocs, Ultracite, Oxlint +- Examples: Todo, AI +- DB Setup: Turso, Neon, Supabase, Prisma PostgreSQL, MongoDB Atlas, Cloudflare D1, Docker +- Web Deploy: Cloudflare Workers + +Type safety end-to-end, clean monorepo layout, and zero‑lock‑in: you choose only what you need. ## Repository Structure This repository is organized as a monorepo containing: -- **CLI**: [`create-better-t-stack`](apps/cli) - The scaffolding CLI tool -- **Documentation**: [`web`](apps/web) - Official website and documentation +- **CLI**: [`apps/cli`](apps/cli) - The scaffolding CLI tool +- **Documentation**: [`apps/web`](apps/web) - Official website and documentation ## Documentation -Visit [better-t-stack.dev](https://better-t-stack.dev) for full documentation, guides, and examples. +Visit [better-t-stack.dev](https://better-t-stack.dev) for full documentation, guides, and examples. You can also use the visual Stack Builder at `https://better-t-stack.dev/new` to generate a command for your stack. ## Development @@ -65,7 +68,10 @@ bun dev:web ## Want to contribute? -Just fork the repository and submit a pull request! +Please read the Contribution Guide first and open an issue before starting new features to ensure alignment with project goals. + +- Docs: [`Contributing`](/apps/web/content/docs/contributing.mdx) +- Repo guide: [`.github/CONTRIBUTING.md`](.github/CONTRIBUTING.md) ## Star History From 3768226da073471d75a6fa7f0e5e3750d8965f5e Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Fri, 8 Aug 2025 14:33:49 +0530 Subject: [PATCH 4/8] add analytics docs --- apps/web/content/docs/analytics.mdx | 55 +++++++++++++++++++++++++++++ apps/web/content/docs/meta.json | 1 + 2 files changed, 56 insertions(+) create mode 100644 apps/web/content/docs/analytics.mdx diff --git a/apps/web/content/docs/analytics.mdx b/apps/web/content/docs/analytics.mdx new file mode 100644 index 00000000..b1143d57 --- /dev/null +++ b/apps/web/content/docs/analytics.mdx @@ -0,0 +1,55 @@ +--- +title: Analytics & Telemetry +description: What we collect, how to disable it, and where to view aggregated insights +--- + +## What is collected + +On successful project creation, the CLI sends a single event (`project_created`) with: + +- Selected options (stack choices): `frontend`, `backend`, `runtime`, `database`, `orm`, `api`, `auth`, `addons`, `examples`, `dbSetup`, `webDeploy`, `packageManager` +- Environment data: `cli_version`, `node_version`, `platform` +- A random session id: `distinct_id` like `cli_` +- IP removed: `$ip: null` + +Not collected: + +- Project name, path, or file contents (explicitly omitted) +- Secrets or environment variables from your machine + + + +## Disable telemetry + +Telemetry is enabled by default. To disable: + +```bash +# Disable for a single run +BTS_TELEMETRY_DISABLED=1 bun create better-t-stack@latest +``` + +Add `export BTS_TELEMETRY_DISABLED=1` to your shell profile to make it permanent. + +## Where to view analytics + +- Charts: [`/analytics`](/analytics) +- Raw JSON snapshot: `https://r2.amanv.dev/analytics-data.json` +- CSV export: `https://r2.amanv.dev/export.csv` + +Notes: + +- Aggregates are periodically regenerated from incoming events +- Raw data is not publicly exposed; the `/analytics` page presents only summary statistics + +## Full transparency + +Single event per scaffold; randomized id; no IP or project identifiers. See source code below. + +If in doubt, set `BTS_TELEMETRY_DISABLED=1` and proceed. You can still use all CLI features. + +## Source code + +- CLI event sender: [`apps/cli/src/utils/analytics.ts`](https://github.com/better-t-stack/create-better-t-stack/blob/main/apps/cli/src/utils/analytics.ts) +- Telemetry toggle logic: [`apps/cli/src/utils/telemetry.ts`](https://github.com/better-t-stack/create-better-t-stack/blob/main/apps/cli/src/utils/telemetry.ts) +- Aggregation script (builds the charts data): [`apps/web/scripts/generate-analytics.ts`](https://github.com/better-t-stack/create-better-t-stack/blob/main/apps/web/scripts/generate-analytics.ts) + diff --git a/apps/web/content/docs/meta.json b/apps/web/content/docs/meta.json index 70231044..9a2371e9 100644 --- a/apps/web/content/docs/meta.json +++ b/apps/web/content/docs/meta.json @@ -4,6 +4,7 @@ "cli", "project-structure", "bts-config", + "analytics", "contributing", "compatibility", "troubleshooting", From c9e67608571dac5cc30b0d5cecece526182a197c Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Fri, 8 Aug 2025 14:51:15 +0530 Subject: [PATCH 5/8] fix github link --- README.md | 2 +- apps/web/content/docs/analytics.mdx | 6 +++--- apps/web/content/docs/contributing.mdx | 2 +- apps/web/content/docs/meta.json | 1 - apps/web/src/app/(home)/_components/footer.tsx | 4 ++-- apps/web/src/app/(home)/_components/navbar.tsx | 2 +- .../app/(home)/analytics/_components/analytics-header.tsx | 2 +- 7 files changed, 9 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 37aa5a86..c2cb2258 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Visit [better-t-stack.dev](https://better-t-stack.dev) for full documentation, g ```bash # Clone the repository -git clone https://github.com/better-t-stack/create-better-t-stack.git +git clone https://github.com/AmanVarshney01/create-better-t-stack.git # Install dependencies bun install diff --git a/apps/web/content/docs/analytics.mdx b/apps/web/content/docs/analytics.mdx index b1143d57..e4967c52 100644 --- a/apps/web/content/docs/analytics.mdx +++ b/apps/web/content/docs/analytics.mdx @@ -49,7 +49,7 @@ If in doubt, set `BTS_TELEMETRY_DISABLED=1` and proceed. You can still use all C ## Source code -- CLI event sender: [`apps/cli/src/utils/analytics.ts`](https://github.com/better-t-stack/create-better-t-stack/blob/main/apps/cli/src/utils/analytics.ts) -- Telemetry toggle logic: [`apps/cli/src/utils/telemetry.ts`](https://github.com/better-t-stack/create-better-t-stack/blob/main/apps/cli/src/utils/telemetry.ts) -- Aggregation script (builds the charts data): [`apps/web/scripts/generate-analytics.ts`](https://github.com/better-t-stack/create-better-t-stack/blob/main/apps/web/scripts/generate-analytics.ts) +- CLI event sender: [`apps/cli/src/utils/analytics.ts`](https://github.com/AmanVarshney01/create-better-t-stack/blob/main/apps/cli/src/utils/analytics.ts) +- Telemetry toggle logic: [`apps/cli/src/utils/telemetry.ts`](https://github.com/AmanVarshney01/create-better-t-stack/blob/main/apps/cli/src/utils/telemetry.ts) +- Aggregation script (builds the charts data): [`apps/web/scripts/generate-analytics.ts`](https://github.com/AmanVarshney01/create-better-t-stack/blob/main/apps/web/scripts/generate-analytics.ts) diff --git a/apps/web/content/docs/contributing.mdx b/apps/web/content/docs/contributing.mdx index 7ffdcd97..ec46e4bd 100644 --- a/apps/web/content/docs/contributing.mdx +++ b/apps/web/content/docs/contributing.mdx @@ -23,7 +23,7 @@ This project is a monorepo with two main apps: ### Install ```bash -git clone https://github.com/better-t-stack/create-better-t-stack.git +git clone https://github.com/AmanVarshney01/create-better-t-stack.git cd create-better-t-stack bun install ``` diff --git a/apps/web/content/docs/meta.json b/apps/web/content/docs/meta.json index 9a2371e9..0753258c 100644 --- a/apps/web/content/docs/meta.json +++ b/apps/web/content/docs/meta.json @@ -7,7 +7,6 @@ "analytics", "contributing", "compatibility", - "troubleshooting", "faq" ] } diff --git a/apps/web/src/app/(home)/_components/footer.tsx b/apps/web/src/app/(home)/_components/footer.tsx index bfa46514..fa6ee508 100644 --- a/apps/web/src/app/(home)/_components/footer.tsx +++ b/apps/web/src/app/(home)/_components/footer.tsx @@ -18,7 +18,7 @@ const Footer = () => {

{
  • GitHub Repository diff --git a/apps/web/src/app/(home)/_components/navbar.tsx b/apps/web/src/app/(home)/_components/navbar.tsx index a0780d09..2794f18f 100644 --- a/apps/web/src/app/(home)/_components/navbar.tsx +++ b/apps/web/src/app/(home)/_components/navbar.tsx @@ -85,7 +85,7 @@ export default function Navbar() { target: "_blank", }, { - href: "https://www.github.com/better-t-stack/create-better-t-stack", + href: "https://www.github.com/AmanVarshney01/create-better-t-stack", label: "GitHub", icon: , target: "_blank", diff --git a/apps/web/src/app/(home)/analytics/_components/analytics-header.tsx b/apps/web/src/app/(home)/analytics/_components/analytics-header.tsx index 9abfa284..6d605492 100644 --- a/apps/web/src/app/(home)/analytics/_components/analytics-header.tsx +++ b/apps/web/src/app/(home)/analytics/_components/analytics-header.tsx @@ -48,7 +48,7 @@ export function AnalyticsHeader({ Source:{" "} Date: Fri, 8 Aug 2025 15:08:02 +0530 Subject: [PATCH 6/8] fix --- apps/cli/src/prompts/project-name.ts | 2 ++ apps/web/content/docs/cli/meta.json | 14 +++----------- apps/web/src/app/docs/layout.tsx | 6 +----- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/apps/cli/src/prompts/project-name.ts b/apps/cli/src/prompts/project-name.ts index eeae2a9f..c08232ce 100644 --- a/apps/cli/src/prompts/project-name.ts +++ b/apps/cli/src/prompts/project-name.ts @@ -1,5 +1,6 @@ import path from "node:path"; import { cancel, isCancel, text } from "@clack/prompts"; +import consola from "consola"; import fs from "fs-extra"; import pc from "picocolors"; import { DEFAULT_CONFIG } from "../constants"; @@ -31,6 +32,7 @@ export async function getProjectName(initialName?: string): Promise { if (!validationError) { const projectDir = path.resolve(process.cwd(), initialName); if (!isPathWithinCwd(projectDir)) { + consola.error(pc.red("Project path must be within current directory")); } else { return initialName; } diff --git a/apps/web/content/docs/cli/meta.json b/apps/web/content/docs/cli/meta.json index a32f0751..fd5ecdab 100644 --- a/apps/web/content/docs/cli/meta.json +++ b/apps/web/content/docs/cli/meta.json @@ -1,13 +1,5 @@ { - "title": "CLI", - "defaultOpen": true, - "pages": [ - "index", - "init", - "add", - "builder", - "docs", - "sponsors" - ] + "title": "CLI", + "defaultOpen": true, + "pages": ["index", "init", "add", "builder", "docs", "sponsors"] } - diff --git a/apps/web/src/app/docs/layout.tsx b/apps/web/src/app/docs/layout.tsx index 1593f33e..6f9c84cf 100644 --- a/apps/web/src/app/docs/layout.tsx +++ b/apps/web/src/app/docs/layout.tsx @@ -14,9 +14,5 @@ const docsOptions: DocsLayoutProps = { }; export default function Layout({ children }: { children: ReactNode }) { - return ( - <> - {children} - - ); + return {children}; } From 50d8e06f46285a03cd70efc50676835e4d589001 Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Fri, 8 Aug 2025 15:50:44 +0530 Subject: [PATCH 7/8] improve logic --- apps/cli/src/prompts/api.ts | 6 +- apps/cli/src/prompts/examples.ts | 6 +- apps/cli/src/prompts/project-name.ts | 5 +- apps/cli/src/utils/compatibility-rules.ts | 2 +- .../utils/generate-reproducible-command.ts | 2 +- apps/cli/src/validation.ts | 134 ++++++++++++++---- 6 files changed, 122 insertions(+), 33 deletions(-) diff --git a/apps/cli/src/prompts/api.ts b/apps/cli/src/prompts/api.ts index 5ca001c0..26b0c780 100644 --- a/apps/cli/src/prompts/api.ts +++ b/apps/cli/src/prompts/api.ts @@ -12,9 +12,11 @@ export async function getApiChoice( return "none"; } - if (Api) return Api; - const allowed = allowedApisForFrontends(frontend ?? []); + + if (Api) { + return allowed.includes(Api) ? Api : allowed[0]; + } const apiOptions = allowed.map((a) => a === "trpc" ? { diff --git a/apps/cli/src/prompts/examples.ts b/apps/cli/src/prompts/examples.ts index bb0c2da3..13244edc 100644 --- a/apps/cli/src/prompts/examples.ts +++ b/apps/cli/src/prompts/examples.ts @@ -52,11 +52,15 @@ export async function getExamplesChoice( }); } + if (options.length === 0) return []; + response = await multiselect({ message: "Include examples", options: options, required: false, - initialValues: DEFAULT_CONFIG.examples, + initialValues: DEFAULT_CONFIG.examples?.filter((ex) => + options.some((o) => o.value === ex), + ), }); if (isCancel(response)) { diff --git a/apps/cli/src/prompts/project-name.ts b/apps/cli/src/prompts/project-name.ts index c08232ce..762a163a 100644 --- a/apps/cli/src/prompts/project-name.ts +++ b/apps/cli/src/prompts/project-name.ts @@ -31,11 +31,10 @@ export async function getProjectName(initialName?: string): Promise { const validationError = validateDirectoryName(finalDirName); if (!validationError) { const projectDir = path.resolve(process.cwd(), initialName); - if (!isPathWithinCwd(projectDir)) { - consola.error(pc.red("Project path must be within current directory")); - } else { + if (isPathWithinCwd(projectDir)) { return initialName; } + consola.error(pc.red("Project path must be within current directory")); } } diff --git a/apps/cli/src/utils/compatibility-rules.ts b/apps/cli/src/utils/compatibility-rules.ts index 9b21a863..637abdca 100644 --- a/apps/cli/src/utils/compatibility-rules.ts +++ b/apps/cli/src/utils/compatibility-rules.ts @@ -130,7 +130,7 @@ export function validateWorkersCompatibility( } if ( - providedFlags.has("db-setup") && + providedFlags.has("dbSetup") && options.dbSetup === "docker" && config.runtime === "workers" ) { diff --git a/apps/cli/src/utils/generate-reproducible-command.ts b/apps/cli/src/utils/generate-reproducible-command.ts index 99e0c190..76434959 100644 --- a/apps/cli/src/utils/generate-reproducible-command.ts +++ b/apps/cli/src/utils/generate-reproducible-command.ts @@ -34,7 +34,7 @@ export function generateReproducibleCommand(config: ProjectConfig): string { flags.push(`--package-manager ${config.packageManager}`); flags.push(config.install ? "--install" : "--no-install"); - let baseCommand = ""; + let baseCommand = "npx create-better-t-stack@latest"; const pkgManager = config.packageManager; if (pkgManager === "bun") { diff --git a/apps/cli/src/validation.ts b/apps/cli/src/validation.ts index 64a4fbc9..830d8c69 100644 --- a/apps/cli/src/validation.ts +++ b/apps/cli/src/validation.ts @@ -140,6 +140,16 @@ export function processAndValidateFlags( config.frontend = validOptions; } } + + if ( + providedFlags.has("api") && + providedFlags.has("frontend") && + config.api && + config.frontend && + config.frontend.length > 0 + ) { + validateApiFrontendCompatibility(config.api, config.frontend); + } if (options.addons && options.addons.length > 0) { if (options.addons.includes("none")) { if (options.addons.length > 1) { @@ -206,7 +216,12 @@ export function processAndValidateFlags( coerceBackendPresets(config); } - if (config.orm === "mongoose" && config.database !== "mongodb") { + if ( + providedFlags.has("orm") && + providedFlags.has("database") && + config.orm === "mongoose" && + config.database !== "mongodb" + ) { consola.fatal( "Mongoose ORM requires MongoDB database. Please use '--database mongodb' or choose a different ORM.", ); @@ -214,6 +229,8 @@ export function processAndValidateFlags( } if ( + providedFlags.has("database") && + providedFlags.has("orm") && config.database === "mongodb" && config.orm && config.orm !== "mongoose" && @@ -225,28 +242,50 @@ export function processAndValidateFlags( process.exit(1); } - if (config.orm === "drizzle" && config.database === "mongodb") { + if ( + providedFlags.has("orm") && + providedFlags.has("database") && + config.orm === "drizzle" && + config.database === "mongodb" + ) { consola.fatal( "Drizzle ORM does not support MongoDB. Please use '--orm mongoose' or '--orm prisma' or choose a different database.", ); process.exit(1); } - if (config.database && config.database !== "none" && config.orm === "none") { + if ( + providedFlags.has("database") && + providedFlags.has("orm") && + config.database && + config.database !== "none" && + config.orm === "none" + ) { consola.fatal( "Database selection requires an ORM. Please choose '--orm drizzle', '--orm prisma', or '--orm mongoose'.", ); process.exit(1); } - if (config.orm && config.orm !== "none" && config.database === "none") { + if ( + providedFlags.has("orm") && + providedFlags.has("database") && + config.orm && + config.orm !== "none" && + config.database === "none" + ) { consola.fatal( "ORM selection requires a database. Please choose a database or set '--orm none'.", ); process.exit(1); } - if (config.auth && config.database === "none") { + if ( + providedFlags.has("auth") && + providedFlags.has("database") && + config.auth && + config.database === "none" + ) { consola.fatal( "Authentication requires a database. Please choose a database or set '--no-auth'.", ); @@ -254,6 +293,8 @@ export function processAndValidateFlags( } if ( + providedFlags.has("dbSetup") && + providedFlags.has("database") && config.dbSetup && config.dbSetup !== "none" && config.database === "none" @@ -264,35 +305,60 @@ export function processAndValidateFlags( process.exit(1); } - if (config.dbSetup === "turso" && config.database !== "sqlite") { + if ( + providedFlags.has("dbSetup") && + (config.database ? providedFlags.has("database") : true) && + config.dbSetup === "turso" && + config.database !== "sqlite" + ) { consola.fatal( "Turso setup requires SQLite database. Please use '--database sqlite' or choose a different setup.", ); process.exit(1); } - if (config.dbSetup === "neon" && config.database !== "postgres") { + if ( + providedFlags.has("dbSetup") && + (config.database ? providedFlags.has("database") : true) && + config.dbSetup === "neon" && + config.database !== "postgres" + ) { consola.fatal( "Neon setup requires PostgreSQL database. Please use '--database postgres' or choose a different setup.", ); process.exit(1); } - if (config.dbSetup === "prisma-postgres" && config.database !== "postgres") { + if ( + providedFlags.has("dbSetup") && + (config.database ? providedFlags.has("database") : true) && + config.dbSetup === "prisma-postgres" && + config.database !== "postgres" + ) { consola.fatal( "Prisma PostgreSQL setup requires PostgreSQL database. Please use '--database postgres' or choose a different setup.", ); process.exit(1); } - if (config.dbSetup === "mongodb-atlas" && config.database !== "mongodb") { + if ( + providedFlags.has("dbSetup") && + (config.database ? providedFlags.has("database") : true) && + config.dbSetup === "mongodb-atlas" && + config.database !== "mongodb" + ) { consola.fatal( "MongoDB Atlas setup requires MongoDB database. Please use '--database mongodb' or choose a different setup.", ); process.exit(1); } - if (config.dbSetup === "supabase" && config.database !== "postgres") { + if ( + providedFlags.has("dbSetup") && + (config.database ? providedFlags.has("database") : true) && + config.dbSetup === "supabase" && + config.database !== "postgres" + ) { consola.fatal( "Supabase setup requires PostgreSQL database. Please use '--database postgres' or choose a different setup.", ); @@ -300,29 +366,49 @@ export function processAndValidateFlags( } if (config.dbSetup === "d1") { - if (config.database !== "sqlite") { - consola.fatal( - "Cloudflare D1 setup requires SQLite database. Please use '--database sqlite' or choose a different setup.", - ); - process.exit(1); + if ( + (providedFlags.has("dbSetup") && providedFlags.has("database")) || + (providedFlags.has("dbSetup") && !config.database) + ) { + if (config.database !== "sqlite") { + consola.fatal( + "Cloudflare D1 setup requires SQLite database. Please use '--database sqlite' or choose a different setup.", + ); + process.exit(1); + } } - if (config.runtime !== "workers") { - consola.fatal( - "Cloudflare D1 setup requires the Cloudflare Workers runtime. Please use '--runtime workers' or choose a different setup.", - ); - process.exit(1); + if ( + (providedFlags.has("dbSetup") && providedFlags.has("runtime")) || + (providedFlags.has("dbSetup") && !config.runtime) + ) { + if (config.runtime !== "workers") { + consola.fatal( + "Cloudflare D1 setup requires the Cloudflare Workers runtime. Please use '--runtime workers' or choose a different setup.", + ); + process.exit(1); + } } } - if (config.dbSetup === "docker" && config.database === "sqlite") { + if ( + providedFlags.has("dbSetup") && + providedFlags.has("database") && + config.dbSetup === "docker" && + config.database === "sqlite" + ) { consola.fatal( "Docker setup is not compatible with SQLite database. SQLite is file-based and doesn't require Docker. Please use '--database postgres', '--database mysql', '--database mongodb', or choose a different setup.", ); process.exit(1); } - if (config.dbSetup === "docker" && config.runtime === "workers") { + if ( + providedFlags.has("dbSetup") && + providedFlags.has("runtime") && + config.dbSetup === "docker" && + config.runtime === "workers" + ) { consola.fatal( "Docker setup is not compatible with Cloudflare Workers runtime. Workers runtime uses serverless databases (D1) and doesn't support local Docker containers. Please use '--db-setup d1' for SQLite or choose a different runtime.", ); @@ -334,9 +420,7 @@ export function processAndValidateFlags( const hasWebFrontendFlag = (config.frontend ?? []).some((f) => isWebFrontend(f), ); - if (providedFlags.has("frontend")) { - validateWebDeployRequiresWebFrontend(config.webDeploy, hasWebFrontendFlag); - } + validateWebDeployRequiresWebFrontend(config.webDeploy, hasWebFrontendFlag); return config; } From 342bdddb5a92767083fd2504b70fcd74920dba12 Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Fri, 8 Aug 2025 17:33:15 +0530 Subject: [PATCH 8/8] chore(web): improve docs and readme --- README.md | 17 +- apps/cli/README.md | 23 +- apps/web/content/docs/analytics.mdx | 24 +- apps/web/content/docs/cli-commands.mdx | 595 ------------------------- apps/web/content/docs/cli/add.mdx | 49 +- apps/web/content/docs/cli/builder.mdx | 1 + apps/web/content/docs/cli/docs.mdx | 1 + apps/web/content/docs/cli/init.mdx | 118 ++++- apps/web/content/docs/cli/sponsors.mdx | 1 + apps/web/content/docs/index.mdx | 267 ++++++++--- 10 files changed, 412 insertions(+), 684 deletions(-) delete mode 100644 apps/web/content/docs/cli-commands.mdx diff --git a/README.md b/README.md index c2cb2258..01480783 100644 --- a/README.md +++ b/README.md @@ -10,17 +10,24 @@ A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with ![demo](https://cdn.jsdelivr.net/gh/amanvarshney01/create-better-t-stack/demo.gif) +## Philosophy + +- Roll your own stack: you pick only the parts you need, nothing extra. +- Minimal templates: bare-bones scaffolds with zero bloat. +- Latest dependencies: always use current, stable versions by default. +- Free and open source: forever. + ## Quick Start ```bash -# Using npm -npx create-better-t-stack@latest - -# Using bun +# Using bun (recommended) bun create better-t-stack@latest # Using pnpm pnpm create better-t-stack@latest + +# Using npm +npx create-better-t-stack@latest ``` ## Features @@ -37,7 +44,7 @@ pnpm create better-t-stack@latest - DB Setup: Turso, Neon, Supabase, Prisma PostgreSQL, MongoDB Atlas, Cloudflare D1, Docker - Web Deploy: Cloudflare Workers -Type safety end-to-end, clean monorepo layout, and zero‑lock‑in: you choose only what you need. +Type safety end-to-end, clean monorepo layout, and zero lock-in: you choose only what you need. ## Repository Structure diff --git a/apps/cli/README.md b/apps/cli/README.md index 94e541e4..419039be 100644 --- a/apps/cli/README.md +++ b/apps/cli/README.md @@ -15,14 +15,14 @@ A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with Run without installing globally: ```bash -# Using npm -npx create-better-t-stack@latest - -# Using bun +# Using bun (recommended) bun create better-t-stack@latest # Using pnpm pnpm create better-t-stack@latest + +# Using npm +npx create-better-t-stack@latest ``` Follow the prompts to configure your project or use the `--yes` flag for defaults. @@ -58,14 +58,15 @@ Options: --auth Include authentication --no-auth Exclude authentication --frontend Frontend types (tanstack-router, react-router, tanstack-start, next, nuxt, svelte, solid, native-nativewind, native-unistyles, none) - --addons Additional addons (pwa, tauri, starlight, biome, husky, turborepo, none) + --addons Additional addons (pwa, tauri, starlight, biome, husky, turborepo, fumadocs, ultracite, oxlint, none) --examples Examples to include (todo, ai, none) --git Initialize git repository --no-git Skip git initialization --package-manager Package manager (npm, pnpm, bun) --install Install dependencies --no-install Skip installing dependencies - --db-setup Database setup (turso, d1, neon, supabase, prisma-postgres, mongodb-atlas, none) + --db-setup Database setup (turso, d1, neon, supabase, prisma-postgres, mongodb-atlas, docker, none) + --web-deploy Web deployment (workers, none) --backend Backend framework (hono, express, elysia, next, convex, fastify, none) --runtime Runtime (bun, node, workers, none) --api API type (trpc, orpc, none) @@ -84,7 +85,7 @@ This CLI collects anonymous usage data to help improve the tool. The data collec ### Disabling Telemetry -You can disable telemetry by setting the `BTS_TELEMETRY` environment variable: +You can disable telemetry by setting the `BTS_TELEMETRY_DISABLED` environment variable: ```bash # Disable telemetry for a single run @@ -94,10 +95,6 @@ BTS_TELEMETRY_DISABLED=1 npx create-better-t-stack my-app export BTS_TELEMETRY_DISABLED=1 ``` -### Development - -During development, telemetry is automatically disabled when `NODE_ENV=development`. - ## Examples Create a project with default configuration: @@ -118,10 +115,10 @@ Create a project with Elysia backend and Node.js runtime: npx create-better-t-stack my-app --backend elysia --runtime node ``` -Create a project with multiple frontend options: +Create a project with multiple frontend options (one web + one native): ```bash -npx create-better-t-stack my-app --frontend tanstack-router native +npx create-better-t-stack my-app --frontend tanstack-router native-nativewind ``` Create a project with examples: diff --git a/apps/web/content/docs/analytics.mdx b/apps/web/content/docs/analytics.mdx index e4967c52..162c132c 100644 --- a/apps/web/content/docs/analytics.mdx +++ b/apps/web/content/docs/analytics.mdx @@ -23,10 +23,26 @@ Not collected: Telemetry is enabled by default. To disable: -```bash -# Disable for a single run -BTS_TELEMETRY_DISABLED=1 bun create better-t-stack@latest -``` + + + ```bash + # Disable for a single run + BTS_TELEMETRY_DISABLED=1 bun create better-t-stack@latest + ``` + + + ```bash + # Disable for a single run + BTS_TELEMETRY_DISABLED=1 pnpm create better-t-stack@latest + ``` + + + ```bash + # Disable for a single run + BTS_TELEMETRY_DISABLED=1 npx create-better-t-stack@latest + ``` + + Add `export BTS_TELEMETRY_DISABLED=1` to your shell profile to make it permanent. diff --git a/apps/web/content/docs/cli-commands.mdx b/apps/web/content/docs/cli-commands.mdx deleted file mode 100644 index 408a6cbc..00000000 --- a/apps/web/content/docs/cli-commands.mdx +++ /dev/null @@ -1,595 +0,0 @@ ---- -title: CLI Commands -description: Complete reference for all Better-T-Stack CLI commands and options ---- - -## Quick Usage - - - - ```bash - # Interactive setup - bun create better-t-stack@latest - - # With project name - bun create better-t-stack@latest my-project - ``` - - - ```bash - pnpm create better-t-stack@latest - pnpm create better-t-stack@latest my-project - ``` - - - ```bash - npx create-better-t-stack@latest - npx create-better-t-stack@latest my-project - ``` - - - -## Commands Overview - -| Command | Description | -|---------|-------------| -| `init` (default) | Create a new Better-T-Stack project | -| `add` | Add addons or deployment configurations to existing projects | -| `sponsors` | Display project sponsors | -| `docs` | Open documentation in browser | -| `builder` | Open web-based stack builder | - ---- - -## `init` - Create Project (Default) - -The primary command for creating new Better-T-Stack projects. - -### Basic Usage - - - - ```bash - # Interactive setup - bun create better-t-stack@latest - - # With project name - bun create better-t-stack@latest my-project - - # With specific directory - bun create better-t-stack@latest ./path/to/project - - # Use current directory - bun create better-t-stack@latest . - ``` - - - ```bash - pnpm create better-t-stack@latest - pnpm create better-t-stack@latest my-project - pnpm create better-t-stack@latest ./path/to/project - pnpm create better-t-stack@latest . - ``` - - - ```bash - npx create-better-t-stack@latest - npx create-better-t-stack@latest my-project - npx create-better-t-stack@latest ./path/to/project - npx create-better-t-stack@latest . - ``` - - - -### Flags Reference - -#### General Options - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--yes, -y` | boolean | `false` | Skip prompts, use defaults | -| `--help, -h` | boolean | - | Show help information | -| `--version, -V` | boolean | - | Show CLI version | - -#### Frontend Options - -| Flag | Values | Default | Description | -|------|--------|---------|-------------| -| `--frontend` | Multiple values | `tanstack-router` | Frontend frameworks to include | - -**Available Frontend Values:** -- `tanstack-router` - React with TanStack Router -- `react-router` - React with React Router -- `tanstack-start` - React with TanStack Start (SSR) -- `next` - Next.js framework -- `nuxt` - Vue.js with Nuxt -- `svelte` - SvelteKit -- `solid` - SolidJS -- `native-nativewind` - React Native with NativeWind -- `native-unistyles` - React Native with Unistyles -- `none` - No frontend - -**Examples:** -```bash -# Single web frontend ---frontend tanstack-router - -# Web + Mobile ---frontend tanstack-router native-nativewind - -# No frontend (API-only) ---frontend none -``` - -Note: Select at most one web frontend (one of: tanstack-router, react-router, tanstack-start, next, nuxt, svelte, solid) and at most one native frontend (one of: native-nativewind, native-unistyles). -Do not combine `none` with other frontend values. - -#### Backend Options - -| Flag | Values | Default | Description | -|------|--------|---------|-------------| -| `--backend` | Single value | `hono` | Backend framework | - -**Available Backend Values:** -- `hono` - Hono web framework -- `express` - Express.js -- `fastify` - Fastify framework -- `elysia` - Elysia framework -- `next` - Next.js API routes -- `convex` - Convex backend-as-a-service -- `none` - No backend - -**Examples:** -```bash ---backend hono ---backend convex ---backend none -``` - -#### Runtime Options - -| Flag | Values | Default | Description | -|------|--------|---------|-------------| -| `--runtime` | Single value | `bun` | Runtime environment | - -**Available Runtime Values:** -- `bun` - Bun runtime -- `node` - Node.js runtime -- `workers` - Cloudflare Workers (Hono only) -- `none` - No runtime (Convex/none backend) - -**Examples:** -```bash ---runtime bun ---runtime workers # Only with --backend hono -``` - -#### Database Options - -| Flag | Values | Default | Description | -|------|--------|---------|-------------| -| `--database` | Single value | `sqlite` | Database type | - -**Available Database Values:** -- `sqlite` - SQLite database -- `postgres` - PostgreSQL -- `mysql` - MySQL -- `mongodb` - MongoDB -- `none` - No database - -**Examples:** -```bash ---database postgres ---database none -``` - -#### ORM Options - -| Flag | Values | Default | Description | -|------|--------|---------|-------------| -| `--orm` | Single value | `drizzle` | ORM/Database toolkit | - -**Available ORM Values:** -- `drizzle` - Drizzle ORM (TypeScript-first) -- `prisma` - Prisma ORM (feature-rich) -- `mongoose` - Mongoose (MongoDB only) -- `none` - No ORM - -**Examples:** -```bash ---orm drizzle ---orm prisma ---orm none -``` - -#### API Layer Options - -| Flag | Values | Default | Description | -|------|--------|---------|-------------| -| `--api` | Single value | `trpc` | API layer type | - -**Available API Values:** -- `trpc` - tRPC (end-to-end type safety) -- `orpc` - oRPC (OpenAPI compatible) -- `none` - No API layer - -**Examples:** -```bash ---api trpc ---api orpc ---api none -``` - -#### Authentication Options - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--auth` | boolean | `true` | Enable authentication | -| `--no-auth` | boolean | - | Disable authentication | - -**Examples:** -```bash ---auth # Enable auth ---no-auth # Disable auth -``` - -#### Addons Options - -| Flag | Values | Default | Description | -|------|--------|---------|-------------| -| `--addons` | Multiple values | `turborepo` | Additional features | - -**Available Addon Values:** -- `turborepo` - Turborepo build system -- `pwa` - Progressive Web App support -- `tauri` - Desktop app with Tauri -- `biome` - Biome linter/formatter -- `husky` - Git hooks with Husky -- `starlight` - Documentation site - - `fumadocs` - Fumadocs docs site - - `ultracite` - Markdown/MDX processing - - `oxlint` - Fast linter -- `none` - No addons - -Note: Do not combine `none` with other addon values. - -**Examples:** -```bash ---addons turborepo pwa ---addons biome husky ---addons none -``` - -#### Examples Options - -| Flag | Values | Default | Description | -|------|--------|---------|-------------| -| `--examples` | Multiple values | `[]` | Example applications | - -**Available Example Values:** -- `todo` - Todo CRUD application -- `ai` - AI chat interface -- `none` - No examples - -**Examples:** -```bash ---examples todo ---examples todo ai ---examples none -``` - -Note: Do not combine `none` with other example values. - -#### Database Setup Options - -| Flag | Values | Default | Description | -|------|--------|---------|-------------| -| `--db-setup` | Single value | `none` | Database hosting setup | - -**Available Database Setup Values:** -- `turso` - Turso SQLite hosting -- `neon` - Neon PostgreSQL -- `supabase` - Supabase PostgreSQL -- `prisma-postgres` - Prisma PostgreSQL -- `mongodb-atlas` - MongoDB Atlas -- `d1` - Cloudflare D1 (Workers only) -- `docker` - Local Docker setup -- `none` - Manual setup - -**Examples:** -```bash ---db-setup neon ---db-setup docker ---db-setup none -``` - -#### Deployment Options - -| Flag | Values | Default | Description | -|------|--------|---------|-------------| -| `--web-deploy` | Single value | `none` | Web deployment setup | - -**Available Deployment Values:** -- `workers` - Cloudflare Workers -- `none` - No deployment setup - -**Examples:** -```bash ---web-deploy workers ---web-deploy none -``` - -#### Project Management Options - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--git` | boolean | `true` | Initialize git repository | -| `--no-git` | boolean | - | Skip git initialization | -| `--install` | boolean | `true` | Install dependencies | -| `--no-install` | boolean | - | Skip dependency installation | -| `--package-manager` | string | auto-detect | Package manager to use | - -**Package Manager Values:** -- `npm` - Use npm -- `pnpm` - Use pnpm -- `bun` - Use bun - -**Examples:** -```bash ---git --install --package-manager pnpm ---no-git --no-install -``` - ---- - -## `add` - Add to Existing Project - -Add addons or deployment configurations to existing Better-T-Stack projects. - -### Usage - - - - ```bash - # Interactive addon selection - bun create better-t-stack@latest add - - # Add specific addons - bun create better-t-stack@latest add --addons pwa tauri - - # Add deployment - bun create better-t-stack@latest add --web-deploy workers - - # Add both - bun create better-t-stack@latest add --addons biome --web-deploy workers - ``` - - - ```bash - pnpm create better-t-stack@latest add - pnpm create better-t-stack@latest add --addons pwa tauri - pnpm create better-t-stack@latest add --web-deploy workers - pnpm create better-t-stack@latest add --addons biome --web-deploy workers - ``` - - - ```bash - npx create-better-t-stack@latest add - npx create-better-t-stack@latest add --addons pwa tauri - npx create-better-t-stack@latest add --web-deploy workers - npx create-better-t-stack@latest add --addons biome --web-deploy workers - ``` - - - -### Flags - -| Flag | Values | Description | -|------|--------|-------------| -| `--addons` | Multiple values | Addons to add (same as init) | -| `--web-deploy` | Single value | Deployment to add | -| `--project-dir` | string | Target project directory (default: current) | -| `--install` | boolean | Install dependencies after adding | -| `--no-install` | boolean | Skip dependency installation | -| `--package-manager` | string | Package manager to use | - -### Examples - -```bash -# Add PWA support to current project -npx create-better-t-stack@latest add --addons pwa - -# Add multiple addons with dependency installation -npx create-better-t-stack@latest add --addons biome husky --install - -# Add to specific project directory -npx create-better-t-stack@latest add --project-dir ./my-project --addons tauri -``` - ---- - -## `sponsors` - View Sponsors - -Display Better-T-Stack project sponsors. - -### Usage - - - - ```bash - bun create better-t-stack@latest sponsors - ``` - - - ```bash - pnpm create better-t-stack@latest sponsors - ``` - - - ```bash - npx create-better-t-stack@latest sponsors - ``` - - - -Shows a list of project sponsors with their GitHub profiles and websites. - ---- - -## `docs` - Open Documentation - -Open Better-T-Stack documentation in your default browser. - -### Usage - - - - ```bash - bun create better-t-stack@latest docs - ``` - - - ```bash - pnpm create better-t-stack@latest docs - ``` - - - ```bash - npx create-better-t-stack@latest docs - ``` - - - -Opens: https://better-t-stack.dev/docs - ---- - -## `builder` - Open Stack Builder - -Open the web-based interactive stack builder. - -### Usage - - - - ```bash - bun create better-t-stack@latest builder - ``` - - - ```bash - pnpm create better-t-stack@latest builder - ``` - - - ```bash - npx create-better-t-stack@latest builder - ``` - - - -Opens: https://better-t-stack.dev/new - -The web builder provides a visual interface for configuring your stack and generates the corresponding CLI command. - ---- - -## Complete Examples - -### Full-Stack Web Application - -```bash -bun create better-t-stack@latest my-webapp \ - --frontend tanstack-router \ - --backend hono \ - --runtime bun \ - --database postgres \ - --orm drizzle \ - --api trpc \ - --auth \ - --db-setup neon \ - --addons pwa turborepo \ - --examples todo ai -``` - -### Mobile + Web Application - -```bash -bun create better-t-stack@latest my-mobile-app \ - --frontend tanstack-router native-nativewind \ - --backend hono \ - --database sqlite \ - --orm drizzle \ - --auth \ - --db-setup turso \ - --addons turborepo -``` - -### Cloudflare Workers Project - -```bash -bun create better-t-stack@latest my-workers-app \ - --frontend tanstack-router \ - --backend hono \ - --runtime workers \ - --database sqlite \ - --orm drizzle \ - --db-setup d1 \ - --web-deploy workers -``` - -### API-Only Project - -```bash -bun create better-t-stack@latest my-api \ - --frontend none \ - --backend fastify \ - --runtime node \ - --database postgres \ - --orm prisma \ - --api trpc \ - --db-setup docker -``` - -### Quick Defaults - -```bash -# Use all defaults with immediate setup -bun create better-t-stack@latest my-project --yes - -# Convex full-stack (automatically configures compatible options) -bun create better-t-stack@latest my-convex-app --backend convex -``` - ---- - -## Compatibility Notes - -Some options have compatibility requirements: - -- **Cloudflare Workers**: Only with `--backend hono`, `--orm drizzle` or `--orm none`, `--runtime workers` -- **MongoDB**: Requires `--orm mongoose` or `--orm prisma` -- **Convex**: Forces `--no-auth`, `--database none`, `--orm none`, `--api none`, `--runtime none`, `--db-setup none`; sets `--examples todo`; Solid frontend is not supported with Convex -- **PWA**: Requires compatible web frontend -- **Tauri**: Requires compatible web frontend -- **AI Examples**: Not compatible with `--backend elysia` or `--frontend solid` -- **tRPC + Nuxt/Svelte/Solid**: Use `--api orpc` (tRPC is not supported with `nuxt`, `svelte`, or `solid`) -- **Todo Example**: Requires a database when a backend (other than Convex) is selected -- **Web Deploy**: `--web-deploy workers` requires selecting a web frontend -- **Examples with `--api none`**: Cannot select examples when `--api none` (unless `--backend convex`) -- **Runtime `none`**: Only allowed with `--backend convex` or `--backend none` -- **Mongoose ORM**: Requires `--database mongodb` -- **Drizzle ORM**: Not compatible with `--database mongodb` -- **Database requires ORM**: Selecting a database requires a non-`none` ORM -- **ORM requires database**: Selecting a non-`none` ORM requires a database -- **Auth requires database**: `--auth` requires a non-`none` database -- **DB Setup constraints**: - - `--db-setup turso` → requires `--database sqlite` - - `--db-setup neon` → requires `--database postgres` - - `--db-setup prisma-postgres` → requires `--database postgres` - - `--db-setup mongodb-atlas` → requires `--database mongodb` - - `--db-setup supabase` → requires `--database postgres` - - `--db-setup d1` → requires `--database sqlite` and `--runtime workers` - - `--db-setup docker` → not compatible with `--database sqlite` or `--runtime workers` - -The CLI will validate compatibility and show helpful error messages for invalid combinations. diff --git a/apps/web/content/docs/cli/add.mdx b/apps/web/content/docs/cli/add.mdx index 292f2f11..388a897e 100644 --- a/apps/web/content/docs/cli/add.mdx +++ b/apps/web/content/docs/cli/add.mdx @@ -8,28 +8,61 @@ description: Add addons or deployment to an existing project ```bash - bun create better-t-stack@latest add [options] + bun create better-t-stack@latest add ``` ```bash - pnpm create better-t-stack@latest add [options] + pnpm create better-t-stack@latest add ``` ```bash - npx create-better-t-stack@latest add [options] + npx create-better-t-stack@latest add ``` -### Options +## Flags + +### Addons + +- `--addons` Multiple values to add features + - Values: `pwa`, `tauri`, `starlight`, `biome`, `husky`, `turborepo`, `fumadocs`, `ultracite`, `oxlint`, `none` + - Do not combine `none` with other values + +### Deployment -- `--addons` Multiple values - `--web-deploy` One of: `workers`, `none` -- `--project-dir` Path -- `--install` / `--no-install` + - Requires that the project includes a web frontend + +### Project directory and install + +- `--project-dir` Path to target project (default: current directory) +- `--install` / `--no-install` Install dependencies after applying changes - `--package-manager` One of: `bun`, `pnpm`, `npm` -See also: [Compatibility](/docs/compatibility) +## Examples + +```bash +# Add PWA and Turborepo to the current project +bun create better-t-stack@latest add --addons pwa turborepo --install +``` + +```bash +# Add Cloudflare Workers deployment +bun create better-t-stack@latest add --web-deploy workers +``` + +```bash +# Operate on a specific project directory using bun +bun create better-t-stack@latest add --project-dir ./apps/web --addons biome --package-manager bun +``` + +## Compatibility notes + +- Web deployment requires a web frontend to be present +- Addons must be compatible with the selected frontend; the CLI validates this and fails with a clear error if incompatible + +For general compatibility rules, see the main CLI reference. diff --git a/apps/web/content/docs/cli/builder.mdx b/apps/web/content/docs/cli/builder.mdx index 39df6b0a..1d30afa4 100644 --- a/apps/web/content/docs/cli/builder.mdx +++ b/apps/web/content/docs/cli/builder.mdx @@ -23,3 +23,4 @@ description: Open the web-based stack builder +This command has no flags. diff --git a/apps/web/content/docs/cli/docs.mdx b/apps/web/content/docs/cli/docs.mdx index f5902b2e..649e3e75 100644 --- a/apps/web/content/docs/cli/docs.mdx +++ b/apps/web/content/docs/cli/docs.mdx @@ -23,3 +23,4 @@ description: Open the documentation +This command has no flags. diff --git a/apps/web/content/docs/cli/init.mdx b/apps/web/content/docs/cli/init.mdx index eb6bd22e..f0940190 100644 --- a/apps/web/content/docs/cli/init.mdx +++ b/apps/web/content/docs/cli/init.mdx @@ -31,5 +31,121 @@ You can pass `.` to use the current directory. bun create better-t-stack@latest my-app --yes ``` -See also: [Compatibility](/docs/compatibility) +## Flags Reference + +### General + +- `--yes, -y` Skip all prompts and use defaults +- `--help, -h` Show help +- `--version, -V` Show CLI version + +### Frontend + +- `--frontend` Choose one web frontend and optionally one native frontend + - Web: `tanstack-router`, `react-router`, `tanstack-start`, `next`, `nuxt`, `svelte`, `solid` + - Native: `native-nativewind`, `native-unistyles` + - Special: `none` + - Notes: At most one from each group; do not combine `none` with others + +### Backend + +- `--backend` One of: `hono`, `express`, `fastify`, `next`, `elysia`, `convex`, `none` + +### Runtime + +- `--runtime` One of: `bun`, `node`, `workers`, `none` + - `workers` only with `--backend hono` + - `none` only with `--backend convex` or `--backend none` + +### Database + +- `--database` One of: `sqlite`, `postgres`, `mysql`, `mongodb`, `none` + +### ORM + +- `--orm` One of: `drizzle`, `prisma`, `mongoose`, `none` + - `mongoose` requires `--database mongodb` + - `drizzle` is not compatible with `--database mongodb` + +### API + +- `--api` One of: `trpc`, `orpc`, `none` + - Use `orpc` with `nuxt`, `svelte`, or `solid` (tRPC not supported there) + +### Authentication + +- `--auth` Enable auth +- `--no-auth` Disable auth + - Auth requires a non-`none` database + +### Addons + +- `--addons` Multiple values: `pwa`, `tauri`, `starlight`, `biome`, `husky`, `turborepo`, `fumadocs`, `ultracite`, `oxlint`, `none` + - Do not combine `none` with other values + +### Examples + +- `--examples` Multiple values: `todo`, `ai`, `none` + - Do not combine `none` with other values + +### Database setup + +- `--db-setup` One of: `turso`, `neon`, `prisma-postgres`, `mongodb-atlas`, `supabase`, `d1`, `docker`, `none` + - `turso` → requires `--database sqlite` + - `neon`, `prisma-postgres`, `supabase` → require `--database postgres` + - `mongodb-atlas` → requires `--database mongodb` + - `d1` → requires `--database sqlite` and `--runtime workers` + - `docker` → not compatible with `--database sqlite` or `--runtime workers` + +### Web deployment + +- `--web-deploy` One of: `workers`, `none` + - Requires selecting a web frontend + +### Project setup + +- `--git` / `--no-git` Initialize git repository +- `--install` / `--no-install` Install dependencies +- `--package-manager` One of: `bun`, `pnpm`, `npm` + +## Examples + +```bash +# Full-stack web app +bun create better-t-stack@latest my-webapp \ + --frontend tanstack-router \ + --backend hono \ + --runtime bun \ + --database postgres \ + --orm drizzle \ + --api trpc \ + --auth \ + --db-setup neon \ + --addons pwa turborepo \ + --examples todo +``` + +```bash +# Cloudflare Workers +bun create better-t-stack@latest my-workers \ + --frontend tanstack-router \ + --backend hono \ + --runtime workers \ + --database sqlite \ + --orm drizzle \ + --db-setup d1 \ + --web-deploy workers +``` + +## Compatibility notes + +- Workers runtime only with `--backend hono` and `--orm drizzle` or `--orm none` +- MongoDB requires `--orm mongoose` or `--orm prisma` +- Convex backend forces: no auth, no db, no orm, no api, no runtime, no db-setup; Solid is not supported +- Todo example requires a database when a non-Convex backend is selected +- AI example is not compatible with `--backend elysia` or `--frontend solid` + +The CLI validates incompatible combinations and fails fast with clear messages. + +See also: Compatibility overview in the main CLI reference. diff --git a/apps/web/content/docs/cli/sponsors.mdx b/apps/web/content/docs/cli/sponsors.mdx index b44f1cc7..4e8f8025 100644 --- a/apps/web/content/docs/cli/sponsors.mdx +++ b/apps/web/content/docs/cli/sponsors.mdx @@ -23,3 +23,4 @@ description: View project sponsors +This command has no flags. diff --git a/apps/web/content/docs/index.mdx b/apps/web/content/docs/index.mdx index 05acb1ff..81314765 100644 --- a/apps/web/content/docs/index.mdx +++ b/apps/web/content/docs/index.mdx @@ -5,93 +5,244 @@ description: Create your first Better-T-Stack project in minutes ## Philosophy -- With Better T Stack, you freely choose only the parts you want; nothing extra is added. -- Pick your frontend, backend, API layer, database, ORM, auth, addons — or skip any of them. Compatibility is enforced. -- No lock‑in: it’s a generator, not a framework fork. +- Roll your own stack: pick only what you need, nothing extra. +- Minimal templates: bare-bones scaffolds with zero bloat. +- Latest dependencies: always current and stable by default. +- Free and open source: forever. ## Get Started -### Stack Builder (UI) - -- Visit [/new](/new) to pick your stack and copy the generated command -- Or open it via: - -```bash -bun create better-t-stack@latest builder -``` - ### CLI (prompts) -```bash -bun create better-t-stack@latest -``` + + + ```bash + bun create better-t-stack@latest + ``` + + + ```bash + pnpm create better-t-stack@latest + ``` + + + ```bash + npx create-better-t-stack@latest + ``` + + Follow the interactive prompts to choose your frontend, backend, database, ORM, API layer, and addons. Skip prompts and use the default stack: -```bash -bun create better-t-stack@latest my-app --yes -``` + + + ```bash + bun create better-t-stack@latest my-app --yes + ``` + + + ```bash + pnpm create better-t-stack@latest my-app --yes + ``` + + + ```bash + npx create-better-t-stack@latest my-app --yes + ``` + + -Prefer a visual flow? Use the Stack Builder at [/new](/new) to pick your stack and copy the generated command. You can also open it via: + + +### Stack Builder (UI) + +- Visit [/new](/new) to pick your stack and copy the generated command +- Or open it via: -```bash -bun create better-t-stack@latest builder -``` + + + ```bash + bun create better-t-stack@latest builder + ``` + + + ```bash + pnpm create better-t-stack@latest builder + ``` + + + ```bash + npx create-better-t-stack@latest builder + ``` + + ## Common Setups ### Default Stack -```bash -bun create better-t-stack@latest my-webapp \ - --frontend tanstack-router \ - --backend hono \ - --database sqlite \ - --orm drizzle \ - --auth \ - --addons turborepo -``` + + + ```bash + bun create better-t-stack@latest my-webapp \ + --frontend tanstack-router \ + --backend hono \ + --database sqlite \ + --orm drizzle \ + --auth \ + --addons turborepo + ``` + + + ```bash + pnpm create better-t-stack@latest my-webapp \ + --frontend tanstack-router \ + --backend hono \ + --database sqlite \ + --orm drizzle \ + --auth \ + --addons turborepo + ``` + + + ```bash + npx create-better-t-stack@latest my-webapp \ + --frontend tanstack-router \ + --backend hono \ + --database sqlite \ + --orm drizzle \ + --auth \ + --addons turborepo + ``` + + ### Convex + React -```bash -bun create better-t-stack@latest my-convex-app \ - --frontend tanstack-router \ - --backend convex -``` + + + ```bash + bun create better-t-stack@latest my-convex-app \ + --frontend tanstack-router \ + --backend convex + ``` + + + ```bash + pnpm create better-t-stack@latest my-convex-app \ + --frontend tanstack-router \ + --backend convex + ``` + + + ```bash + npx create-better-t-stack@latest my-convex-app \ + --frontend tanstack-router \ + --backend convex + ``` + + ### API Only -```bash -bun create better-t-stack@latest my-api \ - --frontend none \ - --backend fastify \ - --runtime node \ - --database postgres \ - --orm prisma \ - --api trpc -``` + + + ```bash + bun create better-t-stack@latest my-api \ + --frontend none \ + --backend fastify \ + --runtime node \ + --database postgres \ + --orm prisma \ + --api trpc + ``` + + + ```bash + pnpm create better-t-stack@latest my-api \ + --frontend none \ + --backend fastify \ + --runtime node \ + --database postgres \ + --orm prisma \ + --api trpc + ``` + + + ```bash + npx create-better-t-stack@latest my-api \ + --frontend none \ + --backend fastify \ + --runtime node \ + --database postgres \ + --orm prisma \ + --api trpc + ``` + + ### Mobile App (Expo) -```bash -bun create better-t-stack@latest my-native \ - --frontend native-nativewind \ - --backend hono \ - --database sqlite \ - --orm drizzle \ - --auth -``` + + + ```bash + bun create better-t-stack@latest my-native \ + --frontend native-nativewind \ + --backend hono \ + --database sqlite \ + --orm drizzle \ + --auth + ``` + + + ```bash + pnpm create better-t-stack@latest my-native \ + --frontend native-nativewind \ + --backend hono \ + --database sqlite \ + --orm drizzle \ + --auth + ``` + + + ```bash + npx create-better-t-stack@latest my-native \ + --frontend native-nativewind \ + --backend hono \ + --database sqlite \ + --orm drizzle \ + --auth + ``` + + ### Empty Monorepo -```bash -bun create better-t-stack@latest my-workspace \ - --frontend none \ - --backend none -``` + + + ```bash + bun create better-t-stack@latest my-workspace \ + --frontend none \ + --backend none + ``` + + + ```bash + pnpm create better-t-stack@latest my-workspace \ + --frontend none \ + --backend none + ``` + + + ```bash + npx create-better-t-stack@latest my-workspace \ + --frontend none \ + --backend none + ``` + + ## Flags Cheat Sheet