create-better-fullstack 1.4.5 → 1.4.7

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
@@ -26,7 +26,7 @@ Options:
26
26
  --yolo Random configuration (experimental)
27
27
  --database <type> Database type (none, sqlite, postgres, mysql, mongodb)
28
28
  --orm <type> ORM type (drizzle, prisma, mongoose, typeorm, kysely, mikroorm, sequelize, none)
29
- --auth <type> Authentication (better-auth, clerk, nextauth, none)
29
+ --auth <type> Authentication (better-auth, go-better-auth, clerk, nextauth, stack-auth, supabase-auth, auth0, none)
30
30
  --payments <type> Payments (polar, stripe, lemon-squeezy, paddle, dodo, none)
31
31
  --frontend <types...> Frontend types
32
32
  --backend <framework> Backend framework
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { s as createBtsCli } from "./src-B5kV0Yns.mjs";
2
+ import { s as createBtsCli } from "./src-CISBB09-.mjs";
3
3
 
4
4
  //#region src/cli.ts
5
5
  createBtsCli().run();
package/dist/index.d.mts CHANGED
@@ -57,6 +57,7 @@ declare const router: {
57
57
  auth: z.ZodOptional<z.ZodEnum<{
58
58
  none: "none";
59
59
  "better-auth": "better-auth";
60
+ "go-better-auth": "go-better-auth";
60
61
  clerk: "clerk";
61
62
  nextauth: "nextauth";
62
63
  "stack-auth": "stack-auth";
@@ -179,6 +180,11 @@ declare const router: {
179
180
  sentry: "sentry";
180
181
  grafana: "grafana";
181
182
  }>>;
183
+ featureFlags: z.ZodOptional<z.ZodEnum<{
184
+ none: "none";
185
+ growthbook: "growthbook";
186
+ posthog: "posthog";
187
+ }>>;
182
188
  analytics: z.ZodOptional<z.ZodEnum<{
183
189
  none: "none";
184
190
  plausible: "plausible";
@@ -523,7 +529,7 @@ declare const router: {
523
529
  frontend: ("none" | "tanstack-router" | "react-router" | "tanstack-start" | "next" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid" | "solid-start" | "astro" | "qwik" | "angular" | "redwood" | "fresh")[];
524
530
  addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook")[];
525
531
  examples: ("ai" | "none" | "chat-sdk")[];
526
- auth: "none" | "better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
532
+ auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
527
533
  payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
528
534
  git: boolean;
529
535
  packageManager: "bun" | "npm" | "pnpm";
@@ -609,7 +615,7 @@ declare const router: {
609
615
  frontend: ("none" | "tanstack-router" | "react-router" | "tanstack-start" | "next" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid" | "solid-start" | "astro" | "qwik" | "angular" | "redwood" | "fresh")[];
610
616
  addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook")[];
611
617
  examples: ("ai" | "none" | "chat-sdk")[];
612
- auth: "none" | "better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
618
+ auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
613
619
  payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
614
620
  git: boolean;
615
621
  packageManager: "bun" | "npm" | "pnpm";
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { a as builder, c as createVirtual, d as history, f as router, i as add, l as docs, n as TEMPLATE_COUNT, o as create, p as sponsors, r as VirtualFileSystem, s as createBtsCli, t as EMBEDDED_TEMPLATES, u as generateVirtualProject } from "./src-B5kV0Yns.mjs";
2
+ import { a as builder, c as createVirtual, d as history, f as router, i as add, l as docs, n as TEMPLATE_COUNT, o as create, p as sponsors, r as VirtualFileSystem, s as createBtsCli, t as EMBEDDED_TEMPLATES, u as generateVirtualProject } from "./src-CISBB09-.mjs";
3
3
 
4
4
  export { EMBEDDED_TEMPLATES, TEMPLATE_COUNT, VirtualFileSystem, add, builder, create, createBtsCli, createVirtual, docs, generateVirtualProject, history, router, sponsors };
@@ -13,7 +13,7 @@ import { ECOSYSTEM_GROUPS, EMBEDDED_TEMPLATES, EMBEDDED_TEMPLATES as EMBEDDED_TE
13
13
  import gradient from "gradient-string";
14
14
  import path$1 from "path";
15
15
  import { writeTreeToFilesystem } from "@better-fullstack/template-generator/fs-writer";
16
- import { allowedApisForFrontends, getCompatibleAddons, getCompatibleCSSFrameworks, getCompatibleUILibraries, hasWebStyling, isExampleAIAllowed, isExampleChatSdkAllowed, isFrontendAllowedWithBackend, isWebFrontend, requiresChatSdkVercelAIForSelection, splitFrontends, validateAddonCompatibility } from "@better-fullstack/types";
16
+ import { allowedApisForFrontends, getCompatibleAddons, getCompatibleCSSFrameworks, getCompatibleUILibraries, getLocalWebDevPort, hasWebStyling, isExampleAIAllowed, isExampleChatSdkAllowed, isFrontendAllowedWithBackend, isWebFrontend, requiresChatSdkVercelAIForSelection, splitFrontends, validateAddonCompatibility } from "@better-fullstack/types";
17
17
  import consola, { consola as consola$1 } from "consola";
18
18
  import { AsyncLocalStorage } from "node:async_hooks";
19
19
  import { ConfirmPrompt, GroupMultiSelectPrompt, MultiSelectPrompt, SelectPrompt, isCancel as isCancel$1 } from "@clack/core";
@@ -791,61 +791,6 @@ function validateApiFrontendCompatibility(api, frontends = [], astroIntegration)
791
791
  function isFrontendAllowedWithBackend$1(frontend, backend, auth) {
792
792
  return isFrontendAllowedWithBackend(frontend, backend, auth);
793
793
  }
794
- function validateClerkCompatibility(auth, backend, frontends = []) {
795
- if (auth !== "clerk") return;
796
- if (backend === "convex") {
797
- const incompatibleFrontends = frontends.filter((f) => [
798
- "nuxt",
799
- "svelte",
800
- "solid",
801
- "solid-start"
802
- ].includes(f));
803
- if (incompatibleFrontends.length > 0) exitWithError(`In Better-Fullstack, Clerk + Convex is not compatible with the following frontends: ${incompatibleFrontends.join(", ")}. Please choose a different frontend or auth provider.`);
804
- return;
805
- }
806
- if (backend === "self") {
807
- if (frontends.some((f) => [
808
- "native-bare",
809
- "native-uniwind",
810
- "native-unistyles"
811
- ].includes(f))) exitWithError("In Better-Fullstack, Clerk with the 'self' backend is currently supported only for web-only Next.js or TanStack Start projects (no native companion app). Please remove the native frontend or choose a different auth provider.");
812
- const hasNextJs = frontends.includes("next");
813
- const hasTanStackStart = frontends.includes("tanstack-start");
814
- if (!hasNextJs && !hasTanStackStart) {
815
- if (frontends.includes("astro")) exitWithError("In Better-Fullstack, Clerk is not yet supported for Astro fullstack projects. Please use '--frontend next' or '--frontend tanstack-start' with '--backend self', or choose a different auth provider.");
816
- if (frontends.includes("nuxt")) exitWithError("In Better-Fullstack, Clerk is not yet supported for Nuxt fullstack projects. Please use '--frontend next' or '--frontend tanstack-start' with '--backend self', or choose a different auth provider.");
817
- if (frontends.includes("svelte")) exitWithError("In Better-Fullstack, Clerk is not yet supported for SvelteKit fullstack projects. Please use '--frontend next' or '--frontend tanstack-start' with '--backend self', or choose a different auth provider.");
818
- if (frontends.includes("solid-start")) exitWithError("In Better-Fullstack, Clerk is not yet supported for SolidStart fullstack projects. Please use '--frontend next' or '--frontend tanstack-start' with '--backend self', or choose a different auth provider.");
819
- exitWithError("In Better-Fullstack, Clerk with the 'self' backend currently requires the Next.js or TanStack Start frontend. Please use '--frontend next' or '--frontend tanstack-start', or choose a different auth provider.");
820
- }
821
- return;
822
- }
823
- exitWithError("In Better-Fullstack, Clerk authentication is currently supported with the Convex backend, or with the 'self' backend when using Next.js or TanStack Start. Please choose a supported backend/frontend combination or a different auth provider.");
824
- }
825
- function validateNextAuthCompatibility(auth, backend, frontends = []) {
826
- if (auth !== "nextauth") return;
827
- const hasNextJs = frontends.includes("next");
828
- if (backend !== "self") exitWithError("In Better-Fullstack, Auth.js (NextAuth) is currently supported only with the 'self' backend (fullstack Next.js). Please use '--backend self' or choose a different auth provider.");
829
- if (!hasNextJs) exitWithError("In Better-Fullstack, Auth.js (NextAuth) currently requires the Next.js frontend. Please use '--frontend next' or choose a different auth provider.");
830
- }
831
- function validateStackAuthCompatibility(auth, backend, frontends = []) {
832
- if (auth !== "stack-auth") return;
833
- const hasNextJs = frontends.includes("next");
834
- if (backend !== "self") exitWithError("In Better-Fullstack, Stack Auth is currently supported only with the 'self' backend (fullstack Next.js). Please use '--backend self' or choose a different auth provider.");
835
- if (!hasNextJs) exitWithError("In Better-Fullstack, Stack Auth currently requires the Next.js frontend. Please use '--frontend next' or choose a different auth provider.");
836
- }
837
- function validateSupabaseAuthCompatibility(auth, backend, frontends = []) {
838
- if (auth !== "supabase-auth") return;
839
- const hasNextJs = frontends.includes("next");
840
- if (backend !== "self") exitWithError("In Better-Fullstack, Supabase Auth is currently supported only with the 'self' backend (fullstack Next.js). Please use '--backend self' or choose a different auth provider.");
841
- if (!hasNextJs) exitWithError("In Better-Fullstack, Supabase Auth currently requires the Next.js frontend. Please use '--frontend next' or choose a different auth provider.");
842
- }
843
- function validateAuth0Compatibility(auth, backend, frontends = []) {
844
- if (auth !== "auth0") return;
845
- const hasNextJs = frontends.includes("next");
846
- if (backend !== "self") exitWithError("In Better-Fullstack, Auth0 is currently supported only with the 'self' backend (fullstack Next.js). Please use '--backend self' or choose a different auth provider.");
847
- if (!hasNextJs) exitWithError("In Better-Fullstack, Auth0 currently requires the Next.js frontend. Please use '--frontend next' or choose a different auth provider.");
848
- }
849
794
  function allowedApisForFrontends$1(frontends = [], astroIntegration) {
850
795
  return allowedApisForFrontends(frontends, astroIntegration);
851
796
  }
@@ -2411,12 +2356,11 @@ async function setupTauri(config) {
2411
2356
  if (!await fs.pathExists(clientPackageDir)) return;
2412
2357
  try {
2413
2358
  s.start("Setting up Tauri desktop app support...");
2414
- const hasReactRouter = frontend.includes("react-router");
2415
2359
  const hasNuxt = frontend.includes("nuxt");
2416
2360
  const hasSvelte = frontend.includes("svelte");
2417
2361
  const hasNext = frontend.includes("next");
2418
- const devUrl = hasReactRouter || hasSvelte ? "http://localhost:5173" : hasNext ? "http://localhost:3001" : "http://localhost:3001";
2419
- const frontendDist = hasNuxt ? "../.output/public" : hasSvelte ? "../build" : hasNext ? "../.next" : hasReactRouter ? "../build/client" : "../dist";
2362
+ const devUrl = `http://localhost:${getLocalWebDevPort(frontend)}`;
2363
+ const frontendDist = hasNuxt ? "../.output/public" : hasSvelte ? "../build" : hasNext ? "../.next" : frontend.includes("react-router") ? "../build/client" : "../dist";
2420
2364
  const tauriArgs = [
2421
2365
  "@tauri-apps/cli@latest",
2422
2366
  "init",
@@ -3205,103 +3149,36 @@ async function getAstroIntegrationChoice(astroIntegration) {
3205
3149
 
3206
3150
  //#endregion
3207
3151
  //#region src/prompts/auth.ts
3208
- async function getAuthChoice(auth, backend, frontend) {
3152
+ async function getAuthChoice(auth, backend, frontend, ecosystem = "typescript") {
3209
3153
  if (auth !== void 0) return auth;
3210
- if (backend === "none") return "none";
3211
- if (backend === "convex") {
3212
- const supportedBetterAuthFrontends = frontend?.some((f) => [
3213
- "tanstack-router",
3214
- "tanstack-start",
3215
- "next",
3216
- "native-bare",
3217
- "native-uniwind",
3218
- "native-unistyles"
3219
- ].includes(f));
3220
- const hasClerkCompatibleFrontends = frontend?.some((f) => [
3221
- "react-router",
3222
- "tanstack-router",
3223
- "tanstack-start",
3224
- "next",
3225
- "native-bare",
3226
- "native-uniwind",
3227
- "native-unistyles"
3228
- ].includes(f));
3229
- const options$1 = [];
3230
- if (supportedBetterAuthFrontends) options$1.push({
3231
- value: "better-auth",
3232
- label: "Better-Auth",
3233
- hint: "comprehensive auth framework for TypeScript"
3234
- });
3235
- if (hasClerkCompatibleFrontends) options$1.push({
3236
- value: "clerk",
3237
- label: "Clerk",
3238
- hint: "More than auth, Complete User Management"
3239
- });
3240
- if (options$1.length === 0) return "none";
3241
- options$1.push({
3242
- value: "none",
3243
- label: "None",
3244
- hint: "No auth"
3245
- });
3246
- const response$1 = await navigableSelect({
3247
- message: "Select authentication provider",
3248
- options: options$1,
3249
- initialValue: "none"
3250
- });
3251
- if (isCancel$1(response$1)) return exitCancelled("Operation cancelled");
3252
- return response$1;
3253
- }
3254
- const hasNextJs = frontend?.includes("next");
3255
- const hasTanStackStart = frontend?.includes("tanstack-start");
3256
- const isSelfBackend = backend === "self";
3257
- const supportsNextJsAuth = hasNextJs && isSelfBackend;
3258
- const hasNativeFrontend$2 = frontend?.some((f) => [
3259
- "native-bare",
3260
- "native-uniwind",
3261
- "native-unistyles"
3262
- ].includes(f));
3263
- const supportsClerkSelf = isSelfBackend && !hasNativeFrontend$2 && Boolean(hasNextJs || hasTanStackStart);
3264
- const options = [{
3265
- value: "better-auth",
3266
- label: "Better-Auth",
3267
- hint: "comprehensive auth framework for TypeScript"
3268
- }];
3269
- if (supportsClerkSelf) options.push({
3270
- value: "clerk",
3271
- label: "Clerk",
3272
- hint: "More than auth, Complete User Management"
3154
+ const authOptionOrder = [
3155
+ { value: "better-auth" },
3156
+ { value: "go-better-auth" },
3157
+ { value: "clerk" },
3158
+ { value: "nextauth" },
3159
+ { value: "stack-auth" },
3160
+ { value: "supabase-auth" },
3161
+ { value: "auth0" },
3162
+ { value: "none" }
3163
+ ];
3164
+ const supportedOptions = (0, types_exports.getSupportedCapabilityOptions)("auth", {
3165
+ ecosystem,
3166
+ backend,
3167
+ frontend
3273
3168
  });
3274
- if (supportsNextJsAuth) {
3275
- options.push({
3276
- value: "nextauth",
3277
- label: "Auth.js (NextAuth)",
3278
- hint: "Authentication for Next.js (formerly NextAuth.js)"
3279
- });
3280
- options.push({
3281
- value: "stack-auth",
3282
- label: "Stack Auth",
3283
- hint: "Open-source Auth0/Clerk alternative"
3284
- });
3285
- options.push({
3286
- value: "supabase-auth",
3287
- label: "Supabase Auth",
3288
- hint: "Auth with Supabase platform integration"
3289
- });
3290
- options.push({
3291
- value: "auth0",
3292
- label: "Auth0",
3293
- hint: "Flexible identity platform for authentication"
3294
- });
3295
- }
3296
- options.push({
3297
- value: "none",
3298
- label: "None",
3299
- hint: "No authentication"
3169
+ const options = authOptionOrder.flatMap(({ value }) => {
3170
+ const option = supportedOptions.find((candidate) => candidate.id === value);
3171
+ return option ? [option] : [];
3300
3172
  });
3173
+ if (options.length === 1 && options[0]?.id === "none") return "none";
3301
3174
  const response = await navigableSelect({
3302
3175
  message: "Select authentication provider",
3303
- options,
3304
- initialValue: DEFAULT_CONFIG.auth
3176
+ options: options.map((option) => ({
3177
+ value: option.id,
3178
+ label: option.label,
3179
+ hint: option.promptHint
3180
+ })),
3181
+ initialValue: options.some((option) => option.id === DEFAULT_CONFIG.auth) ? DEFAULT_CONFIG.auth : options.find((option) => option.id !== "none")?.id ?? "none"
3305
3182
  });
3306
3183
  if (isCancel$1(response)) return exitCancelled("Operation cancelled");
3307
3184
  return response;
@@ -3976,8 +3853,8 @@ async function getFrontendChoice(frontendOptions, backend, auth) {
3976
3853
  },
3977
3854
  {
3978
3855
  value: "svelte",
3979
- label: "Svelte",
3980
- hint: "web development for the rest of us"
3856
+ label: "SvelteKit",
3857
+ hint: "Full-stack Svelte framework with SSR and server routes"
3981
3858
  },
3982
3859
  {
3983
3860
  value: "solid",
@@ -5708,8 +5585,9 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
5708
5585
  return getApiChoice(flags.api, results.frontend, results.backend, results.astroIntegration);
5709
5586
  },
5710
5587
  auth: ({ results }) => {
5711
- if (results.ecosystem !== "typescript") return Promise.resolve("none");
5712
- return getAuthChoice(flags.auth, results.backend, results.frontend);
5588
+ if (results.ecosystem === "typescript") return getAuthChoice(flags.auth, results.backend, results.frontend, "typescript");
5589
+ if (results.ecosystem === "go") return getAuthChoice(flags.auth, void 0, void 0, "go");
5590
+ return Promise.resolve("none");
5713
5591
  },
5714
5592
  payments: ({ results }) => {
5715
5593
  if (results.ecosystem !== "typescript") return Promise.resolve("none");
@@ -6734,6 +6612,18 @@ function validateDatabaseSetup(config, providedFlags) {
6734
6612
  }
6735
6613
  }
6736
6614
  }
6615
+ function validateEcosystemAuthCompatibility(config, providedFlags) {
6616
+ const auth = config.auth;
6617
+ if (!auth || auth === "none") return;
6618
+ const normalized = (0, types_exports.normalizeCapabilitySelection)("auth", {
6619
+ ecosystem: config.ecosystem,
6620
+ backend: config.backend,
6621
+ frontend: config.frontend
6622
+ }, auth);
6623
+ if (!normalized.normalized || normalized.value === auth) return;
6624
+ config.auth = normalized.value;
6625
+ if (providedFlags?.has("auth") && normalized.reason && !isSilent()) consola.warn(pc.yellow(`Unsupported auth selection '${auth}' for the current stack: ${normalized.reason}. Falling back to '--auth ${normalized.value}'.`));
6626
+ }
6737
6627
  function validateConvexConstraints(config, providedFlags) {
6738
6628
  const { backend } = config;
6739
6629
  if (backend !== "convex") return;
@@ -6786,30 +6676,6 @@ function validateConvexConstraints(config, providedFlags) {
6786
6676
  },
6787
6677
  suggestions: ["Remove --server-deploy flag", "Set --server-deploy none"]
6788
6678
  });
6789
- if (has("auth") && config.auth === "better-auth") {
6790
- const supportedFrontends = [
6791
- "tanstack-router",
6792
- "tanstack-start",
6793
- "next",
6794
- "native-bare",
6795
- "native-uniwind",
6796
- "native-unistyles"
6797
- ];
6798
- if (!config.frontend?.some((f) => supportedFrontends.includes(f))) incompatibilityError({
6799
- message: "Better-Auth with Convex requires specific frontends.",
6800
- provided: {
6801
- backend: "convex",
6802
- auth: "better-auth",
6803
- frontend: config.frontend || []
6804
- },
6805
- suggestions: [
6806
- "Use --frontend tanstack-router",
6807
- "Use --frontend tanstack-start",
6808
- "Use --frontend next",
6809
- "Use a native frontend"
6810
- ]
6811
- });
6812
- }
6813
6679
  }
6814
6680
  function validateBackendNoneConstraints(config, providedFlags) {
6815
6681
  const { backend } = config;
@@ -6819,7 +6685,6 @@ function validateBackendNoneConstraints(config, providedFlags) {
6819
6685
  if (has("database") && config.database !== "none") exitWithError("Backend 'none' requires '--database none'. Please remove the --database flag or set it to 'none'.");
6820
6686
  if (has("orm") && config.orm !== "none") exitWithError("Backend 'none' requires '--orm none'. Please remove the --orm flag or set it to 'none'.");
6821
6687
  if (has("api") && config.api !== "none") exitWithError("Backend 'none' requires '--api none'. Please remove the --api flag or set it to 'none'.");
6822
- if (has("auth") && config.auth !== "none") exitWithError("Backend 'none' requires '--auth none'. Please remove the --auth flag or set it to 'none'.");
6823
6688
  if (has("payments") && config.payments !== "none") exitWithError("Backend 'none' requires '--payments none'. Please remove the --payments flag or set it to 'none'.");
6824
6689
  if (has("dbSetup") && config.dbSetup !== "none") exitWithError("Backend 'none' requires '--db-setup none'. Please remove the --db-setup flag or set it to 'none'.");
6825
6690
  if (has("serverDeploy") && config.serverDeploy !== "none") exitWithError("Backend 'none' requires '--server-deploy none'. Please remove the --server-deploy flag or set it to 'none'.");
@@ -6888,6 +6753,7 @@ function validateShadcnConstraints(config, providedFlags) {
6888
6753
  });
6889
6754
  }
6890
6755
  function validateFullConfig(config, providedFlags, options) {
6756
+ validateEcosystemAuthCompatibility(config, providedFlags);
6891
6757
  validateDatabaseOrmAuth(config, providedFlags);
6892
6758
  validateDatabaseSetup(config, providedFlags);
6893
6759
  validateConvexConstraints(config, providedFlags);
@@ -6909,11 +6775,6 @@ function validateFullConfig(config, providedFlags, options) {
6909
6775
  }
6910
6776
  validateExamplesCompatibility(config.examples ?? [], config.backend, config.frontend ?? [], config.runtime, config.ai);
6911
6777
  validatePaymentsCompatibility(config.payments, config.auth, config.backend, config.frontend ?? []);
6912
- validateClerkCompatibility(config.auth, config.backend, config.frontend ?? []);
6913
- validateNextAuthCompatibility(config.auth, config.backend, config.frontend ?? []);
6914
- validateStackAuthCompatibility(config.auth, config.backend, config.frontend ?? []);
6915
- validateSupabaseAuthCompatibility(config.auth, config.backend, config.frontend ?? []);
6916
- validateAuth0Compatibility(config.auth, config.backend, config.frontend ?? []);
6917
6778
  validateUILibraryFrontendCompatibility(config.uiLibrary, config.frontend ?? [], config.astroIntegration);
6918
6779
  validateUILibraryCSSFrameworkCompatibility(config.uiLibrary, config.cssFramework);
6919
6780
  validateShadcnConstraints(config, providedFlags);
@@ -6921,15 +6782,11 @@ function validateFullConfig(config, providedFlags, options) {
6921
6782
  }
6922
6783
  function validateConfigForProgrammaticUse(config) {
6923
6784
  try {
6785
+ validateEcosystemAuthCompatibility(config);
6924
6786
  validateDatabaseOrmAuth(config);
6925
6787
  if (config.frontend && config.frontend.length > 0) ensureSingleWebAndNative(config.frontend);
6926
6788
  validateApiFrontendCompatibility(config.api, config.frontend, config.astroIntegration);
6927
6789
  validatePaymentsCompatibility(config.payments, config.auth, config.backend, config.frontend);
6928
- validateClerkCompatibility(config.auth, config.backend, config.frontend ?? []);
6929
- validateNextAuthCompatibility(config.auth, config.backend, config.frontend ?? []);
6930
- validateStackAuthCompatibility(config.auth, config.backend, config.frontend ?? []);
6931
- validateSupabaseAuthCompatibility(config.auth, config.backend, config.frontend ?? []);
6932
- validateAuth0Compatibility(config.auth, config.backend, config.frontend ?? []);
6933
6790
  if (config.addons && config.addons.length > 0) validateAddonsAgainstFrontends(config.addons, config.frontend, config.auth);
6934
6791
  validateExamplesCompatibility(config.examples ?? [], config.backend, config.frontend ?? [], config.runtime, config.ai);
6935
6792
  validateUILibraryFrontendCompatibility(config.uiLibrary, config.frontend ?? [], config.astroIntegration);
@@ -7037,6 +6894,8 @@ async function formatCode(filePath, content) {
7037
6894
  }
7038
6895
  async function formatProject(projectDir) {
7039
6896
  async function formatDirectory(dir) {
6897
+ const denoConfigPath = path.join(dir, "deno.json");
6898
+ if (await fs.pathExists(denoConfigPath)) return;
7040
6899
  const entries = await fs.readdir(dir, { withFileTypes: true });
7041
6900
  await Promise.all(entries.map(async (entry) => {
7042
6901
  const fullPath = path.join(dir, entry.name);
@@ -8260,13 +8119,13 @@ async function displayPostInstallInstructions(config) {
8260
8119
  const hasNative = frontend?.includes("native-bare") || frontend?.includes("native-uniwind") || frontend?.includes("native-unistyles");
8261
8120
  const bunWebNativeWarning = packageManager === "bun" && hasNative && hasWeb ? getBunWebNativeWarning() : "";
8262
8121
  const noOrmWarning = !isConvex && database !== "none" && orm === "none" ? getNoOrmWarning() : "";
8263
- const hasReactRouter = frontend?.includes("react-router");
8264
- const hasSvelte = frontend?.includes("svelte");
8265
- const webPort = hasReactRouter || hasSvelte ? "5173" : "3001";
8122
+ const hasFresh = frontend?.includes("fresh");
8123
+ const webPort = String(getLocalWebDevPort(frontend ?? []));
8266
8124
  const betterAuthConvexInstructions = isConvex && config.auth === "better-auth" ? getBetterAuthConvexInstructions(hasWeb ?? false, webPort, packageManager) : "";
8267
8125
  let output = `${pc.bold("Next steps")}\n${pc.cyan("1.")} ${cdCmd}\n`;
8268
8126
  let stepCounter = 2;
8269
8127
  if (!depsInstalled) output += `${pc.cyan(`${stepCounter++}.`)} ${packageManager} install\n`;
8128
+ if (hasFresh) output += `${pc.yellow("NOTE:")} Fresh projects require ${pc.white("deno")} on your PATH\n`;
8270
8129
  if (database === "sqlite" && dbSetup !== "d1") output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} db:local\n${pc.dim(" (optional - starts local SQLite database)")}\n`;
8271
8130
  if (isConvex) {
8272
8131
  output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} dev:setup\n${pc.dim(" (this will guide you through Convex project setup)")}\n`;
@@ -8908,7 +8767,7 @@ const router = os.router({
8908
8767
  yes: z.boolean().optional().default(false).describe("Use default configuration"),
8909
8768
  yolo: z.boolean().optional().default(false).describe("(WARNING - NOT RECOMMENDED) Bypass validations and compatibility checks"),
8910
8769
  verbose: z.boolean().optional().default(false).describe("Show detailed result information"),
8911
- ecosystem: types_exports.EcosystemSchema.optional().describe("Language ecosystem (typescript, rust, or python)"),
8770
+ ecosystem: types_exports.EcosystemSchema.optional().describe("Language ecosystem (typescript, rust, python, or go)"),
8912
8771
  database: types_exports.DatabaseSchema.optional(),
8913
8772
  orm: types_exports.ORMSchema.optional(),
8914
8773
  auth: types_exports.AuthSchema.optional(),
@@ -8926,6 +8785,7 @@ const router = os.router({
8926
8785
  animation: types_exports.AnimationSchema.optional(),
8927
8786
  logging: types_exports.LoggingSchema.optional(),
8928
8787
  observability: types_exports.ObservabilitySchema.optional(),
8788
+ featureFlags: types_exports.FeatureFlagsSchema.optional().describe("Feature flags provider"),
8929
8789
  analytics: types_exports.AnalyticsSchema.optional().describe("Privacy-focused analytics"),
8930
8790
  cms: types_exports.CMSSchema.optional().describe("Headless CMS solution"),
8931
8791
  caching: types_exports.CachingSchema.optional().describe("Caching solution"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-better-fullstack",
3
- "version": "1.4.5",
3
+ "version": "1.4.7",
4
4
  "description": "A CLI-first toolkit for building Full Stack applications. Skip the configuration. Ship the code.",
5
5
  "keywords": [
6
6
  "better-auth",
@@ -76,8 +76,8 @@
76
76
  "prepublishOnly": "npm run build"
77
77
  },
78
78
  "dependencies": {
79
- "@better-fullstack/template-generator": "^1.4.5",
80
- "@better-fullstack/types": "^1.4.5",
79
+ "@better-fullstack/template-generator": "^1.4.7",
80
+ "@better-fullstack/types": "^1.4.7",
81
81
  "@clack/core": "^0.5.0",
82
82
  "@clack/prompts": "^1.0.0-alpha.8",
83
83
  "@orpc/server": "^1.13.0",