create-better-t-stack 2.36.3 → 2.37.0

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/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { createBtsCli } from "./src-CN1zi2A-.js";
2
+ import { createBtsCli } from "./src-CGVrE3la.js";
3
3
 
4
4
  //#region src/cli.ts
5
5
  createBtsCli().run();
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { builder, createBtsCli, docs, init, router, sponsors } from "./src-CN1zi2A-.js";
2
+ import { builder, createBtsCli, docs, init, router, sponsors } from "./src-CGVrE3la.js";
3
3
 
4
4
  export { builder, createBtsCli, docs, init, router, sponsors };
@@ -129,7 +129,7 @@ const dependencyVersionMap = {
129
129
  "nitro-cloudflare-dev": "^0.2.2",
130
130
  "@sveltejs/adapter-cloudflare": "^7.2.1",
131
131
  "@cloudflare/workers-types": "^4.20250822.0",
132
- alchemy: "^0.62.1",
132
+ alchemy: "^0.63.0",
133
133
  nitropack: "^2.12.4",
134
134
  dotenv: "^17.2.1"
135
135
  };
@@ -592,7 +592,7 @@ function validateAlchemyCompatibility(webDeploy, serverDeploy, frontends = []) {
592
592
  const isAlchemyWebDeploy = webDeploy === "alchemy";
593
593
  const isAlchemyServerDeploy = serverDeploy === "alchemy";
594
594
  if (isAlchemyWebDeploy || isAlchemyServerDeploy) {
595
- const incompatibleFrontends = frontends.filter((f) => f === "next" || f === "react-router");
595
+ const incompatibleFrontends = frontends.filter((f) => f === "next");
596
596
  if (incompatibleFrontends.length > 0) {
597
597
  const deployType = isAlchemyWebDeploy && isAlchemyServerDeploy ? "web and server deployment" : isAlchemyWebDeploy ? "web deployment" : "server deployment";
598
598
  exitWithError(`Alchemy ${deployType} is temporarily not compatible with ${incompatibleFrontends.join(" and ")} frontend(s). Please choose a different frontend or deployment option.`);
@@ -1152,7 +1152,7 @@ function getDeploymentDisplay(deployment) {
1152
1152
  async function getDeploymentChoice(deployment, _runtime, _backend, frontend = []) {
1153
1153
  if (deployment !== void 0) return deployment;
1154
1154
  if (!hasWebFrontend(frontend)) return "none";
1155
- const hasIncompatibleFrontend = frontend.some((f) => f === "next" || f === "react-router");
1155
+ const hasIncompatibleFrontend = frontend.some((f) => f === "next");
1156
1156
  const availableDeployments = hasIncompatibleFrontend ? ["wrangler", "none"] : [
1157
1157
  "wrangler",
1158
1158
  "alchemy",
@@ -1176,7 +1176,7 @@ async function getDeploymentChoice(deployment, _runtime, _backend, frontend = []
1176
1176
  }
1177
1177
  async function getDeploymentToAdd(frontend, existingDeployment) {
1178
1178
  if (!hasWebFrontend(frontend)) return "none";
1179
- const hasIncompatibleFrontend = frontend.some((f) => f === "next" || f === "react-router");
1179
+ const hasIncompatibleFrontend = frontend.some((f) => f === "next");
1180
1180
  const options = [];
1181
1181
  if (existingDeployment !== "wrangler") {
1182
1182
  const { label, hint } = getDeploymentDisplay("wrangler");
@@ -2350,10 +2350,7 @@ async function setupDeploymentTemplates(projectDir, context) {
2350
2350
  if (await fs.pathExists(alchemyTemplateSrc)) {
2351
2351
  await processAndCopyFiles("alchemy.run.ts.hbs", alchemyTemplateSrc, projectDir, context);
2352
2352
  const serverAppDir = path.join(projectDir, "apps/server");
2353
- if (await fs.pathExists(serverAppDir)) {
2354
- await processAndCopyFiles("env.d.ts.hbs", alchemyTemplateSrc, serverAppDir, context);
2355
- await processAndCopyFiles("wrangler.jsonc.hbs", alchemyTemplateSrc, serverAppDir, context);
2356
- }
2353
+ if (await fs.pathExists(serverAppDir)) await processAndCopyFiles("env.d.ts.hbs", alchemyTemplateSrc, serverAppDir, context);
2357
2354
  }
2358
2355
  } else {
2359
2356
  if (context.webDeploy === "alchemy") {
@@ -2367,7 +2364,6 @@ async function setupDeploymentTemplates(projectDir, context) {
2367
2364
  if (await fs.pathExists(alchemyTemplateSrc) && await fs.pathExists(serverAppDir)) {
2368
2365
  await processAndCopyFiles("alchemy.run.ts.hbs", alchemyTemplateSrc, serverAppDir, context);
2369
2366
  await processAndCopyFiles("env.d.ts.hbs", alchemyTemplateSrc, serverAppDir, context);
2370
- await processAndCopyFiles("wrangler.jsonc.hbs", alchemyTemplateSrc, serverAppDir, context);
2371
2367
  }
2372
2368
  }
2373
2369
  }
@@ -3000,11 +2996,9 @@ async function setupAlchemyServerDeploy(serverDir, _packageManager) {
3000
2996
  const packageJson = await fs.readJson(packageJsonPath);
3001
2997
  packageJson.scripts = {
3002
2998
  ...packageJson.scripts,
3003
- dev: "wrangler dev --port=3000",
3004
- build: "wrangler deploy --dry-run",
2999
+ dev: "alchemy dev",
3005
3000
  deploy: "alchemy deploy",
3006
- destroy: "alchemy destroy",
3007
- "alchemy:dev": "alchemy dev"
3001
+ destroy: "alchemy destroy"
3008
3002
  };
3009
3003
  await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
3010
3004
  }
@@ -3012,7 +3006,7 @@ async function setupAlchemyServerDeploy(serverDir, _packageManager) {
3012
3006
 
3013
3007
  //#endregion
3014
3008
  //#region src/helpers/deployment/alchemy/alchemy-next-setup.ts
3015
- async function setupNextAlchemyDeploy(projectDir, _packageManager) {
3009
+ async function setupNextAlchemyDeploy(projectDir, _packageManager, options) {
3016
3010
  const webAppDir = path.join(projectDir, "apps/web");
3017
3011
  if (!await fs.pathExists(webAppDir)) return;
3018
3012
  await addPackageDependency({
@@ -3022,11 +3016,11 @@ async function setupNextAlchemyDeploy(projectDir, _packageManager) {
3022
3016
  const pkgPath = path.join(webAppDir, "package.json");
3023
3017
  if (await fs.pathExists(pkgPath)) {
3024
3018
  const pkg = await fs.readJson(pkgPath);
3025
- pkg.scripts = {
3019
+ if (!options?.skipAppScripts) pkg.scripts = {
3026
3020
  ...pkg.scripts,
3027
3021
  deploy: "alchemy deploy",
3028
3022
  destroy: "alchemy destroy",
3029
- "alchemy:dev": "alchemy dev"
3023
+ dev: "alchemy dev"
3030
3024
  };
3031
3025
  await fs.writeJson(pkgPath, pkg, { spaces: 2 });
3032
3026
  }
@@ -3034,7 +3028,7 @@ async function setupNextAlchemyDeploy(projectDir, _packageManager) {
3034
3028
 
3035
3029
  //#endregion
3036
3030
  //#region src/helpers/deployment/alchemy/alchemy-nuxt-setup.ts
3037
- async function setupNuxtAlchemyDeploy(projectDir, _packageManager) {
3031
+ async function setupNuxtAlchemyDeploy(projectDir, _packageManager, options) {
3038
3032
  const webAppDir = path.join(projectDir, "apps/web");
3039
3033
  if (!await fs.pathExists(webAppDir)) return;
3040
3034
  await addPackageDependency({
@@ -3048,11 +3042,11 @@ async function setupNuxtAlchemyDeploy(projectDir, _packageManager) {
3048
3042
  const pkgPath = path.join(webAppDir, "package.json");
3049
3043
  if (await fs.pathExists(pkgPath)) {
3050
3044
  const pkg = await fs.readJson(pkgPath);
3051
- pkg.scripts = {
3045
+ if (!options?.skipAppScripts) pkg.scripts = {
3052
3046
  ...pkg.scripts,
3053
3047
  deploy: "alchemy deploy",
3054
3048
  destroy: "alchemy destroy",
3055
- "alchemy:dev": "alchemy dev"
3049
+ dev: "alchemy dev"
3056
3050
  };
3057
3051
  await fs.writeJson(pkgPath, pkg, { spaces: 2 });
3058
3052
  }
@@ -3102,112 +3096,29 @@ async function setupNuxtAlchemyDeploy(projectDir, _packageManager) {
3102
3096
 
3103
3097
  //#endregion
3104
3098
  //#region src/helpers/deployment/alchemy/alchemy-react-router-setup.ts
3105
- async function setupReactRouterAlchemyDeploy(projectDir, _packageManager) {
3099
+ async function setupReactRouterAlchemyDeploy(projectDir, _packageManager, options) {
3106
3100
  const webAppDir = path.join(projectDir, "apps/web");
3107
3101
  if (!await fs.pathExists(webAppDir)) return;
3108
3102
  await addPackageDependency({
3109
- devDependencies: [
3110
- "alchemy",
3111
- "@cloudflare/vite-plugin",
3112
- "dotenv"
3113
- ],
3103
+ devDependencies: ["alchemy", "dotenv"],
3114
3104
  projectDir: webAppDir
3115
3105
  });
3116
3106
  const pkgPath = path.join(webAppDir, "package.json");
3117
3107
  if (await fs.pathExists(pkgPath)) {
3118
3108
  const pkg = await fs.readJson(pkgPath);
3119
- pkg.scripts = {
3109
+ if (!options?.skipAppScripts) pkg.scripts = {
3120
3110
  ...pkg.scripts,
3121
3111
  deploy: "alchemy deploy",
3122
3112
  destroy: "alchemy destroy",
3123
- "alchemy:dev": "alchemy dev"
3113
+ dev: "alchemy dev"
3124
3114
  };
3125
3115
  await fs.writeJson(pkgPath, pkg, { spaces: 2 });
3126
3116
  }
3127
- const viteConfigPath = path.join(webAppDir, "vite.config.ts");
3128
- if (await fs.pathExists(viteConfigPath)) try {
3129
- const project = new Project({ manipulationSettings: {
3130
- indentationText: IndentationText.TwoSpaces,
3131
- quoteKind: QuoteKind.Double
3132
- } });
3133
- project.addSourceFileAtPath(viteConfigPath);
3134
- const sourceFile = project.getSourceFileOrThrow(viteConfigPath);
3135
- const alchemyImport = sourceFile.getImportDeclaration("alchemy/cloudflare/react-router");
3136
- if (!alchemyImport) sourceFile.addImportDeclaration({
3137
- moduleSpecifier: "alchemy/cloudflare/react-router",
3138
- defaultImport: "alchemy"
3139
- });
3140
- const exportAssignment = sourceFile.getExportAssignment((d) => !d.isExportEquals());
3141
- if (!exportAssignment) return;
3142
- const defineConfigCall = exportAssignment.getExpression();
3143
- if (!Node.isCallExpression(defineConfigCall) || defineConfigCall.getExpression().getText() !== "defineConfig") return;
3144
- let configObject = defineConfigCall.getArguments()[0];
3145
- if (!configObject) configObject = defineConfigCall.addArgument("{}");
3146
- if (Node.isObjectLiteralExpression(configObject)) {
3147
- const pluginsProperty = configObject.getProperty("plugins");
3148
- if (pluginsProperty && Node.isPropertyAssignment(pluginsProperty)) {
3149
- const initializer = pluginsProperty.getInitializer();
3150
- if (Node.isArrayLiteralExpression(initializer)) {
3151
- const hasCloudflarePlugin = initializer.getElements().some((el) => el.getText().includes("cloudflare("));
3152
- if (!hasCloudflarePlugin) initializer.addElement("alchemy()");
3153
- }
3154
- } else if (!pluginsProperty) configObject.addPropertyAssignment({
3155
- name: "plugins",
3156
- initializer: "[alchemy()]"
3157
- });
3158
- }
3159
- await project.save();
3160
- } catch (error) {
3161
- console.warn("Failed to update vite.config.ts:", error);
3162
- }
3163
- const reactRouterConfigPath = path.join(webAppDir, "react-router.config.ts");
3164
- if (await fs.pathExists(reactRouterConfigPath)) try {
3165
- const project = new Project({ manipulationSettings: {
3166
- indentationText: IndentationText.TwoSpaces,
3167
- quoteKind: QuoteKind.Double
3168
- } });
3169
- project.addSourceFileAtPath(reactRouterConfigPath);
3170
- const sourceFile = project.getSourceFileOrThrow(reactRouterConfigPath);
3171
- const exportAssignment = sourceFile.getExportAssignment((d) => !d.isExportEquals());
3172
- if (!exportAssignment) return;
3173
- const configExpression = exportAssignment.getExpression();
3174
- let configObject;
3175
- if (Node.isObjectLiteralExpression(configExpression)) configObject = configExpression;
3176
- else if (Node.isSatisfiesExpression(configExpression)) {
3177
- const expression = configExpression.getExpression();
3178
- if (Node.isObjectLiteralExpression(expression)) configObject = expression;
3179
- }
3180
- if (!configObject || !Node.isObjectLiteralExpression(configObject)) return;
3181
- const futureProperty = configObject.getProperty("future");
3182
- if (!futureProperty) configObject.addPropertyAssignment({
3183
- name: "future",
3184
- initializer: `{
3185
- unstable_viteEnvironmentApi: true,
3186
- }`
3187
- });
3188
- else if (Node.isPropertyAssignment(futureProperty)) {
3189
- const futureInitializer = futureProperty.getInitializer();
3190
- if (Node.isObjectLiteralExpression(futureInitializer)) {
3191
- const viteEnvApiProp = futureInitializer.getProperty("unstable_viteEnvironmentApi");
3192
- if (!viteEnvApiProp) futureInitializer.addPropertyAssignment({
3193
- name: "unstable_viteEnvironmentApi",
3194
- initializer: "true"
3195
- });
3196
- else if (Node.isPropertyAssignment(viteEnvApiProp)) {
3197
- const value = viteEnvApiProp.getInitializer()?.getText();
3198
- if (value === "false") viteEnvApiProp.setInitializer("true");
3199
- }
3200
- }
3201
- }
3202
- await project.save();
3203
- } catch (error) {
3204
- console.warn("Failed to update react-router.config.ts:", error);
3205
- }
3206
3117
  }
3207
3118
 
3208
3119
  //#endregion
3209
3120
  //#region src/helpers/deployment/alchemy/alchemy-solid-setup.ts
3210
- async function setupSolidAlchemyDeploy(projectDir, _packageManager) {
3121
+ async function setupSolidAlchemyDeploy(projectDir, _packageManager, options) {
3211
3122
  const webAppDir = path.join(projectDir, "apps/web");
3212
3123
  if (!await fs.pathExists(webAppDir)) return;
3213
3124
  await addPackageDependency({
@@ -3217,11 +3128,11 @@ async function setupSolidAlchemyDeploy(projectDir, _packageManager) {
3217
3128
  const pkgPath = path.join(webAppDir, "package.json");
3218
3129
  if (await fs.pathExists(pkgPath)) {
3219
3130
  const pkg = await fs.readJson(pkgPath);
3220
- pkg.scripts = {
3131
+ if (!options?.skipAppScripts) pkg.scripts = {
3221
3132
  ...pkg.scripts,
3222
3133
  deploy: "alchemy deploy",
3223
3134
  destroy: "alchemy destroy",
3224
- "alchemy:dev": "alchemy dev"
3135
+ dev: "alchemy dev"
3225
3136
  };
3226
3137
  await fs.writeJson(pkgPath, pkg, { spaces: 2 });
3227
3138
  }
@@ -3229,7 +3140,7 @@ async function setupSolidAlchemyDeploy(projectDir, _packageManager) {
3229
3140
 
3230
3141
  //#endregion
3231
3142
  //#region src/helpers/deployment/alchemy/alchemy-svelte-setup.ts
3232
- async function setupSvelteAlchemyDeploy(projectDir, _packageManager) {
3143
+ async function setupSvelteAlchemyDeploy(projectDir, _packageManager, options) {
3233
3144
  const webAppDir = path.join(projectDir, "apps/web");
3234
3145
  if (!await fs.pathExists(webAppDir)) return;
3235
3146
  await addPackageDependency({
@@ -3243,11 +3154,11 @@ async function setupSvelteAlchemyDeploy(projectDir, _packageManager) {
3243
3154
  const pkgPath = path.join(webAppDir, "package.json");
3244
3155
  if (await fs.pathExists(pkgPath)) {
3245
3156
  const pkg = await fs.readJson(pkgPath);
3246
- pkg.scripts = {
3157
+ if (!options?.skipAppScripts) pkg.scripts = {
3247
3158
  ...pkg.scripts,
3248
3159
  deploy: "alchemy deploy",
3249
3160
  destroy: "alchemy destroy",
3250
- "alchemy:dev": "alchemy dev"
3161
+ dev: "alchemy dev"
3251
3162
  };
3252
3163
  await fs.writeJson(pkgPath, pkg, { spaces: 2 });
3253
3164
  }
@@ -3300,7 +3211,7 @@ function updateAdapterInConfig(configObject) {
3300
3211
 
3301
3212
  //#endregion
3302
3213
  //#region src/helpers/deployment/alchemy/alchemy-tanstack-router-setup.ts
3303
- async function setupTanStackRouterAlchemyDeploy(projectDir, _packageManager) {
3214
+ async function setupTanStackRouterAlchemyDeploy(projectDir, _packageManager, options) {
3304
3215
  const webAppDir = path.join(projectDir, "apps/web");
3305
3216
  if (!await fs.pathExists(webAppDir)) return;
3306
3217
  await addPackageDependency({
@@ -3310,11 +3221,11 @@ async function setupTanStackRouterAlchemyDeploy(projectDir, _packageManager) {
3310
3221
  const pkgPath = path.join(webAppDir, "package.json");
3311
3222
  if (await fs.pathExists(pkgPath)) {
3312
3223
  const pkg = await fs.readJson(pkgPath);
3313
- pkg.scripts = {
3224
+ if (!options?.skipAppScripts) pkg.scripts = {
3314
3225
  ...pkg.scripts,
3315
3226
  deploy: "alchemy deploy",
3316
3227
  destroy: "alchemy destroy",
3317
- "alchemy:dev": "alchemy dev"
3228
+ dev: "alchemy dev"
3318
3229
  };
3319
3230
  await fs.writeJson(pkgPath, pkg, { spaces: 2 });
3320
3231
  }
@@ -3322,7 +3233,7 @@ async function setupTanStackRouterAlchemyDeploy(projectDir, _packageManager) {
3322
3233
 
3323
3234
  //#endregion
3324
3235
  //#region src/helpers/deployment/alchemy/alchemy-tanstack-start-setup.ts
3325
- async function setupTanStackStartAlchemyDeploy(projectDir, _packageManager) {
3236
+ async function setupTanStackStartAlchemyDeploy(projectDir, _packageManager, options) {
3326
3237
  const webAppDir = path.join(projectDir, "apps/web");
3327
3238
  if (!await fs.pathExists(webAppDir)) return;
3328
3239
  await addPackageDependency({
@@ -3336,11 +3247,11 @@ async function setupTanStackStartAlchemyDeploy(projectDir, _packageManager) {
3336
3247
  const pkgPath = path.join(webAppDir, "package.json");
3337
3248
  if (await fs.pathExists(pkgPath)) {
3338
3249
  const pkg = await fs.readJson(pkgPath);
3339
- pkg.scripts = {
3250
+ if (!options?.skipAppScripts) pkg.scripts = {
3340
3251
  ...pkg.scripts,
3341
3252
  deploy: "alchemy deploy",
3342
3253
  destroy: "alchemy destroy",
3343
- "alchemy:dev": "alchemy dev"
3254
+ dev: "alchemy dev"
3344
3255
  };
3345
3256
  await fs.writeJson(pkgPath, pkg, { spaces: 2 });
3346
3257
  }
@@ -3456,7 +3367,7 @@ async function setupCombinedAlchemyDeploy(projectDir, packageManager, config) {
3456
3367
  ...pkg.scripts,
3457
3368
  deploy: "alchemy deploy",
3458
3369
  destroy: "alchemy destroy",
3459
- "alchemy:dev": "alchemy dev"
3370
+ dev: "alchemy dev"
3460
3371
  };
3461
3372
  await fs.writeJson(rootPkgPath, pkg, { spaces: 2 });
3462
3373
  }
@@ -3470,13 +3381,13 @@ async function setupCombinedAlchemyDeploy(projectDir, packageManager, config) {
3470
3381
  const isTanstackStart = frontend.includes("tanstack-start");
3471
3382
  const isReactRouter = frontend.includes("react-router");
3472
3383
  const isSolid = frontend.includes("solid");
3473
- if (isNext) await setupNextAlchemyDeploy(projectDir, packageManager);
3474
- else if (isNuxt) await setupNuxtAlchemyDeploy(projectDir, packageManager);
3475
- else if (isSvelte) await setupSvelteAlchemyDeploy(projectDir, packageManager);
3476
- else if (isTanstackStart) await setupTanStackStartAlchemyDeploy(projectDir, packageManager);
3477
- else if (isTanstackRouter) await setupTanStackRouterAlchemyDeploy(projectDir, packageManager);
3478
- else if (isReactRouter) await setupReactRouterAlchemyDeploy(projectDir, packageManager);
3479
- else if (isSolid) await setupSolidAlchemyDeploy(projectDir, packageManager);
3384
+ if (isNext) await setupNextAlchemyDeploy(projectDir, packageManager, { skipAppScripts: true });
3385
+ else if (isNuxt) await setupNuxtAlchemyDeploy(projectDir, packageManager, { skipAppScripts: true });
3386
+ else if (isSvelte) await setupSvelteAlchemyDeploy(projectDir, packageManager, { skipAppScripts: true });
3387
+ else if (isTanstackStart) await setupTanStackStartAlchemyDeploy(projectDir, packageManager, { skipAppScripts: true });
3388
+ else if (isTanstackRouter) await setupTanStackRouterAlchemyDeploy(projectDir, packageManager, { skipAppScripts: true });
3389
+ else if (isReactRouter) await setupReactRouterAlchemyDeploy(projectDir, packageManager, { skipAppScripts: true });
3390
+ else if (isSolid) await setupSolidAlchemyDeploy(projectDir, packageManager, { skipAppScripts: true });
3480
3391
  }
3481
3392
 
3482
3393
  //#endregion
@@ -5282,7 +5193,7 @@ async function createReadme(projectDir, options) {
5282
5193
  }
5283
5194
  }
5284
5195
  function generateReadmeContent(options) {
5285
- const { projectName, packageManager, database, auth, addons = [], orm = "drizzle", runtime = "bun", frontend = ["tanstack-router"], backend = "hono", api = "trpc" } = options;
5196
+ const { projectName, packageManager, database, auth, addons = [], orm = "drizzle", runtime = "bun", frontend = ["tanstack-router"], backend = "hono", api = "trpc", webDeploy, serverDeploy } = options;
5286
5197
  const isConvex = backend === "convex";
5287
5198
  const hasReactRouter = frontend.includes("react-router");
5288
5199
  const hasNative = frontend.includes("native-nativewind") || frontend.includes("native-unistyles");
@@ -5315,7 +5226,7 @@ This project uses Convex as a backend. You'll need to set up Convex before runni
5315
5226
  ${packageManagerRunCmd} dev:setup
5316
5227
  \`\`\`
5317
5228
 
5318
- Follow the prompts to create a new Convex project and connect it to your application.` : generateDatabaseSetup(database, auth, packageManagerRunCmd, orm, options.dbSetup)}
5229
+ Follow the prompts to create a new Convex project and connect it to your application.` : generateDatabaseSetup(database, auth, packageManagerRunCmd, orm, options.dbSetup, options.serverDeploy)}
5319
5230
 
5320
5231
  Then, run the development server:
5321
5232
 
@@ -5327,6 +5238,8 @@ ${generateRunningInstructions(frontend, backend, webPort, hasNative, isConvex)}
5327
5238
 
5328
5239
  ${addons.includes("pwa") && hasReactRouter ? "\n## PWA Support with React Router v7\n\nThere is a known compatibility issue between VitePWA and React Router v7.\nSee: https://github.com/vite-pwa/vite-plugin-pwa/issues/809\n" : ""}
5329
5240
 
5241
+ ${generateDeploymentCommands(packageManagerRunCmd, webDeploy, serverDeploy)}
5242
+
5330
5243
  ## Project Structure
5331
5244
 
5332
5245
  \`\`\`
@@ -5470,13 +5383,13 @@ function generateFeaturesList(database, auth, addons, orm, runtime, frontend, ba
5470
5383
  else if (addon === "turborepo") addonsList.push("- **Turborepo** - Optimized monorepo build system");
5471
5384
  return addonsList.join("\n");
5472
5385
  }
5473
- function generateDatabaseSetup(database, _auth, packageManagerRunCmd, orm, dbSetup) {
5386
+ function generateDatabaseSetup(database, _auth, packageManagerRunCmd, orm, dbSetup, serverDeploy) {
5474
5387
  if (database === "none") return "";
5475
5388
  let setup = "## Database Setup\n\n";
5476
5389
  if (database === "sqlite") setup += `This project uses SQLite${orm === "drizzle" ? " with Drizzle ORM" : orm === "prisma" ? " with Prisma" : ` with ${orm}`}.
5477
5390
 
5478
5391
  1. Start the local SQLite database:
5479
- ${dbSetup === "d1" ? "Local development for a Cloudflare D1 database will already be running as part of the `wrangler dev` command." : `\`\`\`bash
5392
+ ${dbSetup === "d1" ? serverDeploy === "alchemy" ? "D1 local development and migrations are handled automatically by Alchemy during dev and deploy." : "Local development for a Cloudflare D1 database will already be running as part of the `wrangler dev` command." : `\`\`\`bash
5480
5393
  cd apps/server && ${packageManagerRunCmd} db:local
5481
5394
  \`\`\`
5482
5395
  `}
@@ -5546,6 +5459,21 @@ function generateScriptsList(packageManagerRunCmd, database, orm, _auth, hasNati
5546
5459
  - \`cd apps/docs && ${packageManagerRunCmd} build\`: Build documentation site`;
5547
5460
  return scripts;
5548
5461
  }
5462
+ function generateDeploymentCommands(packageManagerRunCmd, webDeploy, serverDeploy) {
5463
+ const lines = [];
5464
+ if (webDeploy === "alchemy" || serverDeploy === "alchemy") {
5465
+ lines.push("## Deployment (Alchemy)");
5466
+ if (webDeploy === "alchemy" && serverDeploy !== "alchemy") lines.push(`- Web dev: cd apps/web && ${packageManagerRunCmd} dev`, `- Web deploy: cd apps/web && ${packageManagerRunCmd} deploy`, `- Web destroy: cd apps/web && ${packageManagerRunCmd} destroy`);
5467
+ if (serverDeploy === "alchemy" && webDeploy !== "alchemy") lines.push(`- Server dev: cd apps/server && ${packageManagerRunCmd} dev`, `- Server deploy: cd apps/server && ${packageManagerRunCmd} deploy`, `- Server destroy: cd apps/server && ${packageManagerRunCmd} destroy`);
5468
+ if (webDeploy === "alchemy" && serverDeploy === "alchemy") lines.push(`- Dev: ${packageManagerRunCmd} dev`, `- Deploy: ${packageManagerRunCmd} deploy`, `- Destroy: ${packageManagerRunCmd} destroy`);
5469
+ }
5470
+ if (webDeploy === "wrangler" || serverDeploy === "wrangler") {
5471
+ lines.push("\n## Deployment (Cloudflare Wrangler)");
5472
+ if (webDeploy === "wrangler") lines.push(`- Web deploy: cd apps/web && ${packageManagerRunCmd} deploy`);
5473
+ if (serverDeploy === "wrangler") lines.push(`- Server dev: cd apps/server && ${packageManagerRunCmd} dev`, `- Server deploy: cd apps/server && ${packageManagerRunCmd} deploy`);
5474
+ }
5475
+ return lines.length ? `\n${lines.join("\n")}\n` : "";
5476
+ }
5549
5477
 
5550
5478
  //#endregion
5551
5479
  //#region src/helpers/core/git.ts
@@ -5761,9 +5689,9 @@ function getWranglerDeployInstructions(runCmd, webDeploy, serverDeploy) {
5761
5689
  }
5762
5690
  function getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy) {
5763
5691
  const instructions = [];
5764
- if (webDeploy === "alchemy" && serverDeploy !== "alchemy") instructions.push(`${pc.bold("Deploy web with Alchemy:")}\n${pc.cyan("•")} Dev: ${`cd apps/web && ${runCmd} alchemy:dev`}\n${pc.cyan("•")} Deploy: ${`cd apps/web && ${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`cd apps/web && ${runCmd} destroy`}`);
5765
- else if (serverDeploy === "alchemy" && webDeploy !== "alchemy") instructions.push(`${pc.bold("Deploy server with Alchemy:")}\n${pc.cyan("•")} Dev: ${`cd apps/server && ${runCmd} alchemy:dev`}\n${pc.cyan("•")} Deploy: ${`cd apps/server && ${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`cd apps/server && ${runCmd} destroy`}`);
5766
- else if (webDeploy === "alchemy" && serverDeploy === "alchemy") instructions.push(`${pc.bold("Deploy with Alchemy:")}\n${pc.cyan("•")} Dev: ${`${runCmd} alchemy:dev`}\n${pc.cyan("•")} Deploy: ${`${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`${runCmd} destroy`}`);
5692
+ if (webDeploy === "alchemy" && serverDeploy !== "alchemy") instructions.push(`${pc.bold("Deploy web with Alchemy:")}\n${pc.cyan("•")} Dev: ${`cd apps/web && ${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`cd apps/web && ${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`cd apps/web && ${runCmd} destroy`}`);
5693
+ else if (serverDeploy === "alchemy" && webDeploy !== "alchemy") instructions.push(`${pc.bold("Deploy server with Alchemy:")}\n${pc.cyan("•")} Dev: ${`cd apps/server && ${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`cd apps/server && ${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`cd apps/server && ${runCmd} destroy`}`);
5694
+ else if (webDeploy === "alchemy" && serverDeploy === "alchemy") instructions.push(`${pc.bold("Deploy with Alchemy:")}\n${pc.cyan("•")} Dev: ${`${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`${runCmd} destroy`}`);
5767
5695
  return instructions.length ? `\n${instructions.join("\n")}` : "";
5768
5696
  }
5769
5697
 
@@ -5976,10 +5904,10 @@ async function createProject(options) {
5976
5904
  if (options.addons.length > 0 && options.addons[0] !== "none") await setupAddons(options);
5977
5905
  if (!isConvex && options.auth) await setupAuth(options);
5978
5906
  await handleExtras(projectDir, options);
5979
- await setupWebDeploy(options);
5980
- await setupServerDeploy(options);
5981
5907
  await setupEnvironmentVariables(options);
5982
5908
  await updatePackageConfigurations(projectDir, options);
5909
+ await setupWebDeploy(options);
5910
+ await setupServerDeploy(options);
5983
5911
  await createReadme(projectDir, options);
5984
5912
  await writeBtsConfig(options);
5985
5913
  await formatProjectWithBiome(projectDir);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-better-t-stack",
3
- "version": "2.36.3",
3
+ "version": "2.37.0",
4
4
  "description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -17,7 +17,7 @@ import { Vite } from "alchemy/cloudflare";
17
17
  {{/if}}
18
18
  {{/if}}
19
19
  {{#if (eq serverDeploy "alchemy")}}
20
- import { Worker, WranglerJson } from "alchemy/cloudflare";
20
+ import { Worker } from "alchemy/cloudflare";
21
21
  {{#if (eq dbSetup "d1")}}
22
22
  import { D1Database } from "alchemy/cloudflare";
23
23
  {{/if}}
@@ -44,7 +44,6 @@ await Exec("db-generate", {
44
44
  });
45
45
 
46
46
  const db = await D1Database("database", {
47
- name: `${app.name}-${app.stage}-db`,
48
47
  migrationsDir: "apps/server/src/db/migrations",
49
48
  });
50
49
  {{/if}}
@@ -53,7 +52,6 @@ const db = await D1Database("database", {
53
52
  {{#if (includes frontend "next")}}
54
53
  export const web = await Next("web", {
55
54
  {{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
56
- name: `${app.name}-${app.stage}-web`,
57
55
  bindings: {
58
56
  {{#if (eq backend "convex")}}
59
57
  NEXT_PUBLIC_CONVEX_URL: process.env.NEXT_PUBLIC_CONVEX_URL || "",
@@ -68,7 +66,6 @@ export const web = await Next("web", {
68
66
  {{else if (includes frontend "nuxt")}}
69
67
  export const web = await Nuxt("web", {
70
68
  {{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
71
- name: `${app.name}-${app.stage}-web`,
72
69
  bindings: {
73
70
  {{#if (eq backend "convex")}}
74
71
  NUXT_PUBLIC_CONVEX_URL: process.env.NUXT_PUBLIC_CONVEX_URL || "",
@@ -83,7 +80,6 @@ export const web = await Nuxt("web", {
83
80
  {{else if (includes frontend "svelte")}}
84
81
  export const web = await SvelteKit("web", {
85
82
  {{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
86
- name: `${app.name}-${app.stage}-web`,
87
83
  bindings: {
88
84
  {{#if (eq backend "convex")}}
89
85
  PUBLIC_CONVEX_URL: process.env.PUBLIC_CONVEX_URL || "",
@@ -98,7 +94,6 @@ export const web = await SvelteKit("web", {
98
94
  {{else if (includes frontend "tanstack-start")}}
99
95
  export const web = await TanStackStart("web", {
100
96
  {{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
101
- name: `${app.name}-${app.stage}-web`,
102
97
  bindings: {
103
98
  {{#if (eq backend "convex")}}
104
99
  VITE_CONVEX_URL: process.env.VITE_CONVEX_URL || "",
@@ -113,7 +108,6 @@ export const web = await TanStackStart("web", {
113
108
  {{else if (includes frontend "tanstack-router")}}
114
109
  export const web = await Vite("web", {
115
110
  {{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
116
- name: `${app.name}-${app.stage}-web`,
117
111
  assets: "dist",
118
112
  bindings: {
119
113
  {{#if (eq backend "convex")}}
@@ -129,7 +123,6 @@ export const web = await Vite("web", {
129
123
  {{else if (includes frontend "react-router")}}
130
124
  export const web = await ReactRouter("web", {
131
125
  {{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
132
- name: `${app.name}-${app.stage}-web`,
133
126
  bindings: {
134
127
  {{#if (eq backend "convex")}}
135
128
  VITE_CONVEX_URL: process.env.VITE_CONVEX_URL || "",
@@ -144,7 +137,6 @@ export const web = await ReactRouter("web", {
144
137
  {{else if (includes frontend "solid")}}
145
138
  export const web = await Vite("web", {
146
139
  {{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
147
- name: `${app.name}-${app.stage}-web`,
148
140
  assets: "dist",
149
141
  bindings: {
150
142
  {{#if (eq backend "convex")}}
@@ -163,7 +155,6 @@ export const web = await Vite("web", {
163
155
  {{#if (eq serverDeploy "alchemy")}}
164
156
  export const server = await Worker("server", {
165
157
  {{#if (eq webDeploy "alchemy")}}cwd: "apps/server",{{/if}}
166
- name: `${app.name}-${app.stage}`,
167
158
  entrypoint: "src/index.ts",
168
159
  compatibility: "node",
169
160
  bindings: {
@@ -188,14 +179,8 @@ export const server = await Worker("server", {
188
179
  port: 3000,
189
180
  },
190
181
  });
191
-
192
- await WranglerJson("wrangler", {
193
- worker: server,
194
- });
195
182
  {{/if}}
196
183
 
197
-
198
-
199
184
  {{#if (and (eq webDeploy "alchemy") (eq serverDeploy "alchemy"))}}
200
185
  console.log(`Web -> ${web.url}`);
201
186
  console.log(`Server -> ${server.url}`);
@@ -1,11 +0,0 @@
1
- // This is a temporary wrangler.jsonc file that will be overwritten by alchemy
2
- // It's only here so that `wrangler dev` can work or use alchemy dev instead
3
- {
4
- "name": "{{projectName}}",
5
- "main": "src/index.ts",
6
- "compatibility_date": "2025-08-16",
7
- "compatibility_flags": [
8
- "nodejs_compat",
9
- "nodejs_compat_populate_process_env"
10
- ]
11
- }