create-better-t-stack 2.44.0 → 2.45.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.
Files changed (71) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/index.d.ts +38 -1
  3. package/dist/index.js +1 -1
  4. package/dist/{src-CwLBNdNq.js → src-Cve0nldx.js} +21 -9
  5. package/package.json +1 -1
  6. package/templates/auth/better-auth/native/native-base/lib/auth-client.ts.hbs +3 -2
  7. package/templates/auth/better-auth/server/base/src/lib/auth.ts.hbs +5 -5
  8. package/templates/backend/server/next/package.json.hbs +3 -3
  9. package/templates/frontend/native/native-base/assets/images/android-icon-background.png +0 -0
  10. package/templates/frontend/native/native-base/assets/images/android-icon-foreground.png +0 -0
  11. package/templates/frontend/native/native-base/assets/images/android-icon-monochrome.png +0 -0
  12. package/templates/frontend/native/native-base/assets/images/favicon.png +0 -0
  13. package/templates/frontend/native/native-base/assets/images/icon.png +0 -0
  14. package/templates/frontend/native/native-base/assets/images/partial-react-logo.png +0 -0
  15. package/templates/frontend/native/native-base/assets/images/react-logo.png +0 -0
  16. package/templates/frontend/native/native-base/assets/images/react-logo@2x.png +0 -0
  17. package/templates/frontend/native/native-base/assets/images/react-logo@3x.png +0 -0
  18. package/templates/frontend/native/nativewind/app/(drawer)/(tabs)/{_layout.tsx → _layout.tsx.hbs} +3 -3
  19. package/templates/frontend/native/nativewind/app/{+not-found.tsx → +not-found.tsx.hbs} +1 -1
  20. package/templates/frontend/native/nativewind/app.json.hbs +49 -0
  21. package/templates/frontend/native/nativewind/babel.config.js.hbs +14 -0
  22. package/templates/frontend/native/nativewind/components/{container.tsx → container.tsx.hbs} +1 -1
  23. package/templates/frontend/native/nativewind/components/{header-button.tsx → header-button.tsx.hbs} +1 -1
  24. package/templates/frontend/native/{unistyles/components/tabbar-icon.tsx → nativewind/components/tabbar-icon.tsx.hbs} +1 -1
  25. package/templates/frontend/native/nativewind/metro.config.js.hbs +31 -0
  26. package/templates/frontend/native/nativewind/package.json.hbs +23 -21
  27. package/templates/frontend/native/nativewind/tailwind.config.js.hbs +59 -0
  28. package/templates/frontend/native/unistyles/app/(drawer)/(tabs)/{_layout.tsx → _layout.tsx.hbs} +3 -3
  29. package/templates/frontend/native/unistyles/app/(drawer)/index.tsx.hbs +1 -3
  30. package/templates/frontend/native/unistyles/app/{+not-found.tsx → +not-found.tsx.hbs} +2 -2
  31. package/templates/frontend/native/unistyles/app/_layout.tsx.hbs +2 -2
  32. package/templates/frontend/native/unistyles/app.json.hbs +49 -0
  33. package/templates/frontend/native/unistyles/babel.config.js.hbs +21 -0
  34. package/templates/frontend/native/unistyles/components/{container.tsx → container.tsx.hbs} +1 -1
  35. package/templates/frontend/native/unistyles/components/{header-button.tsx → header-button.tsx.hbs} +1 -1
  36. package/templates/frontend/native/{nativewind/components/tabbar-icon.tsx → unistyles/components/tabbar-icon.tsx.hbs} +1 -1
  37. package/templates/frontend/native/unistyles/metro.config.js.hbs +5 -0
  38. package/templates/frontend/native/unistyles/package.json.hbs +29 -28
  39. package/templates/frontend/native/unistyles/theme.ts.hbs +98 -0
  40. package/templates/frontend/react/next/package.json.hbs +3 -3
  41. package/templates/frontend/react/react-router/package.json.hbs +3 -3
  42. package/templates/frontend/react/tanstack-router/package.json.hbs +3 -3
  43. package/templates/frontend/react/tanstack-start/package.json.hbs +3 -3
  44. package/templates/frontend/native/native-base/assets/favicon.png +0 -0
  45. package/templates/frontend/native/native-base/assets/icon.png +0 -0
  46. package/templates/frontend/native/native-base/assets/splash.png +0 -0
  47. package/templates/frontend/native/nativewind/app/+html.tsx +0 -47
  48. package/templates/frontend/native/nativewind/app-env.d.ts +0 -2
  49. package/templates/frontend/native/nativewind/app.json +0 -46
  50. package/templates/frontend/native/nativewind/babel.config.js +0 -11
  51. package/templates/frontend/native/nativewind/metro.config.js +0 -59
  52. package/templates/frontend/native/nativewind/tailwind.config.js +0 -59
  53. package/templates/frontend/native/unistyles/app/+html.tsx +0 -48
  54. package/templates/frontend/native/unistyles/app.json +0 -44
  55. package/templates/frontend/native/unistyles/babel.config.js +0 -21
  56. package/templates/frontend/native/unistyles/expo-env.d.ts +0 -3
  57. package/templates/frontend/native/unistyles/metro.config.js +0 -20
  58. package/templates/frontend/native/unistyles/theme.ts +0 -98
  59. /package/templates/frontend/native/native-base/assets/{adaptive-icon.png → images/splash-icon.png} +0 -0
  60. /package/templates/frontend/native/nativewind/app/(drawer)/(tabs)/{index.tsx → index.tsx.hbs} +0 -0
  61. /package/templates/frontend/native/nativewind/app/(drawer)/(tabs)/{two.tsx → two.tsx.hbs} +0 -0
  62. /package/templates/frontend/native/nativewind/app/{modal.tsx → modal.tsx.hbs} +0 -0
  63. /package/templates/frontend/native/nativewind/lib/{android-navigation-bar.tsx → android-navigation-bar.tsx.hbs} +0 -0
  64. /package/templates/frontend/native/nativewind/lib/{constants.ts → constants.ts.hbs} +0 -0
  65. /package/templates/frontend/native/nativewind/lib/{use-color-scheme.ts → use-color-scheme.ts.hbs} +0 -0
  66. /package/templates/frontend/native/unistyles/app/(drawer)/(tabs)/{index.tsx → index.tsx.hbs} +0 -0
  67. /package/templates/frontend/native/unistyles/app/(drawer)/(tabs)/{two.tsx → two.tsx.hbs} +0 -0
  68. /package/templates/frontend/native/unistyles/app/{modal.tsx → modal.tsx.hbs} +0 -0
  69. /package/templates/frontend/native/unistyles/{breakpoints.ts → breakpoints.ts.hbs} +0 -0
  70. /package/templates/frontend/native/unistyles/{index.js → index.js.hbs} +0 -0
  71. /package/templates/frontend/native/unistyles/{unistyles.ts → unistyles.ts.hbs} +0 -0
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { createBtsCli } from "./src-CwLBNdNq.js";
2
+ import { createBtsCli } from "./src-Cve0nldx.js";
3
3
 
4
4
  //#region src/cli.ts
5
5
  createBtsCli().run();
package/dist/index.d.ts CHANGED
@@ -229,7 +229,44 @@ declare const router: trpcServer.TRPCBuiltRouter<{
229
229
  renderTitle?: boolean | undefined;
230
230
  disableAnalytics?: boolean | undefined;
231
231
  }];
232
- output: InitResult | undefined;
232
+ output: {
233
+ success: boolean;
234
+ projectConfig: {
235
+ projectName: string;
236
+ projectDir: string;
237
+ relativePath: string;
238
+ database: "none";
239
+ orm: "none";
240
+ backend: "none";
241
+ runtime: "none";
242
+ frontend: never[];
243
+ addons: never[];
244
+ examples: never[];
245
+ auth: "none";
246
+ git: false;
247
+ packageManager: "npm";
248
+ install: false;
249
+ dbSetup: "none";
250
+ api: "none";
251
+ webDeploy: "none";
252
+ serverDeploy: "none";
253
+ };
254
+ reproducibleCommand: string;
255
+ timeScaffolded: string;
256
+ elapsedTimeMs: number;
257
+ projectDirectory: string;
258
+ relativePath: string;
259
+ error: string;
260
+ } | {
261
+ success: boolean;
262
+ projectConfig: ProjectConfig;
263
+ reproducibleCommand: string;
264
+ timeScaffolded: string;
265
+ elapsedTimeMs: number;
266
+ projectDirectory: string;
267
+ relativePath: string;
268
+ error?: undefined;
269
+ } | undefined;
233
270
  meta: object;
234
271
  }>;
235
272
  add: trpcServer.TRPCMutationProcedure<{
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-CwLBNdNq.js";
2
+ import { builder, createBtsCli, docs, init, router, sponsors } from "./src-Cve0nldx.js";
3
3
 
4
4
  export { builder, createBtsCli, docs, init, router, sponsors };
@@ -2547,9 +2547,8 @@ async function initializeBiome() {
2547
2547
  biome,
2548
2548
  projectKey
2549
2549
  };
2550
- } catch (error) {
2551
- consola.error("Failed to initialize Biome:", error);
2552
- throw error;
2550
+ } catch (_error) {
2551
+ return null;
2553
2552
  }
2554
2553
  }
2555
2554
  function isSupportedFile(filePath) {
@@ -2579,21 +2578,35 @@ function shouldSkipFile(filePath) {
2579
2578
  async function formatFileWithBiome(filePath, content) {
2580
2579
  if (!isSupportedFile(filePath) || shouldSkipFile(filePath)) return null;
2581
2580
  try {
2582
- const { biome: biomeInstance, projectKey: key } = await initializeBiome();
2581
+ const biomeResult = await initializeBiome();
2582
+ if (!biomeResult) return null;
2583
+ const { biome: biomeInstance, projectKey: key } = biomeResult;
2583
2584
  const result = biomeInstance.formatContent(key, content, { filePath: path.basename(filePath) });
2584
2585
  if (result.diagnostics && result.diagnostics.length > 0) consola.debug(`Biome formatting diagnostics for ${filePath}:`, result.diagnostics);
2585
2586
  return result.content;
2586
- } catch (error) {
2587
- consola.warn(`Failed to format ${filePath} with Biome:`, error);
2587
+ } catch (_error) {
2588
2588
  return null;
2589
2589
  }
2590
2590
  }
2591
2591
 
2592
2592
  //#endregion
2593
2593
  //#region src/utils/template-processor.ts
2594
+ const BINARY_EXTENSIONS = new Set([
2595
+ ".png",
2596
+ ".ico",
2597
+ ".svg"
2598
+ ]);
2599
+ function isBinaryFile(filePath) {
2600
+ const ext = path.extname(filePath).toLowerCase();
2601
+ return BINARY_EXTENSIONS.has(ext);
2602
+ }
2594
2603
  async function processTemplate(srcPath, destPath, context) {
2595
2604
  try {
2596
2605
  await fs.ensureDir(path.dirname(destPath));
2606
+ if (isBinaryFile(srcPath) && !srcPath.endsWith(".hbs")) {
2607
+ await fs.copy(srcPath, destPath);
2608
+ return;
2609
+ }
2597
2610
  let content;
2598
2611
  if (srcPath.endsWith(".hbs")) {
2599
2612
  const templateContent = await fs.readFile(srcPath, "utf-8");
@@ -2961,7 +2974,7 @@ async function handleExtras(projectDir, context) {
2961
2974
  if (context.packageManager === "pnpm") {
2962
2975
  const pnpmWorkspaceSrc = path.join(extrasDir, "pnpm-workspace.yaml");
2963
2976
  const pnpmWorkspaceDest = path.join(projectDir, "pnpm-workspace.yaml");
2964
- if (await fs.pathExists(pnpmWorkspaceSrc)) await fs.copy(pnpmWorkspaceSrc, pnpmWorkspaceDest);
2977
+ if (await fs.pathExists(pnpmWorkspaceSrc)) await processTemplate(pnpmWorkspaceSrc, pnpmWorkspaceDest, context);
2965
2978
  }
2966
2979
  if (context.packageManager === "bun") {
2967
2980
  const bunfigSrc = path.join(extrasDir, "bunfig.toml.hbs");
@@ -5932,8 +5945,7 @@ async function isDockerInstalled() {
5932
5945
  }
5933
5946
  async function isDockerRunning() {
5934
5947
  try {
5935
- const { $: $$1 } = await import("execa");
5936
- await $$1`docker info`;
5948
+ await $`docker info`;
5937
5949
  return true;
5938
5950
  } catch {
5939
5951
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-better-t-stack",
3
- "version": "2.44.0",
3
+ "version": "2.45.0",
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",
@@ -1,12 +1,13 @@
1
- import { createAuthClient } from "better-auth/react";
2
1
  import { expoClient } from "@better-auth/expo/client";
2
+ import { createAuthClient } from "better-auth/react";
3
3
  import * as SecureStore from "expo-secure-store";
4
4
 
5
5
  export const authClient = createAuthClient({
6
6
  baseURL: process.env.EXPO_PUBLIC_SERVER_URL,
7
7
  plugins: [
8
8
  expoClient({
9
- storagePrefix: "my-better-t-app",
9
+ scheme: "mybettertapp",
10
+ storagePrefix: "{{projectName}}",
10
11
  storage: SecureStore,
11
12
  }),
12
13
  ],
@@ -16,7 +16,7 @@ export const auth = betterAuth({
16
16
  trustedOrigins: [
17
17
  process.env.CORS_ORIGIN || "",
18
18
  {{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
19
- "my-better-t-app://",
19
+ "mybettertapp://", "exp://"
20
20
  {{/if}}
21
21
  ],
22
22
  emailAndPassword: {
@@ -55,7 +55,7 @@ export const auth = betterAuth({
55
55
  trustedOrigins: [
56
56
  process.env.CORS_ORIGIN || "",
57
57
  {{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
58
- "my-better-t-app://",
58
+ "mybettertapp://", "exp://"
59
59
  {{/if}}
60
60
  ],
61
61
  emailAndPassword: {
@@ -124,7 +124,7 @@ export const auth = betterAuth({
124
124
  trustedOrigins: [
125
125
  process.env.CORS_ORIGIN || "",
126
126
  {{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
127
- "my-better-t-app://",
127
+ "mybettertapp://", "exp://"
128
128
  {{/if}}
129
129
  ],
130
130
  emailAndPassword: {
@@ -154,7 +154,7 @@ export const auth = betterAuth({
154
154
  trustedOrigins: [
155
155
  process.env.CORS_ORIGIN || "",
156
156
  {{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
157
- "my-better-t-app://",
157
+ "mybettertapp://", "exp://"
158
158
  {{/if}}
159
159
  ],
160
160
  emailAndPassword: {
@@ -171,4 +171,4 @@ export const auth = betterAuth({
171
171
  , plugins: [expo()]
172
172
  {{/if}}
173
173
  });
174
- {{/if}}
174
+ {{/if}}
@@ -9,8 +9,8 @@
9
9
  },
10
10
  "dependencies": {
11
11
  "next": "15.5.0",
12
- "react": "^19.0.0",
13
- "react-dom": "^19.0.0",
12
+ "react": "19.1.0",
13
+ "react-dom": "19.1.0",
14
14
  "dotenv": "^17.2.1"
15
15
  },
16
16
  {{#if (eq dbSetup 'supabase')}}
@@ -20,7 +20,7 @@
20
20
  {{/if}}
21
21
  "devDependencies": {
22
22
  "@types/node": "^20",
23
- "@types/react": "^19",
23
+ "@types/react": "~19.1.10",
24
24
  "zod": "^4.0.13",
25
25
  "typescript": "^5"
26
26
  }
@@ -7,7 +7,7 @@ export default function TabLayout() {
7
7
 
8
8
  return (
9
9
  <Tabs
10
- screenOptions={{
10
+ screenOptions=\{{
11
11
  headerShown: false,
12
12
  tabBarActiveTintColor: isDarkColorScheme
13
13
  ? "hsl(217.2 91.2% 59.8%)"
@@ -27,14 +27,14 @@ export default function TabLayout() {
27
27
  >
28
28
  <Tabs.Screen
29
29
  name="index"
30
- options={{
30
+ options=\{{
31
31
  title: "Home",
32
32
  tabBarIcon: ({ color }) => <TabBarIcon name="home" color={color} />,
33
33
  }}
34
34
  />
35
35
  <Tabs.Screen
36
36
  name="two"
37
- options={{
37
+ options=\{{
38
38
  title: "Explore",
39
39
  tabBarIcon: ({ color }) => (
40
40
  <TabBarIcon name="compass" color={color} />
@@ -5,7 +5,7 @@ import { Text, View } from "react-native";
5
5
  export default function NotFoundScreen() {
6
6
  return (
7
7
  <>
8
- <Stack.Screen options={{ title: "Oops!" }} />
8
+ <Stack.Screen options=\{{ title: "Oops!" }} />
9
9
  <Container>
10
10
  <View className="flex-1 justify-center items-center p-6">
11
11
  <View className="items-center">
@@ -0,0 +1,49 @@
1
+ {
2
+ "expo": {
3
+ "name": "{{projectName}}",
4
+ "slug": "{{projectName}}",
5
+ "version": "1.0.0",
6
+ "orientation": "portrait",
7
+ "icon": "./assets/images/icon.png",
8
+ "scheme": "mybettertapp",
9
+ "userInterfaceStyle": "automatic",
10
+ "newArchEnabled": true,
11
+ "ios": {
12
+ "supportsTablet": true
13
+ },
14
+ "android": {
15
+ "adaptiveIcon": {
16
+ "backgroundColor": "#E6F4FE",
17
+ "foregroundImage": "./assets/images/android-icon-foreground.png",
18
+ "backgroundImage": "./assets/images/android-icon-background.png",
19
+ "monochromeImage": "./assets/images/android-icon-monochrome.png"
20
+ },
21
+ "edgeToEdgeEnabled": true,
22
+ "predictiveBackGestureEnabled": false,
23
+ "package": "com.anonymous.mybettertapp"
24
+ },
25
+ "web": {
26
+ "output": "static",
27
+ "favicon": "./assets/images/favicon.png"
28
+ },
29
+ "plugins": [
30
+ "expo-router",
31
+ [
32
+ "expo-splash-screen",
33
+ {
34
+ "image": "./assets/images/splash-icon.png",
35
+ "imageWidth": 200,
36
+ "resizeMode": "contain",
37
+ "backgroundColor": "#ffffff",
38
+ "dark": {
39
+ "backgroundColor": "#000000"
40
+ }
41
+ }
42
+ ]
43
+ ],
44
+ "experiments": {
45
+ "typedRoutes": true,
46
+ "reactCompiler": true
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,14 @@
1
+ module.exports = (api) => {
2
+ api.cache(true);
3
+ const plugins = [];
4
+
5
+ plugins.push("react-native-worklets/plugin");
6
+
7
+ return {
8
+ presets: [
9
+ ["babel-preset-expo", { jsxImportSource: "nativewind" }],
10
+ "nativewind/babel",
11
+ ],
12
+ plugins,
13
+ };
14
+ };
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { SafeAreaView } from "react-native";
2
+ import { SafeAreaView } from "react-native-safe-area-context";
3
3
 
4
4
  export const Container = ({ children }: { children: React.ReactNode }) => {
5
5
  return (
@@ -16,7 +16,7 @@ export const HeaderButton = forwardRef<
16
16
  name="info-circle"
17
17
  size={20}
18
18
  className="text-secondary-foreground"
19
- style={{
19
+ style=\{{
20
20
  opacity: pressed ? 0.7 : 1,
21
21
  }}
22
22
  />
@@ -4,5 +4,5 @@ export const TabBarIcon = (props: {
4
4
  name: React.ComponentProps<typeof FontAwesome>["name"];
5
5
  color: string;
6
6
  }) => {
7
- return <FontAwesome size={24} style={{ marginBottom: -3 }} {...props} />;
7
+ return <FontAwesome size={24} style=\{{ marginBottom: -3 }} {...props} />;
8
8
  };
@@ -0,0 +1,31 @@
1
+ // Learn more https://docs.expo.io/guides/customizing-metro
2
+ const { getDefaultConfig } = require("expo/metro-config");
3
+ const { FileStore } = require("metro-cache");
4
+ const { withNativeWind } = require("nativewind/metro");
5
+ const path = require("node:path");
6
+
7
+ const config = withTurborepoManagedCache(
8
+ withNativeWind(getDefaultConfig(__dirname), {
9
+ input: "./global.css",
10
+ configPath: "./tailwind.config.js",
11
+ }),
12
+ );
13
+
14
+ config.resolver.unstable_enablePackageExports = true;
15
+
16
+ module.exports = config;
17
+
18
+ /**
19
+ * Move the Metro cache to the `.cache/metro` folder.
20
+ * If you have any environment variables, you can configure Turborepo to invalidate it when needed.
21
+ *
22
+ * @see https://turbo.build/repo/docs/reference/configuration#env
23
+ * @param {import('expo/metro-config').MetroConfig} config
24
+ * @returns {import('expo/metro-config').MetroConfig}
25
+ */
26
+ function withTurborepoManagedCache(config) {
27
+ config.cacheStores = [
28
+ new FileStore({ root: path.join(__dirname, ".cache/metro") }),
29
+ ];
30
+ return config;
31
+ }
@@ -10,39 +10,41 @@
10
10
  "web": "expo start --web"
11
11
  },
12
12
  "dependencies": {
13
- "@expo/vector-icons": "^14.0.4",
13
+ "@expo/vector-icons": "^15.0.2",
14
14
  "@react-navigation/bottom-tabs": "^7.2.0",
15
15
  "@react-navigation/drawer": "^7.1.1",
16
16
  "@react-navigation/native": "^7.0.14",
17
17
  "@tanstack/react-form": "^1.0.5",
18
- "@tanstack/react-query": "^5.69.2",
18
+ "@tanstack/react-query": "^5.85.5",
19
19
  {{#if (includes examples "ai")}}
20
20
  "@stardazed/streams-text-encoding": "^1.0.2",
21
21
  "@ungap/structured-clone": "^1.3.0",
22
22
  {{/if}}
23
- "expo": "^53.0.4",
24
- "expo-constants": "~17.1.4",
25
- "expo-crypto": "~14.1.5",
26
- "expo-linking": "~7.1.4",
27
- "expo-navigation-bar": "~4.2.3",
28
- "expo-router": "~5.0.3",
29
- "expo-secure-store": "~14.2.3",
30
- "expo-status-bar": "~2.2.3",
31
- "expo-system-ui": "~5.0.6",
32
- "expo-web-browser": "~14.1.6",
23
+ "expo": "^54.0.1",
24
+ "expo-constants": "~18.0.8",
25
+ "expo-crypto": "~15.0.6",
26
+ "expo-linking": "~8.0.7",
27
+ "expo-navigation-bar": "~5.0.8",
28
+ "expo-router": "~6.0.0",
29
+ "expo-secure-store": "~15.0.6",
30
+ "expo-splash-screen": "~31.0.8",
31
+ "expo-status-bar": "~3.0.7",
32
+ "expo-system-ui": "~6.0.7",
33
+ "expo-web-browser": "~15.0.6",
33
34
  "nativewind": "^4.1.23",
34
- "react": "19.0.0",
35
- "react-dom": "19.0.0",
36
- "react-native": "0.79.1",
37
- "react-native-gesture-handler": "~2.24.0",
38
- "react-native-reanimated": "~3.17.4",
39
- "react-native-safe-area-context": "5.3.0",
40
- "react-native-screens": "~4.10.0",
41
- "react-native-web": "^0.20.0"
35
+ "react": "19.1.0",
36
+ "react-dom": "19.1.0",
37
+ "react-native": "0.81.4",
38
+ "react-native-gesture-handler": "~2.28.0",
39
+ "react-native-reanimated": "~4.1.0",
40
+ "react-native-safe-area-context": "~5.6.0",
41
+ "react-native-screens": "~4.16.0",
42
+ "react-native-web": "^0.21.0",
43
+ "react-native-worklets": "^0.5.1"
42
44
  },
43
45
  "devDependencies": {
44
46
  "@babel/core": "^7.26.10",
45
- "@types/react": "~19.0.10",
47
+ "@types/react": "~19.1.10",
46
48
  "tailwindcss": "^3.4.17",
47
49
  "typescript": "~5.8.2"
48
50
  },
@@ -0,0 +1,59 @@
1
+ import { hairlineWidth } from "nativewind/theme";
2
+
3
+ /** @type {import('tailwindcss').Config} */
4
+ export const darkMode = "class";
5
+ export const content = [
6
+ "./app/**/*.{js,ts,tsx}",
7
+ "./components/**/*.{js,ts,tsx}",
8
+ ];
9
+ export const presets = [require("nativewind/preset")];
10
+ export const theme = {
11
+ extend: {
12
+ colors: {
13
+ background: "hsl(var(--background))",
14
+ foreground: "hsl(var(--foreground))",
15
+ card: {
16
+ DEFAULT: "hsl(var(--card))",
17
+ foreground: "hsl(var(--card-foreground))",
18
+ },
19
+ popover: {
20
+ DEFAULT: "hsl(var(--popover))",
21
+ foreground: "hsl(var(--popover-foreground))",
22
+ },
23
+ primary: {
24
+ DEFAULT: "hsl(var(--primary))",
25
+ foreground: "hsl(var(--primary-foreground))",
26
+ },
27
+ secondary: {
28
+ DEFAULT: "hsl(var(--secondary))",
29
+ foreground: "hsl(var(--secondary-foreground))",
30
+ },
31
+ muted: {
32
+ DEFAULT: "hsl(var(--muted))",
33
+ foreground: "hsl(var(--muted-foreground))",
34
+ },
35
+ accent: {
36
+ DEFAULT: "hsl(var(--accent))",
37
+ foreground: "hsl(var(--accent-foreground))",
38
+ },
39
+ destructive: {
40
+ DEFAULT: "hsl(var(--destructive))",
41
+ foreground: "hsl(var(--destructive-foreground))",
42
+ },
43
+ border: "hsl(var(--border))",
44
+ input: "hsl(var(--input))",
45
+ ring: "hsl(var(--ring))",
46
+ radius: "var(--radius)",
47
+ },
48
+ borderRadius: {
49
+ xl: "calc(var(--radius) + 4px)",
50
+ lg: "var(--radius)",
51
+ md: "calc(var(--radius) - 2px)",
52
+ sm: "calc(var(--radius) - 4px)",
53
+ },
54
+ borderWidth: {
55
+ hairline: hairlineWidth(),
56
+ },
57
+ },
58
+ };
59
+ export const plugins = [];
@@ -8,7 +8,7 @@ export default function TabLayout() {
8
8
 
9
9
  return (
10
10
  <Tabs
11
- screenOptions={{
11
+ screenOptions=\{{
12
12
  headerShown: false,
13
13
  tabBarActiveTintColor: theme.colors.primary,
14
14
  tabBarInactiveTintColor: theme.colors.mutedForeground,
@@ -20,14 +20,14 @@ export default function TabLayout() {
20
20
  >
21
21
  <Tabs.Screen
22
22
  name="index"
23
- options={{
23
+ options=\{{
24
24
  title: "Home",
25
25
  tabBarIcon: ({ color }) => <TabBarIcon name="home" color={color} />,
26
26
  }}
27
27
  />
28
28
  <Tabs.Screen
29
29
  name="two"
30
- options={{
30
+ options=\{{
31
31
  title: "Explore",
32
32
  tabBarIcon: ({ color }) => (
33
33
  <TabBarIcon name="compass" color={color} />
@@ -46,9 +46,7 @@ export default function Home() {
46
46
  contentContainerStyle={styles.container}
47
47
  showsVerticalScrollIndicator={false}
48
48
  >
49
- <Text className="font-mono text-foreground text-3xl font-bold mb-4">
50
- BETTER T STACK
51
- </Text>
49
+ <Text style={styles.heroTitle}>BETTER T STACK</Text>
52
50
  <View style={styles.statusCard}>
53
51
  <View style={styles.statusHeader}>
54
52
  <Text style={styles.statusTitle}>System Status</Text>
@@ -1,12 +1,12 @@
1
- import { Container } from "@/components/container";
2
1
  import { Link, Stack } from "expo-router";
3
2
  import { Text, View } from "react-native";
4
3
  import { StyleSheet } from "react-native-unistyles";
4
+ import { Container } from "@/components/container";
5
5
 
6
6
  export default function NotFoundScreen() {
7
7
  return (
8
8
  <>
9
- <Stack.Screen options={{ title: "Oops!" }} />
9
+ <Stack.Screen options=\{{ title: "Oops!" }} />
10
10
  <Container>
11
11
  <View style={styles.container}>
12
12
  <View style={styles.content}>
@@ -22,14 +22,14 @@ import { QueryClientProvider } from "@tanstack/react-query";
22
22
  import { Stack } from "expo-router";
23
23
  import { GestureHandlerRootView } from "react-native-gesture-handler";
24
24
  import { useUnistyles } from "react-native-unistyles";
25
+ import { StatusBar } from "expo-status-bar";
25
26
 
26
27
  export const unstable_settings = {
27
- // Ensure that reloading on `/modal` keeps a back button present.
28
28
  initialRouteName: "(drawer)",
29
29
  };
30
30
 
31
31
  {{#if (eq backend "convex")}}
32
- const convex = new ConvexReactClient(process.env.EXPO_PUBLIC_CONVEX_URL!, {
32
+ const convex = new ConvexReactClient(process.env.EXPO_PUBLIC_CONVEX_URL || "", {
33
33
  unsavedChangesWarning: false,
34
34
  });
35
35
  {{/if}}
@@ -0,0 +1,49 @@
1
+ {
2
+ "expo": {
3
+ "name": "{{projectName}}",
4
+ "slug": "{{projectName}}",
5
+ "version": "1.0.0",
6
+ "orientation": "portrait",
7
+ "icon": "./assets/images/icon.png",
8
+ "scheme": "mybettertapp",
9
+ "userInterfaceStyle": "automatic",
10
+ "newArchEnabled": true,
11
+ "ios": {
12
+ "supportsTablet": true
13
+ },
14
+ "android": {
15
+ "adaptiveIcon": {
16
+ "backgroundColor": "#E6F4FE",
17
+ "foregroundImage": "./assets/images/android-icon-foreground.png",
18
+ "backgroundImage": "./assets/images/android-icon-background.png",
19
+ "monochromeImage": "./assets/images/android-icon-monochrome.png"
20
+ },
21
+ "edgeToEdgeEnabled": true,
22
+ "predictiveBackGestureEnabled": false,
23
+ "package": "com.anonymous.mybettertapp6"
24
+ },
25
+ "web": {
26
+ "output": "static",
27
+ "favicon": "./assets/images/favicon.png"
28
+ },
29
+ "plugins": [
30
+ "expo-router",
31
+ [
32
+ "expo-splash-screen",
33
+ {
34
+ "image": "./assets/images/splash-icon.png",
35
+ "imageWidth": 200,
36
+ "resizeMode": "contain",
37
+ "backgroundColor": "#ffffff",
38
+ "dark": {
39
+ "backgroundColor": "#000000"
40
+ }
41
+ }
42
+ ]
43
+ ],
44
+ "experiments": {
45
+ "typedRoutes": true,
46
+ "reactCompiler": true
47
+ }
48
+ }
49
+ }