create-better-t-stack 2.49.1-canary.80158905 → 2.50.0-canary.dd7000f2

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.
Files changed (55) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/index.d.ts +2 -2
  3. package/dist/index.js +1 -1
  4. package/dist/{src-CyG8-I-3.js → src-dv6H37db.js} +257 -157
  5. package/package.json +2 -1
  6. package/templates/api/orpc/server/{rest/src → src}/context.ts.hbs +1 -1
  7. package/templates/api/trpc/server/{rest/src → src}/context.ts.hbs +1 -1
  8. package/templates/auth/better-auth/server/base/src/index.ts.hbs +1 -1
  9. package/templates/auth/clerk/convex/web/react/tanstack-start/src/server.ts.hbs +1 -0
  10. package/templates/backend/server/elysia/src/index.ts.hbs +1 -1
  11. package/templates/backend/server/express/src/index.ts.hbs +1 -1
  12. package/templates/backend/server/fastify/src/index.ts.hbs +1 -1
  13. package/templates/backend/server/hono/src/index.ts.hbs +2 -2
  14. package/templates/db/drizzle/mysql/src/index.ts.hbs +1 -1
  15. package/templates/db/drizzle/postgres/src/index.ts.hbs +1 -1
  16. package/templates/db/drizzle/sqlite/src/index.ts.hbs +1 -1
  17. package/templates/deploy/wrangler/web/react/tanstack-start/wrangler.jsonc.hbs +1 -1
  18. package/templates/frontend/react/tanstack-start/package.json.hbs +7 -7
  19. package/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs +4 -4
  20. package/templates/frontend/react/tanstack-start/vite.config.ts.hbs +1 -1
  21. package/templates/api/orpc/server/next/src/app/rpc/[...all]/route.ts.hbs +0 -52
  22. package/templates/api/trpc/server/next/src/app/trpc/[trpc]/route.ts +0 -14
  23. package/templates/auth/better-auth/server/next/src/app/api/auth/[...all]/route.ts +0 -4
  24. package/templates/backend/server/next/next-env.d.ts +0 -5
  25. package/templates/backend/server/next/next.config.ts +0 -7
  26. package/templates/backend/server/next/package.json.hbs +0 -27
  27. package/templates/backend/server/next/src/app/route.ts +0 -5
  28. package/templates/backend/server/next/src/middleware.ts +0 -19
  29. package/templates/backend/server/next/tsconfig.json.hbs +0 -33
  30. package/templates/examples/ai/server/next/src/app/ai/route.ts.hbs +0 -15
  31. /package/templates/api/orpc/server/{base/_gitignore → _gitignore} +0 -0
  32. /package/templates/api/orpc/server/{base/package.json.hbs → package.json.hbs} +0 -0
  33. /package/templates/api/orpc/server/{rest/src → src}/index.ts.hbs +0 -0
  34. /package/templates/api/orpc/server/{base/src → src}/routers/index.ts.hbs +0 -0
  35. /package/templates/api/orpc/server/{base/tsconfig.json.hbs → tsconfig.json.hbs} +0 -0
  36. /package/templates/api/orpc/server/{base/tsdown.config.ts.hbs → tsdown.config.ts.hbs} +0 -0
  37. /package/templates/api/trpc/server/{base/_gitignore → _gitignore} +0 -0
  38. /package/templates/api/trpc/server/{base/package.json.hbs → package.json.hbs} +0 -0
  39. /package/templates/api/trpc/server/{rest/src → src}/index.ts.hbs +0 -0
  40. /package/templates/api/trpc/server/{base/src → src}/routers/index.ts.hbs +0 -0
  41. /package/templates/api/trpc/server/{base/tsconfig.json.hbs → tsconfig.json.hbs} +0 -0
  42. /package/templates/api/trpc/server/{base/tsdown.config.ts.hbs → tsdown.config.ts.hbs} +0 -0
  43. /package/templates/auth/better-auth/server/db/drizzle/mysql/src/schema/{auth.ts → auth.ts.hbs} +0 -0
  44. /package/templates/auth/better-auth/server/db/drizzle/postgres/src/schema/{auth.ts → auth.ts.hbs} +0 -0
  45. /package/templates/auth/better-auth/server/db/drizzle/sqlite/src/schema/{auth.ts → auth.ts.hbs} +0 -0
  46. /package/templates/auth/better-auth/server/db/mongoose/mongodb/src/models/{auth.model.ts → auth.model.ts.hbs} +0 -0
  47. /package/templates/auth/better-auth/server/db/prisma/mongodb/prisma/schema/{auth.prisma → auth.prisma.hbs} +0 -0
  48. /package/templates/auth/better-auth/server/db/prisma/mysql/prisma/schema/{auth.prisma → auth.prisma.hbs} +0 -0
  49. /package/templates/auth/better-auth/server/db/prisma/postgres/prisma/schema/{auth.prisma → auth.prisma.hbs} +0 -0
  50. /package/templates/auth/better-auth/server/db/prisma/sqlite/prisma/schema/{auth.prisma → auth.prisma.hbs} +0 -0
  51. /package/templates/auth/better-auth/web/nuxt/app/middleware/{auth.ts → auth.ts.hbs} +0 -0
  52. /package/templates/examples/todo/server/drizzle/mysql/src/{db/schema → schema}/todo.ts +0 -0
  53. /package/templates/examples/todo/server/drizzle/postgres/src/{db/schema → schema}/todo.ts +0 -0
  54. /package/templates/examples/todo/server/drizzle/sqlite/src/{db/schema → schema}/todo.ts +0 -0
  55. /package/templates/examples/todo/server/mongoose/mongodb/src/{db/models → models}/todo.model.ts.hbs +0 -0
@@ -15,6 +15,7 @@ import { IndentationText, Node, Project, QuoteKind, SyntaxKind } from "ts-morph"
15
15
  import { glob } from "tinyglobby";
16
16
  import handlebars from "handlebars";
17
17
  import { Biome } from "@biomejs/js-api/nodejs";
18
+ import yaml from "yaml";
18
19
  import os$1 from "node:os";
19
20
 
20
21
  //#region src/utils/get-package-manager.ts
@@ -65,7 +66,7 @@ const dependencyVersionMap = {
65
66
  "@better-auth/expo": "^1.3.13",
66
67
  "@clerk/nextjs": "^6.31.5",
67
68
  "@clerk/clerk-react": "^5.45.0",
68
- "@clerk/tanstack-react-start": "^0.23.1",
69
+ "@clerk/tanstack-react-start": "^0.25.1",
69
70
  "@clerk/clerk-expo": "^2.14.25",
70
71
  "drizzle-orm": "^0.44.2",
71
72
  "drizzle-kit": "^0.31.2",
@@ -124,6 +125,7 @@ const dependencyVersionMap = {
124
125
  "@trpc/tanstack-react-query": "^11.5.0",
125
126
  "@trpc/server": "^11.5.0",
126
127
  "@trpc/client": "^11.5.0",
128
+ next: "^15.1.0",
127
129
  convex: "^1.27.0",
128
130
  "@convex-dev/react-query": "^0.0.0-alpha.8",
129
131
  "convex-svelte": "^0.0.11",
@@ -139,13 +141,13 @@ const dependencyVersionMap = {
139
141
  "@tanstack/solid-query": "^5.87.4",
140
142
  "@tanstack/solid-query-devtools": "^5.87.4",
141
143
  "@tanstack/solid-router-devtools": "^1.131.44",
142
- wrangler: "^4.23.0",
143
- "@cloudflare/vite-plugin": "^1.9.0",
144
+ wrangler: "^4.40.3",
145
+ "@cloudflare/vite-plugin": "^1.13.8",
144
146
  "@opennextjs/cloudflare": "^1.6.5",
145
147
  "nitro-cloudflare-dev": "^0.2.2",
146
148
  "@sveltejs/adapter-cloudflare": "^7.2.1",
147
149
  "@cloudflare/workers-types": "^4.20250822.0",
148
- alchemy: "^0.67.0",
150
+ alchemy: "^0.70.0",
149
151
  nitropack: "^2.12.4",
150
152
  dotenv: "^17.2.2",
151
153
  tsdown: "^0.15.5",
@@ -198,9 +200,9 @@ const BackendSchema = z.enum([
198
200
  "hono",
199
201
  "express",
200
202
  "fastify",
201
- "next",
202
203
  "elysia",
203
204
  "convex",
205
+ "self",
204
206
  "none"
205
207
  ]).describe("Backend framework");
206
208
  const RuntimeSchema = z.enum([
@@ -346,6 +348,22 @@ function ensureSingleWebAndNative(frontends) {
346
348
  if (web.length > 1) exitWithError("Cannot select multiple web frameworks. Choose only one of: tanstack-router, tanstack-start, react-router, next, nuxt, svelte, solid");
347
349
  if (native.length > 1) exitWithError("Cannot select multiple native frameworks. Choose only one of: native-nativewind, native-unistyles");
348
350
  }
351
+ const FULLSTACK_FRONTENDS$1 = [
352
+ "next",
353
+ "nuxt",
354
+ "svelte",
355
+ "tanstack-start"
356
+ ];
357
+ function validateSelfBackendCompatibility(providedFlags, options, config) {
358
+ const backend = config.backend || options.backend;
359
+ const frontends = config.frontend || options.frontend || [];
360
+ if (backend === "self") {
361
+ if (!frontends.some((f) => FULLSTACK_FRONTENDS$1.includes(f))) exitWithError("Backend 'self' (fullstack) requires a fullstack-capable frontend. Please use --frontend with one of: next, nuxt, svelte, tanstack-start");
362
+ if (frontends.length > 1) exitWithError("Backend 'self' (fullstack) can only be used with a single frontend framework.");
363
+ }
364
+ const hasFullstackFrontend = frontends.some((f) => FULLSTACK_FRONTENDS$1.includes(f));
365
+ if (providedFlags.has("backend") && !hasFullstackFrontend && backend === "self") exitWithError("Backend 'self' (fullstack) is only compatible with fullstack-capable frontends: next, nuxt, svelte, tanstack-start. Please choose a different backend or use a fullstack frontend.");
366
+ }
349
367
  function validateWorkersCompatibility(providedFlags, options, config) {
350
368
  if (providedFlags.has("runtime") && options.runtime === "workers" && config.backend && config.backend !== "hono") exitWithError(`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.`);
351
369
  if (providedFlags.has("backend") && config.backend && config.backend !== "hono" && config.runtime === "workers") exitWithError(`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.`);
@@ -667,36 +685,39 @@ async function getAuthChoice(auth, hasDatabase, backend, frontend) {
667
685
 
668
686
  //#endregion
669
687
  //#region src/prompts/backend.ts
688
+ const FULLSTACK_FRONTENDS = [
689
+ "next",
690
+ "nuxt",
691
+ "svelte",
692
+ "tanstack-start"
693
+ ];
670
694
  async function getBackendFrameworkChoice(backendFramework, frontends) {
671
695
  if (backendFramework !== void 0) return backendFramework;
672
696
  const hasIncompatibleFrontend = frontends?.some((f) => f === "solid");
673
- const backendOptions = [
674
- {
675
- value: "hono",
676
- label: "Hono",
677
- hint: "Lightweight, ultrafast web framework"
678
- },
679
- {
680
- value: "next",
681
- label: "Next.js",
682
- hint: "separate api routes only backend"
683
- },
684
- {
685
- value: "express",
686
- label: "Express",
687
- hint: "Fast, unopinionated, minimalist web framework for Node.js"
688
- },
689
- {
690
- value: "fastify",
691
- label: "Fastify",
692
- hint: "Fast, low-overhead web framework for Node.js"
693
- },
694
- {
695
- value: "elysia",
696
- label: "Elysia",
697
- hint: "Ergonomic web framework for building backend servers"
698
- }
699
- ];
697
+ const hasFullstackFrontend = frontends?.some((f) => FULLSTACK_FRONTENDS.includes(f));
698
+ const backendOptions = [];
699
+ if (hasFullstackFrontend) backendOptions.push({
700
+ value: "self",
701
+ label: "Self (Fullstack)",
702
+ hint: "Use frontend's built-in backend capabilities"
703
+ });
704
+ backendOptions.push({
705
+ value: "hono",
706
+ label: "Hono",
707
+ hint: "Lightweight, ultrafast web framework"
708
+ }, {
709
+ value: "express",
710
+ label: "Express",
711
+ hint: "Fast, unopinionated, minimalist web framework for Node.js"
712
+ }, {
713
+ value: "fastify",
714
+ label: "Fastify",
715
+ hint: "Fast, low-overhead web framework for Node.js"
716
+ }, {
717
+ value: "elysia",
718
+ label: "Elysia",
719
+ hint: "Ergonomic web framework for building backend servers"
720
+ });
700
721
  if (!hasIncompatibleFrontend) backendOptions.push({
701
722
  value: "convex",
702
723
  label: "Convex",
@@ -710,7 +731,7 @@ async function getBackendFrameworkChoice(backendFramework, frontends) {
710
731
  const response = await select({
711
732
  message: "Select backend",
712
733
  options: backendOptions,
713
- initialValue: DEFAULT_CONFIG.backend
734
+ initialValue: hasFullstackFrontend ? "self" : DEFAULT_CONFIG.backend
714
735
  });
715
736
  if (isCancel(response)) return exitCancelled("Operation cancelled");
716
737
  return response;
@@ -1089,9 +1110,8 @@ async function getPaymentsChoice(payments, auth, backend, frontends) {
1089
1110
  //#endregion
1090
1111
  //#region src/prompts/runtime.ts
1091
1112
  async function getRuntimeChoice(runtime, backend) {
1092
- if (backend === "convex" || backend === "none") return "none";
1113
+ if (backend === "convex" || backend === "none" || backend === "self") return "none";
1093
1114
  if (runtime !== void 0) return runtime;
1094
- if (backend === "next") return "node";
1095
1115
  const runtimeOptions = [{
1096
1116
  value: "bun",
1097
1117
  label: "Bun",
@@ -1768,8 +1788,8 @@ function validateBackendConstraints(config, providedFlags, options) {
1768
1788
  ].includes(f));
1769
1789
  if (incompatibleFrontends.length > 0) exitWithError(`Clerk authentication is not compatible with the following frontends: ${incompatibleFrontends.join(", ")}. Please choose a different frontend or auth provider.`);
1770
1790
  }
1771
- if (providedFlags.has("backend") && backend && backend !== "convex" && backend !== "none") {
1772
- if (providedFlags.has("runtime") && options.runtime === "none") exitWithError("'--runtime none' is only supported with '--backend convex' or '--backend none'. Please choose 'bun', 'node', or remove the --runtime flag.");
1791
+ if (providedFlags.has("backend") && backend && backend !== "convex" && backend !== "none" && backend !== "self") {
1792
+ if (providedFlags.has("runtime") && options.runtime === "none") exitWithError("'--runtime none' is only supported with '--backend convex', '--backend none', or '--backend self'. Please choose 'bun', 'node', or remove the --runtime flag.");
1773
1793
  }
1774
1794
  if (backend === "convex" && providedFlags.has("frontend") && options.frontend) {
1775
1795
  const incompatibleFrontends = options.frontend.filter((f) => f === "solid");
@@ -1799,6 +1819,7 @@ function validateFullConfig(config, providedFlags, options) {
1799
1819
  validateFrontendConstraints(config, providedFlags);
1800
1820
  validateApiConstraints(config, options);
1801
1821
  validateServerDeployRequiresBackend(config.serverDeploy, config.backend);
1822
+ validateSelfBackendCompatibility(providedFlags, options, config);
1802
1823
  validateWorkersCompatibility(providedFlags, options, config);
1803
1824
  if (config.runtime === "workers" && config.serverDeploy === "none") exitWithError("Cloudflare Workers runtime requires a server deployment. Please choose 'wrangler' or 'alchemy' for --server-deploy.");
1804
1825
  if (config.addons && config.addons.length > 0) {
@@ -1852,6 +1873,7 @@ const CORE_STACK_FLAGS = new Set([
1852
1873
  "examples",
1853
1874
  "auth",
1854
1875
  "dbSetup",
1876
+ "payments",
1855
1877
  "api",
1856
1878
  "webDeploy",
1857
1879
  "serverDeploy"
@@ -2660,8 +2682,12 @@ async function processTemplate(srcPath, destPath, context) {
2660
2682
  }
2661
2683
  handlebars.registerHelper("eq", (a, b) => a === b);
2662
2684
  handlebars.registerHelper("ne", (a, b) => a !== b);
2663
- handlebars.registerHelper("and", (a, b) => a && b);
2664
- handlebars.registerHelper("or", (a, b) => a || b);
2685
+ handlebars.registerHelper("and", (...args) => {
2686
+ return args.slice(0, -1).every((value) => value);
2687
+ });
2688
+ handlebars.registerHelper("or", (...args) => {
2689
+ return args.slice(0, -1).some((value) => value);
2690
+ });
2665
2691
  handlebars.registerHelper("includes", (array, value) => Array.isArray(array) && array.includes(value));
2666
2692
 
2667
2693
  //#endregion
@@ -2763,40 +2789,52 @@ async function setupFrontendTemplates(projectDir, context) {
2763
2789
  }
2764
2790
  }
2765
2791
  }
2766
- async function setupBackendFramework(projectDir, context) {
2767
- if (context.backend === "none") return;
2792
+ async function setupApiPackage(projectDir, context) {
2793
+ if (context.api === "none") return;
2794
+ const apiPackageDir = path.join(projectDir, "packages/api");
2795
+ await fs.ensureDir(apiPackageDir);
2796
+ const apiServerDir = path.join(PKG_ROOT, `templates/api/${context.api}/server`);
2797
+ if (await fs.pathExists(apiServerDir)) await processAndCopyFiles("**/*", apiServerDir, apiPackageDir, context);
2798
+ }
2799
+ async function setupDbPackage(projectDir, context) {
2800
+ if (context.database === "none" || context.orm === "none") return;
2801
+ const dbPackageDir = path.join(projectDir, "packages/db");
2802
+ await fs.ensureDir(dbPackageDir);
2803
+ const dbBaseDir = path.join(PKG_ROOT, "templates/db/base");
2804
+ if (await fs.pathExists(dbBaseDir)) await processAndCopyFiles("**/*", dbBaseDir, dbPackageDir, context);
2805
+ const dbOrmSrcDir = path.join(PKG_ROOT, `templates/db/${context.orm}/${context.database}`);
2806
+ if (await fs.pathExists(dbOrmSrcDir)) await processAndCopyFiles("**/*", dbOrmSrcDir, dbPackageDir, context);
2807
+ }
2808
+ async function setupConvexBackend(projectDir, context) {
2809
+ const serverAppDir = path.join(projectDir, "apps/server");
2810
+ if (await fs.pathExists(serverAppDir)) await fs.remove(serverAppDir);
2811
+ const convexBackendDestDir = path.join(projectDir, "packages/backend");
2812
+ const convexSrcDir = path.join(PKG_ROOT, "templates/backend/convex/packages/backend");
2813
+ await fs.ensureDir(convexBackendDestDir);
2814
+ if (await fs.pathExists(convexSrcDir)) await processAndCopyFiles("**/*", convexSrcDir, convexBackendDestDir, context);
2815
+ }
2816
+ async function setupServerApp(projectDir, context) {
2768
2817
  const serverAppDir = path.join(projectDir, "apps/server");
2769
- if (context.backend === "convex") {
2770
- if (await fs.pathExists(serverAppDir)) await fs.remove(serverAppDir);
2771
- const convexBackendDestDir = path.join(projectDir, "packages/backend");
2772
- const convexSrcDir = path.join(PKG_ROOT, "templates/backend/convex/packages/backend");
2773
- await fs.ensureDir(convexBackendDestDir);
2774
- if (await fs.pathExists(convexSrcDir)) await processAndCopyFiles("**/*", convexSrcDir, convexBackendDestDir, context);
2775
- return;
2776
- }
2777
2818
  await fs.ensureDir(serverAppDir);
2778
2819
  const serverBaseDir = path.join(PKG_ROOT, "templates/backend/server/base");
2779
2820
  if (await fs.pathExists(serverBaseDir)) await processAndCopyFiles("**/*", serverBaseDir, serverAppDir, context);
2780
2821
  const frameworkSrcDir = path.join(PKG_ROOT, `templates/backend/server/${context.backend}`);
2781
2822
  if (await fs.pathExists(frameworkSrcDir)) await processAndCopyFiles("**/*", frameworkSrcDir, serverAppDir, context, true);
2782
- if (context.api !== "none") {
2783
- const apiPackageDir = path.join(projectDir, "packages/api");
2784
- await fs.ensureDir(apiPackageDir);
2785
- const apiServerBaseDir = path.join(PKG_ROOT, `templates/api/${context.api}/server/base`);
2786
- if (await fs.pathExists(apiServerBaseDir)) await processAndCopyFiles("**/*", apiServerBaseDir, apiPackageDir, context);
2787
- let apiServerFrameworkDir = "";
2788
- if (context.backend === "next") apiServerFrameworkDir = path.join(PKG_ROOT, `templates/api/${context.api}/server/${context.backend}`);
2789
- else apiServerFrameworkDir = path.join(PKG_ROOT, `templates/api/${context.api}/server/rest`);
2790
- if (await fs.pathExists(apiServerFrameworkDir)) await processAndCopyFiles("**/*", apiServerFrameworkDir, apiPackageDir, context, true);
2791
- }
2792
- if (context.database !== "none" && context.orm !== "none") {
2793
- const dbPackageDir = path.join(projectDir, "packages/db");
2794
- await fs.ensureDir(dbPackageDir);
2795
- const dbBaseDir = path.join(PKG_ROOT, "templates/db/base");
2796
- if (await fs.pathExists(dbBaseDir)) await processAndCopyFiles("**/*", dbBaseDir, dbPackageDir, context);
2797
- const dbOrmSrcDir = path.join(PKG_ROOT, `templates/db/${context.orm}/${context.database}`);
2798
- if (await fs.pathExists(dbOrmSrcDir)) await processAndCopyFiles("**/*", dbOrmSrcDir, dbPackageDir, context);
2823
+ }
2824
+ async function setupBackendFramework(projectDir, context) {
2825
+ if (context.backend === "none") return;
2826
+ if (context.backend === "convex") {
2827
+ await setupConvexBackend(projectDir, context);
2828
+ return;
2829
+ }
2830
+ if (context.backend === "self") {
2831
+ await setupApiPackage(projectDir, context);
2832
+ await setupDbPackage(projectDir, context);
2833
+ return;
2799
2834
  }
2835
+ await setupServerApp(projectDir, context);
2836
+ await setupApiPackage(projectDir, context);
2837
+ await setupDbPackage(projectDir, context);
2800
2838
  }
2801
2839
  async function setupAuthTemplate(projectDir, context) {
2802
2840
  if (!context.auth || context.auth === "none") return;
@@ -2876,15 +2914,11 @@ async function setupAuthTemplate(projectDir, context) {
2876
2914
  }
2877
2915
  return;
2878
2916
  }
2879
- if (serverAppDirExists && context.backend !== "convex") {
2917
+ if ((serverAppDirExists || context.backend === "self") && context.backend !== "convex") {
2880
2918
  const authPackageDir = path.join(projectDir, "packages/auth");
2881
2919
  await fs.ensureDir(authPackageDir);
2882
2920
  const authServerBaseSrc = path.join(PKG_ROOT, `templates/auth/${authProvider}/server/base`);
2883
2921
  if (await fs.pathExists(authServerBaseSrc)) await processAndCopyFiles("**/*", authServerBaseSrc, authPackageDir, context);
2884
- if (context.backend === "next") {
2885
- const authServerNextSrc = path.join(PKG_ROOT, `templates/auth/${authProvider}/server/next`);
2886
- if (await fs.pathExists(authServerNextSrc)) await processAndCopyFiles("**/*", authServerNextSrc, authPackageDir, context);
2887
- }
2888
2922
  if (context.orm !== "none" && context.database !== "none") {
2889
2923
  const dbPackageDir = path.join(projectDir, "packages/db");
2890
2924
  await fs.ensureDir(dbPackageDir);
@@ -2940,7 +2974,7 @@ async function setupPaymentsTemplate(projectDir, context) {
2940
2974
  const webAppDir = path.join(projectDir, "apps/web");
2941
2975
  const serverAppDirExists = await fs.pathExists(serverAppDir);
2942
2976
  const webAppDirExists = await fs.pathExists(webAppDir);
2943
- if (serverAppDirExists && context.backend !== "convex") {
2977
+ if ((serverAppDirExists || context.backend === "self") && context.backend !== "convex") {
2944
2978
  const authPackageDir = path.join(projectDir, "packages/auth");
2945
2979
  await fs.ensureDir(authPackageDir);
2946
2980
  const paymentsServerSrc = path.join(PKG_ROOT, `templates/payments/${context.payments}/server/base`);
@@ -3020,7 +3054,7 @@ async function setupExamplesTemplate(projectDir, context) {
3020
3054
  for (const example of context.examples) {
3021
3055
  if (example === "none") continue;
3022
3056
  const exampleBaseDir = path.join(PKG_ROOT, `templates/examples/${example}`);
3023
- if (serverAppDirExists && context.backend !== "convex" && context.backend !== "none") {
3057
+ if ((serverAppDirExists || context.backend === "self") && context.backend !== "convex" && context.backend !== "none") {
3024
3058
  const exampleServerSrc = path.join(exampleBaseDir, "server");
3025
3059
  if (context.api !== "none") {
3026
3060
  const apiPackageDir = path.join(projectDir, "packages/api");
@@ -3034,10 +3068,6 @@ async function setupExamplesTemplate(projectDir, context) {
3034
3068
  const exampleDbSchemaSrc = path.join(exampleServerSrc, context.orm, context.database);
3035
3069
  if (await fs.pathExists(exampleDbSchemaSrc)) await processAndCopyFiles("**/*", exampleDbSchemaSrc, dbPackageDir, context, false);
3036
3070
  }
3037
- if (example === "ai" && context.backend === "next") {
3038
- const aiNextServerSrc = path.join(exampleServerSrc, "next");
3039
- if (await fs.pathExists(aiNextServerSrc)) await processAndCopyFiles("**/*", aiNextServerSrc, serverAppDir, context, false);
3040
- }
3041
3071
  }
3042
3072
  if (webAppDirExists) {
3043
3073
  if (hasReactWeb) {
@@ -3526,8 +3556,8 @@ async function setupTanStackStartAlchemyDeploy(projectDir, _packageManager, opti
3526
3556
  await addPackageDependency({
3527
3557
  devDependencies: [
3528
3558
  "alchemy",
3529
- "nitropack",
3530
- "dotenv"
3559
+ "dotenv",
3560
+ "@cloudflare/vite-plugin"
3531
3561
  ],
3532
3562
  projectDir: webAppDir
3533
3563
  });
@@ -3555,17 +3585,6 @@ async function setupTanStackStartAlchemyDeploy(projectDir, _packageManager, opti
3555
3585
  defaultImport: "alchemy"
3556
3586
  });
3557
3587
  else alchemyImport.setModuleSpecifier("alchemy/cloudflare/tanstack-start");
3558
- const reactImport = sourceFile.getImportDeclaration("@vitejs/plugin-react");
3559
- let reactPluginIdentifier = "viteReact";
3560
- if (!reactImport) sourceFile.addImportDeclaration({
3561
- moduleSpecifier: "@vitejs/plugin-react",
3562
- defaultImport: "viteReact"
3563
- });
3564
- else {
3565
- const defaultImport = reactImport.getDefaultImport();
3566
- if (defaultImport) reactPluginIdentifier = defaultImport.getText();
3567
- else reactImport.setDefaultImport("viteReact");
3568
- }
3569
3588
  const exportAssignment = sourceFile.getExportAssignment((d) => !d.isExportEquals());
3570
3589
  if (!exportAssignment) return;
3571
3590
  const defineConfigCall = exportAssignment.getExpression();
@@ -3573,47 +3592,11 @@ async function setupTanStackStartAlchemyDeploy(projectDir, _packageManager, opti
3573
3592
  let configObject = defineConfigCall.getArguments()[0];
3574
3593
  if (!configObject) configObject = defineConfigCall.addArgument("{}");
3575
3594
  if (Node.isObjectLiteralExpression(configObject)) {
3576
- if (!configObject.getProperty("build")) configObject.addPropertyAssignment({
3577
- name: "build",
3578
- initializer: `{
3579
- target: "esnext",
3580
- rollupOptions: {
3581
- external: ["node:async_hooks", "cloudflare:workers"],
3582
- },
3583
- }`
3584
- });
3585
3595
  const pluginsProperty = configObject.getProperty("plugins");
3586
3596
  if (pluginsProperty && Node.isPropertyAssignment(pluginsProperty)) {
3587
3597
  const initializer = pluginsProperty.getInitializer();
3588
3598
  if (Node.isArrayLiteralExpression(initializer)) {
3589
- if (!initializer.getElements().some((el) => el.getText().includes("alchemy"))) initializer.addElement("alchemy()");
3590
- const tanstackElements = initializer.getElements().filter((el) => el.getText().includes("tanstackStart"));
3591
- let needsReactPlugin = false;
3592
- tanstackElements.forEach((element) => {
3593
- if (Node.isCallExpression(element)) {
3594
- const args = element.getArguments();
3595
- if (args.length === 0) {
3596
- element.addArgument(`{
3597
- target: "cloudflare-module",
3598
- customViteReactPlugin: true,
3599
- }`);
3600
- needsReactPlugin = true;
3601
- } else if (args.length === 1 && Node.isObjectLiteralExpression(args[0])) {
3602
- const configObj = args[0];
3603
- if (!configObj.getProperty("target")) configObj.addPropertyAssignment({
3604
- name: "target",
3605
- initializer: "\"cloudflare-module\""
3606
- });
3607
- if (!!!configObj.getProperty("customViteReactPlugin")) configObj.addPropertyAssignment({
3608
- name: "customViteReactPlugin",
3609
- initializer: "true"
3610
- });
3611
- needsReactPlugin = true;
3612
- }
3613
- }
3614
- });
3615
- const hasReactPlugin = initializer.getElements().some((el) => Node.isCallExpression(el) && el.getExpression().getText() === reactPluginIdentifier);
3616
- if (needsReactPlugin && !hasReactPlugin) initializer.addElement(`${reactPluginIdentifier}()`);
3599
+ if (!initializer.getElements().some((el) => el.getText().includes("alchemy("))) initializer.addElement("alchemy()");
3617
3600
  }
3618
3601
  } else configObject.addPropertyAssignment({
3619
3602
  name: "plugins",
@@ -3624,16 +3607,6 @@ async function setupTanStackStartAlchemyDeploy(projectDir, _packageManager, opti
3624
3607
  } catch (error) {
3625
3608
  console.warn("Failed to update vite.config.ts:", error);
3626
3609
  }
3627
- const nitroConfigPath = path.join(webAppDir, "nitro.config.ts");
3628
- await fs.writeFile(nitroConfigPath, `import { defineNitroConfig } from "nitropack/config";
3629
-
3630
- export default defineNitroConfig({
3631
- preset: "cloudflare-module",
3632
- cloudflare: {
3633
- nodeCompat: true,
3634
- },
3635
- });
3636
- `, "utf-8");
3637
3610
  }
3638
3611
 
3639
3612
  //#endregion
@@ -3800,7 +3773,7 @@ async function setupTanstackStartWorkersDeploy(projectDir, packageManager) {
3800
3773
  const webAppDir = path.join(projectDir, "apps/web");
3801
3774
  if (!await fs.pathExists(webAppDir)) return;
3802
3775
  await addPackageDependency({
3803
- devDependencies: ["wrangler"],
3776
+ devDependencies: ["wrangler", "@cloudflare/vite-plugin"],
3804
3777
  projectDir: webAppDir
3805
3778
  });
3806
3779
  const pkgPath = path.join(webAppDir, "package.json");
@@ -3817,6 +3790,12 @@ async function setupTanstackStartWorkersDeploy(projectDir, packageManager) {
3817
3790
  if (!await fs.pathExists(viteConfigPath)) return;
3818
3791
  const sourceFile = tsProject.addSourceFileAtPathIfExists(viteConfigPath);
3819
3792
  if (!sourceFile) return;
3793
+ const cfImport = sourceFile.getImportDeclaration("@cloudflare/vite-plugin");
3794
+ if (!cfImport) sourceFile.addImportDeclaration({
3795
+ moduleSpecifier: "@cloudflare/vite-plugin",
3796
+ namedImports: [{ name: "cloudflare" }]
3797
+ });
3798
+ else if (!cfImport.getNamedImports().some((ni) => ni.getName() === "cloudflare")) cfImport.addNamedImport({ name: "cloudflare" });
3820
3799
  const reactImport = sourceFile.getImportDeclaration("@vitejs/plugin-react");
3821
3800
  let reactPluginIdentifier = "viteReact";
3822
3801
  if (!reactImport) sourceFile.addImportDeclaration({
@@ -3836,10 +3815,7 @@ async function setupTanstackStartWorkersDeploy(projectDir, packageManager) {
3836
3815
  const configObj = defineCall.getArguments()[0];
3837
3816
  if (!configObj) return;
3838
3817
  const pluginsArray = ensureArrayProperty(configObj, "plugins");
3839
- const tanstackPluginIndex = pluginsArray.getElements().findIndex((el) => el.getText().includes("tanstackStart("));
3840
- const tanstackPluginText = "tanstackStart({ target: \"cloudflare-module\", customViteReactPlugin: true })";
3841
- if (tanstackPluginIndex === -1) pluginsArray.addElement(tanstackPluginText);
3842
- else pluginsArray.getElements()[tanstackPluginIndex].replaceWithText(tanstackPluginText);
3818
+ if (!pluginsArray.getElements().some((el) => el.getText().includes("cloudflare("))) pluginsArray.insertElement(0, "cloudflare({ viteEnvironment: { name: 'ssr' } })");
3843
3819
  if (!pluginsArray.getElements().some((el) => Node.isCallExpression(el) && el.getExpression().getText() === reactPluginIdentifier)) {
3844
3820
  const nextIndex = pluginsArray.getElements().findIndex((el) => el.getText().includes("tanstackStart(")) + 1;
3845
3821
  if (nextIndex > 0) pluginsArray.insertElement(nextIndex, `${reactPluginIdentifier}()`);
@@ -3977,6 +3953,110 @@ async function addDeploymentToProject(input) {
3977
3953
  }
3978
3954
  }
3979
3955
 
3956
+ //#endregion
3957
+ //#region src/utils/setup-catalogs.ts
3958
+ async function setupCatalogs(projectDir, options) {
3959
+ if (options.packageManager === "npm") return;
3960
+ const packagePaths = [
3961
+ "apps/server",
3962
+ "apps/web",
3963
+ "packages/api",
3964
+ "packages/db",
3965
+ "packages/auth",
3966
+ "packages/backend"
3967
+ ];
3968
+ const packagesInfo = [];
3969
+ for (const pkgPath of packagePaths) {
3970
+ const fullPath = path.join(projectDir, pkgPath);
3971
+ const pkgJsonPath = path.join(fullPath, "package.json");
3972
+ if (await fs.pathExists(pkgJsonPath)) {
3973
+ const pkgJson = await fs.readJson(pkgJsonPath);
3974
+ packagesInfo.push({
3975
+ path: fullPath,
3976
+ dependencies: pkgJson.dependencies || {},
3977
+ devDependencies: pkgJson.devDependencies || {}
3978
+ });
3979
+ }
3980
+ }
3981
+ const catalog = findDuplicateDependencies(packagesInfo, options.projectName);
3982
+ if (Object.keys(catalog).length === 0) return;
3983
+ if (options.packageManager === "bun") await setupBunCatalogs(projectDir, catalog);
3984
+ else if (options.packageManager === "pnpm") await setupPnpmCatalogs(projectDir, catalog);
3985
+ await updatePackageJsonsWithCatalogs(packagesInfo, catalog);
3986
+ }
3987
+ function findDuplicateDependencies(packagesInfo, projectName) {
3988
+ const depCount = /* @__PURE__ */ new Map();
3989
+ const projectScope = `@${projectName}/`;
3990
+ for (const pkg of packagesInfo) {
3991
+ const allDeps = {
3992
+ ...pkg.dependencies,
3993
+ ...pkg.devDependencies
3994
+ };
3995
+ for (const [depName, version] of Object.entries(allDeps)) {
3996
+ if (depName.startsWith(projectScope)) continue;
3997
+ if (version.startsWith("workspace:")) continue;
3998
+ const existing = depCount.get(depName);
3999
+ if (existing) existing.packages.push(pkg.path);
4000
+ else depCount.set(depName, {
4001
+ version,
4002
+ packages: [pkg.path]
4003
+ });
4004
+ }
4005
+ }
4006
+ const catalog = {};
4007
+ for (const [depName, info] of depCount.entries()) if (info.packages.length > 1) catalog[depName] = info.version;
4008
+ return catalog;
4009
+ }
4010
+ async function setupBunCatalogs(projectDir, catalog) {
4011
+ const rootPkgJsonPath = path.join(projectDir, "package.json");
4012
+ const rootPkgJson = await fs.readJson(rootPkgJsonPath);
4013
+ if (!rootPkgJson.workspaces) rootPkgJson.workspaces = {};
4014
+ if (Array.isArray(rootPkgJson.workspaces)) rootPkgJson.workspaces = {
4015
+ packages: rootPkgJson.workspaces,
4016
+ catalog
4017
+ };
4018
+ else if (typeof rootPkgJson.workspaces === "object") {
4019
+ if (!rootPkgJson.workspaces.catalog) rootPkgJson.workspaces.catalog = {};
4020
+ rootPkgJson.workspaces.catalog = {
4021
+ ...rootPkgJson.workspaces.catalog,
4022
+ ...catalog
4023
+ };
4024
+ }
4025
+ await fs.writeJson(rootPkgJsonPath, rootPkgJson, { spaces: 2 });
4026
+ }
4027
+ async function setupPnpmCatalogs(projectDir, catalog) {
4028
+ const workspaceYamlPath = path.join(projectDir, "pnpm-workspace.yaml");
4029
+ if (!await fs.pathExists(workspaceYamlPath)) return;
4030
+ const workspaceContent = await fs.readFile(workspaceYamlPath, "utf-8");
4031
+ const workspaceYaml = yaml.parse(workspaceContent);
4032
+ if (!workspaceYaml.catalog) workspaceYaml.catalog = {};
4033
+ workspaceYaml.catalog = {
4034
+ ...workspaceYaml.catalog,
4035
+ ...catalog
4036
+ };
4037
+ await fs.writeFile(workspaceYamlPath, yaml.stringify(workspaceYaml));
4038
+ }
4039
+ async function updatePackageJsonsWithCatalogs(packagesInfo, catalog) {
4040
+ for (const pkg of packagesInfo) {
4041
+ const pkgJsonPath = path.join(pkg.path, "package.json");
4042
+ const pkgJson = await fs.readJson(pkgJsonPath);
4043
+ let updated = false;
4044
+ if (pkgJson.dependencies) {
4045
+ for (const depName of Object.keys(pkgJson.dependencies)) if (catalog[depName]) {
4046
+ pkgJson.dependencies[depName] = "catalog:";
4047
+ updated = true;
4048
+ }
4049
+ }
4050
+ if (pkgJson.devDependencies) {
4051
+ for (const depName of Object.keys(pkgJson.devDependencies)) if (catalog[depName]) {
4052
+ pkgJson.devDependencies[depName] = "catalog:";
4053
+ updated = true;
4054
+ }
4055
+ }
4056
+ if (updated) await fs.writeJson(pkgJsonPath, pkgJson, { spaces: 2 });
4057
+ }
4058
+ }
4059
+
3980
4060
  //#endregion
3981
4061
  //#region src/helpers/addons/examples-setup.ts
3982
4062
  async function setupExamples(config) {
@@ -4149,6 +4229,9 @@ async function setupApi(config) {
4149
4229
  else if (backend === "elysia") frameworkDeps.push("elysia");
4150
4230
  else if (backend === "express") frameworkDeps.push("express", "@types/express");
4151
4231
  else if (backend === "fastify") frameworkDeps.push("fastify");
4232
+ else if (backend === "self") {
4233
+ if (frontend.includes("next")) frameworkDeps.push("next");
4234
+ }
4152
4235
  if (frameworkDeps.length > 0) await addPackageDependency({
4153
4236
  dependencies: frameworkDeps,
4154
4237
  projectDir: apiPackageDir
@@ -5756,7 +5839,7 @@ async function setupDatabase(config, cliInput) {
5756
5839
  //#region src/helpers/core/runtime-setup.ts
5757
5840
  async function setupRuntime(config) {
5758
5841
  const { runtime, backend, projectDir } = config;
5759
- if (backend === "convex" || backend === "next" || runtime === "none") return;
5842
+ if (backend === "convex" || backend === "self" || runtime === "none") return;
5760
5843
  const serverDir = path.join(projectDir, "apps/server");
5761
5844
  if (!await fs.pathExists(serverDir)) return;
5762
5845
  if (runtime === "bun") await setupBunRuntime(serverDir, backend);
@@ -6276,7 +6359,7 @@ async function displayPostInstallInstructions(config) {
6276
6359
  else if (!hasNative && !addons?.includes("starlight")) output += `${pc.yellow("NOTE:")} You are creating a backend-only app\n (no frontend selected)\n`;
6277
6360
  if (!isConvex) {
6278
6361
  output += `${pc.cyan("•")} Backend API: http://localhost:3000\n`;
6279
- if (api === "orpc") if (backend === "next") output += `${pc.cyan("•")} OpenAPI (Scalar UI): http://localhost:3000/rpc/api\n`;
6362
+ if (api === "orpc") if (backend === "self") output += `${pc.cyan("•")} OpenAPI (Scalar UI): http://localhost:3000/rpc/api\n`;
6280
6363
  else output += `${pc.cyan("•")} OpenAPI (Scalar UI): http://localhost:3000/api\n`;
6281
6364
  }
6282
6365
  if (addons?.includes("starlight")) output += `${pc.cyan("•")} Docs: http://localhost:4321\n`;
@@ -6431,10 +6514,17 @@ async function setupWorkspaceDependencies(projectDir, options) {
6431
6514
  },
6432
6515
  projectDir: serverPackageDir
6433
6516
  });
6434
- if (options.api && options.api !== "none") {
6435
- const webPackageDir = path.join(projectDir, "apps/web");
6436
- if (await fs.pathExists(webPackageDir)) await addPackageDependency({
6437
- customDependencies: { [`@${projectName}/api`]: workspaceVersion },
6517
+ const needsApiDependency = options.api && options.api !== "none";
6518
+ const webPackageDir = path.join(projectDir, "apps/web");
6519
+ if (await fs.pathExists(webPackageDir)) {
6520
+ const webDeps = {};
6521
+ if (options.backend === "self") {
6522
+ webDeps[`@${projectName}/api`] = workspaceVersion;
6523
+ webDeps[`@${projectName}/auth`] = workspaceVersion;
6524
+ webDeps[`@${projectName}/db`] = workspaceVersion;
6525
+ } else if (needsApiDependency) webDeps[`@${projectName}/api`] = workspaceVersion;
6526
+ if (Object.keys(webDeps).length > 0) await addPackageDependency({
6527
+ customDependencies: webDeps,
6438
6528
  projectDir: webPackageDir
6439
6529
  });
6440
6530
  }
@@ -6444,12 +6534,17 @@ async function setupWorkspaceDependencies(projectDir, options) {
6444
6534
  //#region src/helpers/core/project-config.ts
6445
6535
  async function updatePackageConfigurations(projectDir, options) {
6446
6536
  await updateRootPackageJson(projectDir, options);
6447
- if (options.backend !== "convex") {
6537
+ if (options.backend === "convex") await updateConvexPackageJson(projectDir, options);
6538
+ else if (options.backend === "self") {
6539
+ await updateAuthPackageJson(projectDir, options);
6540
+ await updateApiPackageJson(projectDir, options);
6541
+ await setupWorkspaceDependencies(projectDir, options);
6542
+ } else if (options.backend !== "none") {
6448
6543
  await updateServerPackageJson(projectDir, options);
6449
6544
  await updateAuthPackageJson(projectDir, options);
6450
6545
  await updateApiPackageJson(projectDir, options);
6451
6546
  await setupWorkspaceDependencies(projectDir, options);
6452
- } else await updateConvexPackageJson(projectDir, options);
6547
+ }
6453
6548
  }
6454
6549
  async function updateRootPackageJson(projectDir, options) {
6455
6550
  const rootPackageJsonPath = path.join(projectDir, "package.json");
@@ -6476,7 +6571,7 @@ async function updateRootPackageJson(projectDir, options) {
6476
6571
  scripts["check-types"] = "turbo check-types";
6477
6572
  scripts["dev:native"] = "turbo -F native dev";
6478
6573
  scripts["dev:web"] = "turbo -F web dev";
6479
- scripts["dev:server"] = serverDevScript;
6574
+ if (options.backend !== "self" && options.backend !== "none") scripts["dev:server"] = serverDevScript;
6480
6575
  if (options.backend === "convex") scripts["dev:setup"] = `turbo -F ${backendPackageName} dev:setup`;
6481
6576
  if (needsDbScripts) {
6482
6577
  scripts["db:push"] = `turbo -F ${dbPackageName} db:push`;
@@ -6501,7 +6596,7 @@ async function updateRootPackageJson(projectDir, options) {
6501
6596
  scripts["check-types"] = "pnpm -r check-types";
6502
6597
  scripts["dev:native"] = "pnpm --filter native dev";
6503
6598
  scripts["dev:web"] = "pnpm --filter web dev";
6504
- scripts["dev:server"] = serverDevScript;
6599
+ if (options.backend !== "self" && options.backend !== "none") scripts["dev:server"] = serverDevScript;
6505
6600
  if (options.backend === "convex") scripts["dev:setup"] = `pnpm --filter ${backendPackageName} dev:setup`;
6506
6601
  if (needsDbScripts) {
6507
6602
  scripts["db:push"] = `pnpm --filter ${dbPackageName} db:push`;
@@ -6526,7 +6621,7 @@ async function updateRootPackageJson(projectDir, options) {
6526
6621
  scripts["check-types"] = "npm run check-types --workspaces";
6527
6622
  scripts["dev:native"] = "npm run dev --workspace native";
6528
6623
  scripts["dev:web"] = "npm run dev --workspace web";
6529
- scripts["dev:server"] = serverDevScript;
6624
+ if (options.backend !== "self" && options.backend !== "none") scripts["dev:server"] = serverDevScript;
6530
6625
  if (options.backend === "convex") scripts["dev:setup"] = `npm run dev:setup --workspace ${backendPackageName}`;
6531
6626
  if (needsDbScripts) {
6532
6627
  scripts["db:push"] = `npm run db:push --workspace ${dbPackageName}`;
@@ -6551,7 +6646,7 @@ async function updateRootPackageJson(projectDir, options) {
6551
6646
  scripts["check-types"] = "bun run --filter '*' check-types";
6552
6647
  scripts["dev:native"] = "bun run --filter native dev";
6553
6648
  scripts["dev:web"] = "bun run --filter web dev";
6554
- scripts["dev:server"] = serverDevScript;
6649
+ if (options.backend !== "self" && options.backend !== "none") scripts["dev:server"] = serverDevScript;
6555
6650
  if (options.backend === "convex") scripts["dev:setup"] = `bun run --filter ${backendPackageName} dev:setup`;
6556
6651
  if (needsDbScripts) {
6557
6652
  scripts["db:push"] = `bun run --filter ${dbPackageName} db:push`;
@@ -6654,12 +6749,14 @@ async function updateConvexPackageJson(projectDir, options) {
6654
6749
  async function createProject(options, cliInput) {
6655
6750
  const projectDir = options.projectDir;
6656
6751
  const isConvex = options.backend === "convex";
6752
+ const isSelfBackend = options.backend === "self";
6753
+ const needsServerSetup = !isConvex && !isSelfBackend;
6657
6754
  try {
6658
6755
  await fs.ensureDir(projectDir);
6659
6756
  await copyBaseTemplate(projectDir, options);
6660
6757
  await setupFrontendTemplates(projectDir, options);
6661
6758
  await setupBackendFramework(projectDir, options);
6662
- if (!isConvex) await setupDockerComposeTemplates(projectDir, options);
6759
+ if (needsServerSetup) await setupDockerComposeTemplates(projectDir, options);
6663
6760
  await setupAuthTemplate(projectDir, options);
6664
6761
  if (options.payments && options.payments !== "none") await setupPaymentsTemplate(projectDir, options);
6665
6762
  if (options.examples.length > 0 && options.examples[0] !== "none") await setupExamplesTemplate(projectDir, options);
@@ -6667,9 +6764,11 @@ async function createProject(options, cliInput) {
6667
6764
  await setupDeploymentTemplates(projectDir, options);
6668
6765
  await setupApi(options);
6669
6766
  if (!isConvex) {
6670
- await setupBackendDependencies(options);
6767
+ if (needsServerSetup) {
6768
+ await setupBackendDependencies(options);
6769
+ await setupRuntime(options);
6770
+ }
6671
6771
  await setupDatabase(options, cliInput);
6672
- await setupRuntime(options);
6673
6772
  if (options.examples.length > 0 && options.examples[0] !== "none") await setupExamples(options);
6674
6773
  }
6675
6774
  if (options.addons.length > 0 && options.addons[0] !== "none") await setupAddons(options);
@@ -6678,6 +6777,7 @@ async function createProject(options, cliInput) {
6678
6777
  await handleExtras(projectDir, options);
6679
6778
  await setupEnvironmentVariables(options);
6680
6779
  await updatePackageConfigurations(projectDir, options);
6780
+ await setupCatalogs(projectDir, options);
6681
6781
  await setupWebDeploy(options);
6682
6782
  await setupServerDeploy(options);
6683
6783
  await createReadme(projectDir, options);