create-better-t-stack 3.35.3 → 3.36.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -68,8 +68,8 @@ Options:
68
68
  --install Install dependencies
69
69
  --no-install Skip installing dependencies
70
70
  --db-setup <setup> Database setup (turso, d1, neon, supabase, prisma-postgres, planetscale, mongodb-atlas, docker, none)
71
- --web-deploy <setup> Web deployment (cloudflare, docker, none)
72
- --server-deploy <setup> Server deployment (cloudflare, docker, none)
71
+ --web-deploy <setup> Web deployment (cloudflare, docker, vercel, none)
72
+ --server-deploy <setup> Server deployment (cloudflare, docker, vercel, none)
73
73
  --backend <framework> Backend framework (hono, express, fastify, elysia, convex, self, none)
74
74
  --runtime <runtime> Runtime (bun, node, workers, none)
75
75
  --api <type> API type (trpc, orpc, none)
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { _ as types_exports, i as SchemaNameSchema, l as create, m as getSchemaResult, s as add, u as createBtsCli, v as getLatestCLIVersion } from "./src-DR1L7L2P.mjs";
2
+ import { _ as types_exports, i as SchemaNameSchema, l as create, m as getSchemaResult, s as add, u as createBtsCli, v as getLatestCLIVersion } from "./src-CAiTgv6S.mjs";
3
3
  import z from "zod";
4
4
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
5
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
package/dist/index.d.mts CHANGED
@@ -184,8 +184,8 @@ declare const router: _$_trpc_server0.TRPCBuiltRouter<{
184
184
  backend?: "none" | "hono" | "express" | "fastify" | "elysia" | "convex" | "self" | undefined;
185
185
  runtime?: "none" | "bun" | "node" | "workers" | undefined;
186
186
  api?: "none" | "trpc" | "orpc" | undefined;
187
- webDeploy?: "none" | "docker" | "cloudflare" | undefined;
188
- serverDeploy?: "none" | "docker" | "cloudflare" | undefined;
187
+ webDeploy?: "none" | "docker" | "cloudflare" | "vercel" | undefined;
188
+ serverDeploy?: "none" | "docker" | "cloudflare" | "vercel" | undefined;
189
189
  directoryConflict?: "merge" | "overwrite" | "increment" | "error" | undefined;
190
190
  renderTitle?: boolean | undefined;
191
191
  disableAnalytics?: boolean | undefined;
@@ -249,7 +249,7 @@ declare const router: _$_trpc_server0.TRPCBuiltRouter<{
249
249
  ultracite?: {
250
250
  linter?: "biome" | "oxlint" | "eslint" | undefined;
251
251
  editors?: ("void" | "antigravity" | "cursor" | "vscode" | "zed" | "windsurf" | "trae" | "codebuddy" | "bob" | "kiro")[] | undefined;
252
- agents?: ("cline" | "codex" | "opencode" | "goose" | "amp" | "pi" | "qoder" | "droid" | "zencoder" | "mcpjam" | "bob" | "universal" | "claude" | "jules" | "replit" | "devin" | "lovable" | "ona" | "openclaw" | "continue" | "snowflake-cortex" | "deepagents" | "kimi-cli" | "mux" | "adal" | "copilot" | "aider" | "firebase-studio" | "open-hands" | "gemini" | "junie" | "augmentcode" | "kilo-code" | "roo-code" | "warp" | "crush" | "qwen" | "amazon-q-cli" | "firebender" | "cursor-cli" | "mistral-vibe" | "vercel")[] | undefined;
252
+ agents?: ("vercel" | "cline" | "codex" | "opencode" | "goose" | "amp" | "pi" | "qoder" | "droid" | "zencoder" | "mcpjam" | "bob" | "universal" | "claude" | "jules" | "replit" | "devin" | "lovable" | "ona" | "openclaw" | "continue" | "snowflake-cortex" | "deepagents" | "kimi-cli" | "mux" | "adal" | "copilot" | "aider" | "firebase-studio" | "open-hands" | "gemini" | "junie" | "augmentcode" | "kilo-code" | "roo-code" | "warp" | "crush" | "qwen" | "amazon-q-cli" | "firebender" | "cursor-cli" | "mistral-vibe")[] | undefined;
253
253
  hooks?: ("cursor" | "windsurf" | "codebuddy" | "claude" | "copilot")[] | undefined;
254
254
  } | undefined;
255
255
  } | undefined;
@@ -283,8 +283,8 @@ declare const router: _$_trpc_server0.TRPCBuiltRouter<{
283
283
  backend?: "none" | "hono" | "express" | "fastify" | "elysia" | "convex" | "self" | undefined;
284
284
  runtime?: "none" | "bun" | "node" | "workers" | undefined;
285
285
  api?: "none" | "trpc" | "orpc" | undefined;
286
- webDeploy?: "none" | "docker" | "cloudflare" | undefined;
287
- serverDeploy?: "none" | "docker" | "cloudflare" | undefined;
286
+ webDeploy?: "none" | "docker" | "cloudflare" | "vercel" | undefined;
287
+ serverDeploy?: "none" | "docker" | "cloudflare" | "vercel" | undefined;
288
288
  directoryConflict?: "merge" | "overwrite" | "increment" | "error" | undefined;
289
289
  renderTitle?: boolean | undefined;
290
290
  disableAnalytics?: boolean | undefined;
@@ -359,12 +359,12 @@ declare const router: _$_trpc_server0.TRPCBuiltRouter<{
359
359
  ultracite?: {
360
360
  linter?: "biome" | "oxlint" | "eslint" | undefined;
361
361
  editors?: ("void" | "antigravity" | "cursor" | "vscode" | "zed" | "windsurf" | "trae" | "codebuddy" | "bob" | "kiro")[] | undefined;
362
- agents?: ("cline" | "codex" | "opencode" | "goose" | "amp" | "pi" | "qoder" | "droid" | "zencoder" | "mcpjam" | "bob" | "universal" | "claude" | "jules" | "replit" | "devin" | "lovable" | "ona" | "openclaw" | "continue" | "snowflake-cortex" | "deepagents" | "kimi-cli" | "mux" | "adal" | "copilot" | "aider" | "firebase-studio" | "open-hands" | "gemini" | "junie" | "augmentcode" | "kilo-code" | "roo-code" | "warp" | "crush" | "qwen" | "amazon-q-cli" | "firebender" | "cursor-cli" | "mistral-vibe" | "vercel")[] | undefined;
362
+ agents?: ("vercel" | "cline" | "codex" | "opencode" | "goose" | "amp" | "pi" | "qoder" | "droid" | "zencoder" | "mcpjam" | "bob" | "universal" | "claude" | "jules" | "replit" | "devin" | "lovable" | "ona" | "openclaw" | "continue" | "snowflake-cortex" | "deepagents" | "kimi-cli" | "mux" | "adal" | "copilot" | "aider" | "firebase-studio" | "open-hands" | "gemini" | "junie" | "augmentcode" | "kilo-code" | "roo-code" | "warp" | "crush" | "qwen" | "amazon-q-cli" | "firebender" | "cursor-cli" | "mistral-vibe")[] | undefined;
363
363
  hooks?: ("cursor" | "windsurf" | "codebuddy" | "claude" | "copilot")[] | undefined;
364
364
  } | undefined;
365
365
  } | undefined;
366
- webDeploy?: "none" | "docker" | "cloudflare" | undefined;
367
- serverDeploy?: "none" | "docker" | "cloudflare" | undefined;
366
+ webDeploy?: "none" | "docker" | "cloudflare" | "vercel" | undefined;
367
+ serverDeploy?: "none" | "docker" | "cloudflare" | "vercel" | undefined;
368
368
  projectDir?: string | undefined;
369
369
  install?: boolean | undefined;
370
370
  packageManager?: "bun" | "npm" | "pnpm" | undefined;
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { C as ProjectCreationError, S as DirectoryConflictError, T as ValidationError, a as TEMPLATE_COUNT, b as CompatibilityError, c as builder, d as createVirtual, f as docs, g as sponsors, h as router, i as SchemaNameSchema, l as create, m as getSchemaResult, n as GeneratorError, o as VirtualFileSystem, p as generate, r as Result, s as add, t as EMBEDDED_TEMPLATES, u as createBtsCli, w as UserCancelledError, x as DatabaseSetupError, y as CLIError } from "./src-DR1L7L2P.mjs";
2
+ import { C as ProjectCreationError, S as DirectoryConflictError, T as ValidationError, a as TEMPLATE_COUNT, b as CompatibilityError, c as builder, d as createVirtual, f as docs, g as sponsors, h as router, i as SchemaNameSchema, l as create, m as getSchemaResult, n as GeneratorError, o as VirtualFileSystem, p as generate, r as Result, s as add, t as EMBEDDED_TEMPLATES, u as createBtsCli, w as UserCancelledError, x as DatabaseSetupError, y as CLIError } from "./src-CAiTgv6S.mjs";
3
3
  export { CLIError, CompatibilityError, DatabaseSetupError, DirectoryConflictError, EMBEDDED_TEMPLATES, GeneratorError, ProjectCreationError, Result, SchemaNameSchema, TEMPLATE_COUNT, UserCancelledError, ValidationError, VirtualFileSystem, add, builder, create, createBtsCli, createVirtual, docs, generate, getSchemaResult, router, sponsors };
@@ -883,10 +883,17 @@ function validateDockerServerDeploy(serverDeploy, backend, runtime) {
883
883
  if (runtime === "workers") return validationErr$1("'--server-deploy docker' is not compatible with '--runtime workers'. Use '--runtime bun' or '--runtime node', or choose '--server-deploy cloudflare'.");
884
884
  return Result.ok(void 0);
885
885
  }
886
+ function validateVercelServerDeploy(serverDeploy, backend, runtime) {
887
+ if (serverDeploy !== "vercel") return Result.ok(void 0);
888
+ if (backend === "convex" || backend === "self") return validationErr$1("'--server-deploy vercel' requires a separate server backend (hono, express, fastify, elysia). For a fullstack 'self' backend, use '--web-deploy vercel' instead.");
889
+ if (runtime === "workers") return validationErr$1("'--server-deploy vercel' is not compatible with '--runtime workers'. Use '--runtime bun' or '--runtime node', or choose '--server-deploy cloudflare'.");
890
+ return Result.ok(void 0);
891
+ }
886
892
  const DOCKER_SERVER_OUTPUT_FRONTENDS = [
887
893
  "next",
888
894
  "svelte",
889
- "astro"
895
+ "astro",
896
+ "react-router"
890
897
  ];
891
898
  function validateDockerWebDeployDesktopAddons(webDeploy, addons, frontend, backend, auth) {
892
899
  if (webDeploy !== "docker" || !addons || !frontend) return Result.ok(void 0);
@@ -895,13 +902,17 @@ function validateDockerWebDeployDesktopAddons(webDeploy, addons, frontend, backe
895
902
  const affected = frontend.find((f) => DOCKER_SERVER_OUTPUT_FRONTENDS.includes(f));
896
903
  if (!affected) return Result.ok(void 0);
897
904
  if (affected === "next" && !desktopAddons.includes("tauri") && backend === "convex" && auth === "better-auth") return Result.ok(void 0);
898
- return validationErr$1(`'--web-deploy docker' is not compatible with the ${desktopAddons.join(", ")} addon on '${affected}' because desktop addons switch the web build to a static export, which the docker image cannot serve. Remove the addon or use a static-serving frontend (tanstack-router, react-router, solid).`);
905
+ return validationErr$1(`'--web-deploy docker' is not compatible with the ${desktopAddons.join(", ")} addon on '${affected}' because desktop addons switch the web build to a static export, which the docker image cannot serve. Remove the addon or use a static-serving frontend (tanstack-router, solid).`);
899
906
  }
900
907
  function validateAddonCompatibility(addon, frontend, auth, backend, runtime) {
901
908
  if (addon === "evlog" && !supportsEvlogAddon(frontend, backend, runtime)) return {
902
909
  isCompatible: false,
903
910
  reason: evlogCompatibilityMessage
904
911
  };
912
+ if (STATIC_DESKTOP_ADDONS.includes(addon) && auth === "clerk" && frontend.includes("react-router")) return {
913
+ isCompatible: false,
914
+ reason: `${addon} addon forces React Router into a static export, but Clerk on React Router requires SSR middleware. Remove the addon or use a different auth/frontend.`
915
+ };
905
916
  if (backend === "self" && STATIC_DESKTOP_ADDONS.includes(addon)) return {
906
917
  isCompatible: false,
907
918
  reason: `${addon} addon requires a separate backend or no backend because backend 'self' emits server routes that cannot be bundled as static desktop assets.`
@@ -4694,6 +4705,7 @@ function validateFullConfig(config, providedFlags, options) {
4694
4705
  yield* validateApiConstraints(config, options);
4695
4706
  yield* validateServerDeployRequiresBackend(config.serverDeploy, config.backend);
4696
4707
  yield* validateDockerServerDeploy(config.serverDeploy, config.backend, config.runtime);
4708
+ yield* validateVercelServerDeploy(config.serverDeploy, config.backend, config.runtime);
4697
4709
  yield* validateDockerWebDeployDesktopAddons(config.webDeploy, config.addons, config.frontend, config.backend, config.auth);
4698
4710
  yield* validateSelfBackendCompatibility(providedFlags, options, config);
4699
4711
  yield* validateWorkersCompatibility(providedFlags, options, config);
@@ -4851,6 +4863,10 @@ function getDeploymentDisplay$1(deployment) {
4851
4863
  label: "Docker",
4852
4864
  hint: "Self-host with a Dockerfile and docker-compose.yml"
4853
4865
  };
4866
+ if (deployment === "vercel") return {
4867
+ label: "Vercel",
4868
+ hint: "Deploy to Vercel with Services"
4869
+ };
4854
4870
  return {
4855
4871
  label: deployment,
4856
4872
  hint: `Add ${deployment} deployment`
@@ -4861,7 +4877,11 @@ async function getServerDeploymentChoice(deployment, runtime, backend, _webDeplo
4861
4877
  if (!backend || !SERVER_APP_BACKENDS.includes(backend)) return "none";
4862
4878
  if (runtime === "workers") return "cloudflare";
4863
4879
  if (runtime !== "bun" && runtime !== "node") return "none";
4864
- const options = ["docker", "none"].map((deploy) => {
4880
+ const options = [
4881
+ "docker",
4882
+ "vercel",
4883
+ "none"
4884
+ ].map((deploy) => {
4865
4885
  const { label, hint } = deploy === "none" ? {
4866
4886
  label: "None",
4867
4887
  hint: "Skip deployment setup"
@@ -4894,6 +4914,10 @@ function getDeploymentDisplay(deployment) {
4894
4914
  label: "Docker",
4895
4915
  hint: "Self-host with a Dockerfile and docker-compose.yml"
4896
4916
  };
4917
+ if (deployment === "vercel") return {
4918
+ label: "Vercel",
4919
+ hint: "Deploy to Vercel with Services"
4920
+ };
4897
4921
  return {
4898
4922
  label: deployment,
4899
4923
  hint: `Add ${deployment} deployment`
@@ -4906,6 +4930,7 @@ async function getDeploymentChoice(deployment, _runtime, backend, frontend = [],
4906
4930
  const options = [
4907
4931
  "cloudflare",
4908
4932
  "docker",
4933
+ "vercel",
4909
4934
  "none"
4910
4935
  ].map((deploy) => {
4911
4936
  const { label, hint } = getDeploymentDisplay(deploy);
@@ -6962,11 +6987,11 @@ async function displayPostInstallInstructions(config) {
6962
6987
  if (vitePlusNativeHooksInstructions) output += `\n${vitePlusNativeHooksInstructions.trim()}\n`;
6963
6988
  if (lintingInstructions) output += `\n${lintingInstructions.trim()}\n`;
6964
6989
  if (pwaInstructions) output += `\n${pwaInstructions.trim()}\n`;
6965
- if (alchemyDeployInstructions) output += `\n${alchemyDeployInstructions.trim()}\n`;
6966
6990
  if (starlightInstructions) output += `\n${starlightInstructions.trim()}\n`;
6967
6991
  if (clerkInstructions) output += `\n${clerkInstructions.trim()}\n`;
6968
6992
  if (betterAuthConvexInstructions) output += `\n${betterAuthConvexInstructions.trim()}\n`;
6969
6993
  if (polarInstructions) output += `\n${polarInstructions.trim()}\n`;
6994
+ if (alchemyDeployInstructions) output += `\n${alchemyDeployInstructions.trim()}\n`;
6970
6995
  if (noOrmWarning) output += `\n${noOrmWarning.trim()}\n`;
6971
6996
  if (bunWebNativeWarning) output += `\n${bunWebNativeWarning.trim()}\n`;
6972
6997
  const sponsorsResult = await fetchSponsorsQuietly();
@@ -7133,13 +7158,25 @@ function getPolarInstructions(backend, packageManager) {
7133
7158
  function getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy, backend) {
7134
7159
  const instructions = [];
7135
7160
  const isBackendSelf = backend === "self";
7136
- if (webDeploy === "cloudflare" && serverDeploy !== "cloudflare" && !isBackendSelf) instructions.push(`${pc.bold("Deploy web with Cloudflare (Alchemy):")}\n${pc.cyan("•")} Dev: ${`${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`${runCmd} destroy`}`);
7137
- else if (serverDeploy === "cloudflare" && webDeploy !== "cloudflare" && !isBackendSelf) instructions.push(`${pc.bold("Deploy server with Cloudflare (Alchemy):")}\n${pc.cyan("•")} Dev: ${`${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`${runCmd} destroy`}`);
7138
- else if (webDeploy === "cloudflare" && (serverDeploy === "cloudflare" || isBackendSelf)) instructions.push(`${pc.bold("Deploy with Cloudflare (Alchemy):")}\n${pc.cyan("•")} Dev: ${`${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`${runCmd} destroy`}`);
7161
+ if (webDeploy === "cloudflare" && serverDeploy !== "cloudflare" && !isBackendSelf) {
7162
+ const cfDeploy = serverDeploy === "vercel" ? "deploy:web" : "deploy";
7163
+ instructions.push(`${pc.bold("Deploy web with Cloudflare (Alchemy):")}\n${pc.cyan("•")} Dev: ${`${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`${runCmd} ${cfDeploy}`}\n${pc.cyan("•")} Destroy: ${`${runCmd} destroy`}`);
7164
+ } else if (serverDeploy === "cloudflare" && webDeploy !== "cloudflare" && !isBackendSelf) {
7165
+ const cfDeploy = webDeploy === "vercel" ? "deploy:server" : "deploy";
7166
+ instructions.push(`${pc.bold("Deploy server with Cloudflare (Alchemy):")}\n${pc.cyan("•")} Dev: ${`${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`${runCmd} ${cfDeploy}`}\n${pc.cyan("•")} Destroy: ${`${runCmd} destroy`}`);
7167
+ } else if (webDeploy === "cloudflare" && (serverDeploy === "cloudflare" || isBackendSelf)) instructions.push(`${pc.bold("Deploy with Cloudflare (Alchemy):")}\n${pc.cyan("•")} Dev: ${`${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`${runCmd} destroy`}`);
7139
7168
  if (webDeploy === "docker" || serverDeploy === "docker") {
7140
7169
  const dockerTargets = webDeploy === "docker" && serverDeploy === "docker" ? "web + server" : webDeploy === "docker" ? "web" : "server";
7141
7170
  instructions.push(`${pc.bold(`Deploy ${dockerTargets} with Docker Compose:`)}\n${pc.cyan("•")} Start: ${`${runCmd} docker:up`}\n${pc.cyan("•")} Logs: ${`${runCmd} docker:logs`}\n${pc.cyan("•")} Stop: ${`${runCmd} docker:down`}\n${pc.cyan("•")} Config: docker-compose.yml`);
7142
7171
  }
7172
+ if (webDeploy === "vercel" || serverDeploy === "vercel") {
7173
+ const mixedWithCloudflare = webDeploy === "cloudflare" || serverDeploy === "cloudflare";
7174
+ const vercelSetupScript = "deploy:setup";
7175
+ const vercelEnvScript = "env:production";
7176
+ const vercelDeployScript = mixedWithCloudflare ? webDeploy === "vercel" ? "deploy:web:prod" : "deploy:server:prod" : "deploy:prod";
7177
+ const vercelTargets = webDeploy === "vercel" && (serverDeploy === "vercel" || isBackendSelf) ? "web + server" : webDeploy === "vercel" ? "web" : "server";
7178
+ instructions.push(`${pc.bold(`Deploy ${vercelTargets} with Vercel Services:`)}\n${pc.cyan("•")} Link project: ${`${runCmd} ${vercelSetupScript}`}\n${pc.cyan("•")} Sync env (before first deploy): ${`${runCmd} ${vercelEnvScript}`}\n${pc.cyan("•")} Deploy: ${`${runCmd} ${vercelDeployScript}`}\n${pc.cyan("•")} Guide: https://www.better-t-stack.dev/docs/guides/vercel`);
7179
+ }
7143
7180
  return instructions.length ? `\n${instructions.join("\n")}` : "";
7144
7181
  }
7145
7182
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-better-t-stack",
3
- "version": "3.35.3",
3
+ "version": "3.36.1",
4
4
  "description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
5
5
  "keywords": [
6
6
  "better-auth",
@@ -69,8 +69,8 @@
69
69
  "prepublishOnly": "npm run build"
70
70
  },
71
71
  "dependencies": {
72
- "@better-t-stack/template-generator": "^3.35.3",
73
- "@better-t-stack/types": "^3.35.3",
72
+ "@better-t-stack/template-generator": "^3.36.1",
73
+ "@better-t-stack/types": "^3.36.1",
74
74
  "@clack/core": "^1.4.1",
75
75
  "@clack/prompts": "^1.5.1",
76
76
  "@modelcontextprotocol/sdk": "1.29.0",