create-better-fullstack 1.5.4 → 1.6.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.
@@ -1,11 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { s as dependencyVersionMap, t as readBtsConfig } from "./bts-config-BYD8mHt-.mjs";
2
+ import { s as dependencyVersionMap, t as readBtsConfig } from "./bts-config-snHxP_EH.mjs";
3
3
  import { autocompleteMultiselect, cancel, group, isCancel, log, multiselect, select, spinner } from "@clack/prompts";
4
4
  import pc from "picocolors";
5
5
  import fs from "fs-extra";
6
6
  import path from "node:path";
7
- import { getLocalWebDevPort } from "@better-fullstack/types";
8
- import consola, { consola as consola$1 } from "consola";
7
+ import consola from "consola";
9
8
  import { AsyncLocalStorage } from "node:async_hooks";
10
9
  import { $ } from "execa";
11
10
 
@@ -987,39 +986,16 @@ async function setupStarlight(config) {
987
986
 
988
987
  //#endregion
989
988
  //#region src/helpers/addons/tauri-setup.ts
990
- async function setupTauri(config) {
991
- const { packageManager, frontend, projectDir } = config;
992
- const s = spinner();
993
- const clientPackageDir = path.join(projectDir, "apps/web");
994
- if (!await fs.pathExists(clientPackageDir)) return;
995
- try {
996
- s.start("Setting up Tauri desktop app support...");
997
- const hasNuxt = frontend.includes("nuxt");
998
- const hasSvelte = frontend.includes("svelte");
999
- const hasNext = frontend.includes("next");
1000
- const devUrl = `http://localhost:${getLocalWebDevPort(frontend)}`;
1001
- const frontendDist = hasNuxt ? "../.output/public" : hasSvelte ? "../build" : hasNext ? "../.next" : frontend.includes("react-router") ? "../build/client" : frontend.includes("react-vite") ? "../dist" : "../dist";
1002
- const tauriArgs = [
1003
- "@tauri-apps/cli@latest",
1004
- "init",
1005
- `--app-name=${path.basename(projectDir)}`,
1006
- `--window-title=${path.basename(projectDir)}`,
1007
- `--frontend-dist=${frontendDist}`,
1008
- `--dev-url=${devUrl}`,
1009
- `--before-dev-command=${packageManager} run dev`,
1010
- `--before-build-command=${packageManager} run build`
1011
- ];
1012
- const prefix = getPackageRunnerPrefix(packageManager);
1013
- await $({
1014
- cwd: clientPackageDir,
1015
- env: { CI: "true" }
1016
- })`${[...prefix, ...tauriArgs]}`;
1017
- s.stop("Tauri desktop app support configured successfully!");
1018
- } catch (error) {
1019
- s.stop(pc.red("Failed to set up Tauri"));
1020
- if (error instanceof Error) consola$1.error(pc.red(error.message));
1021
- }
1022
- }
989
+ /**
990
+ * Tauri setup is now handled entirely by template generation.
991
+ * The src-tauri/ directory (tauri.conf.json, Cargo.toml, main.rs, lib.rs, etc.)
992
+ * is emitted by the addons template handler from templates/addons/tauri/.
993
+ * Dependencies (@tauri-apps/cli, @tauri-apps/api) and scripts (tauri, desktop:dev,
994
+ * desktop:build) are added by addons-deps.ts.
995
+ *
996
+ * This function is kept as a no-op for backward compatibility with addons-setup.ts.
997
+ */
998
+ async function setupTauri(_config) {}
1023
999
 
1024
1000
  //#endregion
1025
1001
  //#region src/helpers/addons/tui-setup.ts
@@ -1290,7 +1266,7 @@ async function setupAddons(config) {
1290
1266
  const hasSvelteFrontend = frontend.includes("svelte");
1291
1267
  const hasSolidFrontend = frontend.includes("solid");
1292
1268
  const hasNextFrontend = frontend.includes("next");
1293
- if (addons.includes("tauri") && (hasReactWebFrontend || hasNuxtFrontend || hasSvelteFrontend || hasSolidFrontend || hasNextFrontend)) await setupTauri(config);
1269
+ if (addons.includes("tauri") && (hasReactWebFrontend || hasNuxtFrontend || hasSvelteFrontend || hasSolidFrontend || hasNextFrontend)) await /* @__PURE__ */ setupTauri(config);
1294
1270
  const hasUltracite = addons.includes("ultracite");
1295
1271
  const hasBiome = addons.includes("biome");
1296
1272
  const hasHusky = addons.includes("husky");
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import "./bts-config-snHxP_EH.mjs";
3
+ import { i as setupLefthook, n as setupBiome, r as setupHusky, t as setupAddons } from "./addons-setup--oB72n29.mjs";
4
+
5
+ export { setupAddons };
@@ -38,6 +38,7 @@ const DEFAULT_CONFIG_BASE = {
38
38
  realtime: "none",
39
39
  jobQueue: "none",
40
40
  caching: "none",
41
+ i18n: "none",
41
42
  search: "none",
42
43
  fileStorage: "none",
43
44
  animation: "none",
@@ -73,11 +74,15 @@ const DEFAULT_CONFIG_BASE = {
73
74
  rustCli: "none",
74
75
  rustLibraries: [],
75
76
  rustLogging: "tracing",
77
+ rustErrorHandling: "anyhow-thiserror",
78
+ rustCaching: "none",
76
79
  pythonWebFramework: "fastapi",
77
80
  pythonOrm: "sqlalchemy",
78
81
  pythonValidation: "pydantic",
79
82
  pythonAi: [],
83
+ pythonAuth: "none",
80
84
  pythonTaskQueue: "none",
85
+ pythonGraphql: "none",
81
86
  pythonQuality: "ruff",
82
87
  goWebFramework: "gin",
83
88
  goOrm: "gorm",
@@ -174,6 +179,7 @@ async function writeBtsConfig(projectConfig) {
174
179
  analytics: projectConfig.analytics,
175
180
  cms: projectConfig.cms,
176
181
  caching: projectConfig.caching,
182
+ i18n: projectConfig.i18n,
177
183
  search: projectConfig.search,
178
184
  fileStorage: projectConfig.fileStorage,
179
185
  rustWebFramework: projectConfig.rustWebFramework,
@@ -183,11 +189,15 @@ async function writeBtsConfig(projectConfig) {
183
189
  rustCli: projectConfig.rustCli,
184
190
  rustLibraries: projectConfig.rustLibraries,
185
191
  rustLogging: projectConfig.rustLogging,
192
+ rustErrorHandling: projectConfig.rustErrorHandling,
193
+ rustCaching: projectConfig.rustCaching,
186
194
  pythonWebFramework: projectConfig.pythonWebFramework,
187
195
  pythonOrm: projectConfig.pythonOrm,
188
196
  pythonValidation: projectConfig.pythonValidation,
189
197
  pythonAi: projectConfig.pythonAi,
198
+ pythonAuth: projectConfig.pythonAuth,
190
199
  pythonTaskQueue: projectConfig.pythonTaskQueue,
200
+ pythonGraphql: projectConfig.pythonGraphql,
191
201
  pythonQuality: projectConfig.pythonQuality,
192
202
  goWebFramework: projectConfig.goWebFramework,
193
203
  goOrm: projectConfig.goOrm,
@@ -235,6 +245,7 @@ async function writeBtsConfig(projectConfig) {
235
245
  analytics: btsConfig.analytics,
236
246
  cms: btsConfig.cms,
237
247
  caching: btsConfig.caching,
248
+ i18n: btsConfig.i18n,
238
249
  search: btsConfig.search,
239
250
  fileStorage: btsConfig.fileStorage,
240
251
  rustWebFramework: btsConfig.rustWebFramework,
@@ -244,10 +255,13 @@ async function writeBtsConfig(projectConfig) {
244
255
  rustCli: btsConfig.rustCli,
245
256
  rustLibraries: btsConfig.rustLibraries,
246
257
  rustLogging: btsConfig.rustLogging,
258
+ rustErrorHandling: btsConfig.rustErrorHandling,
259
+ rustCaching: btsConfig.rustCaching,
247
260
  pythonWebFramework: btsConfig.pythonWebFramework,
248
261
  pythonOrm: btsConfig.pythonOrm,
249
262
  pythonValidation: btsConfig.pythonValidation,
250
263
  pythonAi: btsConfig.pythonAi,
264
+ pythonAuth: btsConfig.pythonAuth,
251
265
  pythonTaskQueue: btsConfig.pythonTaskQueue,
252
266
  pythonQuality: btsConfig.pythonQuality,
253
267
  goWebFramework: btsConfig.goWebFramework,
package/dist/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  //#region src/cli.ts
3
- if (process.argv[2] === "mcp" && process.argv.length === 3) import("./mcp-CRjipp-w.mjs").then((m) => m.startMcpServer());
3
+ if (process.argv[2] === "mcp" && process.argv.length === 3) import("./mcp-Bx_Esljk.mjs").then((m) => m.startMcpServer());
4
4
  else import("./index.mjs").then((m) => m.createBtsCli().run());
5
5
 
6
6
  //#endregion
package/dist/index.d.mts CHANGED
@@ -204,6 +204,11 @@ declare const router: {
204
204
  none: "none";
205
205
  "upstash-redis": "upstash-redis";
206
206
  }>>;
207
+ i18n: z.ZodOptional<z.ZodEnum<{
208
+ none: "none";
209
+ i18next: "i18next";
210
+ "next-intl": "next-intl";
211
+ }>>;
207
212
  search: z.ZodOptional<z.ZodEnum<{
208
213
  none: "none";
209
214
  meilisearch: "meilisearch";
@@ -325,6 +330,7 @@ declare const router: {
325
330
  orpc: "orpc";
326
331
  "ts-rest": "ts-rest";
327
332
  garph: "garph";
333
+ "graphql-yoga": "graphql-yoga";
328
334
  }>>;
329
335
  cssFramework: z.ZodOptional<z.ZodEnum<{
330
336
  none: "none";
@@ -422,6 +428,7 @@ declare const router: {
422
428
  fly: "fly";
423
429
  railway: "railway";
424
430
  sst: "sst";
431
+ vercel: "vercel";
425
432
  }>>;
426
433
  serverDeploy: z.ZodOptional<z.ZodEnum<{
427
434
  none: "none";
@@ -430,6 +437,7 @@ declare const router: {
430
437
  fly: "fly";
431
438
  railway: "railway";
432
439
  sst: "sst";
440
+ vercel: "vercel";
433
441
  }>>;
434
442
  directoryConflict: z.ZodOptional<z.ZodEnum<{
435
443
  merge: "merge";
@@ -444,6 +452,7 @@ declare const router: {
444
452
  none: "none";
445
453
  axum: "axum";
446
454
  "actix-web": "actix-web";
455
+ rocket: "rocket";
447
456
  }>>;
448
457
  rustFrontend: z.ZodOptional<z.ZodEnum<{
449
458
  none: "none";
@@ -454,6 +463,7 @@ declare const router: {
454
463
  none: "none";
455
464
  "sea-orm": "sea-orm";
456
465
  sqlx: "sqlx";
466
+ diesel: "diesel";
457
467
  }>>;
458
468
  rustApi: z.ZodOptional<z.ZodEnum<{
459
469
  none: "none";
@@ -479,11 +489,22 @@ declare const router: {
479
489
  tracing: "tracing";
480
490
  "env-logger": "env-logger";
481
491
  }>>;
492
+ rustErrorHandling: z.ZodOptional<z.ZodEnum<{
493
+ none: "none";
494
+ "anyhow-thiserror": "anyhow-thiserror";
495
+ eyre: "eyre";
496
+ }>>;
497
+ rustCaching: z.ZodOptional<z.ZodEnum<{
498
+ none: "none";
499
+ redis: "redis";
500
+ moka: "moka";
501
+ }>>;
482
502
  pythonWebFramework: z.ZodOptional<z.ZodEnum<{
483
503
  none: "none";
484
504
  fastapi: "fastapi";
485
505
  django: "django";
486
506
  flask: "flask";
507
+ litestar: "litestar";
487
508
  }>>;
488
509
  pythonOrm: z.ZodOptional<z.ZodEnum<{
489
510
  none: "none";
@@ -503,10 +524,19 @@ declare const router: {
503
524
  "anthropic-sdk": "anthropic-sdk";
504
525
  crewai: "crewai";
505
526
  }>>>;
527
+ pythonAuth: z.ZodOptional<z.ZodEnum<{
528
+ none: "none";
529
+ authlib: "authlib";
530
+ jwt: "jwt";
531
+ }>>;
506
532
  pythonTaskQueue: z.ZodOptional<z.ZodEnum<{
507
533
  none: "none";
508
534
  celery: "celery";
509
535
  }>>;
536
+ pythonGraphql: z.ZodOptional<z.ZodEnum<{
537
+ none: "none";
538
+ strawberry: "strawberry";
539
+ }>>;
510
540
  pythonQuality: z.ZodOptional<z.ZodEnum<{
511
541
  none: "none";
512
542
  ruff: "ruff";
@@ -516,11 +546,13 @@ declare const router: {
516
546
  gin: "gin";
517
547
  echo: "echo";
518
548
  fiber: "fiber";
549
+ chi: "chi";
519
550
  }>>;
520
551
  goOrm: z.ZodOptional<z.ZodEnum<{
521
552
  none: "none";
522
553
  gorm: "gorm";
523
554
  sqlc: "sqlc";
555
+ ent: "ent";
524
556
  }>>;
525
557
  goApi: z.ZodOptional<z.ZodEnum<{
526
558
  none: "none";
@@ -534,6 +566,8 @@ declare const router: {
534
566
  goLogging: z.ZodOptional<z.ZodEnum<{
535
567
  none: "none";
536
568
  zap: "zap";
569
+ zerolog: "zerolog";
570
+ slog: "slog";
537
571
  }>>;
538
572
  aiDocs: z.ZodOptional<z.ZodArray<z.ZodEnum<{
539
573
  none: "none";
@@ -562,9 +596,9 @@ declare const router: {
562
596
  versionChannel: "stable" | "latest" | "beta";
563
597
  install: boolean;
564
598
  dbSetup: "none" | "turso" | "neon" | "prisma-postgres" | "planetscale" | "mongodb-atlas" | "supabase" | "upstash" | "d1" | "docker";
565
- api: "none" | "trpc" | "orpc" | "ts-rest" | "garph";
566
- webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst";
567
- serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst";
599
+ api: "none" | "trpc" | "orpc" | "ts-rest" | "garph" | "graphql-yoga";
600
+ webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
601
+ serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
568
602
  ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai";
569
603
  effect: "effect" | "none" | "effect-full";
570
604
  stateManagement: "none" | "zustand" | "jotai" | "nanostores" | "redux-toolkit" | "mobx" | "xstate" | "valtio" | "tanstack-store" | "legend-state";
@@ -584,26 +618,31 @@ declare const router: {
584
618
  analytics: "none" | "plausible" | "umami";
585
619
  cms: "none" | "payload" | "sanity" | "strapi" | "tinacms";
586
620
  caching: "none" | "upstash-redis";
621
+ i18n: "none" | "i18next" | "next-intl";
587
622
  search: "none" | "meilisearch" | "typesense" | "elasticsearch" | "algolia";
588
623
  fileStorage: "none" | "s3" | "r2";
589
- rustWebFramework: "none" | "axum" | "actix-web";
624
+ rustWebFramework: "none" | "axum" | "actix-web" | "rocket";
590
625
  rustFrontend: "none" | "leptos" | "dioxus";
591
- rustOrm: "none" | "sea-orm" | "sqlx";
626
+ rustOrm: "none" | "sea-orm" | "sqlx" | "diesel";
592
627
  rustApi: "none" | "tonic" | "async-graphql";
593
628
  rustCli: "none" | "clap" | "ratatui";
594
629
  rustLibraries: ("none" | "serde" | "validator" | "jsonwebtoken" | "argon2" | "tokio-test" | "mockall")[];
595
630
  rustLogging: "none" | "tracing" | "env-logger";
596
- pythonWebFramework: "none" | "fastapi" | "django" | "flask";
631
+ rustErrorHandling: "none" | "anyhow-thiserror" | "eyre";
632
+ rustCaching: "none" | "redis" | "moka";
633
+ pythonWebFramework: "none" | "fastapi" | "django" | "flask" | "litestar";
597
634
  pythonOrm: "none" | "sqlalchemy" | "sqlmodel";
598
635
  pythonValidation: "none" | "pydantic";
599
636
  pythonAi: ("none" | "langgraph" | "langchain" | "llamaindex" | "openai-sdk" | "anthropic-sdk" | "crewai")[];
637
+ pythonAuth: "none" | "authlib" | "jwt";
600
638
  pythonTaskQueue: "none" | "celery";
639
+ pythonGraphql: "none" | "strawberry";
601
640
  pythonQuality: "none" | "ruff";
602
- goWebFramework: "none" | "gin" | "echo" | "fiber";
603
- goOrm: "none" | "gorm" | "sqlc";
641
+ goWebFramework: "none" | "gin" | "echo" | "fiber" | "chi";
642
+ goOrm: "none" | "gorm" | "sqlc" | "ent";
604
643
  goApi: "none" | "grpc-go";
605
644
  goCli: "none" | "cobra" | "bubbletea";
606
- goLogging: "none" | "zap";
645
+ goLogging: "none" | "zap" | "zerolog" | "slog";
607
646
  aiDocs: ("none" | "claude-md" | "agents-md" | "cursorrules")[];
608
647
  astroIntegration?: "none" | "svelte" | "solid" | "react" | "vue" | undefined;
609
648
  shadcnBase?: "radix" | "base" | undefined;
@@ -645,9 +684,9 @@ declare const router: {
645
684
  versionChannel: "stable" | "latest" | "beta";
646
685
  install: boolean;
647
686
  dbSetup: "none" | "turso" | "neon" | "prisma-postgres" | "planetscale" | "mongodb-atlas" | "supabase" | "upstash" | "d1" | "docker";
648
- api: "none" | "trpc" | "orpc" | "ts-rest" | "garph";
649
- webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst";
650
- serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst";
687
+ api: "none" | "trpc" | "orpc" | "ts-rest" | "garph" | "graphql-yoga";
688
+ webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
689
+ serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
651
690
  ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai";
652
691
  effect: "effect" | "none" | "effect-full";
653
692
  stateManagement: "none" | "zustand" | "jotai" | "nanostores" | "redux-toolkit" | "mobx" | "xstate" | "valtio" | "tanstack-store" | "legend-state";
@@ -667,26 +706,31 @@ declare const router: {
667
706
  analytics: "none" | "plausible" | "umami";
668
707
  cms: "none" | "payload" | "sanity" | "strapi" | "tinacms";
669
708
  caching: "none" | "upstash-redis";
709
+ i18n: "none" | "i18next" | "next-intl";
670
710
  search: "none" | "meilisearch" | "typesense" | "elasticsearch" | "algolia";
671
711
  fileStorage: "none" | "s3" | "r2";
672
- rustWebFramework: "none" | "axum" | "actix-web";
712
+ rustWebFramework: "none" | "axum" | "actix-web" | "rocket";
673
713
  rustFrontend: "none" | "leptos" | "dioxus";
674
- rustOrm: "none" | "sea-orm" | "sqlx";
714
+ rustOrm: "none" | "sea-orm" | "sqlx" | "diesel";
675
715
  rustApi: "none" | "tonic" | "async-graphql";
676
716
  rustCli: "none" | "clap" | "ratatui";
677
717
  rustLibraries: ("none" | "serde" | "validator" | "jsonwebtoken" | "argon2" | "tokio-test" | "mockall")[];
678
718
  rustLogging: "none" | "tracing" | "env-logger";
679
- pythonWebFramework: "none" | "fastapi" | "django" | "flask";
719
+ rustErrorHandling: "none" | "anyhow-thiserror" | "eyre";
720
+ rustCaching: "none" | "redis" | "moka";
721
+ pythonWebFramework: "none" | "fastapi" | "django" | "flask" | "litestar";
680
722
  pythonOrm: "none" | "sqlalchemy" | "sqlmodel";
681
723
  pythonValidation: "none" | "pydantic";
682
724
  pythonAi: ("none" | "langgraph" | "langchain" | "llamaindex" | "openai-sdk" | "anthropic-sdk" | "crewai")[];
725
+ pythonAuth: "none" | "authlib" | "jwt";
683
726
  pythonTaskQueue: "none" | "celery";
727
+ pythonGraphql: "none" | "strawberry";
684
728
  pythonQuality: "none" | "ruff";
685
- goWebFramework: "none" | "gin" | "echo" | "fiber";
686
- goOrm: "none" | "gorm" | "sqlc";
729
+ goWebFramework: "none" | "gin" | "echo" | "fiber" | "chi";
730
+ goOrm: "none" | "gorm" | "sqlc" | "ent";
687
731
  goApi: "none" | "grpc-go";
688
732
  goCli: "none" | "cobra" | "bubbletea";
689
- goLogging: "none" | "zap";
733
+ goLogging: "none" | "zap" | "zerolog" | "slog";
690
734
  aiDocs: ("none" | "claude-md" | "agents-md" | "cursorrules")[];
691
735
  astroIntegration?: "none" | "svelte" | "solid" | "react" | "vue" | undefined;
692
736
  shadcnBase?: "radix" | "base" | undefined;
@@ -741,9 +785,9 @@ declare const router: {
741
785
  versionChannel: "stable" | "latest" | "beta";
742
786
  install: boolean;
743
787
  dbSetup: "none" | "turso" | "neon" | "prisma-postgres" | "planetscale" | "mongodb-atlas" | "supabase" | "upstash" | "d1" | "docker";
744
- api: "none" | "trpc" | "orpc" | "ts-rest" | "garph";
745
- webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst";
746
- serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst";
788
+ api: "none" | "trpc" | "orpc" | "ts-rest" | "garph" | "graphql-yoga";
789
+ webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
790
+ serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
747
791
  ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai";
748
792
  effect: "effect" | "none" | "effect-full";
749
793
  stateManagement: "none" | "zustand" | "jotai" | "nanostores" | "redux-toolkit" | "mobx" | "xstate" | "valtio" | "tanstack-store" | "legend-state";
@@ -763,26 +807,31 @@ declare const router: {
763
807
  analytics: "none" | "plausible" | "umami";
764
808
  cms: "none" | "payload" | "sanity" | "strapi" | "tinacms";
765
809
  caching: "none" | "upstash-redis";
810
+ i18n: "none" | "i18next" | "next-intl";
766
811
  search: "none" | "meilisearch" | "typesense" | "elasticsearch" | "algolia";
767
812
  fileStorage: "none" | "s3" | "r2";
768
- rustWebFramework: "none" | "axum" | "actix-web";
813
+ rustWebFramework: "none" | "axum" | "actix-web" | "rocket";
769
814
  rustFrontend: "none" | "leptos" | "dioxus";
770
- rustOrm: "none" | "sea-orm" | "sqlx";
815
+ rustOrm: "none" | "sea-orm" | "sqlx" | "diesel";
771
816
  rustApi: "none" | "tonic" | "async-graphql";
772
817
  rustCli: "none" | "clap" | "ratatui";
773
818
  rustLibraries: ("none" | "serde" | "validator" | "jsonwebtoken" | "argon2" | "tokio-test" | "mockall")[];
774
819
  rustLogging: "none" | "tracing" | "env-logger";
775
- pythonWebFramework: "none" | "fastapi" | "django" | "flask";
820
+ rustErrorHandling: "none" | "anyhow-thiserror" | "eyre";
821
+ rustCaching: "none" | "redis" | "moka";
822
+ pythonWebFramework: "none" | "fastapi" | "django" | "flask" | "litestar";
776
823
  pythonOrm: "none" | "sqlalchemy" | "sqlmodel";
777
824
  pythonValidation: "none" | "pydantic";
778
825
  pythonAi: ("none" | "langgraph" | "langchain" | "llamaindex" | "openai-sdk" | "anthropic-sdk" | "crewai")[];
826
+ pythonAuth: "none" | "authlib" | "jwt";
779
827
  pythonTaskQueue: "none" | "celery";
828
+ pythonGraphql: "none" | "strawberry";
780
829
  pythonQuality: "none" | "ruff";
781
- goWebFramework: "none" | "gin" | "echo" | "fiber";
782
- goOrm: "none" | "gorm" | "sqlc";
830
+ goWebFramework: "none" | "gin" | "echo" | "fiber" | "chi";
831
+ goOrm: "none" | "gorm" | "sqlc" | "ent";
783
832
  goApi: "none" | "grpc-go";
784
833
  goCli: "none" | "cobra" | "bubbletea";
785
- goLogging: "none" | "zap";
834
+ goLogging: "none" | "zap" | "zerolog" | "slog";
786
835
  aiDocs: ("none" | "claude-md" | "agents-md" | "cursorrules")[];
787
836
  astroIntegration?: "none" | "svelte" | "solid" | "react" | "vue" | undefined;
788
837
  shadcnBase?: "radix" | "base" | undefined;
@@ -824,9 +873,9 @@ declare const router: {
824
873
  versionChannel: "stable" | "latest" | "beta";
825
874
  install: boolean;
826
875
  dbSetup: "none" | "turso" | "neon" | "prisma-postgres" | "planetscale" | "mongodb-atlas" | "supabase" | "upstash" | "d1" | "docker";
827
- api: "none" | "trpc" | "orpc" | "ts-rest" | "garph";
828
- webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst";
829
- serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst";
876
+ api: "none" | "trpc" | "orpc" | "ts-rest" | "garph" | "graphql-yoga";
877
+ webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
878
+ serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
830
879
  ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai";
831
880
  effect: "effect" | "none" | "effect-full";
832
881
  stateManagement: "none" | "zustand" | "jotai" | "nanostores" | "redux-toolkit" | "mobx" | "xstate" | "valtio" | "tanstack-store" | "legend-state";
@@ -846,26 +895,31 @@ declare const router: {
846
895
  analytics: "none" | "plausible" | "umami";
847
896
  cms: "none" | "payload" | "sanity" | "strapi" | "tinacms";
848
897
  caching: "none" | "upstash-redis";
898
+ i18n: "none" | "i18next" | "next-intl";
849
899
  search: "none" | "meilisearch" | "typesense" | "elasticsearch" | "algolia";
850
900
  fileStorage: "none" | "s3" | "r2";
851
- rustWebFramework: "none" | "axum" | "actix-web";
901
+ rustWebFramework: "none" | "axum" | "actix-web" | "rocket";
852
902
  rustFrontend: "none" | "leptos" | "dioxus";
853
- rustOrm: "none" | "sea-orm" | "sqlx";
903
+ rustOrm: "none" | "sea-orm" | "sqlx" | "diesel";
854
904
  rustApi: "none" | "tonic" | "async-graphql";
855
905
  rustCli: "none" | "clap" | "ratatui";
856
906
  rustLibraries: ("none" | "serde" | "validator" | "jsonwebtoken" | "argon2" | "tokio-test" | "mockall")[];
857
907
  rustLogging: "none" | "tracing" | "env-logger";
858
- pythonWebFramework: "none" | "fastapi" | "django" | "flask";
908
+ rustErrorHandling: "none" | "anyhow-thiserror" | "eyre";
909
+ rustCaching: "none" | "redis" | "moka";
910
+ pythonWebFramework: "none" | "fastapi" | "django" | "flask" | "litestar";
859
911
  pythonOrm: "none" | "sqlalchemy" | "sqlmodel";
860
912
  pythonValidation: "none" | "pydantic";
861
913
  pythonAi: ("none" | "langgraph" | "langchain" | "llamaindex" | "openai-sdk" | "anthropic-sdk" | "crewai")[];
914
+ pythonAuth: "none" | "authlib" | "jwt";
862
915
  pythonTaskQueue: "none" | "celery";
916
+ pythonGraphql: "none" | "strawberry";
863
917
  pythonQuality: "none" | "ruff";
864
- goWebFramework: "none" | "gin" | "echo" | "fiber";
865
- goOrm: "none" | "gorm" | "sqlc";
918
+ goWebFramework: "none" | "gin" | "echo" | "fiber" | "chi";
919
+ goOrm: "none" | "gorm" | "sqlc" | "ent";
866
920
  goApi: "none" | "grpc-go";
867
921
  goCli: "none" | "cobra" | "bubbletea";
868
- goLogging: "none" | "zap";
922
+ goLogging: "none" | "zap" | "zerolog" | "slog";
869
923
  aiDocs: ("none" | "claude-md" | "agents-md" | "cursorrules")[];
870
924
  astroIntegration?: "none" | "svelte" | "solid" | "react" | "vue" | undefined;
871
925
  shadcnBase?: "radix" | "base" | undefined;
@@ -936,6 +990,7 @@ declare const router: {
936
990
  fly: "fly";
937
991
  railway: "railway";
938
992
  sst: "sst";
993
+ vercel: "vercel";
939
994
  }>>;
940
995
  serverDeploy: z.ZodOptional<z.ZodEnum<{
941
996
  none: "none";
@@ -944,6 +999,7 @@ declare const router: {
944
999
  fly: "fly";
945
1000
  railway: "railway";
946
1001
  sst: "sst";
1002
+ vercel: "vercel";
947
1003
  }>>;
948
1004
  install: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
949
1005
  packageManager: z.ZodOptional<z.ZodEnum<{
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { t as __reExport } from "./chunk-CCII7kTE.mjs";
3
- import { a as DEFAULT_CONFIG, c as getDefaultConfig, i as getLatestCLIVersion, l as getUserPkgManager, n as updateBtsConfig, o as DEFAULT_UI_LIBRARY_BY_FRONTEND, r as writeBtsConfig, t as readBtsConfig } from "./bts-config-BYD8mHt-.mjs";
4
- import { _ as setLastPromptShownUI, a as getPackageExecutionArgs, c as UserCancelledError, d as handleError, f as didLastPromptShowUI, g as setIsFirstPrompt$1, h as runWithContextAsync, l as exitCancelled, m as isSilent, o as addPackageDependency, p as isFirstPrompt, s as CLIError, t as setupAddons, u as exitWithError } from "./addons-setup-Bll5VFJd.mjs";
3
+ import { a as DEFAULT_CONFIG, c as getDefaultConfig, i as getLatestCLIVersion, l as getUserPkgManager, n as updateBtsConfig, o as DEFAULT_UI_LIBRARY_BY_FRONTEND, r as writeBtsConfig, t as readBtsConfig } from "./bts-config-snHxP_EH.mjs";
4
+ import { _ as setLastPromptShownUI, a as getPackageExecutionArgs, c as UserCancelledError, d as handleError, f as didLastPromptShowUI, g as setIsFirstPrompt$1, h as runWithContextAsync, l as exitCancelled, m as isSilent, o as addPackageDependency, p as isFirstPrompt, s as CLIError, t as setupAddons, u as exitWithError } from "./addons-setup--oB72n29.mjs";
5
5
  import { cancel, confirm, intro, isCancel, log, outro, select, spinner, text } from "@clack/prompts";
6
6
  import { createRouterClient, os } from "@orpc/server";
7
7
  import pc from "picocolors";
@@ -1720,6 +1720,11 @@ async function getApiChoice(Api, frontend, backend, astroIntegration) {
1720
1720
  label: "Garph",
1721
1721
  hint: "Fullstack GraphQL framework with end-to-end type safety"
1722
1722
  },
1723
+ "graphql-yoga": {
1724
+ value: "graphql-yoga",
1725
+ label: "GraphQL Yoga",
1726
+ hint: "Batteries-included GraphQL server with Pothos schema builder"
1727
+ },
1723
1728
  none: {
1724
1729
  value: "none",
1725
1730
  label: "None",
@@ -2618,6 +2623,11 @@ async function getGoWebFrameworkChoice(goWebFramework) {
2618
2623
  label: "Fiber",
2619
2624
  hint: "Express-inspired web framework built on Fasthttp"
2620
2625
  },
2626
+ {
2627
+ value: "chi",
2628
+ label: "Chi",
2629
+ hint: "Lightweight, zero-dependency router built on net/http"
2630
+ },
2621
2631
  {
2622
2632
  value: "none",
2623
2633
  label: "None",
@@ -2644,6 +2654,11 @@ async function getGoOrmChoice(goOrm) {
2644
2654
  label: "sqlc",
2645
2655
  hint: "Generate type-safe Go code from SQL"
2646
2656
  },
2657
+ {
2658
+ value: "ent",
2659
+ label: "Ent",
2660
+ hint: "Code-first ORM by Meta with graph traversal API, 15k+ stars"
2661
+ },
2647
2662
  {
2648
2663
  value: "none",
2649
2664
  label: "None",
@@ -2703,21 +2718,63 @@ async function getGoLoggingChoice(goLogging) {
2703
2718
  if (goLogging !== void 0) return goLogging;
2704
2719
  const response = await navigableSelect({
2705
2720
  message: "Select Go logging library",
2706
- options: [{
2707
- value: "zap",
2708
- label: "Zap",
2709
- hint: "Blazing fast, structured, leveled logging in Go"
2710
- }, {
2711
- value: "none",
2712
- label: "None",
2713
- hint: "No logging library"
2714
- }],
2721
+ options: [
2722
+ {
2723
+ value: "zap",
2724
+ label: "Zap",
2725
+ hint: "Blazing fast, structured, leveled logging in Go"
2726
+ },
2727
+ {
2728
+ value: "zerolog",
2729
+ label: "Zerolog",
2730
+ hint: "Zero-allocation JSON logger, fastest in benchmarks"
2731
+ },
2732
+ {
2733
+ value: "slog",
2734
+ label: "slog",
2735
+ hint: "Go 1.21+ stdlib structured logging (no external dependency)"
2736
+ },
2737
+ {
2738
+ value: "none",
2739
+ label: "None",
2740
+ hint: "No logging library"
2741
+ }
2742
+ ],
2715
2743
  initialValue: "zap"
2716
2744
  });
2717
2745
  if (isCancel$1(response)) return exitCancelled("Operation cancelled");
2718
2746
  return response;
2719
2747
  }
2720
2748
 
2749
+ //#endregion
2750
+ //#region src/prompts/i18n.ts
2751
+ async function getI18nChoice(i18n, frontend) {
2752
+ if (i18n !== void 0) return i18n;
2753
+ const response = await navigableSelect({
2754
+ message: "Select internationalization (i18n) library",
2755
+ options: [
2756
+ {
2757
+ value: "i18next",
2758
+ label: "i18next",
2759
+ hint: "Full-featured i18n framework, works with all frontends"
2760
+ },
2761
+ ...frontend?.includes("next") ?? false ? [{
2762
+ value: "next-intl",
2763
+ label: "next-intl",
2764
+ hint: "Lightweight i18n for Next.js with App Router support"
2765
+ }] : [],
2766
+ {
2767
+ value: "none",
2768
+ label: "None",
2769
+ hint: "No internationalization setup"
2770
+ }
2771
+ ],
2772
+ initialValue: "none"
2773
+ });
2774
+ if (isCancel$1(response)) return exitCancelled("Operation cancelled");
2775
+ return response;
2776
+ }
2777
+
2721
2778
  //#endregion
2722
2779
  //#region src/utils/command-exists.ts
2723
2780
  async function commandExists(command) {
@@ -3098,6 +3155,11 @@ async function getPythonWebFrameworkChoice(pythonWebFramework) {
3098
3155
  label: "Flask",
3099
3156
  hint: "Lightweight WSGI web framework with minimal boilerplate"
3100
3157
  },
3158
+ {
3159
+ value: "litestar",
3160
+ label: "Litestar",
3161
+ hint: "High-performance ASGI framework with class-based controllers"
3162
+ },
3101
3163
  {
3102
3164
  value: "none",
3103
3165
  label: "None",
@@ -3201,6 +3263,32 @@ async function getPythonAiChoice(pythonAi) {
3201
3263
  if (response.includes("none")) return [];
3202
3264
  return response;
3203
3265
  }
3266
+ async function getPythonAuthChoice(pythonAuth) {
3267
+ if (pythonAuth !== void 0) return pythonAuth;
3268
+ const response = await navigableSelect({
3269
+ message: "Select Python authentication library",
3270
+ options: [
3271
+ {
3272
+ value: "authlib",
3273
+ label: "Authlib",
3274
+ hint: "Comprehensive auth library — OAuth1/2, OIDC, JWS, JWK, JWT"
3275
+ },
3276
+ {
3277
+ value: "jwt",
3278
+ label: "JWT (python-jose)",
3279
+ hint: "Simple JWT token creation and verification"
3280
+ },
3281
+ {
3282
+ value: "none",
3283
+ label: "None",
3284
+ hint: "No authentication library"
3285
+ }
3286
+ ],
3287
+ initialValue: "none"
3288
+ });
3289
+ if (isCancel$1(response)) return exitCancelled("Operation cancelled");
3290
+ return response;
3291
+ }
3204
3292
  async function getPythonTaskQueueChoice(pythonTaskQueue) {
3205
3293
  if (pythonTaskQueue !== void 0) return pythonTaskQueue;
3206
3294
  const response = await navigableSelect({
@@ -3219,6 +3307,24 @@ async function getPythonTaskQueueChoice(pythonTaskQueue) {
3219
3307
  if (isCancel$1(response)) return exitCancelled("Operation cancelled");
3220
3308
  return response;
3221
3309
  }
3310
+ async function getPythonGraphqlChoice(pythonGraphql) {
3311
+ if (pythonGraphql !== void 0) return pythonGraphql;
3312
+ const response = await navigableSelect({
3313
+ message: "Select Python GraphQL framework",
3314
+ options: [{
3315
+ value: "strawberry",
3316
+ label: "Strawberry",
3317
+ hint: "Python GraphQL library using dataclasses and type hints"
3318
+ }, {
3319
+ value: "none",
3320
+ label: "None",
3321
+ hint: "No GraphQL framework"
3322
+ }],
3323
+ initialValue: "none"
3324
+ });
3325
+ if (isCancel$1(response)) return exitCancelled("Operation cancelled");
3326
+ return response;
3327
+ }
3222
3328
  async function getPythonQualityChoice(pythonQuality) {
3223
3329
  if (pythonQuality !== void 0) return pythonQuality;
3224
3330
  const response = await navigableSelect({
@@ -3333,6 +3439,11 @@ async function getRustWebFrameworkChoice(rustWebFramework) {
3333
3439
  label: "Actix Web",
3334
3440
  hint: "Powerful, pragmatic, and extremely fast web framework"
3335
3441
  },
3442
+ {
3443
+ value: "rocket",
3444
+ label: "Rocket",
3445
+ hint: "Convention-over-configuration web framework, 25k+ stars"
3446
+ },
3336
3447
  {
3337
3448
  value: "none",
3338
3449
  label: "None",
@@ -3385,6 +3496,11 @@ async function getRustOrmChoice(rustOrm) {
3385
3496
  label: "SQLx",
3386
3497
  hint: "Async SQL toolkit with compile-time checked queries"
3387
3498
  },
3499
+ {
3500
+ value: "diesel",
3501
+ label: "Diesel",
3502
+ hint: "Safe, extensible ORM with compile-time query validation"
3503
+ },
3388
3504
  {
3389
3505
  value: "none",
3390
3506
  label: "None",
@@ -3516,6 +3632,58 @@ async function getRustLoggingChoice(rustLogging) {
3516
3632
  if (isCancel$1(response)) return exitCancelled("Operation cancelled");
3517
3633
  return response;
3518
3634
  }
3635
+ async function getRustErrorHandlingChoice(rustErrorHandling) {
3636
+ if (rustErrorHandling !== void 0) return rustErrorHandling;
3637
+ const response = await navigableSelect({
3638
+ message: "Select Rust error handling library",
3639
+ options: [
3640
+ {
3641
+ value: "anyhow-thiserror",
3642
+ label: "anyhow + thiserror",
3643
+ hint: "anyhow for application errors, thiserror for custom error types"
3644
+ },
3645
+ {
3646
+ value: "eyre",
3647
+ label: "eyre + color-eyre",
3648
+ hint: "Customizable error reports with pretty backtraces via color-eyre"
3649
+ },
3650
+ {
3651
+ value: "none",
3652
+ label: "None",
3653
+ hint: "No error handling library (uses standard library only)"
3654
+ }
3655
+ ],
3656
+ initialValue: "anyhow-thiserror"
3657
+ });
3658
+ if (isCancel$1(response)) return exitCancelled("Operation cancelled");
3659
+ return response;
3660
+ }
3661
+ async function getRustCachingChoice(rustCaching) {
3662
+ if (rustCaching !== void 0) return rustCaching;
3663
+ const response = await navigableSelect({
3664
+ message: "Select Rust caching library",
3665
+ options: [
3666
+ {
3667
+ value: "moka",
3668
+ label: "Moka",
3669
+ hint: "High-performance concurrent in-memory cache (Caffeine-inspired)"
3670
+ },
3671
+ {
3672
+ value: "redis",
3673
+ label: "Redis",
3674
+ hint: "Redis client with async support and connection pooling"
3675
+ },
3676
+ {
3677
+ value: "none",
3678
+ label: "None",
3679
+ hint: "No caching library"
3680
+ }
3681
+ ],
3682
+ initialValue: "none"
3683
+ });
3684
+ if (isCancel$1(response)) return exitCancelled("Operation cancelled");
3685
+ return response;
3686
+ }
3519
3687
 
3520
3688
  //#endregion
3521
3689
  //#region src/prompts/search.ts
@@ -4220,6 +4388,10 @@ function getDeploymentDisplay(deployment) {
4220
4388
  label: "Cloudflare",
4221
4389
  hint: "Deploy to Cloudflare Workers using Alchemy"
4222
4390
  };
4391
+ if (deployment === "vercel") return {
4392
+ label: "Vercel",
4393
+ hint: "Deploy to Vercel's edge network"
4394
+ };
4223
4395
  return {
4224
4396
  label: deployment,
4225
4397
  hint: `Add ${deployment} deployment`
@@ -4230,7 +4402,11 @@ async function getDeploymentChoice(deployment, _runtime, _backend, frontend = []
4230
4402
  if (!hasWebFrontend(frontend)) return "none";
4231
4403
  const response = await navigableSelect({
4232
4404
  message: "Select web deployment",
4233
- options: ["cloudflare", "none"].map((deploy) => {
4405
+ options: [
4406
+ "cloudflare",
4407
+ "vercel",
4408
+ "none"
4409
+ ].map((deploy) => {
4234
4410
  const { label, hint } = getDeploymentDisplay(deploy);
4235
4411
  return {
4236
4412
  value: deploy,
@@ -4398,6 +4574,10 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
4398
4574
  if (results.ecosystem !== "typescript") return Promise.resolve("none");
4399
4575
  return getCachingChoice(flags.caching, results.backend);
4400
4576
  },
4577
+ i18n: ({ results }) => {
4578
+ if (results.ecosystem !== "typescript") return Promise.resolve("none");
4579
+ return getI18nChoice(flags.i18n, results.frontend);
4580
+ },
4401
4581
  search: ({ results }) => {
4402
4582
  if (results.ecosystem !== "typescript") return Promise.resolve("none");
4403
4583
  return getSearchChoice(flags.search, results.backend);
@@ -4434,6 +4614,14 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
4434
4614
  if (results.ecosystem !== "rust") return Promise.resolve("none");
4435
4615
  return getRustLoggingChoice(flags.rustLogging);
4436
4616
  },
4617
+ rustErrorHandling: ({ results }) => {
4618
+ if (results.ecosystem !== "rust") return Promise.resolve("none");
4619
+ return getRustErrorHandlingChoice(flags.rustErrorHandling);
4620
+ },
4621
+ rustCaching: ({ results }) => {
4622
+ if (results.ecosystem !== "rust") return Promise.resolve("none");
4623
+ return getRustCachingChoice(flags.rustCaching);
4624
+ },
4437
4625
  pythonWebFramework: ({ results }) => {
4438
4626
  if (results.ecosystem !== "python") return Promise.resolve("none");
4439
4627
  return getPythonWebFrameworkChoice(flags.pythonWebFramework);
@@ -4450,10 +4638,18 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
4450
4638
  if (results.ecosystem !== "python") return Promise.resolve([]);
4451
4639
  return getPythonAiChoice(flags.pythonAi);
4452
4640
  },
4641
+ pythonAuth: ({ results }) => {
4642
+ if (results.ecosystem !== "python") return Promise.resolve("none");
4643
+ return getPythonAuthChoice(flags.pythonAuth);
4644
+ },
4453
4645
  pythonTaskQueue: ({ results }) => {
4454
4646
  if (results.ecosystem !== "python") return Promise.resolve("none");
4455
4647
  return getPythonTaskQueueChoice(flags.pythonTaskQueue);
4456
4648
  },
4649
+ pythonGraphql: ({ results }) => {
4650
+ if (results.ecosystem !== "python") return Promise.resolve("none");
4651
+ return getPythonGraphqlChoice(flags.pythonGraphql);
4652
+ },
4457
4653
  pythonQuality: ({ results }) => {
4458
4654
  if (results.ecosystem !== "python") return Promise.resolve("none");
4459
4655
  return getPythonQualityChoice(flags.pythonQuality);
@@ -4527,6 +4723,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
4527
4723
  analytics: result.analytics,
4528
4724
  cms: result.cms,
4529
4725
  caching: result.caching,
4726
+ i18n: result.i18n,
4530
4727
  search: result.search,
4531
4728
  fileStorage: result.fileStorage,
4532
4729
  ecosystem: result.ecosystem,
@@ -4537,11 +4734,15 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
4537
4734
  rustCli: result.rustCli,
4538
4735
  rustLibraries: result.rustLibraries,
4539
4736
  rustLogging: result.rustLogging,
4737
+ rustErrorHandling: result.rustErrorHandling,
4738
+ rustCaching: result.rustCaching,
4540
4739
  pythonWebFramework: result.pythonWebFramework,
4541
4740
  pythonOrm: result.pythonOrm,
4542
4741
  pythonValidation: result.pythonValidation,
4543
4742
  pythonAi: result.pythonAi,
4743
+ pythonAuth: result.pythonAuth,
4544
4744
  pythonTaskQueue: result.pythonTaskQueue,
4745
+ pythonGraphql: result.pythonGraphql,
4545
4746
  pythonQuality: result.pythonQuality,
4546
4747
  goWebFramework: result.goWebFramework,
4547
4748
  goOrm: result.goOrm,
@@ -4802,6 +5003,7 @@ function getTypeScriptFlags(config) {
4802
5003
  flags.push(`--logging ${config.logging}`);
4803
5004
  flags.push(`--observability ${config.observability}`);
4804
5005
  flags.push(`--caching ${config.caching}`);
5006
+ flags.push(`--i18n ${config.i18n}`);
4805
5007
  flags.push(`--cms ${config.cms}`);
4806
5008
  flags.push(`--search ${config.search}`);
4807
5009
  flags.push(`--file-storage ${config.fileStorage}`);
@@ -4824,6 +5026,8 @@ function getRustFlags(config) {
4824
5026
  flags.push(`--rust-cli ${config.rustCli}`);
4825
5027
  flags.push(formatArrayFlag("rust-libraries", config.rustLibraries));
4826
5028
  flags.push(`--rust-logging ${config.rustLogging}`);
5029
+ flags.push(`--rust-error-handling ${config.rustErrorHandling}`);
5030
+ flags.push(`--rust-caching ${config.rustCaching}`);
4827
5031
  appendSharedNonTypeScriptFlags(flags, config);
4828
5032
  appendCommonFlags(flags, config);
4829
5033
  return flags;
@@ -4834,7 +5038,9 @@ function getPythonFlags(config) {
4834
5038
  flags.push(`--python-orm ${config.pythonOrm}`);
4835
5039
  flags.push(`--python-validation ${config.pythonValidation}`);
4836
5040
  flags.push(formatArrayFlag("python-ai", config.pythonAi));
5041
+ flags.push(`--python-auth ${config.pythonAuth}`);
4837
5042
  flags.push(`--python-task-queue ${config.pythonTaskQueue}`);
5043
+ flags.push(`--python-graphql ${config.pythonGraphql}`);
4838
5044
  flags.push(`--python-quality ${config.pythonQuality}`);
4839
5045
  appendSharedNonTypeScriptFlags(flags, config);
4840
5046
  appendCommonFlags(flags, config);
@@ -5071,6 +5277,7 @@ function processFlags(options, projectName) {
5071
5277
  if (options.observability !== void 0) config.observability = options.observability;
5072
5278
  if (options.cms !== void 0) config.cms = options.cms;
5073
5279
  if (options.caching !== void 0) config.caching = options.caching;
5280
+ if (options.i18n !== void 0) config.i18n = options.i18n;
5074
5281
  if (options.search !== void 0) config.search = options.search;
5075
5282
  if (options.fileStorage !== void 0) config.fileStorage = options.fileStorage;
5076
5283
  if (options.analytics !== void 0) config.analytics = options.analytics;
@@ -5107,11 +5314,15 @@ function processFlags(options, projectName) {
5107
5314
  if (options.rustCli !== void 0) config.rustCli = options.rustCli;
5108
5315
  if (options.rustLibraries !== void 0) config.rustLibraries = processArrayOption(options.rustLibraries);
5109
5316
  if (options.rustLogging !== void 0) config.rustLogging = options.rustLogging;
5317
+ if (options.rustErrorHandling !== void 0) config.rustErrorHandling = options.rustErrorHandling;
5318
+ if (options.rustCaching !== void 0) config.rustCaching = options.rustCaching;
5110
5319
  if (options.pythonWebFramework !== void 0) config.pythonWebFramework = options.pythonWebFramework;
5111
5320
  if (options.pythonOrm !== void 0) config.pythonOrm = options.pythonOrm;
5112
5321
  if (options.pythonValidation !== void 0) config.pythonValidation = options.pythonValidation;
5113
5322
  if (options.pythonAi !== void 0) config.pythonAi = processArrayOption(options.pythonAi);
5323
+ if (options.pythonAuth !== void 0) config.pythonAuth = options.pythonAuth;
5114
5324
  if (options.pythonTaskQueue !== void 0) config.pythonTaskQueue = options.pythonTaskQueue;
5325
+ if (options.pythonGraphql !== void 0) config.pythonGraphql = options.pythonGraphql;
5115
5326
  if (options.pythonQuality !== void 0) config.pythonQuality = options.pythonQuality;
5116
5327
  if (options.goWebFramework !== void 0) config.goWebFramework = options.goWebFramework;
5117
5328
  if (options.goOrm !== void 0) config.goOrm = options.goOrm;
@@ -5603,6 +5814,18 @@ function validateFullConfig(config, providedFlags, options) {
5603
5814
  validateWorkersCompatibility(providedFlags, options, config);
5604
5815
  if (config.runtime === "workers" && config.serverDeploy === "none") exitWithError("Cloudflare Workers runtime requires a server deployment. Please choose 'alchemy' for --server-deploy.");
5605
5816
  if (providedFlags.has("serverDeploy") && config.serverDeploy === "cloudflare" && config.runtime !== "workers") exitWithError(`Server deployment '${config.serverDeploy}' requires '--runtime workers'. Please use '--runtime workers' or choose a different server deployment.`);
5817
+ if (config.serverDeploy === "vercel" && [
5818
+ "nestjs",
5819
+ "adonisjs",
5820
+ "encore"
5821
+ ].includes(config.backend)) incompatibilityError({
5822
+ message: "Vercel serverless functions cannot host persistent-process backends",
5823
+ provided: {
5824
+ backend: config.backend,
5825
+ serverDeploy: config.serverDeploy
5826
+ },
5827
+ suggestions: ["Use --server-deploy fly or --server-deploy railway for NestJS/AdonisJS", "Switch to a serverless-compatible backend like Hono or Express"]
5828
+ });
5606
5829
  if (config.addons && config.addons.length > 0) {
5607
5830
  validateAddonsAgainstFrontends(config.addons, config.frontend, config.auth);
5608
5831
  config.addons = [...new Set(config.addons)];
@@ -6977,6 +7200,7 @@ async function displayPostInstallInstructions(config) {
6977
7200
  const polarInstructions = config.payments === "polar" ? getPolarInstructions(backend, packageManager) : "";
6978
7201
  const paymentSetupInstructions = getPaymentSetupInstructions(config.payments, backend);
6979
7202
  const alchemyDeployInstructions = getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy, backend);
7203
+ const vercelDeployInstructions = getVercelDeployInstructions(webDeploy, serverDeploy, backend);
6980
7204
  const hasWeb = frontend?.some((f) => WEB_FRAMEWORKS.includes(f));
6981
7205
  const hasNative = frontend?.includes("native-bare") || frontend?.includes("native-uniwind") || frontend?.includes("native-unistyles");
6982
7206
  const bunWebNativeWarning = packageManager === "bun" && hasNative && hasWeb ? getBunWebNativeWarning() : "";
@@ -7022,6 +7246,7 @@ async function displayPostInstallInstructions(config) {
7022
7246
  if (lintingInstructions) output += `\n${lintingInstructions.trim()}\n`;
7023
7247
  if (pwaInstructions) output += `\n${pwaInstructions.trim()}\n`;
7024
7248
  if (alchemyDeployInstructions) output += `\n${alchemyDeployInstructions.trim()}\n`;
7249
+ if (vercelDeployInstructions) output += `\n${vercelDeployInstructions.trim()}\n`;
7025
7250
  if (starlightInstructions) output += `\n${starlightInstructions.trim()}\n`;
7026
7251
  if (clerkInstructions) output += `\n${clerkInstructions.trim()}\n`;
7027
7252
  if (authSetupInstructions) output += `\n${authSetupInstructions.trim()}\n`;
@@ -7162,6 +7387,18 @@ function getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy, backend)
7162
7387
  else if (webDeploy === "cloudflare" && (serverDeploy === "cloudflare" || isBackendSelf)) 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`}`);
7163
7388
  return instructions.length ? `\n${instructions.join("\n")}` : "";
7164
7389
  }
7390
+ function getVercelDeployInstructions(webDeploy, serverDeploy, backend) {
7391
+ const instructions = [];
7392
+ const isBackendSelf = backend === "self";
7393
+ if (webDeploy === "vercel" || serverDeploy === "vercel") {
7394
+ instructions.push(pc.bold("Deploy with Vercel:"));
7395
+ instructions.push(`${pc.cyan("•")} Install Vercel CLI: ${pc.white("npm i -g vercel")}`);
7396
+ if (webDeploy === "vercel") instructions.push(`${pc.cyan("•")} Deploy web: ${pc.white(`cd apps/web && vercel`)}`);
7397
+ if (serverDeploy === "vercel" && !isBackendSelf) instructions.push(`${pc.cyan("•")} Deploy server: ${pc.white(`cd apps/server && vercel`)}`);
7398
+ instructions.push(`${pc.cyan("•")} Docs: ${pc.underline("https://vercel.com/docs")}`);
7399
+ }
7400
+ return instructions.length ? `\n${instructions.join("\n")}` : "";
7401
+ }
7165
7402
  function displayRustInstructions(config) {
7166
7403
  const { relativePath, rustWebFramework, rustFrontend, rustOrm, rustApi, rustCli } = config;
7167
7404
  const cdCmd = `cd ${relativePath}`;
@@ -7198,6 +7435,16 @@ function displayRustInstructions(config) {
7198
7435
  tracing: "Tracing",
7199
7436
  "env-logger": "env_logger"
7200
7437
  }[rustLogging] || rustLogging}\n`;
7438
+ const { rustErrorHandling } = config;
7439
+ if (rustErrorHandling && rustErrorHandling !== "none") output += `${pc.cyan("•")} Error Handling: ${{
7440
+ "anyhow-thiserror": "anyhow + thiserror",
7441
+ eyre: "eyre + color-eyre"
7442
+ }[rustErrorHandling] || rustErrorHandling}\n`;
7443
+ const { rustCaching } = config;
7444
+ if (rustCaching && rustCaching !== "none") output += `${pc.cyan("•")} Caching: ${{
7445
+ moka: "Moka",
7446
+ redis: "Redis"
7447
+ }[rustCaching] || rustCaching}\n`;
7201
7448
  output += `\n${pc.bold("Common Cargo commands:")}\n`;
7202
7449
  output += `${pc.cyan("•")} Build: cargo build\n`;
7203
7450
  output += `${pc.cyan("•")} Run: cargo run\n`;
@@ -7221,18 +7468,24 @@ function displayGoInstructions(config) {
7221
7468
  if (goWebFramework && goWebFramework !== "none") output += `${pc.cyan("•")} Web Framework: ${{
7222
7469
  gin: "Gin",
7223
7470
  echo: "Echo",
7224
- fiber: "Fiber"
7471
+ fiber: "Fiber",
7472
+ chi: "Chi"
7225
7473
  }[goWebFramework] || goWebFramework}\n`;
7226
7474
  if (goOrm && goOrm !== "none") output += `${pc.cyan("•")} Database: ${{
7227
7475
  gorm: "GORM",
7228
- sqlc: "sqlc"
7476
+ sqlc: "sqlc",
7477
+ ent: "Ent"
7229
7478
  }[goOrm] || goOrm}\n`;
7230
7479
  if (goApi && goApi !== "none") output += `${pc.cyan("•")} API: ${{ "grpc-go": "gRPC-Go" }[goApi] || goApi}\n`;
7231
7480
  if (goCli && goCli !== "none") output += `${pc.cyan("•")} CLI: ${{
7232
7481
  cobra: "Cobra",
7233
7482
  bubbletea: "Bubble Tea"
7234
7483
  }[goCli] || goCli}\n`;
7235
- if (goLogging && goLogging !== "none") output += `${pc.cyan("•")} Logging: ${{ zap: "Zap" }[goLogging] || goLogging}\n`;
7484
+ if (goLogging && goLogging !== "none") output += `${pc.cyan("•")} Logging: ${{
7485
+ zap: "Zap",
7486
+ zerolog: "Zerolog",
7487
+ slog: "slog"
7488
+ }[goLogging] || goLogging}\n`;
7236
7489
  output += `\n${pc.bold("Common Go commands:")}\n`;
7237
7490
  output += `${pc.cyan("•")} Build: go build ./...\n`;
7238
7491
  output += `${pc.cyan("•")} Run: go run cmd/server/main.go\n`;
@@ -7254,6 +7507,7 @@ function displayPythonInstructions(config) {
7254
7507
  let runCommand = "uv run uvicorn app.main:app --reload";
7255
7508
  if (pythonWebFramework === "django") runCommand = "uv run python manage.py runserver";
7256
7509
  else if (pythonWebFramework === "flask") runCommand = "uv run flask --app app.main run --reload";
7510
+ else if (pythonWebFramework === "litestar") runCommand = "litestar --app src.app.main:app run --reload --port 3001";
7257
7511
  let output = `${pc.bold("Next steps")}\n${pc.cyan("1.")} ${cdCmd}\n`;
7258
7512
  let stepCounter = 2;
7259
7513
  if (!depsInstalled) output += `${pc.cyan(`${stepCounter++}.`)} uv sync\n`;
@@ -7262,7 +7516,8 @@ function displayPythonInstructions(config) {
7262
7516
  if (pythonWebFramework && pythonWebFramework !== "none") output += `${pc.cyan("•")} Web Framework: ${{
7263
7517
  fastapi: "FastAPI",
7264
7518
  django: "Django",
7265
- flask: "Flask"
7519
+ flask: "Flask",
7520
+ litestar: "Litestar"
7266
7521
  }[pythonWebFramework] || pythonWebFramework}\n`;
7267
7522
  if (pythonOrm && pythonOrm !== "none") output += `${pc.cyan("•")} ORM: ${{
7268
7523
  sqlalchemy: "SQLAlchemy",
@@ -7450,8 +7705,11 @@ async function createProjectHandler(input, options = {}) {
7450
7705
  rustCli: "none",
7451
7706
  rustLibraries: [],
7452
7707
  rustLogging: "none",
7708
+ rustErrorHandling: "none",
7709
+ rustCaching: "none",
7453
7710
  cms: "none",
7454
7711
  caching: "none",
7712
+ i18n: "none",
7455
7713
  search: "none",
7456
7714
  featureFlags: "none",
7457
7715
  analytics: "none",
@@ -7460,7 +7718,9 @@ async function createProjectHandler(input, options = {}) {
7460
7718
  pythonOrm: "none",
7461
7719
  pythonValidation: "none",
7462
7720
  pythonAi: [],
7721
+ pythonAuth: "none",
7463
7722
  pythonTaskQueue: "none",
7723
+ pythonGraphql: "none",
7464
7724
  pythonQuality: "none",
7465
7725
  goWebFramework: "none",
7466
7726
  goOrm: "none",
@@ -7764,6 +8024,7 @@ const router = os.router({
7764
8024
  analytics: types_exports.AnalyticsSchema.optional().describe("Privacy-focused analytics"),
7765
8025
  cms: types_exports.CMSSchema.optional().describe("Headless CMS solution"),
7766
8026
  caching: types_exports.CachingSchema.optional().describe("Caching solution"),
8027
+ i18n: types_exports.I18nSchema.optional().describe("Internationalization (i18n) library"),
7767
8028
  search: types_exports.SearchSchema.optional().describe("Search engine solution"),
7768
8029
  fileStorage: types_exports.FileStorageSchema.optional().describe("File storage solution (S3, R2)"),
7769
8030
  frontend: z.array(types_exports.FrontendSchema).optional(),
@@ -7800,17 +8061,21 @@ const router = os.router({
7800
8061
  rustCli: types_exports.RustCliSchema.optional().describe("Rust CLI tools (clap, ratatui)"),
7801
8062
  rustLibraries: z.array(types_exports.RustLibrariesSchema).optional().describe("Rust core libraries"),
7802
8063
  rustLogging: types_exports.RustLoggingSchema.optional().describe("Rust logging (tracing, env-logger)"),
8064
+ rustErrorHandling: types_exports.RustErrorHandlingSchema.optional().describe("Rust error handling (anyhow-thiserror, eyre)"),
8065
+ rustCaching: types_exports.RustCachingSchema.optional().describe("Rust caching (moka, redis)"),
7803
8066
  pythonWebFramework: types_exports.PythonWebFrameworkSchema.optional().describe("Python web framework (fastapi, django)"),
7804
8067
  pythonOrm: types_exports.PythonOrmSchema.optional().describe("Python ORM/database (sqlalchemy, sqlmodel)"),
7805
8068
  pythonValidation: types_exports.PythonValidationSchema.optional().describe("Python validation (pydantic)"),
7806
8069
  pythonAi: z.array(types_exports.PythonAiSchema).optional().describe("Python AI/ML frameworks"),
8070
+ pythonAuth: types_exports.PythonAuthSchema.optional().describe("Python auth library (authlib, jwt)"),
7807
8071
  pythonTaskQueue: types_exports.PythonTaskQueueSchema.optional().describe("Python task queue (celery)"),
8072
+ pythonGraphql: types_exports.PythonGraphqlSchema.optional().describe("Python GraphQL framework (strawberry)"),
7808
8073
  pythonQuality: types_exports.PythonQualitySchema.optional().describe("Python code quality (ruff)"),
7809
8074
  goWebFramework: types_exports.GoWebFrameworkSchema.optional().describe("Go web framework (gin, echo, fiber)"),
7810
8075
  goOrm: types_exports.GoOrmSchema.optional().describe("Go ORM/database (gorm, sqlc)"),
7811
8076
  goApi: types_exports.GoApiSchema.optional().describe("Go API layer (grpc-go)"),
7812
8077
  goCli: types_exports.GoCliSchema.optional().describe("Go CLI tools (cobra, bubbletea)"),
7813
- goLogging: types_exports.GoLoggingSchema.optional().describe("Go logging (zap)"),
8078
+ goLogging: types_exports.GoLoggingSchema.optional().describe("Go logging (zap, zerolog, slog)"),
7814
8079
  aiDocs: z.array(types_exports.AiDocsSchema).optional().describe("AI documentation files (claude-md, agents-md, cursorrules)")
7815
8080
  })])).handler(async ({ input }) => {
7816
8081
  const [projectName, options] = input;
@@ -8032,6 +8297,7 @@ async function createVirtual(options) {
8032
8297
  analytics: options.analytics || "none",
8033
8298
  cms: options.cms || "none",
8034
8299
  caching: options.caching || "none",
8300
+ i18n: options.i18n || "none",
8035
8301
  search: options.search || "none",
8036
8302
  fileStorage: options.fileStorage || "none",
8037
8303
  rustWebFramework: options.rustWebFramework || "none",
@@ -8041,11 +8307,15 @@ async function createVirtual(options) {
8041
8307
  rustCli: options.rustCli || "none",
8042
8308
  rustLibraries: options.rustLibraries || [],
8043
8309
  rustLogging: options.rustLogging || (options.ecosystem === "rust" ? "tracing" : "none"),
8310
+ rustErrorHandling: options.rustErrorHandling || (options.ecosystem === "rust" ? "anyhow-thiserror" : "none"),
8311
+ rustCaching: options.rustCaching || "none",
8044
8312
  pythonWebFramework: options.pythonWebFramework || "none",
8045
8313
  pythonOrm: options.pythonOrm || "none",
8046
8314
  pythonValidation: options.pythonValidation || "none",
8047
8315
  pythonAi: options.pythonAi || [],
8316
+ pythonAuth: options.pythonAuth || "none",
8048
8317
  pythonTaskQueue: options.pythonTaskQueue || "none",
8318
+ pythonGraphql: options.pythonGraphql || "none",
8049
8319
  pythonQuality: options.pythonQuality || "none",
8050
8320
  goWebFramework: options.goWebFramework || "none",
8051
8321
  goOrm: options.goOrm || "none",
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import "./bts-config-BYD8mHt-.mjs";
2
+ import "./bts-config-snHxP_EH.mjs";
3
3
  import { t as startMcpServer } from "./mcp-entry.mjs";
4
4
 
5
5
  export { startMcpServer };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { i as getLatestCLIVersion, r as writeBtsConfig, t as readBtsConfig } from "./bts-config-BYD8mHt-.mjs";
2
+ import { i as getLatestCLIVersion, r as writeBtsConfig, t as readBtsConfig } from "./bts-config-snHxP_EH.mjs";
3
3
  import z from "zod";
4
- import { AISchema, APISchema, AddonsSchema, AnalyticsSchema, AnimationSchema, AstroIntegrationSchema, AuthSchema, BackendSchema, CMSSchema, CSSFrameworkSchema, CachingSchema, DatabaseSchema, DatabaseSetupSchema, EcosystemSchema, EffectSchema, EmailSchema, ExamplesSchema, FeatureFlagsSchema, FileStorageSchema, FileUploadSchema, FormsSchema, FrontendSchema, GoApiSchema, GoCliSchema, GoLoggingSchema, GoOrmSchema, GoWebFrameworkSchema, JobQueueSchema, LoggingSchema, ORMSchema, ObservabilitySchema, PackageManagerSchema, PaymentsSchema, PythonAiSchema, PythonOrmSchema, PythonQualitySchema, PythonTaskQueueSchema, PythonValidationSchema, PythonWebFrameworkSchema, RealtimeSchema, RuntimeSchema, RustApiSchema, RustCliSchema, RustFrontendSchema, RustLibrariesSchema, RustLoggingSchema, RustOrmSchema, RustWebFrameworkSchema, SearchSchema, ServerDeploySchema, StateManagementSchema, TestingSchema, UILibrarySchema, ValidationSchema, WebDeploySchema, analyzeStackCompatibility } from "@better-fullstack/types";
4
+ import { AISchema, APISchema, AddonsSchema, AnalyticsSchema, AnimationSchema, AstroIntegrationSchema, AuthSchema, BackendSchema, CMSSchema, CSSFrameworkSchema, CachingSchema, DatabaseSchema, DatabaseSetupSchema, EcosystemSchema, EffectSchema, EmailSchema, ExamplesSchema, FeatureFlagsSchema, FileStorageSchema, FileUploadSchema, FormsSchema, FrontendSchema, GoApiSchema, GoCliSchema, GoLoggingSchema, GoOrmSchema, GoWebFrameworkSchema, I18nSchema, JobQueueSchema, LoggingSchema, ORMSchema, ObservabilitySchema, PackageManagerSchema, PaymentsSchema, PythonAiSchema, PythonAuthSchema, PythonGraphqlSchema, PythonOrmSchema, PythonQualitySchema, PythonTaskQueueSchema, PythonValidationSchema, PythonWebFrameworkSchema, RealtimeSchema, RuntimeSchema, RustApiSchema, RustCachingSchema, RustCliSchema, RustErrorHandlingSchema, RustFrontendSchema, RustLibrariesSchema, RustLoggingSchema, RustOrmSchema, RustWebFrameworkSchema, SearchSchema, ServerDeploySchema, StateManagementSchema, TestingSchema, UILibrarySchema, ValidationSchema, WebDeploySchema, analyzeStackCompatibility } from "@better-fullstack/types";
5
5
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
6
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
7
7
 
@@ -99,6 +99,7 @@ const SCHEMA_MAP = {
99
99
  analytics: AnalyticsSchema,
100
100
  cms: CMSSchema,
101
101
  caching: CachingSchema,
102
+ i18n: I18nSchema,
102
103
  search: SearchSchema,
103
104
  fileStorage: FileStorageSchema,
104
105
  addons: AddonsSchema,
@@ -115,11 +116,15 @@ const SCHEMA_MAP = {
115
116
  rustCli: RustCliSchema,
116
117
  rustLibraries: RustLibrariesSchema,
117
118
  rustLogging: RustLoggingSchema,
119
+ rustErrorHandling: RustErrorHandlingSchema,
120
+ rustCaching: RustCachingSchema,
118
121
  pythonWebFramework: PythonWebFrameworkSchema,
119
122
  pythonOrm: PythonOrmSchema,
120
123
  pythonValidation: PythonValidationSchema,
121
124
  pythonAi: PythonAiSchema,
125
+ pythonAuth: PythonAuthSchema,
122
126
  pythonTaskQueue: PythonTaskQueueSchema,
127
+ pythonGraphql: PythonGraphqlSchema,
123
128
  pythonQuality: PythonQualitySchema,
124
129
  goWebFramework: GoWebFrameworkSchema,
125
130
  goOrm: GoOrmSchema,
@@ -156,6 +161,7 @@ const ECOSYSTEM_CATEGORIES = {
156
161
  "analytics",
157
162
  "cms",
158
163
  "caching",
164
+ "i18n",
159
165
  "search",
160
166
  "fileStorage",
161
167
  "astroIntegration"
@@ -167,14 +173,18 @@ const ECOSYSTEM_CATEGORIES = {
167
173
  "rustApi",
168
174
  "rustCli",
169
175
  "rustLibraries",
170
- "rustLogging"
176
+ "rustLogging",
177
+ "rustErrorHandling",
178
+ "rustCaching"
171
179
  ],
172
180
  python: [
173
181
  "pythonWebFramework",
174
182
  "pythonOrm",
175
183
  "pythonValidation",
176
184
  "pythonAi",
185
+ "pythonAuth",
177
186
  "pythonTaskQueue",
187
+ "pythonGraphql",
178
188
  "pythonQuality"
179
189
  ],
180
190
  go: [
@@ -285,6 +295,7 @@ function buildProjectConfig(input, overrides) {
285
295
  analytics: "none",
286
296
  cms: input.cms ?? "none",
287
297
  caching: input.caching ?? "none",
298
+ i18n: input.i18n ?? "none",
288
299
  search: input.search ?? "none",
289
300
  fileStorage: input.fileStorage ?? "none",
290
301
  addons: input.addons ?? [],
@@ -305,11 +316,15 @@ function buildProjectConfig(input, overrides) {
305
316
  rustCli: input.rustCli ?? "none",
306
317
  rustLibraries: input.rustLibraries ?? [],
307
318
  rustLogging: input.rustLogging ?? "none",
319
+ rustErrorHandling: input.rustErrorHandling ?? "none",
320
+ rustCaching: input.rustCaching ?? "none",
308
321
  pythonWebFramework: input.pythonWebFramework ?? "none",
309
322
  pythonOrm: input.pythonOrm ?? "none",
310
323
  pythonValidation: input.pythonValidation ?? "none",
311
324
  pythonAi: input.pythonAi ?? [],
325
+ pythonAuth: input.pythonAuth ?? "none",
312
326
  pythonTaskQueue: input.pythonTaskQueue ?? "none",
327
+ pythonGraphql: input.pythonGraphql ?? "none",
313
328
  pythonQuality: input.pythonQuality ?? "none",
314
329
  goWebFramework: input.goWebFramework ?? "none",
315
330
  goOrm: input.goOrm ?? "none",
@@ -367,6 +382,7 @@ function buildCompatibilityInput(input) {
367
382
  realtime: input.realtime ?? "none",
368
383
  jobQueue: input.jobQueue ?? "none",
369
384
  caching: input.caching ?? "none",
385
+ i18n: input.i18n ?? "none",
370
386
  animation: input.animation ?? "none",
371
387
  cssFramework: input.cssFramework ?? "tailwind",
372
388
  uiLibrary: input.uiLibrary ?? "none",
@@ -394,11 +410,15 @@ function buildCompatibilityInput(input) {
394
410
  rustCli: input.rustCli ?? "none",
395
411
  rustLibraries: (input.rustLibraries ?? []).join(",") || "none",
396
412
  rustLogging: input.rustLogging ?? "none",
413
+ rustErrorHandling: input.rustErrorHandling ?? "none",
414
+ rustCaching: input.rustCaching ?? "none",
397
415
  pythonWebFramework: input.pythonWebFramework ?? "none",
398
416
  pythonOrm: input.pythonOrm ?? "none",
399
417
  pythonValidation: input.pythonValidation ?? "none",
400
418
  pythonAi: (input.pythonAi ?? []).join(",") || "none",
419
+ pythonAuth: input.pythonAuth ?? "none",
401
420
  pythonTaskQueue: input.pythonTaskQueue ?? "none",
421
+ pythonGraphql: input.pythonGraphql ?? "none",
402
422
  pythonQuality: input.pythonQuality ?? "none",
403
423
  goWebFramework: input.goWebFramework ?? "none",
404
424
  goOrm: input.goOrm ?? "none",
@@ -584,6 +604,7 @@ async function startMcpServer() {
584
604
  observability: ObservabilitySchema.optional().describe("Observability"),
585
605
  search: SearchSchema.optional().describe("Search engine"),
586
606
  caching: CachingSchema.optional().describe("Caching solution"),
607
+ i18n: I18nSchema.optional().describe("Internationalization (i18n) library"),
587
608
  cms: CMSSchema.optional().describe("CMS"),
588
609
  fileStorage: FileStorageSchema.optional().describe("File storage"),
589
610
  fileUpload: FileUploadSchema.optional().describe("File upload"),
@@ -597,10 +618,13 @@ async function startMcpServer() {
597
618
  rustCli: RustCliSchema.optional().describe("Rust CLI framework"),
598
619
  rustLibraries: z.array(RustLibrariesSchema).optional().describe("Rust libraries"),
599
620
  rustLogging: RustLoggingSchema.optional().describe("Rust logging library"),
621
+ rustErrorHandling: RustErrorHandlingSchema.optional().describe("Rust error handling library"),
622
+ rustCaching: RustCachingSchema.optional().describe("Rust caching library"),
600
623
  pythonWebFramework: PythonWebFrameworkSchema.optional().describe("Python web framework"),
601
624
  pythonOrm: PythonOrmSchema.optional().describe("Python ORM"),
602
625
  pythonValidation: PythonValidationSchema.optional().describe("Python validation"),
603
626
  pythonAi: z.array(PythonAiSchema).optional().describe("Python AI libraries"),
627
+ pythonAuth: PythonAuthSchema.optional().describe("Python auth library"),
604
628
  pythonTaskQueue: PythonTaskQueueSchema.optional().describe("Python task queue"),
605
629
  pythonQuality: PythonQualitySchema.optional().describe("Python code quality"),
606
630
  goWebFramework: GoWebFrameworkSchema.optional().describe("Go web framework"),
@@ -676,7 +700,7 @@ async function startMcpServer() {
676
700
  await writeBtsConfig(config);
677
701
  let addonWarnings = [];
678
702
  if (config.addons.length > 0 && config.addons[0] !== "none") {
679
- const { setupAddons } = await import("./addons-setup-CWGwxN68.mjs");
703
+ const { setupAddons } = await import("./addons-setup-By7Kqjss.mjs");
680
704
  addonWarnings = await setupAddons(config);
681
705
  }
682
706
  const installCmd = getInstallCommand(input.ecosystem ?? "typescript", projectName, input.packageManager);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-better-fullstack",
3
- "version": "1.5.4",
3
+ "version": "1.6.0",
4
4
  "description": "Scaffold production-ready fullstack apps in seconds. Pick your stack from 270+ options — the CLI wires everything together.",
5
5
  "keywords": [
6
6
  "angular",
@@ -112,8 +112,8 @@
112
112
  "prepublishOnly": "npm run build"
113
113
  },
114
114
  "dependencies": {
115
- "@better-fullstack/template-generator": "^1.5.4",
116
- "@better-fullstack/types": "^1.5.4",
115
+ "@better-fullstack/template-generator": "^1.6.0",
116
+ "@better-fullstack/types": "^1.6.0",
117
117
  "@clack/core": "^0.5.0",
118
118
  "@clack/prompts": "^1.2.0",
119
119
  "@orpc/server": "^1.13.13",
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
- import "./bts-config-BYD8mHt-.mjs";
3
- import { i as setupLefthook, n as setupBiome, r as setupHusky, t as setupAddons } from "./addons-setup-Bll5VFJd.mjs";
4
-
5
- export { setupAddons };