create-better-t-stack 3.6.1 → 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-DaTuAN3w.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-DaTuAN3w.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
  }
@@ -6326,7 +6343,7 @@ async function displayPostInstallInstructions(config) {
6326
6343
  const databaseInstructions = !isConvex && database !== "none" ? await getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup, serverDeploy, backend) : "";
6327
6344
  const tauriInstructions = addons?.includes("tauri") ? getTauriInstructions(runCmd) : "";
6328
6345
  const lintingInstructions = hasHuskyOrBiome ? getLintingInstructions(runCmd) : "";
6329
- 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 || []) : "";
6330
6347
  const pwaInstructions = addons?.includes("pwa") && frontend?.includes("react-router") ? getPwaInstructions() : "";
6331
6348
  const starlightInstructions = addons?.includes("starlight") ? getStarlightInstructions(runCmd) : "";
6332
6349
  const clerkInstructions = isConvex && config.auth === "clerk" ? getClerkInstructions() : "";
@@ -6363,16 +6380,19 @@ async function displayPostInstallInstructions(config) {
6363
6380
  output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} dev\n`;
6364
6381
  }
6365
6382
  }
6366
- output += `${pc.bold("Your project will be available at:")}\n`;
6367
- if (hasWeb) output += `${pc.cyan("")} Frontend: http://localhost:${webPort}\n`;
6368
- else if (!hasNative && !addons?.includes("starlight")) output += `${pc.yellow("NOTE:")} You are creating a backend-only app\n (no frontend selected)\n`;
6369
- if (!isConvex && !isBackendSelf) {
6370
- output += `${pc.cyan("")} Backend API: http://localhost:3000\n`;
6371
- 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`;
6372
6395
  }
6373
- if (isBackendSelf && api === "orpc") output += `${pc.cyan("•")} OpenAPI (Scalar UI): http://localhost:${webPort}/api/rpc/api-reference\n`;
6374
- if (addons?.includes("starlight")) output += `${pc.cyan("•")} Docs: http://localhost:4321\n`;
6375
- if (addons?.includes("fumadocs")) output += `${pc.cyan("•")} Fumadocs: http://localhost:4000\n`;
6376
6396
  if (nativeInstructions) output += `\n${nativeInstructions.trim()}\n`;
6377
6397
  if (databaseInstructions) output += `\n${databaseInstructions.trim()}\n`;
6378
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.1",
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",