create-better-fullstack 1.6.1 → 1.6.3

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
@@ -1,23 +1,28 @@
1
1
  # Better Fullstack
2
2
 
3
- Scaffold production-ready fullstack apps in seconds. Pick your stack from 270+ options — the CLI wires everything together.
3
+ Scaffold production-ready fullstack apps in seconds. Pick your stack from 425 options — the CLI wires everything together.
4
4
 
5
5
  ## Quick Start
6
6
 
7
7
  ```bash
8
- # Using bun (recommended)
9
- bun create better-fullstack@latest
8
+ # Using npm
9
+ npm create better-fullstack@latest
10
+
11
+ # Using npx
12
+ npx create-better-fullstack@latest
10
13
 
11
14
  # Using pnpm
12
15
  pnpm create better-fullstack@latest
13
16
 
14
- # Using npm
15
- npx create-better-fullstack@latest
17
+ # Using bun
18
+ bun create better-fullstack@latest
16
19
 
17
20
  # Using yarn
18
21
  yarn create better-fullstack@latest
19
22
  ```
20
23
 
24
+ Bun is required only when the generated project selects Bun as its runtime or package manager. Node.js with npm is enough for Node-based projects.
25
+
21
26
  ## Web Builder
22
27
 
23
28
  Configure your stack visually — pick every option from a UI, preview your choices, and get a ready-to-run command.
@@ -26,8 +31,8 @@ Configure your stack visually — pick every option from a UI, preview your choi
26
31
 
27
32
  ## Features
28
33
 
29
- - **270+ options** — frontend, backend, database, auth, payments, AI, DevOps, and more
30
- - **4 ecosystems** — TypeScript, Rust, Python, Go
34
+ - **425 options** — frontend, backend, database, auth, payments, AI, DevOps, and more
35
+ - **5 ecosystems** — TypeScript, Rust, Python, Go, Java
31
36
  - **Visual builder** — configure your stack in the browser
32
37
  - **Wired for you** — every picked integration is preconfigured and working out of the box
33
38
 
@@ -37,7 +42,7 @@ Configure your stack visually — pick every option from a UI, preview your choi
37
42
  --yes # Accept all defaults
38
43
  --yolo # Scaffold a random stack — good for exploring
39
44
  --template <name> # Use a preset (t3, mern, pern, uniwind)
40
- --ecosystem <lang> # Start in rust, python, or go mode
45
+ --ecosystem <lang> # Start in typescript, rust, python, go, or java mode
41
46
  --version-channel # Dependency channel: stable, latest, beta
42
47
  --no-git # Skip git initialization
43
48
  --no-install # Skip dependency installation
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  import "./bts-config-B_rZ4_sj.mjs";
3
- import { i as setupLefthook, n as setupBiome, r as setupHusky, t as setupAddons } from "./addons-setup-Cgup_RHm.mjs";
3
+ import { i as setupLefthook, n as setupBiome, r as setupHusky, t as setupAddons } from "./addons-setup-DQa6TRrx.mjs";
4
4
 
5
5
  export { setupAddons };
@@ -626,45 +626,50 @@ async function setupRuler(config) {
626
626
  log.error(pc.red("Ruler template directory not found. Please ensure ruler addon is properly installed."));
627
627
  return;
628
628
  }
629
- const selectedEditors = await autocompleteMultiselect({
630
- message: "Select AI assistants for Ruler",
631
- options: Object.entries({
632
- agentsmd: { label: "Agents.md" },
633
- aider: { label: "Aider" },
634
- amazonqcli: { label: "Amazon Q CLI" },
635
- amp: { label: "AMP" },
636
- antigravity: { label: "Antigravity" },
637
- augmentcode: { label: "AugmentCode" },
638
- claude: { label: "Claude Code" },
639
- cline: { label: "Cline" },
640
- codex: { label: "OpenAI Codex CLI" },
641
- copilot: { label: "GitHub Copilot" },
642
- crush: { label: "Crush" },
643
- cursor: { label: "Cursor" },
644
- firebase: { label: "Firebase Studio" },
645
- firebender: { label: "Firebender" },
646
- "gemini-cli": { label: "Gemini CLI" },
647
- goose: { label: "Goose" },
648
- jules: { label: "Jules" },
649
- junie: { label: "Junie" },
650
- kilocode: { label: "Kilo Code" },
651
- kiro: { label: "Kiro" },
652
- mistral: { label: "Mistral" },
653
- opencode: { label: "OpenCode" },
654
- openhands: { label: "Open Hands" },
655
- qwen: { label: "Qwen" },
656
- roo: { label: "RooCode" },
657
- trae: { label: "Trae AI" },
658
- warp: { label: "Warp" },
659
- windsurf: { label: "Windsurf" },
660
- zed: { label: "Zed" }
661
- }).map(([key, v]) => ({
662
- value: key,
663
- label: v.label
664
- })),
665
- required: false
666
- });
667
- if (isCancel(selectedEditors)) return exitCancelled("Operation cancelled");
629
+ const EDITORS$1 = {
630
+ agentsmd: { label: "Agents.md" },
631
+ aider: { label: "Aider" },
632
+ amazonqcli: { label: "Amazon Q CLI" },
633
+ amp: { label: "AMP" },
634
+ antigravity: { label: "Antigravity" },
635
+ augmentcode: { label: "AugmentCode" },
636
+ claude: { label: "Claude Code" },
637
+ cline: { label: "Cline" },
638
+ codex: { label: "OpenAI Codex CLI" },
639
+ copilot: { label: "GitHub Copilot" },
640
+ crush: { label: "Crush" },
641
+ cursor: { label: "Cursor" },
642
+ firebase: { label: "Firebase Studio" },
643
+ firebender: { label: "Firebender" },
644
+ "gemini-cli": { label: "Gemini CLI" },
645
+ goose: { label: "Goose" },
646
+ jules: { label: "Jules" },
647
+ junie: { label: "Junie" },
648
+ kilocode: { label: "Kilo Code" },
649
+ kiro: { label: "Kiro" },
650
+ mistral: { label: "Mistral" },
651
+ opencode: { label: "OpenCode" },
652
+ openhands: { label: "Open Hands" },
653
+ qwen: { label: "Qwen" },
654
+ roo: { label: "RooCode" },
655
+ trae: { label: "Trae AI" },
656
+ warp: { label: "Warp" },
657
+ windsurf: { label: "Windsurf" },
658
+ zed: { label: "Zed" }
659
+ };
660
+ let selectedEditors = [];
661
+ if (canPromptInteractively()) {
662
+ const prompted = await autocompleteMultiselect({
663
+ message: "Select AI assistants for Ruler",
664
+ options: Object.entries(EDITORS$1).map(([key, v]) => ({
665
+ value: key,
666
+ label: v.label
667
+ })),
668
+ required: false
669
+ });
670
+ if (isCancel(prompted)) return exitCancelled("Operation cancelled");
671
+ selectedEditors = [...prompted];
672
+ } else log.info("Skipping AI assistant selection (non-interactive mode).");
668
673
  if (selectedEditors.length === 0) {
669
674
  log.info("No AI assistants selected. To apply rules later, run:");
670
675
  log.info(pc.cyan(`${getPackageExecutionCommand(packageManager, "@intellectronica/ruler@latest apply --local-only")}`));
@@ -940,6 +945,10 @@ async function setupSkills(config) {
940
945
  }));
941
946
  });
942
947
  if (skillOptions.length === 0) return;
948
+ if (!canPromptInteractively()) {
949
+ log.info("Skipping skills installation (non-interactive mode). Run the skills CLI manually to install.");
950
+ return;
951
+ }
943
952
  const scope = await select({
944
953
  message: "Where should skills be installed?",
945
954
  options: [{
package/dist/index.d.mts CHANGED
@@ -148,6 +148,7 @@ declare const router: {
148
148
  langchain: "langchain";
149
149
  llamaindex: "llamaindex";
150
150
  "tanstack-ai": "tanstack-ai";
151
+ "ai-cli": "ai-cli";
151
152
  }>>;
152
153
  realtime: z.ZodOptional<z.ZodEnum<{
153
154
  none: "none";
@@ -273,6 +274,7 @@ declare const router: {
273
274
  "tanstack-virtual": "tanstack-virtual";
274
275
  "tanstack-db": "tanstack-db";
275
276
  "tanstack-pacer": "tanstack-pacer";
277
+ "docker-compose": "docker-compose";
276
278
  }>>>;
277
279
  examples: z.ZodOptional<z.ZodArray<z.ZodEnum<{
278
280
  none: "none";
@@ -602,12 +604,23 @@ declare const router: {
602
604
  "spring-actuator": "spring-actuator";
603
605
  "spring-validation": "spring-validation";
604
606
  flyway: "flyway";
607
+ liquibase: "liquibase";
608
+ "springdoc-openapi": "springdoc-openapi";
609
+ lombok: "lombok";
610
+ mapstruct: "mapstruct";
611
+ caffeine: "caffeine";
605
612
  }>>>;
606
613
  javaTestingLibraries: z.ZodOptional<z.ZodArray<z.ZodEnum<{
607
614
  none: "none";
608
615
  junit5: "junit5";
609
616
  mockito: "mockito";
610
617
  testcontainers: "testcontainers";
618
+ assertj: "assertj";
619
+ "rest-assured": "rest-assured";
620
+ wiremock: "wiremock";
621
+ awaitility: "awaitility";
622
+ archunit: "archunit";
623
+ jqwik: "jqwik";
611
624
  }>>>;
612
625
  aiDocs: z.ZodOptional<z.ZodArray<z.ZodEnum<{
613
626
  none: "none";
@@ -627,7 +640,7 @@ declare const router: {
627
640
  backend: "none" | "hono" | "express" | "fastify" | "elysia" | "fets" | "nestjs" | "adonisjs" | "nitro" | "encore" | "convex" | "self";
628
641
  runtime: "none" | "bun" | "node" | "workers";
629
642
  frontend: ("none" | "tanstack-router" | "react-router" | "react-vite" | "tanstack-start" | "next" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid" | "solid-start" | "astro" | "qwik" | "angular" | "redwood" | "fresh")[];
630
- addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer")[];
643
+ addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer" | "docker-compose")[];
631
644
  examples: ("ai" | "none" | "chat-sdk" | "tanstack-showcase")[];
632
645
  auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
633
646
  payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
@@ -639,7 +652,7 @@ declare const router: {
639
652
  api: "none" | "trpc" | "orpc" | "ts-rest" | "garph" | "graphql-yoga";
640
653
  webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
641
654
  serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
642
- ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai";
655
+ ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai" | "ai-cli";
643
656
  effect: "effect" | "none" | "effect-full";
644
657
  stateManagement: "none" | "zustand" | "jotai" | "nanostores" | "redux-toolkit" | "mobx" | "xstate" | "valtio" | "tanstack-store" | "legend-state";
645
658
  forms: "none" | "tanstack-form" | "react-hook-form" | "formik" | "final-form" | "conform" | "modular-forms";
@@ -689,8 +702,8 @@ declare const router: {
689
702
  javaBuildTool: "none" | "maven" | "gradle";
690
703
  javaOrm: "none" | "spring-data-jpa";
691
704
  javaAuth: "none" | "spring-security";
692
- javaLibraries: ("none" | "spring-actuator" | "spring-validation" | "flyway")[];
693
- javaTestingLibraries: ("none" | "junit5" | "mockito" | "testcontainers")[];
705
+ javaLibraries: ("none" | "spring-actuator" | "spring-validation" | "flyway" | "liquibase" | "springdoc-openapi" | "lombok" | "mapstruct" | "caffeine")[];
706
+ javaTestingLibraries: ("none" | "junit5" | "mockito" | "testcontainers" | "assertj" | "rest-assured" | "wiremock" | "awaitility" | "archunit" | "jqwik")[];
694
707
  aiDocs: ("none" | "claude-md" | "agents-md" | "cursorrules")[];
695
708
  astroIntegration?: "none" | "svelte" | "solid" | "react" | "vue" | undefined;
696
709
  shadcnBase?: "radix" | "base" | undefined;
@@ -723,7 +736,7 @@ declare const router: {
723
736
  backend: "none" | "hono" | "express" | "fastify" | "elysia" | "fets" | "nestjs" | "adonisjs" | "nitro" | "encore" | "convex" | "self";
724
737
  runtime: "none" | "bun" | "node" | "workers";
725
738
  frontend: ("none" | "tanstack-router" | "react-router" | "react-vite" | "tanstack-start" | "next" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid" | "solid-start" | "astro" | "qwik" | "angular" | "redwood" | "fresh")[];
726
- addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer")[];
739
+ addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer" | "docker-compose")[];
727
740
  examples: ("ai" | "none" | "chat-sdk" | "tanstack-showcase")[];
728
741
  auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
729
742
  payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
@@ -735,7 +748,7 @@ declare const router: {
735
748
  api: "none" | "trpc" | "orpc" | "ts-rest" | "garph" | "graphql-yoga";
736
749
  webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
737
750
  serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
738
- ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai";
751
+ ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai" | "ai-cli";
739
752
  effect: "effect" | "none" | "effect-full";
740
753
  stateManagement: "none" | "zustand" | "jotai" | "nanostores" | "redux-toolkit" | "mobx" | "xstate" | "valtio" | "tanstack-store" | "legend-state";
741
754
  forms: "none" | "tanstack-form" | "react-hook-form" | "formik" | "final-form" | "conform" | "modular-forms";
@@ -785,8 +798,8 @@ declare const router: {
785
798
  javaBuildTool: "none" | "maven" | "gradle";
786
799
  javaOrm: "none" | "spring-data-jpa";
787
800
  javaAuth: "none" | "spring-security";
788
- javaLibraries: ("none" | "spring-actuator" | "spring-validation" | "flyway")[];
789
- javaTestingLibraries: ("none" | "junit5" | "mockito" | "testcontainers")[];
801
+ javaLibraries: ("none" | "spring-actuator" | "spring-validation" | "flyway" | "liquibase" | "springdoc-openapi" | "lombok" | "mapstruct" | "caffeine")[];
802
+ javaTestingLibraries: ("none" | "junit5" | "mockito" | "testcontainers" | "assertj" | "rest-assured" | "wiremock" | "awaitility" | "archunit" | "jqwik")[];
790
803
  aiDocs: ("none" | "claude-md" | "agents-md" | "cursorrules")[];
791
804
  astroIntegration?: "none" | "svelte" | "solid" | "react" | "vue" | undefined;
792
805
  shadcnBase?: "radix" | "base" | undefined;
@@ -832,7 +845,7 @@ declare const router: {
832
845
  backend: "none" | "hono" | "express" | "fastify" | "elysia" | "fets" | "nestjs" | "adonisjs" | "nitro" | "encore" | "convex" | "self";
833
846
  runtime: "none" | "bun" | "node" | "workers";
834
847
  frontend: ("none" | "tanstack-router" | "react-router" | "react-vite" | "tanstack-start" | "next" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid" | "solid-start" | "astro" | "qwik" | "angular" | "redwood" | "fresh")[];
835
- addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer")[];
848
+ addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer" | "docker-compose")[];
836
849
  examples: ("ai" | "none" | "chat-sdk" | "tanstack-showcase")[];
837
850
  auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
838
851
  payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
@@ -844,7 +857,7 @@ declare const router: {
844
857
  api: "none" | "trpc" | "orpc" | "ts-rest" | "garph" | "graphql-yoga";
845
858
  webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
846
859
  serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
847
- ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai";
860
+ ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai" | "ai-cli";
848
861
  effect: "effect" | "none" | "effect-full";
849
862
  stateManagement: "none" | "zustand" | "jotai" | "nanostores" | "redux-toolkit" | "mobx" | "xstate" | "valtio" | "tanstack-store" | "legend-state";
850
863
  forms: "none" | "tanstack-form" | "react-hook-form" | "formik" | "final-form" | "conform" | "modular-forms";
@@ -894,8 +907,8 @@ declare const router: {
894
907
  javaBuildTool: "none" | "maven" | "gradle";
895
908
  javaOrm: "none" | "spring-data-jpa";
896
909
  javaAuth: "none" | "spring-security";
897
- javaLibraries: ("none" | "spring-actuator" | "spring-validation" | "flyway")[];
898
- javaTestingLibraries: ("none" | "junit5" | "mockito" | "testcontainers")[];
910
+ javaLibraries: ("none" | "spring-actuator" | "spring-validation" | "flyway" | "liquibase" | "springdoc-openapi" | "lombok" | "mapstruct" | "caffeine")[];
911
+ javaTestingLibraries: ("none" | "junit5" | "mockito" | "testcontainers" | "assertj" | "rest-assured" | "wiremock" | "awaitility" | "archunit" | "jqwik")[];
899
912
  aiDocs: ("none" | "claude-md" | "agents-md" | "cursorrules")[];
900
913
  astroIntegration?: "none" | "svelte" | "solid" | "react" | "vue" | undefined;
901
914
  shadcnBase?: "radix" | "base" | undefined;
@@ -928,7 +941,7 @@ declare const router: {
928
941
  backend: "none" | "hono" | "express" | "fastify" | "elysia" | "fets" | "nestjs" | "adonisjs" | "nitro" | "encore" | "convex" | "self";
929
942
  runtime: "none" | "bun" | "node" | "workers";
930
943
  frontend: ("none" | "tanstack-router" | "react-router" | "react-vite" | "tanstack-start" | "next" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid" | "solid-start" | "astro" | "qwik" | "angular" | "redwood" | "fresh")[];
931
- addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer")[];
944
+ addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer" | "docker-compose")[];
932
945
  examples: ("ai" | "none" | "chat-sdk" | "tanstack-showcase")[];
933
946
  auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
934
947
  payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
@@ -940,7 +953,7 @@ declare const router: {
940
953
  api: "none" | "trpc" | "orpc" | "ts-rest" | "garph" | "graphql-yoga";
941
954
  webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
942
955
  serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
943
- ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai";
956
+ ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai" | "ai-cli";
944
957
  effect: "effect" | "none" | "effect-full";
945
958
  stateManagement: "none" | "zustand" | "jotai" | "nanostores" | "redux-toolkit" | "mobx" | "xstate" | "valtio" | "tanstack-store" | "legend-state";
946
959
  forms: "none" | "tanstack-form" | "react-hook-form" | "formik" | "final-form" | "conform" | "modular-forms";
@@ -990,8 +1003,8 @@ declare const router: {
990
1003
  javaBuildTool: "none" | "maven" | "gradle";
991
1004
  javaOrm: "none" | "spring-data-jpa";
992
1005
  javaAuth: "none" | "spring-security";
993
- javaLibraries: ("none" | "spring-actuator" | "spring-validation" | "flyway")[];
994
- javaTestingLibraries: ("none" | "junit5" | "mockito" | "testcontainers")[];
1006
+ javaLibraries: ("none" | "spring-actuator" | "spring-validation" | "flyway" | "liquibase" | "springdoc-openapi" | "lombok" | "mapstruct" | "caffeine")[];
1007
+ javaTestingLibraries: ("none" | "junit5" | "mockito" | "testcontainers" | "assertj" | "rest-assured" | "wiremock" | "awaitility" | "archunit" | "jqwik")[];
995
1008
  aiDocs: ("none" | "claude-md" | "agents-md" | "cursorrules")[];
996
1009
  astroIntegration?: "none" | "svelte" | "solid" | "react" | "vue" | undefined;
997
1010
  shadcnBase?: "radix" | "base" | undefined;
@@ -1054,6 +1067,7 @@ declare const router: {
1054
1067
  "tanstack-virtual": "tanstack-virtual";
1055
1068
  "tanstack-db": "tanstack-db";
1056
1069
  "tanstack-pacer": "tanstack-pacer";
1070
+ "docker-compose": "docker-compose";
1057
1071
  }>>>;
1058
1072
  webDeploy: z.ZodOptional<z.ZodEnum<{
1059
1073
  none: "none";
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
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-B_rZ4_sj.mjs";
4
- import { _ as setIsFirstPrompt$1, a as canPromptInteractively, c as CLIError, d as exitWithError, f as handleError, g as runWithContextAsync, h as isSilent, l as UserCancelledError, m as isFirstPrompt, o as getPackageExecutionArgs, p as didLastPromptShowUI, s as addPackageDependency, t as setupAddons, u as exitCancelled, v as setLastPromptShownUI } from "./addons-setup-Cgup_RHm.mjs";
4
+ import { _ as setIsFirstPrompt$1, a as canPromptInteractively, c as CLIError, d as exitWithError, f as handleError, g as runWithContextAsync, h as isSilent, l as UserCancelledError, m as isFirstPrompt, o as getPackageExecutionArgs, p as didLastPromptShowUI, s as addPackageDependency, t as setupAddons, u as exitCancelled, v as setLastPromptShownUI } from "./addons-setup-DQa6TRrx.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";
@@ -10,7 +10,7 @@ import z from "zod";
10
10
  import envPaths from "env-paths";
11
11
  import fs from "fs-extra";
12
12
  import path from "node:path";
13
- import { allowedApisForFrontends, getCompatibleAddons, getCompatibleCSSFrameworks, getCompatibleUILibraries, getLocalWebDevPort, hasWebStyling, isExampleAIAllowed, isExampleChatSdkAllowed, isFrontendAllowedWithBackend, isWebFrontend, requiresChatSdkVercelAIForSelection, splitFrontends, validateAddonCompatibility } from "@better-fullstack/types";
13
+ import { allowedApisForFrontends, getCompatibleAddons, getCompatibleCSSFrameworks, getCompatibleUILibraries, getLocalWebDevPort, hasDockerComposeCompatibleFrontend, hasWebStyling, isExampleAIAllowed, isExampleChatSdkAllowed, isFrontendAllowedWithBackend, isWebFrontend, requiresChatSdkVercelAIForSelection, splitFrontends, validateAddonCompatibility } from "@better-fullstack/types";
14
14
  import { ECOSYSTEM_GROUPS, EMBEDDED_TEMPLATES, EMBEDDED_TEMPLATES as EMBEDDED_TEMPLATES$1, TEMPLATE_COUNT, VirtualFileSystem, VirtualFileSystem as VirtualFileSystem$1, checkAllVersions, generateCliReport, generateVirtualProject, generateVirtualProject as generateVirtualProject$1, listEcosystems, processAddonTemplates, processAddonsDeps, validatePreflightConfig } from "@better-fullstack/template-generator";
15
15
  import gradient from "gradient-string";
16
16
  import path$1 from "path";
@@ -693,16 +693,51 @@ function validateWebDeployRequiresWebFrontend(webDeploy, hasWebFrontendFlag) {
693
693
  function validateServerDeployRequiresBackend(serverDeploy, backend) {
694
694
  if (serverDeploy && serverDeploy !== "none" && (!backend || backend === "none")) exitWithError("'--server-deploy' requires a backend. Please select a backend or set '--server-deploy none'.");
695
695
  }
696
- function validateAddonCompatibility$1(addon, frontend, _auth) {
697
- return validateAddonCompatibility(addon, frontend, _auth);
696
+ function validateAddonCompatibility$1(addon, frontend, _auth, backend, runtime, ecosystem, rustFrontend, javaWebFramework, database) {
697
+ const baseCompatibility = validateAddonCompatibility(addon, frontend, _auth);
698
+ if (!baseCompatibility.isCompatible) return baseCompatibility;
699
+ if (addon === "docker-compose") {
700
+ if (backend === "convex") return {
701
+ isCompatible: false,
702
+ reason: "docker-compose is not compatible with Convex backend (managed service)"
703
+ };
704
+ if (runtime === "workers") return {
705
+ isCompatible: false,
706
+ reason: "docker-compose is not compatible with Cloudflare Workers runtime"
707
+ };
708
+ if (ecosystem === "typescript" && !hasDockerComposeCompatibleFrontend(frontend)) return {
709
+ isCompatible: false,
710
+ reason: "Docker Compose currently supports Next.js, TanStack Router, React Router, React Vite, Solid, or Astro"
711
+ };
712
+ if (ecosystem === "typescript" && backend === "self" && !frontend.includes("next")) return {
713
+ isCompatible: false,
714
+ reason: "Docker Compose self-backend support currently requires Next.js"
715
+ };
716
+ if (ecosystem === "rust" && rustFrontend && rustFrontend !== "none") return {
717
+ isCompatible: false,
718
+ reason: "Docker Compose for Rust currently supports server-only projects"
719
+ };
720
+ if (ecosystem === "java" && javaWebFramework && javaWebFramework !== "spring-boot") return {
721
+ isCompatible: false,
722
+ reason: "Docker Compose for Java currently requires Spring Boot"
723
+ };
724
+ if (ecosystem === "python" && database && database !== "none" && database !== "sqlite" && database !== "postgres") return {
725
+ isCompatible: false,
726
+ reason: "Docker Compose for Python ORM projects currently supports SQLite defaults or Postgres"
727
+ };
728
+ }
729
+ return { isCompatible: true };
698
730
  }
699
- function getCompatibleAddons$1(allAddons, frontend, existingAddons = [], auth) {
700
- return getCompatibleAddons(allAddons, frontend, existingAddons, auth);
731
+ function getCompatibleAddons$1(allAddons, frontend, existingAddons = [], auth, backend, runtime) {
732
+ return getCompatibleAddons(allAddons, frontend, existingAddons, auth).filter((addon) => {
733
+ const { isCompatible } = validateAddonCompatibility$1(addon, frontend, auth, backend, runtime);
734
+ return isCompatible;
735
+ });
701
736
  }
702
- function validateAddonsAgainstFrontends(addons = [], frontends = [], auth) {
737
+ function validateAddonsAgainstFrontends(addons = [], frontends = [], auth, backend, runtime, ecosystem, rustFrontend, javaWebFramework, database) {
703
738
  for (const addon of addons) {
704
739
  if (addon === "none") continue;
705
- const { isCompatible, reason } = validateAddonCompatibility$1(addon, frontends, auth);
740
+ const { isCompatible, reason } = validateAddonCompatibility$1(addon, frontends, auth, backend, runtime, ecosystem, rustFrontend, javaWebFramework, database);
706
741
  if (!isCompatible) exitWithError(`Incompatible addon/frontend combination: ${reason}`);
707
742
  }
708
743
  }
@@ -1147,6 +1182,10 @@ function getAddonDisplay(addon) {
1147
1182
  label = "TanStack Pacer";
1148
1183
  hint = "Debounce, throttle, rate-limit & queue utilities (Beta)";
1149
1184
  break;
1185
+ case "docker-compose":
1186
+ label = "Docker Compose";
1187
+ hint = "Containerize your app for deployment";
1188
+ break;
1150
1189
  default:
1151
1190
  label = addon;
1152
1191
  hint = `Add ${addon}`;
@@ -1171,7 +1210,8 @@ const ADDON_GROUPS = {
1171
1210
  "tauri",
1172
1211
  "opentui",
1173
1212
  "wxt",
1174
- "ruler"
1213
+ "ruler",
1214
+ "docker-compose"
1175
1215
  ],
1176
1216
  Integrations: ["msw", "storybook"],
1177
1217
  "AI Agents": ["mcp", "skills"],
@@ -1183,7 +1223,13 @@ const ADDON_GROUPS = {
1183
1223
  "tanstack-pacer"
1184
1224
  ]
1185
1225
  };
1186
- async function getAddonsChoice(addons, frontends, auth) {
1226
+ function validateAddonCompatibilityForPrompt(addon, frontends, auth, backend, runtime) {
1227
+ return validateAddonCompatibility$1(addon, frontends, auth, backend, runtime);
1228
+ }
1229
+ function getCompatibleAddonsForPrompt(allAddons, frontends, existingAddons = [], auth, backend, runtime) {
1230
+ return getCompatibleAddons$1(allAddons, frontends, existingAddons, auth, backend, runtime);
1231
+ }
1232
+ async function getAddonsChoice(addons, frontends, auth, backend, runtime) {
1187
1233
  if (addons !== void 0) return addons;
1188
1234
  const allAddons = types_exports.AddonsSchema.options.filter((addon) => addon !== "none");
1189
1235
  const groupedOptions = {
@@ -1196,7 +1242,7 @@ async function getAddonsChoice(addons, frontends, auth) {
1196
1242
  };
1197
1243
  const frontendsArray = frontends || [];
1198
1244
  for (const addon of allAddons) {
1199
- const { isCompatible } = validateAddonCompatibility$1(addon, frontendsArray, auth);
1245
+ const { isCompatible } = validateAddonCompatibilityForPrompt(addon, frontendsArray, auth, backend, runtime);
1200
1246
  if (!isCompatible) continue;
1201
1247
  const { label, hint } = getAddonDisplay(addon);
1202
1248
  const option = {
@@ -1229,7 +1275,7 @@ async function getAddonsChoice(addons, frontends, auth) {
1229
1275
  if (isCancel$1(response)) return exitCancelled("Operation cancelled");
1230
1276
  return response;
1231
1277
  }
1232
- async function getAddonsToAdd(frontend, existingAddons = [], auth) {
1278
+ async function getAddonsToAdd(frontend, existingAddons = [], auth, backend, runtime) {
1233
1279
  const groupedOptions = {
1234
1280
  Tooling: [],
1235
1281
  Documentation: [],
@@ -1239,7 +1285,7 @@ async function getAddonsToAdd(frontend, existingAddons = [], auth) {
1239
1285
  TanStack: []
1240
1286
  };
1241
1287
  const frontendArray = frontend || [];
1242
- const compatibleAddons = getCompatibleAddons$1(types_exports.AddonsSchema.options.filter((addon) => addon !== "none"), frontendArray, existingAddons, auth);
1288
+ const compatibleAddons = getCompatibleAddonsForPrompt(types_exports.AddonsSchema.options.filter((addon) => addon !== "none"), frontendArray, existingAddons, auth, backend, runtime);
1243
1289
  for (const addon of compatibleAddons) {
1244
1290
  const { label, hint } = getAddonDisplay(addon);
1245
1291
  const option = {
@@ -1752,6 +1798,11 @@ const AI_PROMPT_OPTIONS = [
1752
1798
  label: "TanStack AI",
1753
1799
  hint: "Unified LLM interface for AI-powered apps (Alpha)"
1754
1800
  },
1801
+ {
1802
+ value: "ai-cli",
1803
+ label: "AI CLI",
1804
+ hint: "Agent-native terminal CLI for generating text, images, and video"
1805
+ },
1755
1806
  {
1756
1807
  value: "none",
1757
1808
  label: "None",
@@ -3480,6 +3531,36 @@ const JAVA_TESTING_LIBRARY_PROMPT_OPTIONS = [
3480
3531
  label: "Testcontainers",
3481
3532
  hint: "Disposable Docker-based integration tests"
3482
3533
  },
3534
+ {
3535
+ value: "assertj",
3536
+ label: "AssertJ",
3537
+ hint: "Fluent assertions for Java tests"
3538
+ },
3539
+ {
3540
+ value: "rest-assured",
3541
+ label: "REST Assured",
3542
+ hint: "DSL for HTTP API and REST endpoint tests"
3543
+ },
3544
+ {
3545
+ value: "wiremock",
3546
+ label: "WireMock",
3547
+ hint: "HTTP service stubs for integration tests"
3548
+ },
3549
+ {
3550
+ value: "awaitility",
3551
+ label: "Awaitility",
3552
+ hint: "Wait helpers for asynchronous Java tests"
3553
+ },
3554
+ {
3555
+ value: "archunit",
3556
+ label: "ArchUnit",
3557
+ hint: "Architecture rules for Java package boundaries"
3558
+ },
3559
+ {
3560
+ value: "jqwik",
3561
+ label: "jqwik",
3562
+ hint: "Property-based testing on the JUnit Platform"
3563
+ },
3483
3564
  {
3484
3565
  value: "none",
3485
3566
  label: "None",
@@ -3502,6 +3583,31 @@ const JAVA_LIBRARY_PROMPT_OPTIONS = [
3502
3583
  label: "Flyway",
3503
3584
  hint: "Versioned SQL database migrations for JPA-backed apps"
3504
3585
  },
3586
+ {
3587
+ value: "liquibase",
3588
+ label: "Liquibase",
3589
+ hint: "Database change management for JPA-backed apps"
3590
+ },
3591
+ {
3592
+ value: "springdoc-openapi",
3593
+ label: "Springdoc OpenAPI",
3594
+ hint: "OpenAPI and Swagger UI documentation for Spring MVC APIs"
3595
+ },
3596
+ {
3597
+ value: "lombok",
3598
+ label: "Lombok",
3599
+ hint: "Annotation processor for reducing Java boilerplate"
3600
+ },
3601
+ {
3602
+ value: "mapstruct",
3603
+ label: "MapStruct",
3604
+ hint: "Compile-time generated mappers for DTO and entity conversions"
3605
+ },
3606
+ {
3607
+ value: "caffeine",
3608
+ label: "Caffeine",
3609
+ hint: "High-performance in-memory caching through Spring Cache"
3610
+ },
3505
3611
  {
3506
3612
  value: "none",
3507
3613
  label: "None",
@@ -5568,7 +5674,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
5568
5674
  return getRuntimeChoice(flags.runtime, results.backend);
5569
5675
  },
5570
5676
  database: ({ results }) => {
5571
- if (results.ecosystem !== "typescript") return Promise.resolve("none");
5677
+ if (results.ecosystem !== "typescript") return Promise.resolve(results.ecosystem === "python" ? flags.database ?? "none" : "none");
5572
5678
  return getDatabaseChoice(flags.database, results.backend, results.runtime);
5573
5679
  },
5574
5680
  orm: ({ results }) => {
@@ -5597,8 +5703,11 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
5597
5703
  return getEffectChoice(flags.effect);
5598
5704
  },
5599
5705
  addons: ({ results }) => {
5600
- if (results.ecosystem !== "typescript") return Promise.resolve([]);
5601
- return getAddonsChoice(flags.addons, results.frontend, results.auth);
5706
+ if (results.ecosystem !== "typescript") {
5707
+ const nonTypeScriptAddons = (flags.addons ?? []).filter((addon) => addon === "docker-compose");
5708
+ return Promise.resolve(nonTypeScriptAddons);
5709
+ }
5710
+ return getAddonsChoice(flags.addons, results.frontend, results.auth, results.backend, results.runtime);
5602
5711
  },
5603
5712
  examples: ({ results }) => {
5604
5713
  if (results.ecosystem !== "typescript") return Promise.resolve([]);
@@ -7040,7 +7149,7 @@ function validateFullConfig(config, providedFlags, options) {
7040
7149
  suggestions: ["Use --server-deploy fly or --server-deploy railway for NestJS/AdonisJS", "Switch to a serverless-compatible backend like Hono or Express"]
7041
7150
  });
7042
7151
  if (config.addons && config.addons.length > 0) {
7043
- validateAddonsAgainstFrontends(config.addons, config.frontend, config.auth);
7152
+ validateAddonsAgainstFrontends(config.addons, config.frontend, config.auth, config.backend, config.runtime, config.ecosystem, config.rustFrontend, config.javaWebFramework, config.database);
7044
7153
  config.addons = [...new Set(config.addons)];
7045
7154
  }
7046
7155
  validateExamplesCompatibility(config.examples ?? [], config.backend, config.frontend ?? [], config.runtime, config.ai);
@@ -7059,7 +7168,7 @@ function validateConfigForProgrammaticUse(config) {
7059
7168
  validateApiFrontendCompatibility(config.api, config.frontend, config.astroIntegration);
7060
7169
  validateJavaConstraints(config);
7061
7170
  validatePaymentsCompatibility(config.payments, config.auth, config.backend, config.frontend);
7062
- if (config.addons && config.addons.length > 0) validateAddonsAgainstFrontends(config.addons, config.frontend, config.auth);
7171
+ if (config.addons && config.addons.length > 0) validateAddonsAgainstFrontends(config.addons, config.frontend, config.auth, config.backend, config.runtime, config.ecosystem, config.rustFrontend, config.javaWebFramework, config.database);
7063
7172
  validateExamplesCompatibility(config.examples ?? [], config.backend, config.frontend ?? [], config.runtime, config.ai);
7064
7173
  validateAIFrontendCompatibility(config.ai, config.frontend ?? []);
7065
7174
  validateUILibraryFrontendCompatibility(config.uiLibrary, config.frontend ?? [], config.astroIntegration);
@@ -8833,7 +8942,15 @@ function displayJavaInstructions(config) {
8833
8942
  const { projectName, relativePath, depsInstalled, javaWebFramework, javaBuildTool, javaOrm, javaAuth, javaLibraries, javaTestingLibraries } = config;
8834
8943
  const cdCmd = `cd ${relativePath}`;
8835
8944
  const isSpringBoot = javaWebFramework === "spring-boot" && javaBuildTool !== "none";
8836
- const effectiveJavaLibraries = isSpringBoot ? javaLibraries.filter((library) => library !== "none") : [];
8945
+ const rawJavaLibraries = isSpringBoot ? javaLibraries.filter((library) => library !== "none") : [];
8946
+ const rawJavaLibrarySet = new Set(rawJavaLibraries);
8947
+ const jpaRequiredJavaLibraries = new Set(["flyway", "liquibase"]);
8948
+ const effectiveJavaLibraries = [];
8949
+ for (const library of rawJavaLibraries) {
8950
+ if (jpaRequiredJavaLibraries.has(library) && javaOrm !== "spring-data-jpa") continue;
8951
+ if (library === "liquibase" && rawJavaLibrarySet.has("flyway")) continue;
8952
+ effectiveJavaLibraries.push(library);
8953
+ }
8837
8954
  const effectiveJavaTestingLibraries = javaBuildTool === "none" ? [] : javaTestingLibraries.filter((library) => library !== "none");
8838
8955
  const buildToolCommand = javaBuildTool === "none" ? null : javaBuildTool === "gradle" ? process.platform === "win32" ? "gradlew.bat" : "./gradlew" : process.platform === "win32" ? "mvnw.cmd" : "./mvnw";
8839
8956
  const runCommand = buildToolCommand ? isSpringBoot ? javaBuildTool === "gradle" ? `${buildToolCommand} bootRun` : `${buildToolCommand} spring-boot:run` : javaBuildTool === "gradle" ? `${buildToolCommand} run` : `${buildToolCommand} exec:java` : null;
@@ -8862,7 +8979,12 @@ function displayJavaInstructions(config) {
8862
8979
  const libraryNames = {
8863
8980
  "spring-actuator": "Spring Actuator",
8864
8981
  "spring-validation": "Spring Validation",
8865
- flyway: "Flyway"
8982
+ flyway: "Flyway",
8983
+ liquibase: "Liquibase",
8984
+ "springdoc-openapi": "Springdoc OpenAPI",
8985
+ lombok: "Lombok",
8986
+ mapstruct: "MapStruct",
8987
+ caffeine: "Caffeine"
8866
8988
  };
8867
8989
  const libraryList = effectiveJavaLibraries.map((library) => libraryNames[library] || library).join(", ");
8868
8990
  output += `${pc.cyan("•")} Libraries: ${libraryList}\n`;
@@ -8871,7 +8993,13 @@ function displayJavaInstructions(config) {
8871
8993
  const testingNames = {
8872
8994
  junit5: "JUnit 5",
8873
8995
  mockito: "Mockito",
8874
- testcontainers: "Testcontainers"
8996
+ testcontainers: "Testcontainers",
8997
+ assertj: "AssertJ",
8998
+ "rest-assured": "REST Assured",
8999
+ wiremock: "WireMock",
9000
+ awaitility: "Awaitility",
9001
+ archunit: "ArchUnit",
9002
+ jqwik: "jqwik"
8875
9003
  };
8876
9004
  const testingList = effectiveJavaTestingLibraries.map((library) => testingNames[library] || library).join(", ");
8877
9005
  output += `${pc.cyan("•")} Testing: ${testingList}\n`;
@@ -9402,9 +9530,10 @@ function displaySponsorsBox(sponsors$1) {
9402
9530
 
9403
9531
  //#endregion
9404
9532
  //#region src/index.ts
9533
+ const OPTION_ENTRY_COUNT = Object.values(types_exports.OPTION_CATEGORY_METADATA).reduce((sum, metadata) => sum + metadata.options.length, 0);
9405
9534
  const router = os.router({
9406
9535
  create: os.meta({
9407
- description: "Scaffold a new Better Fullstack project from 270+ compatible stack options",
9536
+ description: `Scaffold a new Better Fullstack project from ${OPTION_ENTRY_COUNT} compatible stack options`,
9408
9537
  default: true,
9409
9538
  negateBooleans: true
9410
9539
  }).input(CreateCommandInputSchema).handler(async ({ input }) => {
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import { i as getLatestCLIVersion, r as writeBtsConfig, t as readBtsConfig } from "./bts-config-B_rZ4_sj.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, GoAuthSchema, GoCliSchema, GoLoggingSchema, GoOrmSchema, GoWebFrameworkSchema, I18nSchema, JavaAuthSchema, JavaBuildToolSchema, JavaLibrariesSchema, JavaOrmSchema, JavaTestingLibrariesSchema, JavaWebFrameworkSchema, JobQueueSchema, LoggingSchema, ORMSchema, ObservabilitySchema, PackageManagerSchema, PaymentsSchema, PythonAiSchema, PythonAuthSchema, PythonGraphqlSchema, PythonOrmSchema, PythonQualitySchema, PythonTaskQueueSchema, PythonValidationSchema, PythonWebFrameworkSchema, RealtimeSchema, RuntimeSchema, RustApiSchema, RustAuthSchema, RustCachingSchema, RustCliSchema, RustErrorHandlingSchema, 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, GoAuthSchema, GoCliSchema, GoLoggingSchema, GoOrmSchema, GoWebFrameworkSchema, I18nSchema, JavaAuthSchema, JavaBuildToolSchema, JavaLibrariesSchema, JavaOrmSchema, JavaTestingLibrariesSchema, JavaWebFrameworkSchema, JobQueueSchema, LoggingSchema, OPTION_CATEGORY_METADATA, ORMSchema, ObservabilitySchema, PackageManagerSchema, PaymentsSchema, PythonAiSchema, PythonAuthSchema, PythonGraphqlSchema, PythonOrmSchema, PythonQualitySchema, PythonTaskQueueSchema, PythonValidationSchema, PythonWebFrameworkSchema, RealtimeSchema, RuntimeSchema, RustApiSchema, RustAuthSchema, 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
 
8
8
  //#region src/mcp.ts
9
- const INSTRUCTIONS = `Better-Fullstack scaffolds fullstack projects across TypeScript, Rust, Go, Python, and Java ecosystems with 270+ configurable options.
9
+ const INSTRUCTIONS = `Better-Fullstack scaffolds fullstack projects across TypeScript, Rust, Go, Python, and Java ecosystems with ${Object.values(OPTION_CATEGORY_METADATA).reduce((sum, metadata) => sum + metadata.options.length, 0)} configurable options.
10
10
 
11
11
  RECOMMENDED WORKFLOW:
12
12
  1. Call bfs_get_guidance to understand field semantics, required fields, and workflow rules.
@@ -766,7 +766,7 @@ async function startMcpServer() {
766
766
  await writeBtsConfig(config);
767
767
  let addonWarnings = [];
768
768
  if (config.addons.length > 0 && config.addons[0] !== "none") {
769
- const { setupAddons } = await import("./addons-setup-Cx9DU_sr.mjs");
769
+ const { setupAddons } = await import("./addons-setup-CBK1Htlc.mjs");
770
770
  addonWarnings = await setupAddons(config);
771
771
  }
772
772
  const installCmd = getInstallCommand(input.ecosystem ?? "typescript", projectName, input.packageManager, input.javaBuildTool);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "create-better-fullstack",
3
- "version": "1.6.1",
4
- "description": "Scaffold production-ready fullstack apps in seconds. Pick your stack from 340+ options — the CLI wires everything together.",
3
+ "version": "1.6.3",
4
+ "description": "Scaffold production-ready fullstack apps in seconds. Pick your stack from 425 options — the CLI wires everything together.",
5
5
  "keywords": [
6
6
  "algolia",
7
7
  "angular",
@@ -127,11 +127,11 @@
127
127
  "prepublishOnly": "npm run build"
128
128
  },
129
129
  "dependencies": {
130
- "@better-fullstack/template-generator": "^1.6.1",
131
- "@better-fullstack/types": "^1.6.1",
130
+ "@better-fullstack/template-generator": "^1.6.3",
131
+ "@better-fullstack/types": "^1.6.3",
132
132
  "@clack/core": "^0.5.0",
133
133
  "@clack/prompts": "^1.2.0",
134
- "@orpc/server": "^1.13.14",
134
+ "@orpc/server": "^1.14.0",
135
135
  "consola": "^3.4.2",
136
136
  "env-paths": "^4.0.0",
137
137
  "execa": "^9.6.1",
@@ -149,7 +149,7 @@
149
149
  "zod": "^4.3.6"
150
150
  },
151
151
  "devDependencies": {
152
- "@types/bun": "^1.3.12",
152
+ "@types/bun": "^1.3.13",
153
153
  "@types/fs-extra": "^11.0.4",
154
154
  "@types/node": "^25.6.0",
155
155
  "publint": "^0.3.18",