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.
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +38 -1
- package/dist/index.js +1 -1
- package/dist/{src-CwLBNdNq.js → src-Cve0nldx.js} +21 -9
- package/package.json +1 -1
- package/templates/auth/better-auth/native/native-base/lib/auth-client.ts.hbs +3 -2
- package/templates/auth/better-auth/server/base/src/lib/auth.ts.hbs +5 -5
- package/templates/backend/server/next/package.json.hbs +3 -3
- package/templates/frontend/native/native-base/assets/images/android-icon-background.png +0 -0
- package/templates/frontend/native/native-base/assets/images/android-icon-foreground.png +0 -0
- package/templates/frontend/native/native-base/assets/images/android-icon-monochrome.png +0 -0
- package/templates/frontend/native/native-base/assets/images/favicon.png +0 -0
- package/templates/frontend/native/native-base/assets/images/icon.png +0 -0
- package/templates/frontend/native/native-base/assets/images/partial-react-logo.png +0 -0
- package/templates/frontend/native/native-base/assets/images/react-logo.png +0 -0
- package/templates/frontend/native/native-base/assets/images/react-logo@2x.png +0 -0
- package/templates/frontend/native/native-base/assets/images/react-logo@3x.png +0 -0
- package/templates/frontend/native/nativewind/app/(drawer)/(tabs)/{_layout.tsx → _layout.tsx.hbs} +3 -3
- package/templates/frontend/native/nativewind/app/{+not-found.tsx → +not-found.tsx.hbs} +1 -1
- package/templates/frontend/native/nativewind/app.json.hbs +49 -0
- package/templates/frontend/native/nativewind/babel.config.js.hbs +14 -0
- package/templates/frontend/native/nativewind/components/{container.tsx → container.tsx.hbs} +1 -1
- package/templates/frontend/native/nativewind/components/{header-button.tsx → header-button.tsx.hbs} +1 -1
- package/templates/frontend/native/{unistyles/components/tabbar-icon.tsx → nativewind/components/tabbar-icon.tsx.hbs} +1 -1
- package/templates/frontend/native/nativewind/metro.config.js.hbs +31 -0
- package/templates/frontend/native/nativewind/package.json.hbs +23 -21
- package/templates/frontend/native/nativewind/tailwind.config.js.hbs +59 -0
- package/templates/frontend/native/unistyles/app/(drawer)/(tabs)/{_layout.tsx → _layout.tsx.hbs} +3 -3
- package/templates/frontend/native/unistyles/app/(drawer)/index.tsx.hbs +1 -3
- package/templates/frontend/native/unistyles/app/{+not-found.tsx → +not-found.tsx.hbs} +2 -2
- package/templates/frontend/native/unistyles/app/_layout.tsx.hbs +2 -2
- package/templates/frontend/native/unistyles/app.json.hbs +49 -0
- package/templates/frontend/native/unistyles/babel.config.js.hbs +21 -0
- package/templates/frontend/native/unistyles/components/{container.tsx → container.tsx.hbs} +1 -1
- package/templates/frontend/native/unistyles/components/{header-button.tsx → header-button.tsx.hbs} +1 -1
- package/templates/frontend/native/{nativewind/components/tabbar-icon.tsx → unistyles/components/tabbar-icon.tsx.hbs} +1 -1
- package/templates/frontend/native/unistyles/metro.config.js.hbs +5 -0
- package/templates/frontend/native/unistyles/package.json.hbs +29 -28
- package/templates/frontend/native/unistyles/theme.ts.hbs +98 -0
- package/templates/frontend/react/next/package.json.hbs +3 -3
- package/templates/frontend/react/react-router/package.json.hbs +3 -3
- package/templates/frontend/react/tanstack-router/package.json.hbs +3 -3
- package/templates/frontend/react/tanstack-start/package.json.hbs +3 -3
- package/templates/frontend/native/native-base/assets/favicon.png +0 -0
- package/templates/frontend/native/native-base/assets/icon.png +0 -0
- package/templates/frontend/native/native-base/assets/splash.png +0 -0
- package/templates/frontend/native/nativewind/app/+html.tsx +0 -47
- package/templates/frontend/native/nativewind/app-env.d.ts +0 -2
- package/templates/frontend/native/nativewind/app.json +0 -46
- package/templates/frontend/native/nativewind/babel.config.js +0 -11
- package/templates/frontend/native/nativewind/metro.config.js +0 -59
- package/templates/frontend/native/nativewind/tailwind.config.js +0 -59
- package/templates/frontend/native/unistyles/app/+html.tsx +0 -48
- package/templates/frontend/native/unistyles/app.json +0 -44
- package/templates/frontend/native/unistyles/babel.config.js +0 -21
- package/templates/frontend/native/unistyles/expo-env.d.ts +0 -3
- package/templates/frontend/native/unistyles/metro.config.js +0 -20
- package/templates/frontend/native/unistyles/theme.ts +0 -98
- /package/templates/frontend/native/native-base/assets/{adaptive-icon.png → images/splash-icon.png} +0 -0
- /package/templates/frontend/native/nativewind/app/(drawer)/(tabs)/{index.tsx → index.tsx.hbs} +0 -0
- /package/templates/frontend/native/nativewind/app/(drawer)/(tabs)/{two.tsx → two.tsx.hbs} +0 -0
- /package/templates/frontend/native/nativewind/app/{modal.tsx → modal.tsx.hbs} +0 -0
- /package/templates/frontend/native/nativewind/lib/{android-navigation-bar.tsx → android-navigation-bar.tsx.hbs} +0 -0
- /package/templates/frontend/native/nativewind/lib/{constants.ts → constants.ts.hbs} +0 -0
- /package/templates/frontend/native/nativewind/lib/{use-color-scheme.ts → use-color-scheme.ts.hbs} +0 -0
- /package/templates/frontend/native/unistyles/app/(drawer)/(tabs)/{index.tsx → index.tsx.hbs} +0 -0
- /package/templates/frontend/native/unistyles/app/(drawer)/(tabs)/{two.tsx → two.tsx.hbs} +0 -0
- /package/templates/frontend/native/unistyles/app/{modal.tsx → modal.tsx.hbs} +0 -0
- /package/templates/frontend/native/unistyles/{breakpoints.ts → breakpoints.ts.hbs} +0 -0
- /package/templates/frontend/native/unistyles/{index.js → index.js.hbs} +0 -0
- /package/templates/frontend/native/unistyles/{unistyles.ts → unistyles.ts.hbs} +0 -0
package/dist/cli.js
CHANGED
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:
|
|
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
|
@@ -2547,9 +2547,8 @@ async function initializeBiome() {
|
|
|
2547
2547
|
biome,
|
|
2548
2548
|
projectKey
|
|
2549
2549
|
};
|
|
2550
|
-
} catch (
|
|
2551
|
-
|
|
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
|
|
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 (
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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": "
|
|
13
|
-
"react-dom": "
|
|
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": "
|
|
23
|
+
"@types/react": "~19.1.10",
|
|
24
24
|
"zod": "^4.0.13",
|
|
25
25
|
"typescript": "^5"
|
|
26
26
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/templates/frontend/native/nativewind/app/(drawer)/(tabs)/{_layout.tsx → _layout.tsx.hbs}
RENAMED
|
@@ -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
|
|
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
|
+
};
|
|
@@ -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
|
|
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": "^
|
|
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.
|
|
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
|
-
|
|
24
|
-
"expo-constants": "~
|
|
25
|
-
"expo-crypto": "~
|
|
26
|
-
"expo-linking": "~
|
|
27
|
-
"expo-navigation-bar": "~
|
|
28
|
-
"expo-router": "~
|
|
29
|
-
"expo-secure-store": "~
|
|
30
|
-
"expo-
|
|
31
|
-
"expo-
|
|
32
|
-
"expo-
|
|
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.
|
|
35
|
-
"react-dom": "19.
|
|
36
|
-
"react-native": "0.
|
|
37
|
-
"react-native-gesture-handler": "~2.
|
|
38
|
-
"react-native-reanimated": "~
|
|
39
|
-
"react-native-safe-area-context": "5.
|
|
40
|
-
"react-native-screens": "~4.
|
|
41
|
-
"react-native-web": "^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.
|
|
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 = [];
|
package/templates/frontend/native/unistyles/app/(drawer)/(tabs)/{_layout.tsx → _layout.tsx.hbs}
RENAMED
|
@@ -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
|
|
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
|
|
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
|
+
}
|