create-better-fullstack 1.8.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -43,13 +43,27 @@ Configure your stack visually — pick every option from a UI, preview your choi
43
43
  --yolo # Scaffold a random stack — good for exploring
44
44
  --template <name> # Use a preset (t3, mern, pern, uniwind)
45
45
  --ecosystem <lang> # Start in typescript, react-native, rust, python, go, java, or elixir mode
46
+ --part <binding> # Add a multi-ecosystem stack part, e.g. frontend:typescript:next
46
47
  --version-channel # Dependency channel: stable, latest, beta
47
48
  --no-git # Skip git initialization
48
49
  --no-install # Skip dependency installation
50
+ --verify # Run generated project checks without starting dev servers
49
51
  --package-manager # Package manager (bun, pnpm, npm, yarn)
50
52
  --verbose # Show detailed output
51
53
  ```
52
54
 
55
+ ## Multi-Ecosystem Example
56
+
57
+ Use repeated `--part` flags to bind each generated app or capability to an ecosystem:
58
+
59
+ ```bash
60
+ bun create better-fullstack@latest my-mixed-app \
61
+ --part frontend:typescript:next \
62
+ --part backend:go:gin \
63
+ --part backend.orm:go:gorm \
64
+ --part database:universal:postgres
65
+ ```
66
+
53
67
  ## Links
54
68
 
55
69
  - [Website](https://better-fullstack.dev)
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import "./bts-config-BMniWIbd.mjs";
3
+ import { i as setupLefthook, n as setupBiome, r as setupHusky, t as setupAddons } from "./addons-setup-DHoByttt.mjs";
4
+
5
+ export { setupAddons };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { s as dependencyVersionMap, t as readBtsConfig } from "./bts-config-YcroedMK.mjs";
2
+ import { m as dependencyVersionMap, t as readBtsConfig } from "./bts-config-BMniWIbd.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";
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { t as __reExport } from "./chunk-CCII7kTE.mjs";
2
3
  import fs from "fs-extra";
3
4
  import path from "node:path";
4
5
  import { fileURLToPath } from "node:url";
@@ -70,13 +71,169 @@ const getLatestCLIVersion = () => {
70
71
  return fs.readJSONSync(packageJsonPath).version ?? "1.0.0";
71
72
  };
72
73
 
74
+ //#endregion
75
+ //#region src/types.ts
76
+ var types_exports = {};
77
+ import * as import__better_fullstack_types from "@better-fullstack/types";
78
+ __reExport(types_exports, import__better_fullstack_types);
79
+
80
+ //#endregion
81
+ //#region src/utils/graph-summary.ts
82
+ const FRONTEND_LABELS = {
83
+ next: "Next.js web app",
84
+ astro: "Astro web app",
85
+ "react-vite": "React + Vite app",
86
+ "react-router": "React Router app",
87
+ "tanstack-router": "TanStack Router app",
88
+ "tanstack-start": "TanStack Start app",
89
+ nuxt: "Nuxt app",
90
+ svelte: "SvelteKit app",
91
+ solid: "Solid app",
92
+ "solid-start": "SolidStart app",
93
+ qwik: "Qwik app",
94
+ angular: "Angular app",
95
+ redwood: "RedwoodJS app",
96
+ fresh: "Fresh app"
97
+ };
98
+ const BACKEND_LABELS = {
99
+ "rust:axum": "Rust Axum API",
100
+ "rust:actix-web": "Rust Actix Web API",
101
+ "rust:rocket": "Rust Rocket API",
102
+ "rust:warp": "Rust Warp API",
103
+ "rust:poem": "Rust Poem API",
104
+ "rust:salvo": "Rust Salvo API",
105
+ "python:fastapi": "Python FastAPI API",
106
+ "python:django": "Python Django API",
107
+ "python:flask": "Python Flask API",
108
+ "python:litestar": "Python Litestar API",
109
+ "go:gin": "Go Gin API",
110
+ "go:echo": "Go Echo API",
111
+ "go:fiber": "Go Fiber API",
112
+ "go:chi": "Go Chi API",
113
+ "java:spring-boot": "Java Spring Boot API",
114
+ "java:quarkus": "Java Quarkus API",
115
+ "elixir:phoenix": "Elixir Phoenix API",
116
+ "elixir:phoenix-live-view": "Elixir Phoenix LiveView API"
117
+ };
118
+ const TOOL_LABELS = {
119
+ postgres: "Postgres",
120
+ sqlite: "SQLite",
121
+ mysql: "MySQL",
122
+ mongodb: "MongoDB",
123
+ redis: "Redis",
124
+ edgedb: "EdgeDB",
125
+ gorm: "GORM",
126
+ sqlc: "sqlc",
127
+ ent: "Ent",
128
+ "ecto-sql": "Ecto SQL",
129
+ ecto: "Ecto",
130
+ sqlx: "SQLx",
131
+ "sea-orm": "SeaORM",
132
+ sqlalchemy: "SQLAlchemy",
133
+ sqlmodel: "SQLModel",
134
+ "django-orm": "Django ORM",
135
+ "spring-data-jpa": "Spring Data JPA"
136
+ };
137
+ function getSelectedGraphParts(config) {
138
+ return (config.stackParts ?? []).filter((part) => part.source !== "provided");
139
+ }
140
+ function getGraphPart(config, role, ecosystem) {
141
+ return getSelectedGraphParts(config).find((part) => part.role === role && (!ecosystem || part.ecosystem === ecosystem));
142
+ }
143
+ function hasGraphPart(config, role, ecosystem) {
144
+ return Boolean(getGraphPart(config, role, ecosystem));
145
+ }
146
+ function getPrimaryGraphPart(config, role, ecosystem) {
147
+ return getSelectedGraphParts(config).find((part) => part.role === role && !part.ownerPartId && (!ecosystem || part.ecosystem === ecosystem));
148
+ }
149
+ function getGraphBackendUrl(config) {
150
+ switch (getPrimaryGraphPart(config, "backend")?.ecosystem) {
151
+ case "elixir": return "http://localhost:4000";
152
+ case "rust": return "http://localhost:3000";
153
+ case "python": return "http://localhost:8000";
154
+ case "go":
155
+ case "java": return "http://localhost:8080";
156
+ default: return null;
157
+ }
158
+ }
159
+ function getEffectiveStack(config) {
160
+ const effectiveStack = {};
161
+ const parts = getSelectedGraphParts(config);
162
+ for (const part of parts) {
163
+ const key = part.ownerPartId ? `backend.${part.role}` : part.role;
164
+ effectiveStack[key] = `${part.ecosystem}:${part.toolId}`;
165
+ }
166
+ return effectiveStack;
167
+ }
168
+ function labelFor(part) {
169
+ if (!part) return null;
170
+ if (part.role === "frontend" && part.ecosystem === "typescript") return FRONTEND_LABELS[part.toolId] ?? `${part.toolId} web app`;
171
+ if (part.role === "backend") return BACKEND_LABELS[`${part.ecosystem}:${part.toolId}`] ?? `${part.ecosystem} ${part.toolId} API`;
172
+ return TOOL_LABELS[part.toolId] ?? part.toolId;
173
+ }
174
+ function getGraphSummary(config) {
175
+ const selectedParts = getSelectedGraphParts(config);
176
+ if (selectedParts.length === 0) return null;
177
+ const frontend = getPrimaryGraphPart(config, "frontend");
178
+ const backend = getPrimaryGraphPart(config, "backend");
179
+ const database = getPrimaryGraphPart(config, "database");
180
+ const orm = selectedParts.find((part) => part.role === "orm");
181
+ const segments = [labelFor(frontend), labelFor(backend)].filter(Boolean);
182
+ const dataLabel = [labelFor(orm), labelFor(database)].filter(Boolean).join("/");
183
+ if (dataLabel) segments.push(dataLabel);
184
+ return segments.length > 0 ? segments.join(" + ") : selectedParts.map((part) => (0, types_exports.formatStackPartSpec)(part, selectedParts)).join(" + ");
185
+ }
186
+ function getGraphBackendDeployInstructions(config) {
187
+ const backend = getPrimaryGraphPart(config, "backend");
188
+ if (!backend || config.serverDeploy === "none") return "";
189
+ const targetPath = backend.targetPath ?? "apps/server";
190
+ const backendLabel = labelFor(backend) ?? `${backend.ecosystem}:${backend.toolId}`;
191
+ switch (config.serverDeploy) {
192
+ case "railway": return [
193
+ "Server deployment with Railway:",
194
+ `* Backend: ${backendLabel}`,
195
+ `* Config: ${targetPath}/railway.toml`,
196
+ `* Deploy: cd ${targetPath} && railway up`
197
+ ].join("\n");
198
+ case "docker": return [
199
+ "Server deployment with Docker:",
200
+ `* Backend: ${backendLabel}`,
201
+ `* Build: cd ${targetPath} && docker build -t better-fullstack-server .`
202
+ ].join("\n");
203
+ case "fly": return [
204
+ "Server deployment with Fly:",
205
+ `* Backend: ${backendLabel}`,
206
+ `* Deploy: cd ${targetPath} && fly launch`
207
+ ].join("\n");
208
+ case "vercel": return [
209
+ "Server deployment with Vercel:",
210
+ `* Backend: ${backendLabel}`,
211
+ `* Deploy from: ${targetPath}`
212
+ ].join("\n");
213
+ case "cloudflare":
214
+ case "sst": return [
215
+ `Server deployment with ${config.serverDeploy}:`,
216
+ `* Backend: ${backendLabel}`,
217
+ `* Review generated files in ${targetPath}`
218
+ ].join("\n");
219
+ default: return "";
220
+ }
221
+ }
222
+
73
223
  //#endregion
74
224
  //#region src/utils/bts-config.ts
75
225
  const BTS_CONFIG_FILE = "bts.jsonc";
76
226
  async function writeBtsConfig(projectConfig) {
227
+ const stackParts = projectConfig.stackParts ?? (0, types_exports.legacyProjectConfigToStackParts)(projectConfig);
228
+ const graphSummary = projectConfig.stackParts ? getGraphSummary({ stackParts }) : null;
229
+ const effectiveStack = projectConfig.stackParts ? getEffectiveStack({ stackParts }) : void 0;
77
230
  const btsConfig = {
78
231
  version: getLatestCLIVersion(),
79
232
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
233
+ ...graphSummary ? {
234
+ graphSummary,
235
+ effectiveStack
236
+ } : {},
80
237
  ecosystem: projectConfig.ecosystem,
81
238
  database: projectConfig.database,
82
239
  orm: projectConfig.orm,
@@ -168,12 +325,17 @@ async function writeBtsConfig(projectConfig) {
168
325
  elixirTesting: projectConfig.elixirTesting,
169
326
  elixirQuality: projectConfig.elixirQuality,
170
327
  elixirDeploy: projectConfig.elixirDeploy,
171
- aiDocs: projectConfig.aiDocs
328
+ aiDocs: projectConfig.aiDocs,
329
+ stackParts
172
330
  };
173
331
  const baseContent = {
174
332
  $schema: "https://better-fullstack-web.vercel.app/schema.json",
175
333
  version: btsConfig.version,
176
334
  createdAt: btsConfig.createdAt,
335
+ ...btsConfig.graphSummary ? {
336
+ graphSummary: btsConfig.graphSummary,
337
+ effectiveStack: btsConfig.effectiveStack
338
+ } : {},
177
339
  ecosystem: btsConfig.ecosystem,
178
340
  database: btsConfig.database,
179
341
  orm: btsConfig.orm,
@@ -265,7 +427,8 @@ async function writeBtsConfig(projectConfig) {
265
427
  elixirTesting: btsConfig.elixirTesting,
266
428
  elixirQuality: btsConfig.elixirQuality,
267
429
  elixirDeploy: btsConfig.elixirDeploy,
268
- aiDocs: btsConfig.aiDocs
430
+ aiDocs: btsConfig.aiDocs,
431
+ stackParts: btsConfig.stackParts
269
432
  };
270
433
  let configContent = JSON.stringify(baseContent);
271
434
  const formatResult = JSONC.format(configContent, void 0, {
@@ -276,6 +439,7 @@ async function writeBtsConfig(projectConfig) {
276
439
  configContent = JSONC.applyEdits(configContent, formatResult);
277
440
  const finalContent = `// Better Fullstack configuration file
278
441
  // safe to delete
442
+ ${graphSummary ? "// For multi-ecosystem projects, graphSummary/effectiveStack and stackParts are the source of truth.\n// Legacy fields such as backend/orm may stay as compatibility fallbacks.\n" : ""}
279
443
 
280
444
  ${configContent}`;
281
445
  const configPath = path.join(projectConfig.projectDir, BTS_CONFIG_FILE);
@@ -295,7 +459,19 @@ async function readBtsConfig(projectDir) {
295
459
  console.warn("Warning: Found errors parsing bts.jsonc:", errors);
296
460
  return null;
297
461
  }
298
- return config;
462
+ if (config.stackParts && config.stackParts.length > 0) {
463
+ const diagnostics = (0, types_exports.compareLegacyConfigToStackParts)(config, config.stackParts);
464
+ if (diagnostics.length > 0) console.warn(`Warning: bts.jsonc legacy fields differ from stackParts; using stackParts for ${diagnostics.map((diagnostic) => diagnostic.path).filter(Boolean).join(", ")}.`);
465
+ return {
466
+ ...config,
467
+ ...(0, types_exports.stackPartsToLegacyProjectConfigPartial)(config.stackParts),
468
+ stackParts: config.stackParts
469
+ };
470
+ }
471
+ return {
472
+ ...config,
473
+ stackParts: (0, types_exports.legacyProjectConfigToStackParts)(config)
474
+ };
299
475
  } catch {
300
476
  return null;
301
477
  }
@@ -318,4 +494,4 @@ async function updateBtsConfig(projectDir, updates) {
318
494
  }
319
495
 
320
496
  //#endregion
321
- export { DEFAULT_CONFIG as a, getDefaultConfig as c, getLatestCLIVersion as i, getUserPkgManager as l, updateBtsConfig as n, DEFAULT_UI_LIBRARY_BY_FRONTEND as o, writeBtsConfig as r, dependencyVersionMap as s, readBtsConfig as t };
497
+ export { getGraphBackendUrl as a, getPrimaryGraphPart as c, getLatestCLIVersion as d, DEFAULT_CONFIG as f, getUserPkgManager as g, getDefaultConfig as h, getGraphBackendDeployInstructions as i, hasGraphPart as l, dependencyVersionMap as m, updateBtsConfig as n, getGraphPart as o, DEFAULT_UI_LIBRARY_BY_FRONTEND as p, writeBtsConfig as r, getGraphSummary as s, readBtsConfig as t, types_exports as u };
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-DoPutOIG.mjs").then((m) => m.startMcpServer());
3
+ if (process.argv[2] === "mcp" && process.argv.length === 3) import("./mcp-YvDMaVXB.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
@@ -29,8 +29,10 @@ declare const router: {
29
29
  }>>;
30
30
  yes: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
31
31
  yolo: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
32
+ part: z.ZodOptional<z.ZodArray<z.ZodString>>;
32
33
  verbose: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
33
34
  dryRun: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
35
+ verify: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
34
36
  ecosystem: z.ZodOptional<z.ZodEnum<{
35
37
  typescript: "typescript";
36
38
  "react-native": "react-native";
@@ -95,8 +97,8 @@ declare const router: {
95
97
  uppy: "uppy";
96
98
  }>>;
97
99
  effect: z.ZodOptional<z.ZodEnum<{
98
- effect: "effect";
99
100
  none: "none";
101
+ effect: "effect";
100
102
  "effect-full": "effect-full";
101
103
  }>>;
102
104
  stateManagement: z.ZodOptional<z.ZodEnum<{
@@ -180,6 +182,7 @@ declare const router: {
180
182
  none: "none";
181
183
  pino: "pino";
182
184
  winston: "winston";
185
+ evlog: "evlog";
183
186
  }>>;
184
187
  observability: z.ZodOptional<z.ZodEnum<{
185
188
  none: "none";
@@ -206,6 +209,7 @@ declare const router: {
206
209
  sanity: "sanity";
207
210
  strapi: "strapi";
208
211
  tinacms: "tinacms";
212
+ directus: "directus";
209
213
  }>>;
210
214
  caching: z.ZodOptional<z.ZodEnum<{
211
215
  none: "none";
@@ -227,6 +231,7 @@ declare const router: {
227
231
  none: "none";
228
232
  s3: "s3";
229
233
  r2: "r2";
234
+ cloudinary: "cloudinary";
230
235
  }>>;
231
236
  mobileNavigation: z.ZodOptional<z.ZodEnum<{
232
237
  none: "none";
@@ -309,6 +314,7 @@ declare const router: {
309
314
  wxt: "wxt";
310
315
  msw: "msw";
311
316
  storybook: "storybook";
317
+ swr: "swr";
312
318
  "tanstack-query": "tanstack-query";
313
319
  "tanstack-table": "tanstack-table";
314
320
  "tanstack-virtual": "tanstack-virtual";
@@ -317,8 +323,8 @@ declare const router: {
317
323
  "docker-compose": "docker-compose";
318
324
  }>>>;
319
325
  examples: z.ZodOptional<z.ZodArray<z.ZodEnum<{
320
- ai: "ai";
321
326
  none: "none";
327
+ ai: "ai";
322
328
  "chat-sdk": "chat-sdk";
323
329
  "tanstack-showcase": "tanstack-showcase";
324
330
  }>>>;
@@ -383,9 +389,9 @@ declare const router: {
383
389
  "postcss-only": "postcss-only";
384
390
  }>>;
385
391
  uiLibrary: z.ZodOptional<z.ZodEnum<{
386
- mui: "mui";
387
392
  none: "none";
388
393
  "shadcn-ui": "shadcn-ui";
394
+ "shadcn-svelte": "shadcn-svelte";
389
395
  daisyui: "daisyui";
390
396
  "radix-ui": "radix-ui";
391
397
  "headless-ui": "headless-ui";
@@ -393,6 +399,7 @@ declare const router: {
393
399
  "chakra-ui": "chakra-ui";
394
400
  nextui: "nextui";
395
401
  mantine: "mantine";
402
+ mui: "mui";
396
403
  antd: "antd";
397
404
  "base-ui": "base-ui";
398
405
  "ark-ui": "ark-ui";
@@ -626,8 +633,8 @@ declare const router: {
626
633
  chi: "chi";
627
634
  }>>;
628
635
  goOrm: z.ZodOptional<z.ZodEnum<{
629
- gorm: "gorm";
630
636
  none: "none";
637
+ gorm: "gorm";
631
638
  sqlc: "sqlc";
632
639
  ent: "ent";
633
640
  }>>;
@@ -802,7 +809,7 @@ declare const router: {
802
809
  backend: "none" | "hono" | "express" | "fastify" | "elysia" | "fets" | "nestjs" | "adonisjs" | "nitro" | "encore" | "convex" | "self";
803
810
  runtime: "none" | "bun" | "node" | "workers";
804
811
  frontend: ("none" | "tanstack-router" | "react-router" | "react-vite" | "tanstack-start" | "next" | "vinext" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid" | "solid-start" | "astro" | "qwik" | "angular" | "redwood" | "fresh")[];
805
- 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")[];
812
+ addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "swr" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer" | "docker-compose")[];
806
813
  examples: ("ai" | "none" | "chat-sdk" | "tanstack-showcase")[];
807
814
  auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
808
815
  payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
@@ -821,21 +828,21 @@ declare const router: {
821
828
  testing: "none" | "vitest" | "playwright" | "vitest-playwright" | "jest" | "cypress";
822
829
  email: "none" | "react-email" | "resend" | "nodemailer" | "postmark" | "sendgrid" | "aws-ses" | "mailgun" | "plunk";
823
830
  cssFramework: "none" | "tailwind" | "scss" | "less" | "postcss-only";
824
- uiLibrary: "none" | "mui" | "shadcn-ui" | "daisyui" | "radix-ui" | "headless-ui" | "park-ui" | "chakra-ui" | "nextui" | "mantine" | "antd" | "base-ui" | "ark-ui" | "react-aria";
831
+ uiLibrary: "none" | "shadcn-ui" | "shadcn-svelte" | "daisyui" | "radix-ui" | "headless-ui" | "park-ui" | "chakra-ui" | "nextui" | "mantine" | "mui" | "antd" | "base-ui" | "ark-ui" | "react-aria";
825
832
  validation: "none" | "zod" | "valibot" | "arktype" | "typebox" | "typia" | "runtypes" | "effect-schema";
826
833
  realtime: "none" | "socket-io" | "partykit" | "ably" | "pusher" | "liveblocks" | "yjs";
827
834
  jobQueue: "none" | "bullmq" | "trigger-dev" | "inngest" | "temporal";
828
835
  animation: "none" | "framer-motion" | "gsap" | "react-spring" | "auto-animate" | "lottie";
829
836
  fileUpload: "none" | "uploadthing" | "filepond" | "uppy";
830
- logging: "none" | "pino" | "winston";
837
+ logging: "none" | "pino" | "winston" | "evlog";
831
838
  observability: "none" | "opentelemetry" | "sentry" | "grafana";
832
839
  featureFlags: "none" | "growthbook" | "posthog" | "launchdarkly" | "flagsmith" | "unleash";
833
840
  analytics: "none" | "plausible" | "umami";
834
- cms: "none" | "payload" | "sanity" | "strapi" | "tinacms";
841
+ cms: "none" | "payload" | "sanity" | "strapi" | "tinacms" | "directus";
835
842
  caching: "none" | "upstash-redis";
836
843
  i18n: "none" | "i18next" | "next-intl";
837
844
  search: "none" | "meilisearch" | "typesense" | "elasticsearch" | "algolia";
838
- fileStorage: "none" | "s3" | "r2";
845
+ fileStorage: "none" | "s3" | "r2" | "cloudinary";
839
846
  mobileNavigation: "none" | "expo-router" | "react-navigation";
840
847
  mobileUI: "none" | "uniwind" | "tamagui" | "gluestack-ui" | "unistyles";
841
848
  mobileStorage: "none" | "mmkv";
@@ -898,6 +905,17 @@ declare const router: {
898
905
  shadcnBaseColor?: "neutral" | "stone" | "zinc" | "gray" | undefined;
899
906
  shadcnFont?: "inter" | "geist" | "noto-sans" | "nunito-sans" | "figtree" | "roboto" | "raleway" | "dm-sans" | "public-sans" | "outfit" | "jetbrains-mono" | "geist-mono" | undefined;
900
907
  shadcnRadius?: "default" | "none" | "small" | "medium" | "large" | undefined;
908
+ stackParts?: {
909
+ id: string;
910
+ role: "api" | "runtime" | "backend" | "database" | "orm" | "auth" | "payments" | "email" | "logging" | "observability" | "stateManagement" | "forms" | "validation" | "testing" | "jobQueue" | "caching" | "i18n" | "search" | "fileStorage" | "cms" | "featureFlags" | "analytics" | "codeQuality" | "documentation" | "ai" | "frontend" | "mobile" | "deploy" | "ui" | "css" | "appPlatform";
911
+ toolId: string;
912
+ ecosystem: "typescript" | "react-native" | "rust" | "python" | "go" | "java" | "elixir" | "universal";
913
+ source: "selected" | "defaulted" | "provided" | "legacy" | "adjusted";
914
+ ownerPartId?: string | undefined;
915
+ providedByPartId?: string | undefined;
916
+ targetPath?: string | undefined;
917
+ settings?: Record<string, unknown> | undefined;
918
+ }[] | undefined;
901
919
  };
902
920
  reproducibleCommand: string;
903
921
  timeScaffolded: string;
@@ -921,7 +939,7 @@ declare const router: {
921
939
  backend: "none" | "hono" | "express" | "fastify" | "elysia" | "fets" | "nestjs" | "adonisjs" | "nitro" | "encore" | "convex" | "self";
922
940
  runtime: "none" | "bun" | "node" | "workers";
923
941
  frontend: ("none" | "tanstack-router" | "react-router" | "react-vite" | "tanstack-start" | "next" | "vinext" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid" | "solid-start" | "astro" | "qwik" | "angular" | "redwood" | "fresh")[];
924
- 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")[];
942
+ addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "swr" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer" | "docker-compose")[];
925
943
  examples: ("ai" | "none" | "chat-sdk" | "tanstack-showcase")[];
926
944
  auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
927
945
  payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
@@ -940,21 +958,21 @@ declare const router: {
940
958
  testing: "none" | "vitest" | "playwright" | "vitest-playwright" | "jest" | "cypress";
941
959
  email: "none" | "react-email" | "resend" | "nodemailer" | "postmark" | "sendgrid" | "aws-ses" | "mailgun" | "plunk";
942
960
  cssFramework: "none" | "tailwind" | "scss" | "less" | "postcss-only";
943
- uiLibrary: "none" | "mui" | "shadcn-ui" | "daisyui" | "radix-ui" | "headless-ui" | "park-ui" | "chakra-ui" | "nextui" | "mantine" | "antd" | "base-ui" | "ark-ui" | "react-aria";
961
+ uiLibrary: "none" | "shadcn-ui" | "shadcn-svelte" | "daisyui" | "radix-ui" | "headless-ui" | "park-ui" | "chakra-ui" | "nextui" | "mantine" | "mui" | "antd" | "base-ui" | "ark-ui" | "react-aria";
944
962
  validation: "none" | "zod" | "valibot" | "arktype" | "typebox" | "typia" | "runtypes" | "effect-schema";
945
963
  realtime: "none" | "socket-io" | "partykit" | "ably" | "pusher" | "liveblocks" | "yjs";
946
964
  jobQueue: "none" | "bullmq" | "trigger-dev" | "inngest" | "temporal";
947
965
  animation: "none" | "framer-motion" | "gsap" | "react-spring" | "auto-animate" | "lottie";
948
966
  fileUpload: "none" | "uploadthing" | "filepond" | "uppy";
949
- logging: "none" | "pino" | "winston";
967
+ logging: "none" | "pino" | "winston" | "evlog";
950
968
  observability: "none" | "opentelemetry" | "sentry" | "grafana";
951
969
  featureFlags: "none" | "growthbook" | "posthog" | "launchdarkly" | "flagsmith" | "unleash";
952
970
  analytics: "none" | "plausible" | "umami";
953
- cms: "none" | "payload" | "sanity" | "strapi" | "tinacms";
971
+ cms: "none" | "payload" | "sanity" | "strapi" | "tinacms" | "directus";
954
972
  caching: "none" | "upstash-redis";
955
973
  i18n: "none" | "i18next" | "next-intl";
956
974
  search: "none" | "meilisearch" | "typesense" | "elasticsearch" | "algolia";
957
- fileStorage: "none" | "s3" | "r2";
975
+ fileStorage: "none" | "s3" | "r2" | "cloudinary";
958
976
  mobileNavigation: "none" | "expo-router" | "react-navigation";
959
977
  mobileUI: "none" | "uniwind" | "tamagui" | "gluestack-ui" | "unistyles";
960
978
  mobileStorage: "none" | "mmkv";
@@ -1017,6 +1035,17 @@ declare const router: {
1017
1035
  shadcnBaseColor?: "neutral" | "stone" | "zinc" | "gray" | undefined;
1018
1036
  shadcnFont?: "inter" | "geist" | "noto-sans" | "nunito-sans" | "figtree" | "roboto" | "raleway" | "dm-sans" | "public-sans" | "outfit" | "jetbrains-mono" | "geist-mono" | undefined;
1019
1037
  shadcnRadius?: "default" | "none" | "small" | "medium" | "large" | undefined;
1038
+ stackParts?: {
1039
+ id: string;
1040
+ role: "api" | "runtime" | "backend" | "database" | "orm" | "auth" | "payments" | "email" | "logging" | "observability" | "stateManagement" | "forms" | "validation" | "testing" | "jobQueue" | "caching" | "i18n" | "search" | "fileStorage" | "cms" | "featureFlags" | "analytics" | "codeQuality" | "documentation" | "ai" | "frontend" | "mobile" | "deploy" | "ui" | "css" | "appPlatform";
1041
+ toolId: string;
1042
+ ecosystem: "typescript" | "react-native" | "rust" | "python" | "go" | "java" | "elixir" | "universal";
1043
+ source: "selected" | "defaulted" | "provided" | "legacy" | "adjusted";
1044
+ ownerPartId?: string | undefined;
1045
+ providedByPartId?: string | undefined;
1046
+ targetPath?: string | undefined;
1047
+ settings?: Record<string, unknown> | undefined;
1048
+ }[] | undefined;
1020
1049
  };
1021
1050
  reproducibleCommand: string;
1022
1051
  timeScaffolded: string;
@@ -1053,7 +1082,7 @@ declare const router: {
1053
1082
  backend: "none" | "hono" | "express" | "fastify" | "elysia" | "fets" | "nestjs" | "adonisjs" | "nitro" | "encore" | "convex" | "self";
1054
1083
  runtime: "none" | "bun" | "node" | "workers";
1055
1084
  frontend: ("none" | "tanstack-router" | "react-router" | "react-vite" | "tanstack-start" | "next" | "vinext" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid" | "solid-start" | "astro" | "qwik" | "angular" | "redwood" | "fresh")[];
1056
- 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")[];
1085
+ addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "swr" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer" | "docker-compose")[];
1057
1086
  examples: ("ai" | "none" | "chat-sdk" | "tanstack-showcase")[];
1058
1087
  auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
1059
1088
  payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
@@ -1072,21 +1101,21 @@ declare const router: {
1072
1101
  testing: "none" | "vitest" | "playwright" | "vitest-playwright" | "jest" | "cypress";
1073
1102
  email: "none" | "react-email" | "resend" | "nodemailer" | "postmark" | "sendgrid" | "aws-ses" | "mailgun" | "plunk";
1074
1103
  cssFramework: "none" | "tailwind" | "scss" | "less" | "postcss-only";
1075
- uiLibrary: "none" | "mui" | "shadcn-ui" | "daisyui" | "radix-ui" | "headless-ui" | "park-ui" | "chakra-ui" | "nextui" | "mantine" | "antd" | "base-ui" | "ark-ui" | "react-aria";
1104
+ uiLibrary: "none" | "shadcn-ui" | "shadcn-svelte" | "daisyui" | "radix-ui" | "headless-ui" | "park-ui" | "chakra-ui" | "nextui" | "mantine" | "mui" | "antd" | "base-ui" | "ark-ui" | "react-aria";
1076
1105
  validation: "none" | "zod" | "valibot" | "arktype" | "typebox" | "typia" | "runtypes" | "effect-schema";
1077
1106
  realtime: "none" | "socket-io" | "partykit" | "ably" | "pusher" | "liveblocks" | "yjs";
1078
1107
  jobQueue: "none" | "bullmq" | "trigger-dev" | "inngest" | "temporal";
1079
1108
  animation: "none" | "framer-motion" | "gsap" | "react-spring" | "auto-animate" | "lottie";
1080
1109
  fileUpload: "none" | "uploadthing" | "filepond" | "uppy";
1081
- logging: "none" | "pino" | "winston";
1110
+ logging: "none" | "pino" | "winston" | "evlog";
1082
1111
  observability: "none" | "opentelemetry" | "sentry" | "grafana";
1083
1112
  featureFlags: "none" | "growthbook" | "posthog" | "launchdarkly" | "flagsmith" | "unleash";
1084
1113
  analytics: "none" | "plausible" | "umami";
1085
- cms: "none" | "payload" | "sanity" | "strapi" | "tinacms";
1114
+ cms: "none" | "payload" | "sanity" | "strapi" | "tinacms" | "directus";
1086
1115
  caching: "none" | "upstash-redis";
1087
1116
  i18n: "none" | "i18next" | "next-intl";
1088
1117
  search: "none" | "meilisearch" | "typesense" | "elasticsearch" | "algolia";
1089
- fileStorage: "none" | "s3" | "r2";
1118
+ fileStorage: "none" | "s3" | "r2" | "cloudinary";
1090
1119
  mobileNavigation: "none" | "expo-router" | "react-navigation";
1091
1120
  mobileUI: "none" | "uniwind" | "tamagui" | "gluestack-ui" | "unistyles";
1092
1121
  mobileStorage: "none" | "mmkv";
@@ -1149,6 +1178,17 @@ declare const router: {
1149
1178
  shadcnBaseColor?: "neutral" | "stone" | "zinc" | "gray" | undefined;
1150
1179
  shadcnFont?: "inter" | "geist" | "noto-sans" | "nunito-sans" | "figtree" | "roboto" | "raleway" | "dm-sans" | "public-sans" | "outfit" | "jetbrains-mono" | "geist-mono" | undefined;
1151
1180
  shadcnRadius?: "default" | "none" | "small" | "medium" | "large" | undefined;
1181
+ stackParts?: {
1182
+ id: string;
1183
+ role: "api" | "runtime" | "backend" | "database" | "orm" | "auth" | "payments" | "email" | "logging" | "observability" | "stateManagement" | "forms" | "validation" | "testing" | "jobQueue" | "caching" | "i18n" | "search" | "fileStorage" | "cms" | "featureFlags" | "analytics" | "codeQuality" | "documentation" | "ai" | "frontend" | "mobile" | "deploy" | "ui" | "css" | "appPlatform";
1184
+ toolId: string;
1185
+ ecosystem: "typescript" | "react-native" | "rust" | "python" | "go" | "java" | "elixir" | "universal";
1186
+ source: "selected" | "defaulted" | "provided" | "legacy" | "adjusted";
1187
+ ownerPartId?: string | undefined;
1188
+ providedByPartId?: string | undefined;
1189
+ targetPath?: string | undefined;
1190
+ settings?: Record<string, unknown> | undefined;
1191
+ }[] | undefined;
1152
1192
  };
1153
1193
  reproducibleCommand: string;
1154
1194
  timeScaffolded: string;
@@ -1172,7 +1212,7 @@ declare const router: {
1172
1212
  backend: "none" | "hono" | "express" | "fastify" | "elysia" | "fets" | "nestjs" | "adonisjs" | "nitro" | "encore" | "convex" | "self";
1173
1213
  runtime: "none" | "bun" | "node" | "workers";
1174
1214
  frontend: ("none" | "tanstack-router" | "react-router" | "react-vite" | "tanstack-start" | "next" | "vinext" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid" | "solid-start" | "astro" | "qwik" | "angular" | "redwood" | "fresh")[];
1175
- 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")[];
1215
+ addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "swr" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer" | "docker-compose")[];
1176
1216
  examples: ("ai" | "none" | "chat-sdk" | "tanstack-showcase")[];
1177
1217
  auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
1178
1218
  payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
@@ -1191,21 +1231,21 @@ declare const router: {
1191
1231
  testing: "none" | "vitest" | "playwright" | "vitest-playwright" | "jest" | "cypress";
1192
1232
  email: "none" | "react-email" | "resend" | "nodemailer" | "postmark" | "sendgrid" | "aws-ses" | "mailgun" | "plunk";
1193
1233
  cssFramework: "none" | "tailwind" | "scss" | "less" | "postcss-only";
1194
- uiLibrary: "none" | "mui" | "shadcn-ui" | "daisyui" | "radix-ui" | "headless-ui" | "park-ui" | "chakra-ui" | "nextui" | "mantine" | "antd" | "base-ui" | "ark-ui" | "react-aria";
1234
+ uiLibrary: "none" | "shadcn-ui" | "shadcn-svelte" | "daisyui" | "radix-ui" | "headless-ui" | "park-ui" | "chakra-ui" | "nextui" | "mantine" | "mui" | "antd" | "base-ui" | "ark-ui" | "react-aria";
1195
1235
  validation: "none" | "zod" | "valibot" | "arktype" | "typebox" | "typia" | "runtypes" | "effect-schema";
1196
1236
  realtime: "none" | "socket-io" | "partykit" | "ably" | "pusher" | "liveblocks" | "yjs";
1197
1237
  jobQueue: "none" | "bullmq" | "trigger-dev" | "inngest" | "temporal";
1198
1238
  animation: "none" | "framer-motion" | "gsap" | "react-spring" | "auto-animate" | "lottie";
1199
1239
  fileUpload: "none" | "uploadthing" | "filepond" | "uppy";
1200
- logging: "none" | "pino" | "winston";
1240
+ logging: "none" | "pino" | "winston" | "evlog";
1201
1241
  observability: "none" | "opentelemetry" | "sentry" | "grafana";
1202
1242
  featureFlags: "none" | "growthbook" | "posthog" | "launchdarkly" | "flagsmith" | "unleash";
1203
1243
  analytics: "none" | "plausible" | "umami";
1204
- cms: "none" | "payload" | "sanity" | "strapi" | "tinacms";
1244
+ cms: "none" | "payload" | "sanity" | "strapi" | "tinacms" | "directus";
1205
1245
  caching: "none" | "upstash-redis";
1206
1246
  i18n: "none" | "i18next" | "next-intl";
1207
1247
  search: "none" | "meilisearch" | "typesense" | "elasticsearch" | "algolia";
1208
- fileStorage: "none" | "s3" | "r2";
1248
+ fileStorage: "none" | "s3" | "r2" | "cloudinary";
1209
1249
  mobileNavigation: "none" | "expo-router" | "react-navigation";
1210
1250
  mobileUI: "none" | "uniwind" | "tamagui" | "gluestack-ui" | "unistyles";
1211
1251
  mobileStorage: "none" | "mmkv";
@@ -1268,6 +1308,17 @@ declare const router: {
1268
1308
  shadcnBaseColor?: "neutral" | "stone" | "zinc" | "gray" | undefined;
1269
1309
  shadcnFont?: "inter" | "geist" | "noto-sans" | "nunito-sans" | "figtree" | "roboto" | "raleway" | "dm-sans" | "public-sans" | "outfit" | "jetbrains-mono" | "geist-mono" | undefined;
1270
1310
  shadcnRadius?: "default" | "none" | "small" | "medium" | "large" | undefined;
1311
+ stackParts?: {
1312
+ id: string;
1313
+ role: "api" | "runtime" | "backend" | "database" | "orm" | "auth" | "payments" | "email" | "logging" | "observability" | "stateManagement" | "forms" | "validation" | "testing" | "jobQueue" | "caching" | "i18n" | "search" | "fileStorage" | "cms" | "featureFlags" | "analytics" | "codeQuality" | "documentation" | "ai" | "frontend" | "mobile" | "deploy" | "ui" | "css" | "appPlatform";
1314
+ toolId: string;
1315
+ ecosystem: "typescript" | "react-native" | "rust" | "python" | "go" | "java" | "elixir" | "universal";
1316
+ source: "selected" | "defaulted" | "provided" | "legacy" | "adjusted";
1317
+ ownerPartId?: string | undefined;
1318
+ providedByPartId?: string | undefined;
1319
+ targetPath?: string | undefined;
1320
+ settings?: Record<string, unknown> | undefined;
1321
+ }[] | undefined;
1271
1322
  };
1272
1323
  reproducibleCommand: string;
1273
1324
  timeScaffolded: string;
@@ -1316,6 +1367,7 @@ declare const router: {
1316
1367
  wxt: "wxt";
1317
1368
  msw: "msw";
1318
1369
  storybook: "storybook";
1370
+ swr: "swr";
1319
1371
  "tanstack-query": "tanstack-query";
1320
1372
  "tanstack-table": "tanstack-table";
1321
1373
  "tanstack-virtual": "tanstack-virtual";