create-better-t-stack 3.6.0 → 3.6.2

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/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as createBtsCli } from "./src-CWiiwWrU.js";
2
+ import { n as createBtsCli } from "./src-D7BpMan5.js";
3
3
 
4
4
  //#region src/cli.ts
5
5
  createBtsCli().run();
package/dist/index.d.ts CHANGED
@@ -126,6 +126,7 @@ declare const TemplateSchema: z.ZodEnum<{
126
126
  mern: "mern";
127
127
  pern: "pern";
128
128
  t3: "t3";
129
+ uniwind: "uniwind";
129
130
  none: "none";
130
131
  }>;
131
132
  type Template = z.infer<typeof TemplateSchema>;
@@ -221,6 +222,7 @@ declare const router: {
221
222
  mern: "mern";
222
223
  pern: "pern";
223
224
  t3: "t3";
225
+ uniwind: "uniwind";
224
226
  none: "none";
225
227
  }>>;
226
228
  yes: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodBoolean>>;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { a as router, i as init, n as createBtsCli, o as sponsors, r as docs, t as builder } from "./src-CWiiwWrU.js";
2
+ import { a as router, i as init, n as createBtsCli, o as sponsors, r as docs, t as builder } from "./src-D7BpMan5.js";
3
3
 
4
4
  export { builder, createBtsCli, docs, init, router, sponsors };
@@ -295,6 +295,7 @@ const TemplateSchema = z.enum([
295
295
  "mern",
296
296
  "pern",
297
297
  "t3",
298
+ "uniwind",
298
299
  "none"
299
300
  ]).describe("Predefined project template");
300
301
 
@@ -1632,6 +1633,21 @@ const TEMPLATE_PRESETS = {
1632
1633
  webDeploy: "none",
1633
1634
  serverDeploy: "none"
1634
1635
  },
1636
+ uniwind: {
1637
+ database: "none",
1638
+ orm: "none",
1639
+ backend: "none",
1640
+ runtime: "none",
1641
+ frontend: ["native-uniwind"],
1642
+ api: "none",
1643
+ auth: "none",
1644
+ payments: "none",
1645
+ addons: ["none"],
1646
+ examples: ["none"],
1647
+ dbSetup: "none",
1648
+ webDeploy: "none",
1649
+ serverDeploy: "none"
1650
+ },
1635
1651
  none: null
1636
1652
  };
1637
1653
  function getTemplateConfig(template) {
@@ -1645,6 +1661,7 @@ function getTemplateDescription(template) {
1645
1661
  mern: "MongoDB + Express + React + Node.js - Classic MERN stack",
1646
1662
  pern: "PostgreSQL + Express + React + Node.js - Popular PERN stack",
1647
1663
  t3: "T3 Stack - Next.js + tRPC + Prisma + PostgreSQL + Better Auth",
1664
+ uniwind: "Expo + Uniwind native app with no backend services",
1648
1665
  none: "No template - Full customization"
1649
1666
  }[template] || "";
1650
1667
  }
@@ -5729,6 +5746,7 @@ async function setupDatabase(config, cliInput) {
5729
5746
  const s = spinner();
5730
5747
  const dbPackageDir = path.join(projectDir, "packages/db");
5731
5748
  const webDir = path.join(projectDir, "apps/web");
5749
+ const webDirExists = await fs.pathExists(webDir);
5732
5750
  if (!await fs.pathExists(dbPackageDir)) return;
5733
5751
  try {
5734
5752
  if (orm === "prisma") {
@@ -5777,7 +5795,7 @@ async function setupDatabase(config, cliInput) {
5777
5795
  devDependencies: ["drizzle-kit"],
5778
5796
  projectDir: dbPackageDir
5779
5797
  });
5780
- await addPackageDependency({
5798
+ if (webDirExists) await addPackageDependency({
5781
5799
  dependencies: ["@libsql/client", "libsql"],
5782
5800
  projectDir: webDir
5783
5801
  });
@@ -6325,7 +6343,7 @@ async function displayPostInstallInstructions(config) {
6325
6343
  const databaseInstructions = !isConvex && database !== "none" ? await getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup, serverDeploy, backend) : "";
6326
6344
  const tauriInstructions = addons?.includes("tauri") ? getTauriInstructions(runCmd) : "";
6327
6345
  const lintingInstructions = hasHuskyOrBiome ? getLintingInstructions(runCmd) : "";
6328
- const nativeInstructions = frontend?.includes("native-bare") || frontend?.includes("native-uniwind") || frontend?.includes("native-unistyles") ? getNativeInstructions(isConvex, isBackendSelf, frontend || []) : "";
6346
+ const nativeInstructions = (frontend?.includes("native-bare") || frontend?.includes("native-uniwind") || frontend?.includes("native-unistyles")) && backend !== "none" ? getNativeInstructions(isConvex, isBackendSelf, frontend || []) : "";
6329
6347
  const pwaInstructions = addons?.includes("pwa") && frontend?.includes("react-router") ? getPwaInstructions() : "";
6330
6348
  const starlightInstructions = addons?.includes("starlight") ? getStarlightInstructions(runCmd) : "";
6331
6349
  const clerkInstructions = isConvex && config.auth === "clerk" ? getClerkInstructions() : "";
@@ -6362,16 +6380,19 @@ async function displayPostInstallInstructions(config) {
6362
6380
  output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} dev\n`;
6363
6381
  }
6364
6382
  }
6365
- output += `${pc.bold("Your project will be available at:")}\n`;
6366
- if (hasWeb) output += `${pc.cyan("")} Frontend: http://localhost:${webPort}\n`;
6367
- else if (!hasNative && !addons?.includes("starlight")) output += `${pc.yellow("NOTE:")} You are creating a backend-only app\n (no frontend selected)\n`;
6368
- if (!isConvex && !isBackendSelf) {
6369
- output += `${pc.cyan("")} Backend API: http://localhost:3000\n`;
6370
- if (api === "orpc") output += `${pc.cyan("•")} OpenAPI (Scalar UI): http://localhost:3000/api-reference\n`;
6383
+ const hasStandaloneBackend = backend !== "none";
6384
+ if (hasWeb || hasStandaloneBackend || addons?.includes("starlight") || addons?.includes("fumadocs")) {
6385
+ output += `${pc.bold("Your project will be available at:")}\n`;
6386
+ if (hasWeb) output += `${pc.cyan("•")} Frontend: http://localhost:${webPort}\n`;
6387
+ else if (!hasNative && !addons?.includes("starlight")) output += `${pc.yellow("NOTE:")} You are creating a backend-only app\n (no frontend selected)\n`;
6388
+ if (!isConvex && !isBackendSelf && hasStandaloneBackend) {
6389
+ output += `${pc.cyan("•")} Backend API: http://localhost:3000\n`;
6390
+ if (api === "orpc") output += `${pc.cyan("•")} OpenAPI (Scalar UI): http://localhost:3000/api-reference\n`;
6391
+ }
6392
+ if (isBackendSelf && api === "orpc") output += `${pc.cyan("•")} OpenAPI (Scalar UI): http://localhost:${webPort}/api/rpc/api-reference\n`;
6393
+ if (addons?.includes("starlight")) output += `${pc.cyan("•")} Docs: http://localhost:4321\n`;
6394
+ if (addons?.includes("fumadocs")) output += `${pc.cyan("•")} Fumadocs: http://localhost:4000\n`;
6371
6395
  }
6372
- if (isBackendSelf && api === "orpc") output += `${pc.cyan("•")} OpenAPI (Scalar UI): http://localhost:${webPort}/api/rpc/api-reference\n`;
6373
- if (addons?.includes("starlight")) output += `${pc.cyan("•")} Docs: http://localhost:4321\n`;
6374
- if (addons?.includes("fumadocs")) output += `${pc.cyan("•")} Fumadocs: http://localhost:4000\n`;
6375
6396
  if (nativeInstructions) output += `\n${nativeInstructions.trim()}\n`;
6376
6397
  if (databaseInstructions) output += `\n${databaseInstructions.trim()}\n`;
6377
6398
  if (tauriInstructions) output += `\n${tauriInstructions.trim()}\n`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-better-t-stack",
3
- "version": "3.6.0",
3
+ "version": "3.6.2",
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",
@@ -24,128 +24,124 @@ import { SignUp } from "@/components/sign-up";
24
24
  import { useQuery } from "convex/react";
25
25
  import { api } from "@{{projectName}}/backend/convex/_generated/api";
26
26
  {{/if}}
27
+ {{#unless (eq backend "none")}}
27
28
  import { Ionicons } from "@expo/vector-icons";
29
+ {{/unless}}
28
30
  import { Card, Chip, useThemeColor } from "heroui-native";
29
31
 
30
32
  export default function Home() {
31
33
  {{#if (eq api "orpc")}}
32
- const healthCheck = useQuery(orpc.healthCheck.queryOptions());
34
+ const healthCheck = useQuery(orpc.healthCheck.queryOptions());
33
35
  {{/if}}
34
36
  {{#if (eq api "trpc")}}
35
- const healthCheck = useQuery(trpc.healthCheck.queryOptions());
37
+ const healthCheck = useQuery(trpc.healthCheck.queryOptions());
36
38
  {{/if}}
37
39
  {{#if (and (eq backend "convex") (eq auth "clerk"))}}
38
- const { user } = useUser();
39
- const healthCheck = useQuery(api.healthCheck.get);
40
- const privateData = useQuery(api.privateData.get);
40
+ const { user } = useUser();
41
+ const healthCheck = useQuery(api.healthCheck.get);
42
+ const privateData = useQuery(api.privateData.get);
41
43
  {{else if (and (eq backend "convex") (eq auth "better-auth"))}}
42
- const healthCheck = useQuery(api.healthCheck.get);
43
- const { isAuthenticated } = useConvexAuth();
44
- const user = useQuery(api.auth.getCurrentUser, isAuthenticated ? {} : "skip");
44
+ const healthCheck = useQuery(api.healthCheck.get);
45
+ const { isAuthenticated } = useConvexAuth();
46
+ const user = useQuery(api.auth.getCurrentUser, isAuthenticated ? {} : "skip");
45
47
  {{else if (eq backend "convex")}}
46
- const healthCheck = useQuery(api.healthCheck.get);
48
+ const healthCheck = useQuery(api.healthCheck.get);
47
49
  {{/if}}
48
- const mutedColor = useThemeColor("muted");
49
- const successColor = useThemeColor("success");
50
- const dangerColor = useThemeColor("danger");
50
+ {{#unless (eq backend "none")}}
51
+ const mutedColor = useThemeColor("muted");
52
+ const successColor = useThemeColor("success");
53
+ const dangerColor = useThemeColor("danger");
51
54
 
52
55
  {{#if (eq backend "convex")}}
53
- const isConnected = healthCheck === "OK";
54
- const isLoading = healthCheck === undefined;
56
+ const isConnected = healthCheck === "OK";
57
+ const isLoading = healthCheck === undefined;
55
58
  {{else}}
56
59
  {{#unless (eq api "none")}}
57
- const isConnected = healthCheck?.data === "OK";
58
- const isLoading = healthCheck?.isLoading;
60
+ const isConnected = healthCheck?.data === "OK";
61
+ const isLoading = healthCheck?.isLoading;
59
62
  {{/unless}}
60
63
  {{/if}}
64
+ {{/unless}}
61
65
 
62
- return (
63
- <Container className="p-6">
64
- <View className="py-4 mb-6">
65
- <Text className="text-4xl font-bold text-foreground mb-2">
66
- BETTER T STACK
67
- </Text>
68
- </View>
69
-
70
- {{#unless (and (eq backend "convex") (eq auth "better-auth"))}}
71
- <Card variant="secondary" className="p-6">
72
- <View className="flex-row items-center justify-between mb-4">
73
- <Card.Title>System Status</Card.Title>
74
- <Chip
75
- variant="secondary"
76
- color={isConnected ? "success" : "danger"}
77
- size="sm"
78
- >
79
- <Chip.Label>
80
- {isConnected ? "LIVE" : "OFFLINE"}
81
- </Chip.Label>
82
- </Chip>
83
- </View>
84
- <Card className="p-4">
85
- <View className="flex-row items-center">
86
- <View
87
- className={`w-3 h-3 rounded-full mr-3 ${
88
- isConnected ? "bg-success" : "bg-muted"
89
- }`}
90
- />
91
- <View className="flex-1">
92
- <Text className="text-foreground font-medium mb-1">
93
- {{#if (eq backend "convex")}}
94
- Convex Backend
95
- {{else}}
96
- {{#unless (eq api "none")}}
97
- {{#if (eq api "orpc")}}ORPC{{else}}TRPC{{/if}} Backend
98
- {{/unless}}
99
- {{/if}}
100
- </Text>
101
- <Card.Description>
102
- {isLoading
103
- ? "Checking connection..."
104
- : isConnected
105
- ? "Connected to API"
106
- : "API Disconnected"}
107
- </Card.Description>
108
- </View>
109
- {isLoading && (
110
- <Ionicons name="hourglass-outline" size={20} color={mutedColor} />
111
- )}
112
- {!isLoading && isConnected && (
113
- <Ionicons name="checkmark-circle" size={20} color={successColor} />
114
- )}
115
- {!isLoading && !isConnected && (
116
- <Ionicons name="close-circle" size={20} color={dangerColor} />
117
- )}
118
- </View>
119
- </Card>
120
- </Card>
121
- {{/unless}}
66
+ return (
67
+ <Container className="p-6">
68
+ <View className="py-4 mb-6">
69
+ <Text className="text-4xl font-bold text-foreground mb-2">
70
+ BETTER T STACK
71
+ </Text>
72
+ </View>
122
73
 
123
- {{#if (and (eq backend "convex") (eq auth "clerk"))}}
124
- <Authenticated>
125
- <Card variant="secondary" className="mt-6 p-4">
126
- <Text className="text-foreground text-base mb-2">
127
- Hello {user?.emailAddresses[0].emailAddress}
128
- </Text>
129
- <Text className="text-muted text-sm mb-4">
130
- Private Data: {privateData?.message}
74
+ {{#unless (or (eq backend "none") (and (eq backend "convex") (eq auth "better-auth")))}}
75
+ <Card variant="secondary" className="p-6">
76
+ <View className="flex-row items-center justify-between mb-4">
77
+ <Card.Title>System Status</Card.Title>
78
+ <Chip variant="secondary" color={isConnected ? "success" : "danger" } size="sm">
79
+ <Chip.Label>
80
+ {isConnected ? "LIVE" : "OFFLINE"}
81
+ </Chip.Label>
82
+ </Chip>
83
+ </View>
84
+ <Card className="p-4">
85
+ <View className="flex-row items-center">
86
+ <View className={`w-3 h-3 rounded-full mr-3 ${ isConnected ? "bg-success" : "bg-muted" }`} />
87
+ <View className="flex-1">
88
+ <Text className="text-foreground font-medium mb-1">
89
+ {{#if (eq backend "convex")}}
90
+ Convex Backend
91
+ {{else}}
92
+ {{#unless (eq api "none")}}
93
+ {{#if (eq api "orpc")}}ORPC{{else}}TRPC{{/if}} Backend
94
+ {{/unless}}
95
+ {{/if}}
131
96
  </Text>
132
- <SignOutButton />
133
- </Card>
134
- </Authenticated>
135
- <Unauthenticated>
136
- <View className="mt-6 gap-4">
137
- <Link href="/(auth)/sign-in" asChild>
138
- <Text className="text-primary font-semibold">Sign in</Text>
139
- </Link>
140
- <Link href="/(auth)/sign-up" asChild>
141
- <Text className="text-primary font-semibold">Sign up</Text>
142
- </Link>
97
+ <Card.Description>
98
+ {isLoading
99
+ ? "Checking connection..."
100
+ : isConnected
101
+ ? "Connected to API"
102
+ : "API Disconnected"}
103
+ </Card.Description>
143
104
  </View>
144
- </Unauthenticated>
145
- <AuthLoading>
146
- <Text className="text-muted">Loading...</Text>
147
- </AuthLoading>
148
- {{/if}}
149
- </Container>
150
- );
105
+ {isLoading && (
106
+ <Ionicons name="hourglass-outline" size={20} color={mutedColor} />
107
+ )}
108
+ {!isLoading && isConnected && (
109
+ <Ionicons name="checkmark-circle" size={20} color={successColor} />
110
+ )}
111
+ {!isLoading && !isConnected && (
112
+ <Ionicons name="close-circle" size={20} color={dangerColor} />
113
+ )}
114
+ </View>
115
+ </Card>
116
+ </Card>
117
+ {{/unless}}
118
+
119
+ {{#if (and (eq backend "convex") (eq auth "clerk"))}}
120
+ <Authenticated>
121
+ <Card variant="secondary" className="mt-6 p-4">
122
+ <Text className="text-foreground text-base mb-2">
123
+ Hello {user?.emailAddresses[0].emailAddress}
124
+ </Text>
125
+ <Text className="text-muted text-sm mb-4">
126
+ Private Data: {privateData?.message}
127
+ </Text>
128
+ <SignOutButton />
129
+ </Card>
130
+ </Authenticated>
131
+ <Unauthenticated>
132
+ <View className="mt-6 gap-4">
133
+ <Link href="/(auth)/sign-in" asChild>
134
+ <Text className="text-primary font-semibold">Sign in</Text>
135
+ </Link>
136
+ <Link href="/(auth)/sign-up" asChild>
137
+ <Text className="text-primary font-semibold">Sign up</Text>
138
+ </Link>
139
+ </View>
140
+ </Unauthenticated>
141
+ <AuthLoading>
142
+ <Text className="text-muted">Loading...</Text>
143
+ </AuthLoading>
144
+ {{/if}}
145
+ </Container>
146
+ );
151
147
  }
@@ -13,7 +13,7 @@
13
13
  "dependencies": {
14
14
  "@expo/metro-runtime": "~6.1.2",
15
15
  "@expo/vector-icons": "^15.0.3",
16
- "@gorhom/bottom-sheet": "^5",
16
+ "@gorhom/bottom-sheet": "^5.2.6",
17
17
  "@react-navigation/drawer": "^7.3.9",
18
18
  "@react-navigation/elements": "^2.8.1",
19
19
  {{#if (includes examples "ai")}}
@@ -29,22 +29,22 @@
29
29
  "expo-router": "~6.0.14",
30
30
  "expo-secure-store": "~15.0.7",
31
31
  "expo-status-bar": "~3.0.8",
32
- "heroui-native": "^1.0.0-beta.1",
32
+ "heroui-native": "1.0.0-beta.3",
33
33
  "react": "19.1.0",
34
34
  "react-dom": "19.1.0",
35
35
  "react-native": "0.81.5",
36
36
  "react-native-gesture-handler": "~2.28.0",
37
37
  "react-native-keyboard-controller": "1.18.5",
38
- "react-native-reanimated": "~4.1.0",
38
+ "react-native-reanimated": "~4.1.5",
39
39
  "react-native-safe-area-context": "5.6.0",
40
40
  "react-native-screens": "~4.16.0",
41
41
  "react-native-svg": "15.12.1",
42
42
  "react-native-web": "^0.21.0",
43
43
  "react-native-worklets": "0.5.1",
44
- "tailwind-merge": "^3.3.1",
45
- "tailwind-variants": "^3.1.0",
46
- "tailwindcss": "~4.1.16",
47
- "uniwind": "^1.0.0"
44
+ "tailwind-merge": "^3.4.0",
45
+ "tailwind-variants": "3.1.1",
46
+ "tailwindcss": "~4.1.17",
47
+ "uniwind": "^1.0.4"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@types/node": "^24.10.0",