create-better-t-stack 2.35.3 → 2.35.5-canary.449f72a5

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
@@ -45,6 +45,40 @@ Follow the prompts to configure your project or use the `--yes` flag for default
45
45
  | **Examples** | • Todo app<br>• AI Chat interface (using Vercel AI SDK) |
46
46
  | **Developer Experience** | • Automatic Git initialization<br>• Package manager choice (npm, pnpm, bun)<br>• Automatic dependency installation |
47
47
 
48
+ ## MCP (Model Context Protocol) Support
49
+
50
+ The CLI now supports the Model Context Protocol, allowing AI assistants to scaffold projects programmatically. This enables seamless integration with AI coding assistants like Claude, Cursor, and others.
51
+
52
+ ### Quick Start with MCP
53
+
54
+ ```bash
55
+ # Start the MCP server
56
+ npx create-better-t-stack --mcp
57
+ ```
58
+
59
+ ### MCP Client Configuration
60
+
61
+ Add to your MCP client configuration:
62
+
63
+ ```json
64
+ {
65
+ "mcpServers": {
66
+ "better-t-stack": {
67
+ "command": "npx",
68
+ "args": ["-y", "create-better-t-stack", "--mcp"]
69
+ }
70
+ }
71
+ }
72
+ ```
73
+
74
+ ### Available MCP Tools
75
+
76
+ - **`create_project`** - Create a new Better-T Stack project with specified configuration
77
+ - **`list_configurations`** - List all available configuration options
78
+ - **`get_project_info`** - Get information about an existing project
79
+
80
+ For detailed MCP documentation, see [MCP_README.md](./MCP_README.md).
81
+
48
82
  ## Usage
49
83
 
50
84
  ```bash
package/dist/cli.js CHANGED
@@ -1,8 +1,426 @@
1
1
  #!/usr/bin/env node
2
- import { createBtsCli } from "./src-dID--AYy.js";
2
+ import { createBtsCli, init } from "./src-BN1_H4yj.js";
3
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
3
6
 
7
+ //#region src/mcp-server.ts
8
+ const server = new Server({
9
+ name: "create-better-t-stack",
10
+ version: "1.0.0"
11
+ });
12
+ const createProjectTool = {
13
+ name: "create_project",
14
+ description: "Create a new Better-T Stack project with the specified configuration",
15
+ inputSchema: {
16
+ type: "object",
17
+ properties: {
18
+ projectName: {
19
+ type: "string",
20
+ description: "Name of the project to create"
21
+ },
22
+ database: {
23
+ type: "string",
24
+ enum: [
25
+ "none",
26
+ "sqlite",
27
+ "postgres",
28
+ "mysql",
29
+ "mongodb"
30
+ ],
31
+ description: "Database type to use"
32
+ },
33
+ orm: {
34
+ type: "string",
35
+ enum: [
36
+ "drizzle",
37
+ "prisma",
38
+ "mongoose",
39
+ "none"
40
+ ],
41
+ description: "ORM to use"
42
+ },
43
+ backend: {
44
+ type: "string",
45
+ enum: [
46
+ "hono",
47
+ "express",
48
+ "fastify",
49
+ "next",
50
+ "elysia",
51
+ "convex",
52
+ "none"
53
+ ],
54
+ description: "Backend framework to use"
55
+ },
56
+ runtime: {
57
+ type: "string",
58
+ enum: [
59
+ "bun",
60
+ "node",
61
+ "workers",
62
+ "none"
63
+ ],
64
+ description: "Runtime environment"
65
+ },
66
+ frontend: {
67
+ type: "array",
68
+ items: {
69
+ type: "string",
70
+ enum: [
71
+ "tanstack-router",
72
+ "react-router",
73
+ "tanstack-start",
74
+ "next",
75
+ "nuxt",
76
+ "native-nativewind",
77
+ "native-unistyles",
78
+ "svelte",
79
+ "solid",
80
+ "none"
81
+ ]
82
+ },
83
+ description: "Frontend frameworks to use"
84
+ },
85
+ addons: {
86
+ type: "array",
87
+ items: {
88
+ type: "string",
89
+ enum: [
90
+ "pwa",
91
+ "tauri",
92
+ "starlight",
93
+ "biome",
94
+ "husky",
95
+ "ruler",
96
+ "turborepo",
97
+ "fumadocs",
98
+ "ultracite",
99
+ "oxlint",
100
+ "none"
101
+ ]
102
+ },
103
+ description: "Addons to include"
104
+ },
105
+ examples: {
106
+ type: "array",
107
+ items: {
108
+ type: "string",
109
+ enum: [
110
+ "todo",
111
+ "ai",
112
+ "none"
113
+ ]
114
+ },
115
+ description: "Example templates to include"
116
+ },
117
+ auth: {
118
+ type: "boolean",
119
+ description: "Whether to include authentication"
120
+ },
121
+ git: {
122
+ type: "boolean",
123
+ description: "Whether to initialize git repository"
124
+ },
125
+ packageManager: {
126
+ type: "string",
127
+ enum: [
128
+ "npm",
129
+ "pnpm",
130
+ "bun"
131
+ ],
132
+ description: "Package manager to use"
133
+ },
134
+ install: {
135
+ type: "boolean",
136
+ description: "Whether to install dependencies"
137
+ },
138
+ dbSetup: {
139
+ type: "string",
140
+ enum: [
141
+ "turso",
142
+ "neon",
143
+ "prisma-postgres",
144
+ "mongodb-atlas",
145
+ "supabase",
146
+ "d1",
147
+ "docker",
148
+ "none"
149
+ ],
150
+ description: "Database setup configuration"
151
+ },
152
+ api: {
153
+ type: "string",
154
+ enum: [
155
+ "trpc",
156
+ "orpc",
157
+ "none"
158
+ ],
159
+ description: "API type to use"
160
+ },
161
+ webDeploy: {
162
+ type: "string",
163
+ enum: [
164
+ "vercel",
165
+ "netlify",
166
+ "wrangler",
167
+ "alchemy",
168
+ "none"
169
+ ],
170
+ description: "Web deployment platform"
171
+ },
172
+ serverDeploy: {
173
+ type: "string",
174
+ enum: [
175
+ "wrangler",
176
+ "alchemy",
177
+ "none"
178
+ ],
179
+ description: "Server deployment platform"
180
+ },
181
+ directoryConflict: {
182
+ type: "string",
183
+ enum: [
184
+ "merge",
185
+ "overwrite",
186
+ "increment",
187
+ "error"
188
+ ],
189
+ description: "How to handle directory conflicts"
190
+ },
191
+ yes: {
192
+ type: "boolean",
193
+ description: "Use default configuration without prompts"
194
+ },
195
+ yolo: {
196
+ type: "boolean",
197
+ description: "Bypass validations and compatibility checks"
198
+ },
199
+ verbose: {
200
+ type: "boolean",
201
+ description: "Show detailed result information"
202
+ },
203
+ disableAnalytics: {
204
+ type: "boolean",
205
+ description: "Disable analytics"
206
+ }
207
+ },
208
+ required: ["projectName"]
209
+ }
210
+ };
211
+ const listConfigurationsTool = {
212
+ name: "list_configurations",
213
+ description: "List available configurations for Better-T Stack projects",
214
+ inputSchema: {
215
+ type: "object",
216
+ properties: {}
217
+ }
218
+ };
219
+ const getProjectInfoTool = {
220
+ name: "get_project_info",
221
+ description: "Get information about a Better-T Stack project",
222
+ inputSchema: {
223
+ type: "object",
224
+ properties: { projectPath: {
225
+ type: "string",
226
+ description: "Path to the project directory"
227
+ } },
228
+ required: ["projectPath"]
229
+ }
230
+ };
231
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
232
+ return { tools: [
233
+ createProjectTool,
234
+ listConfigurationsTool,
235
+ getProjectInfoTool
236
+ ] };
237
+ });
238
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
239
+ const { name, arguments: args } = request.params;
240
+ switch (name) {
241
+ case "create_project": try {
242
+ const projectConfig = {
243
+ projectName: args?.projectName,
244
+ database: args?.database,
245
+ orm: args?.orm,
246
+ backend: args?.backend,
247
+ runtime: args?.runtime,
248
+ frontend: args?.frontend,
249
+ addons: args?.addons,
250
+ examples: args?.examples,
251
+ auth: args?.auth,
252
+ git: args?.git,
253
+ packageManager: args?.packageManager,
254
+ install: args?.install,
255
+ dbSetup: args?.dbSetup,
256
+ api: args?.api,
257
+ webDeploy: args?.webDeploy,
258
+ serverDeploy: args?.serverDeploy,
259
+ directoryConflict: args?.directoryConflict,
260
+ yes: args?.yes,
261
+ yolo: args?.yolo,
262
+ verbose: args?.verbose,
263
+ disableAnalytics: args?.disableAnalytics
264
+ };
265
+ const result = await init(args?.projectName, projectConfig);
266
+ return { content: [{
267
+ type: "text",
268
+ text: JSON.stringify(result, null, 2)
269
+ }] };
270
+ } catch (error) {
271
+ return {
272
+ content: [{
273
+ type: "text",
274
+ text: `Error creating project: ${error instanceof Error ? error.message : String(error)}`
275
+ }],
276
+ isError: true
277
+ };
278
+ }
279
+ case "list_configurations": {
280
+ const configurations = {
281
+ databases: [
282
+ "none",
283
+ "sqlite",
284
+ "postgres",
285
+ "mysql",
286
+ "mongodb"
287
+ ],
288
+ orms: [
289
+ "drizzle",
290
+ "prisma",
291
+ "mongoose",
292
+ "none"
293
+ ],
294
+ backends: [
295
+ "hono",
296
+ "express",
297
+ "fastify",
298
+ "next",
299
+ "elysia",
300
+ "convex",
301
+ "none"
302
+ ],
303
+ runtimes: [
304
+ "bun",
305
+ "node",
306
+ "workers",
307
+ "none"
308
+ ],
309
+ frontends: [
310
+ "tanstack-router",
311
+ "react-router",
312
+ "tanstack-start",
313
+ "next",
314
+ "nuxt",
315
+ "native-nativewind",
316
+ "native-unistyles",
317
+ "svelte",
318
+ "solid",
319
+ "none"
320
+ ],
321
+ addons: [
322
+ "pwa",
323
+ "tauri",
324
+ "starlight",
325
+ "biome",
326
+ "husky",
327
+ "ruler",
328
+ "turborepo",
329
+ "fumadocs",
330
+ "ultracite",
331
+ "oxlint",
332
+ "none"
333
+ ],
334
+ examples: [
335
+ "todo",
336
+ "ai",
337
+ "none"
338
+ ],
339
+ packageManagers: [
340
+ "npm",
341
+ "pnpm",
342
+ "bun"
343
+ ],
344
+ dbSetups: [
345
+ "turso",
346
+ "neon",
347
+ "prisma-postgres",
348
+ "mongodb-atlas",
349
+ "supabase",
350
+ "d1",
351
+ "docker",
352
+ "none"
353
+ ],
354
+ apis: [
355
+ "trpc",
356
+ "orpc",
357
+ "none"
358
+ ],
359
+ webDeploys: [
360
+ "vercel",
361
+ "netlify",
362
+ "wrangler",
363
+ "alchemy",
364
+ "none"
365
+ ],
366
+ serverDeploys: [
367
+ "wrangler",
368
+ "alchemy",
369
+ "none"
370
+ ],
371
+ directoryConflicts: [
372
+ "merge",
373
+ "overwrite",
374
+ "increment",
375
+ "error"
376
+ ]
377
+ };
378
+ return { content: [{
379
+ type: "text",
380
+ text: JSON.stringify(configurations, null, 2)
381
+ }] };
382
+ }
383
+ case "get_project_info": try {
384
+ return { content: [{
385
+ type: "text",
386
+ text: "Project info functionality not yet implemented"
387
+ }] };
388
+ } catch (error) {
389
+ return {
390
+ content: [{
391
+ type: "text",
392
+ text: `Error getting project info: ${error instanceof Error ? error.message : String(error)}`
393
+ }],
394
+ isError: true
395
+ };
396
+ }
397
+ default: throw new Error(`Unknown tool: ${name}`);
398
+ }
399
+ });
400
+ async function startMCPServer() {
401
+ const transport = new StdioServerTransport();
402
+ await server.connect(transport);
403
+ console.error("Better-T Stack MCP server started");
404
+ }
405
+ async function main$1() {
406
+ await startMCPServer();
407
+ }
408
+ if (import.meta.url === `file://${process.argv[1]}`) main$1().catch((error) => {
409
+ console.error("MCP server error:", error);
410
+ process.exit(1);
411
+ });
412
+
413
+ //#endregion
4
414
  //#region src/cli.ts
5
- createBtsCli().run();
415
+ async function main() {
416
+ const args = process.argv.slice(2);
417
+ if (args.includes("--mcp")) await startMCPServer();
418
+ else createBtsCli().run();
419
+ }
420
+ main().catch((error) => {
421
+ console.error("CLI error:", error);
422
+ process.exit(1);
423
+ });
6
424
 
7
425
  //#endregion
8
426
  export { };
package/dist/index.d.ts CHANGED
@@ -134,6 +134,7 @@ type CreateInput = {
134
134
  directoryConflict?: DirectoryConflict;
135
135
  renderTitle?: boolean;
136
136
  disableAnalytics?: boolean;
137
+ mcp?: boolean;
137
138
  };
138
139
  type AddInput = {
139
140
  addons?: Addons[];
@@ -221,6 +222,7 @@ declare const router: trpcServer.TRPCBuiltRouter<{
221
222
  directoryConflict?: "error" | "merge" | "overwrite" | "increment" | undefined;
222
223
  renderTitle?: boolean | undefined;
223
224
  disableAnalytics?: boolean | undefined;
225
+ mcp?: boolean | undefined;
224
226
  }];
225
227
  output: InitResult | undefined;
226
228
  meta: object;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { builder, createBtsCli, docs, init, router, sponsors } from "./src-dID--AYy.js";
2
+ import { builder, createBtsCli, docs, init, router, sponsors } from "./src-BN1_H4yj.js";
3
3
 
4
4
  export { builder, createBtsCli, docs, init, router, sponsors };
@@ -1080,7 +1080,8 @@ async function getServerDeploymentChoice(deployment, runtime, backend, webDeploy
1080
1080
  if (backend === "none" || backend === "convex") return "none";
1081
1081
  if (backend !== "hono") return "none";
1082
1082
  const options = [];
1083
- if (runtime === "workers") ["alchemy", "wrangler"].forEach((deploy) => {
1083
+ if (runtime !== "workers") return "none";
1084
+ ["alchemy", "wrangler"].forEach((deploy) => {
1084
1085
  const { label, hint } = getDeploymentDisplay$1(deploy);
1085
1086
  options.unshift({
1086
1087
  value: deploy,
@@ -1088,11 +1089,6 @@ async function getServerDeploymentChoice(deployment, runtime, backend, webDeploy
1088
1089
  hint
1089
1090
  });
1090
1091
  });
1091
- else options.push({
1092
- value: "none",
1093
- label: "None",
1094
- hint: "Manual setup"
1095
- });
1096
1092
  const response = await select({
1097
1093
  message: "Select server deployment",
1098
1094
  options,
@@ -1123,11 +1119,7 @@ async function getServerDeploymentToAdd(runtime, existingDeployment, backend) {
1123
1119
  }
1124
1120
  }
1125
1121
  if (existingDeployment && existingDeployment !== "none") return "none";
1126
- if (options.length > 0) options.push({
1127
- value: "none",
1128
- label: "None",
1129
- hint: "Skip deployment setup"
1130
- });
1122
+ if (options.length > 0) {}
1131
1123
  if (options.length === 0) return "none";
1132
1124
  const response = await select({
1133
1125
  message: "Select server deployment",
@@ -1353,7 +1345,7 @@ const getLatestCLIVersion = () => {
1353
1345
  */
1354
1346
  function isTelemetryEnabled() {
1355
1347
  const BTS_TELEMETRY_DISABLED = process.env.BTS_TELEMETRY_DISABLED;
1356
- const BTS_TELEMETRY = "1";
1348
+ const BTS_TELEMETRY = "0";
1357
1349
  if (BTS_TELEMETRY_DISABLED !== void 0) return BTS_TELEMETRY_DISABLED !== "1";
1358
1350
  if (BTS_TELEMETRY !== void 0) return BTS_TELEMETRY === "1";
1359
1351
  return true;
@@ -1361,8 +1353,8 @@ function isTelemetryEnabled() {
1361
1353
 
1362
1354
  //#endregion
1363
1355
  //#region src/utils/analytics.ts
1364
- const POSTHOG_API_KEY = "phc_8ZUxEwwfKMajJLvxz1daGd931dYbQrwKNficBmsdIrs";
1365
- const POSTHOG_HOST = "https://us.i.posthog.com";
1356
+ const POSTHOG_API_KEY = "random";
1357
+ const POSTHOG_HOST = "random";
1366
1358
  function generateSessionId() {
1367
1359
  const rand = Math.random().toString(36).slice(2);
1368
1360
  const now = Date.now().toString(36);
@@ -1740,6 +1732,7 @@ function validateFullConfig(config, providedFlags, options) {
1740
1732
  validateApiConstraints(config, options);
1741
1733
  validateServerDeployRequiresBackend(config.serverDeploy, config.backend);
1742
1734
  validateWorkersCompatibility(providedFlags, options, config);
1735
+ if (config.runtime === "workers" && config.serverDeploy === "none") exitWithError("Cloudflare Workers runtime requires a server deployment. Please choose 'wrangler' or 'alchemy' for --server-deploy.");
1743
1736
  if (config.addons && config.addons.length > 0) {
1744
1737
  validateAddonsAgainstFrontends(config.addons, config.frontend);
1745
1738
  config.addons = [...new Set(config.addons)];
@@ -2983,11 +2976,7 @@ async function setupWorkersServerDeploy(serverDir, _packageManager) {
2983
2976
  };
2984
2977
  await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
2985
2978
  await addPackageDependency({
2986
- devDependencies: [
2987
- "wrangler",
2988
- "@types/node",
2989
- "@cloudflare/workers-types"
2990
- ],
2979
+ devDependencies: ["wrangler", "@types/node"],
2991
2980
  projectDir: serverDir
2992
2981
  });
2993
2982
  }
@@ -3012,7 +3001,6 @@ async function setupAlchemyServerDeploy(serverDir, _packageManager) {
3012
3001
  "alchemy",
3013
3002
  "wrangler",
3014
3003
  "@types/node",
3015
- "@cloudflare/workers-types",
3016
3004
  "dotenv"
3017
3005
  ],
3018
3006
  projectDir: serverDir
@@ -3380,6 +3368,17 @@ async function setupTanStackStartAlchemyDeploy(projectDir, _packageManager) {
3380
3368
  defaultImport: "alchemy"
3381
3369
  });
3382
3370
  else alchemyImport.setModuleSpecifier("alchemy/cloudflare/tanstack-start");
3371
+ const reactImport = sourceFile.getImportDeclaration("@vitejs/plugin-react");
3372
+ let reactPluginIdentifier = "viteReact";
3373
+ if (!reactImport) sourceFile.addImportDeclaration({
3374
+ moduleSpecifier: "@vitejs/plugin-react",
3375
+ defaultImport: "viteReact"
3376
+ });
3377
+ else {
3378
+ const defaultImport = reactImport.getDefaultImport();
3379
+ if (defaultImport) reactPluginIdentifier = defaultImport.getText();
3380
+ else reactImport.setDefaultImport("viteReact");
3381
+ }
3383
3382
  const exportAssignment = sourceFile.getExportAssignment((d) => !d.isExportEquals());
3384
3383
  if (!exportAssignment) return;
3385
3384
  const defineConfigCall = exportAssignment.getExpression();
@@ -3403,26 +3402,33 @@ async function setupTanStackStartAlchemyDeploy(projectDir, _packageManager) {
3403
3402
  const hasShim = initializer.getElements().some((el) => el.getText().includes("alchemy"));
3404
3403
  if (!hasShim) initializer.addElement("alchemy()");
3405
3404
  const tanstackElements = initializer.getElements().filter((el) => el.getText().includes("tanstackStart"));
3405
+ let needsReactPlugin = false;
3406
3406
  tanstackElements.forEach((element) => {
3407
3407
  if (Node.isCallExpression(element)) {
3408
3408
  const args = element.getArguments();
3409
- if (args.length === 0) element.addArgument(`{
3409
+ if (args.length === 0) {
3410
+ element.addArgument(`{
3410
3411
  target: "cloudflare-module",
3411
3412
  customViteReactPlugin: true,
3412
3413
  }`);
3413
- else if (args.length === 1 && Node.isObjectLiteralExpression(args[0])) {
3414
+ needsReactPlugin = true;
3415
+ } else if (args.length === 1 && Node.isObjectLiteralExpression(args[0])) {
3414
3416
  const configObj = args[0];
3415
3417
  if (!configObj.getProperty("target")) configObj.addPropertyAssignment({
3416
3418
  name: "target",
3417
3419
  initializer: "\"cloudflare-module\""
3418
3420
  });
3419
- if (!configObj.getProperty("customViteReactPlugin")) configObj.addPropertyAssignment({
3421
+ const hasCustomViteReactPlugin = !!configObj.getProperty("customViteReactPlugin");
3422
+ if (!hasCustomViteReactPlugin) configObj.addPropertyAssignment({
3420
3423
  name: "customViteReactPlugin",
3421
3424
  initializer: "true"
3422
3425
  });
3426
+ needsReactPlugin = true;
3423
3427
  }
3424
3428
  }
3425
3429
  });
3430
+ const hasReactPlugin = initializer.getElements().some((el) => Node.isCallExpression(el) && el.getExpression().getText() === reactPluginIdentifier);
3431
+ if (needsReactPlugin && !hasReactPlugin) initializer.addElement(`${reactPluginIdentifier}()`);
3426
3432
  }
3427
3433
  } else configObject.addPropertyAssignment({
3428
3434
  name: "plugins",
@@ -3631,6 +3637,17 @@ async function setupTanstackStartWorkersDeploy(projectDir, packageManager) {
3631
3637
  if (!await fs.pathExists(viteConfigPath)) return;
3632
3638
  const sourceFile = tsProject.addSourceFileAtPathIfExists(viteConfigPath);
3633
3639
  if (!sourceFile) return;
3640
+ const reactImport = sourceFile.getImportDeclaration("@vitejs/plugin-react");
3641
+ let reactPluginIdentifier = "viteReact";
3642
+ if (!reactImport) sourceFile.addImportDeclaration({
3643
+ moduleSpecifier: "@vitejs/plugin-react",
3644
+ defaultImport: "viteReact"
3645
+ });
3646
+ else {
3647
+ const defaultImport = reactImport.getDefaultImport();
3648
+ if (defaultImport) reactPluginIdentifier = defaultImport.getText();
3649
+ else reactImport.setDefaultImport("viteReact");
3650
+ }
3634
3651
  const defineCall = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression).find((expr) => {
3635
3652
  const expression = expr.getExpression();
3636
3653
  return Node.isIdentifier(expression) && expression.getText() === "defineConfig";
@@ -3640,9 +3657,15 @@ async function setupTanstackStartWorkersDeploy(projectDir, packageManager) {
3640
3657
  if (!configObj) return;
3641
3658
  const pluginsArray = ensureArrayProperty(configObj, "plugins");
3642
3659
  const tanstackPluginIndex = pluginsArray.getElements().findIndex((el) => el.getText().includes("tanstackStart("));
3643
- const tanstackPluginText = "tanstackStart({ target: \"cloudflare-module\" })";
3660
+ const tanstackPluginText = "tanstackStart({ target: \"cloudflare-module\", customViteReactPlugin: true })";
3644
3661
  if (tanstackPluginIndex === -1) pluginsArray.addElement(tanstackPluginText);
3645
3662
  else pluginsArray.getElements()[tanstackPluginIndex].replaceWithText(tanstackPluginText);
3663
+ const hasReactPlugin = pluginsArray.getElements().some((el) => Node.isCallExpression(el) && el.getExpression().getText() === reactPluginIdentifier);
3664
+ if (!hasReactPlugin) {
3665
+ const nextIndex = pluginsArray.getElements().findIndex((el) => el.getText().includes("tanstackStart(")) + 1;
3666
+ if (nextIndex > 0) pluginsArray.insertElement(nextIndex, `${reactPluginIdentifier}()`);
3667
+ else pluginsArray.addElement(`${reactPluginIdentifier}()`);
3668
+ }
3646
3669
  await tsProject.save();
3647
3670
  }
3648
3671
 
@@ -6297,7 +6320,8 @@ const router = t.router({
6297
6320
  serverDeploy: ServerDeploySchema.optional(),
6298
6321
  directoryConflict: DirectoryConflictSchema.optional(),
6299
6322
  renderTitle: z.boolean().optional(),
6300
- disableAnalytics: z.boolean().optional().default(false).describe("Disable analytics")
6323
+ disableAnalytics: z.boolean().optional().default(false).describe("Disable analytics"),
6324
+ mcp: z.boolean().optional().default(false).describe("Start as MCP server")
6301
6325
  })])).mutation(async ({ input }) => {
6302
6326
  const [projectName, options] = input;
6303
6327
  const combinedInput = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-better-t-stack",
3
- "version": "2.35.3",
3
+ "version": "2.35.5-canary.449f72a5",
4
4
  "description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -67,6 +67,7 @@
67
67
  "@biomejs/js-api": "^3.0.0",
68
68
  "@biomejs/wasm-nodejs": "^2.2.0",
69
69
  "@clack/prompts": "^0.11.0",
70
+ "@modelcontextprotocol/sdk": "^0.4.0",
70
71
  "consola": "^3.4.2",
71
72
  "execa": "^9.6.0",
72
73
  "fs-extra": "^11.3.1",
@@ -8,28 +8,23 @@
8
8
  "skipLibCheck": true,
9
9
  "baseUrl": "./",
10
10
  "paths": {
11
- "@/*": ["./src/*"]
12
- {{#if (eq orm "prisma")}},
13
- "prisma": ["node_modules/prisma"]
14
- {{/if}}
11
+ "@/*": ["./src/*"]{{#if (eq orm "prisma")}},
12
+ "prisma": ["node_modules/prisma"]{{/if}}
15
13
  },
16
14
  "outDir": "./dist",
17
15
  "types": [
18
16
  {{#if (eq runtime "node")}}
19
- "node"
17
+ "node"
20
18
  {{else if (eq runtime "bun")}}
21
- "bun"
19
+ "bun"
22
20
  {{else if (eq runtime "workers")}}
23
- "@cloudflare/workers-types",
24
- "node"
21
+ "node"
25
22
  {{else}}
26
- "node",
27
- "bun"
23
+ "node",
24
+ "bun"
28
25
  {{/if}}
29
- ],
30
- {{#unless (or (eq backend "convex") (eq backend "none"))}}
31
- "composite": true,
32
- {{/unless}}
26
+ ]{{#unless (or (eq backend "convex") (eq backend "none"))}},
27
+ "composite": true{{/unless}},
33
28
  "jsx": "react-jsx"{{#if (eq backend "hono")}},
34
29
  "jsxImportSource": "hono/jsx"{{/if}}
35
30
  }
@@ -35,7 +35,7 @@
35
35
  "@testing-library/react": "^16.2.0",
36
36
  "@types/react": "^19.0.12",
37
37
  "@types/react-dom": "^19.0.4",
38
- "@vitejs/plugin-react": "^4.5.2",
38
+ "@vitejs/plugin-react": "^5.0.1",
39
39
  "jsdom": "^26.0.0",
40
40
  "typescript": "^5.7.2",
41
41
  "vite": "^7.0.2",
@@ -2,7 +2,13 @@ import { defineConfig } from "vite";
2
2
  import tsconfigPaths from "vite-tsconfig-paths";
3
3
  import { tanstackStart } from "@tanstack/react-start/plugin/vite";
4
4
  import tailwindcss from "@tailwindcss/vite";
5
+ import viteReact from "@vitejs/plugin-react";
5
6
 
6
7
  export default defineConfig({
7
- plugins: [tsconfigPaths(), tailwindcss(), tanstackStart({})],
8
+ plugins: [
9
+ tsconfigPaths(),
10
+ tailwindcss(),
11
+ tanstackStart({ customViteReactPlugin: true }),
12
+ viteReact(),
13
+ ],
8
14
  });