create-better-t-stack 2.0.12 → 2.1.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/index.js +81 -81
- package/package.json +1 -1
- package/templates/api/orpc/native/utils/orpc.ts.hbs +49 -0
- package/templates/api/orpc/web/nuxt/app/plugins/orpc.ts.hbs +35 -0
- package/templates/{auth/native/utils/trpc.ts → api/trpc/native/utils/trpc.ts.hbs} +4 -0
- package/templates/api/trpc/web/{base → react/base}/src/utils/trpc.ts.hbs +1 -1
- package/templates/auth/native/app/(drawer)/{index.tsx → index.tsx.hbs} +11 -0
- package/templates/auth/native/components/{sign-in.tsx → sign-in.tsx.hbs} +6 -1
- package/templates/auth/native/components/{sign-up.tsx → sign-up.tsx.hbs} +5 -0
- package/templates/auth/server/base/src/lib/auth.ts.hbs +48 -9
- package/templates/auth/web/nuxt/app/components/SignInForm.vue +78 -0
- package/templates/auth/web/nuxt/app/components/SignUpForm.vue +85 -0
- package/templates/auth/web/nuxt/app/components/UserMenu.vue +43 -0
- package/templates/auth/web/nuxt/app/middleware/auth.ts +12 -0
- package/templates/auth/web/nuxt/app/pages/dashboard.vue +27 -0
- package/templates/auth/web/nuxt/app/pages/login.vue +24 -0
- package/templates/auth/web/nuxt/app/plugins/auth-client.ts +16 -0
- package/templates/examples/ai/web/nuxt/app/pages/ai.vue +64 -0
- package/templates/examples/todo/web/nuxt/app/pages/todos.vue +108 -0
- package/templates/extras/_npmrc.hbs +5 -0
- package/templates/frontend/native/app/(drawer)/{index.tsx → index.tsx.hbs} +10 -0
- package/templates/frontend/native/app/{_layout.tsx → _layout.tsx.hbs} +8 -3
- package/templates/frontend/native/package.json +0 -3
- package/templates/frontend/nuxt/_gitignore +24 -0
- package/templates/frontend/nuxt/app/app.config.ts +15 -0
- package/templates/frontend/nuxt/app/app.vue +13 -0
- package/templates/frontend/nuxt/app/assets/css/main.css +2 -0
- package/templates/frontend/nuxt/app/components/Header.vue.hbs +45 -0
- package/templates/frontend/nuxt/app/components/Loader.vue +5 -0
- package/templates/frontend/nuxt/app/components/ModeToggle.vue +23 -0
- package/templates/frontend/nuxt/app/layouts/default.vue +11 -0
- package/templates/frontend/nuxt/app/pages/index.vue +63 -0
- package/templates/frontend/nuxt/app/plugins/vue-query.ts +44 -0
- package/templates/frontend/nuxt/nuxt.config.ts.hbs +19 -0
- package/templates/frontend/nuxt/package.json +25 -0
- package/templates/frontend/nuxt/public/favicon.ico +0 -0
- package/templates/frontend/nuxt/public/robots.txt +2 -0
- package/templates/frontend/nuxt/server/tsconfig.json +3 -0
- package/templates/frontend/nuxt/tsconfig.json +4 -0
- package/templates/extras/_npmrc +0 -1
- package/templates/frontend/native/utils/trpc.ts +0 -19
- /package/templates/api/orpc/web/{base → react/base}/src/utils/orpc.ts.hbs +0 -0
- /package/templates/auth/web/{base → react/base}/src/lib/auth-client.ts.hbs +0 -0
- /package/templates/auth/web/{next → react/next}/src/app/dashboard/page.tsx.hbs +0 -0
- /package/templates/auth/web/{next → react/next}/src/app/login/page.tsx +0 -0
- /package/templates/auth/web/{next → react/next}/src/components/sign-in-form.tsx +0 -0
- /package/templates/auth/web/{next → react/next}/src/components/sign-up-form.tsx +0 -0
- /package/templates/auth/web/{next → react/next}/src/components/theme-provider.tsx +0 -0
- /package/templates/auth/web/{next → react/next}/src/components/user-menu.tsx +0 -0
- /package/templates/auth/web/{react-router → react/react-router}/src/components/sign-in-form.tsx +0 -0
- /package/templates/auth/web/{react-router → react/react-router}/src/components/sign-up-form.tsx +0 -0
- /package/templates/auth/web/{react-router → react/react-router}/src/components/user-menu.tsx +0 -0
- /package/templates/auth/web/{react-router → react/react-router}/src/routes/dashboard.tsx.hbs +0 -0
- /package/templates/auth/web/{react-router → react/react-router}/src/routes/login.tsx +0 -0
- /package/templates/auth/web/{tanstack-router → react/tanstack-router}/src/components/sign-in-form.tsx +0 -0
- /package/templates/auth/web/{tanstack-router → react/tanstack-router}/src/components/sign-up-form.tsx +0 -0
- /package/templates/auth/web/{tanstack-router → react/tanstack-router}/src/components/user-menu.tsx +0 -0
- /package/templates/auth/web/{tanstack-router → react/tanstack-router}/src/routes/dashboard.tsx.hbs +0 -0
- /package/templates/auth/web/{tanstack-router → react/tanstack-router}/src/routes/login.tsx +0 -0
- /package/templates/auth/web/{tanstack-start → react/tanstack-start}/src/components/sign-in-form.tsx +0 -0
- /package/templates/auth/web/{tanstack-start → react/tanstack-start}/src/components/sign-up-form.tsx +0 -0
- /package/templates/auth/web/{tanstack-start → react/tanstack-start}/src/components/user-menu.tsx +0 -0
- /package/templates/auth/web/{tanstack-start → react/tanstack-start}/src/routes/dashboard.tsx.hbs +0 -0
- /package/templates/auth/web/{tanstack-start → react/tanstack-start}/src/routes/login.tsx +0 -0
- /package/templates/examples/ai/web/{react-router → react/react-router}/src/routes/ai.tsx +0 -0
- /package/templates/examples/ai/web/{tanstack-router → react/tanstack-router}/src/routes/ai.tsx +0 -0
- /package/templates/examples/ai/web/{tanstack-start → react/tanstack-start}/src/routes/ai.tsx +0 -0
- /package/templates/examples/todo/web/{react-router → react/react-router}/src/routes/todos.tsx.hbs +0 -0
- /package/templates/examples/todo/web/{tanstack-router → react/tanstack-router}/src/routes/todos.tsx.hbs +0 -0
- /package/templates/examples/todo/web/{tanstack-start → react/tanstack-start}/src/routes/todos.tsx.hbs +0 -0
- /package/templates/frontend/{next → react/next}/next-env.d.ts +0 -0
- /package/templates/frontend/{next → react/next}/next.config.ts +0 -0
- /package/templates/frontend/{next → react/next}/package.json +0 -0
- /package/templates/frontend/{next → react/next}/postcss.config.mjs +0 -0
- /package/templates/frontend/{next → react/next}/src/app/favicon.ico +0 -0
- /package/templates/frontend/{next → react/next}/src/app/layout.tsx +0 -0
- /package/templates/frontend/{next → react/next}/src/app/page.tsx.hbs +0 -0
- /package/templates/frontend/{next → react/next}/src/components/mode-toggle.tsx +0 -0
- /package/templates/frontend/{next → react/next}/src/components/providers.tsx.hbs +0 -0
- /package/templates/frontend/{next → react/next}/src/components/theme-provider.tsx +0 -0
- /package/templates/frontend/{next → react/next}/tsconfig.json +0 -0
- /package/templates/frontend/{react-router → react/react-router}/package.json +0 -0
- /package/templates/frontend/{react-router → react/react-router}/public/favicon.ico +0 -0
- /package/templates/frontend/{react-router → react/react-router}/react-router.config.ts +0 -0
- /package/templates/frontend/{react-router → react/react-router}/src/components/mode-toggle.tsx +0 -0
- /package/templates/frontend/{react-router → react/react-router}/src/components/theme-provider.tsx +0 -0
- /package/templates/frontend/{react-router → react/react-router}/src/root.tsx.hbs +0 -0
- /package/templates/frontend/{react-router → react/react-router}/src/routes/_index.tsx.hbs +0 -0
- /package/templates/frontend/{react-router → react/react-router}/src/routes.ts +0 -0
- /package/templates/frontend/{react-router → react/react-router}/tsconfig.json +0 -0
- /package/templates/frontend/{react-router → react/react-router}/vite.config.ts.hbs +0 -0
- /package/templates/frontend/{tanstack-router → react/tanstack-router}/index.html +0 -0
- /package/templates/frontend/{tanstack-router → react/tanstack-router}/package.json +0 -0
- /package/templates/frontend/{tanstack-router → react/tanstack-router}/src/components/mode-toggle.tsx +0 -0
- /package/templates/frontend/{tanstack-router → react/tanstack-router}/src/components/theme-provider.tsx +0 -0
- /package/templates/frontend/{tanstack-router → react/tanstack-router}/src/main.tsx.hbs +0 -0
- /package/templates/frontend/{tanstack-router → react/tanstack-router}/src/routes/__root.tsx.hbs +0 -0
- /package/templates/frontend/{tanstack-router → react/tanstack-router}/src/routes/index.tsx.hbs +0 -0
- /package/templates/frontend/{tanstack-router → react/tanstack-router}/tsconfig.json +0 -0
- /package/templates/frontend/{tanstack-router → react/tanstack-router}/vite.config.ts.hbs +0 -0
- /package/templates/frontend/{tanstack-start → react/tanstack-start}/app.config.ts +0 -0
- /package/templates/frontend/{tanstack-start → react/tanstack-start}/package.json +0 -0
- /package/templates/frontend/{tanstack-start → react/tanstack-start}/public/robots.txt +0 -0
- /package/templates/frontend/{tanstack-start → react/tanstack-start}/src/api.ts +0 -0
- /package/templates/frontend/{tanstack-start → react/tanstack-start}/src/client.tsx +0 -0
- /package/templates/frontend/{tanstack-start → react/tanstack-start}/src/router.tsx.hbs +0 -0
- /package/templates/frontend/{tanstack-start → react/tanstack-start}/src/routes/__root.tsx.hbs +0 -0
- /package/templates/frontend/{tanstack-start → react/tanstack-start}/src/routes/index.tsx.hbs +0 -0
- /package/templates/frontend/{tanstack-start → react/tanstack-start}/src/ssr.tsx +0 -0
- /package/templates/frontend/{tanstack-start → react/tanstack-start}/tsconfig.json +0 -0
- /package/templates/frontend/{web-base → react/web-base}/_gitignore +0 -0
- /package/templates/frontend/{web-base → react/web-base}/components.json +0 -0
- /package/templates/frontend/{web-base → react/web-base}/src/components/header.tsx.hbs +0 -0
- /package/templates/frontend/{web-base → react/web-base}/src/components/loader.tsx +0 -0
- /package/templates/frontend/{web-base → react/web-base}/src/components/ui/button.tsx +0 -0
- /package/templates/frontend/{web-base → react/web-base}/src/components/ui/card.tsx +0 -0
- /package/templates/frontend/{web-base → react/web-base}/src/components/ui/checkbox.tsx +0 -0
- /package/templates/frontend/{web-base → react/web-base}/src/components/ui/dropdown-menu.tsx +0 -0
- /package/templates/frontend/{web-base → react/web-base}/src/components/ui/input.tsx +0 -0
- /package/templates/frontend/{web-base → react/web-base}/src/components/ui/label.tsx +0 -0
- /package/templates/frontend/{web-base → react/web-base}/src/components/ui/skeleton.tsx +0 -0
- /package/templates/frontend/{web-base → react/web-base}/src/components/ui/sonner.tsx +0 -0
- /package/templates/frontend/{web-base → react/web-base}/src/index.css +0 -0
- /package/templates/frontend/{web-base → react/web-base}/src/lib/utils.ts +0 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import { useQuery, useMutation, useQueryClient } from '@tanstack/vue-query'
|
|
4
|
+
|
|
5
|
+
const { $orpc } = useNuxtApp()
|
|
6
|
+
|
|
7
|
+
const newTodoText = ref('')
|
|
8
|
+
const queryClient = useQueryClient()
|
|
9
|
+
|
|
10
|
+
const todos = useQuery($orpc.todo.getAll.queryOptions())
|
|
11
|
+
|
|
12
|
+
const createMutation = useMutation($orpc.todo.create.mutationOptions({
|
|
13
|
+
onSuccess: () => {
|
|
14
|
+
queryClient.invalidateQueries()
|
|
15
|
+
newTodoText.value = ''
|
|
16
|
+
}
|
|
17
|
+
}))
|
|
18
|
+
|
|
19
|
+
const toggleMutation = useMutation($orpc.todo.toggle.mutationOptions({
|
|
20
|
+
onSuccess: () => queryClient.invalidateQueries()
|
|
21
|
+
}))
|
|
22
|
+
|
|
23
|
+
const deleteMutation = useMutation($orpc.todo.delete.mutationOptions({
|
|
24
|
+
onSuccess: () => queryClient.invalidateQueries()
|
|
25
|
+
}))
|
|
26
|
+
|
|
27
|
+
function handleAddTodo() {
|
|
28
|
+
if (newTodoText.value.trim()) {
|
|
29
|
+
createMutation.mutate({ text: newTodoText.value })
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function handleToggleTodo(id: number, completed: boolean) {
|
|
34
|
+
toggleMutation.mutate({ id, completed: !completed })
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function handleDeleteTodo(id: number) {
|
|
38
|
+
deleteMutation.mutate({ id })
|
|
39
|
+
}
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<template>
|
|
43
|
+
<div class="mx-auto w-full max-w-md py-10">
|
|
44
|
+
<UCard>
|
|
45
|
+
<template #header>
|
|
46
|
+
<div>
|
|
47
|
+
<div class="text-xl font-bold">Todo List</div>
|
|
48
|
+
<div class="text-muted text-sm">Manage your tasks efficiently</div>
|
|
49
|
+
</div>
|
|
50
|
+
</template>
|
|
51
|
+
<form @submit.prevent="handleAddTodo" class="mb-6 flex items-center gap-2">
|
|
52
|
+
<UInput
|
|
53
|
+
v-model="newTodoText"
|
|
54
|
+
placeholder="Add a new task..."
|
|
55
|
+
autocomplete="off"
|
|
56
|
+
class="w-full"
|
|
57
|
+
/>
|
|
58
|
+
<UButton
|
|
59
|
+
type="submit"
|
|
60
|
+
icon="i-lucide-plus"
|
|
61
|
+
>
|
|
62
|
+
Add
|
|
63
|
+
</UButton>
|
|
64
|
+
</form>
|
|
65
|
+
|
|
66
|
+
<div v-if="todos.status.value === 'pending'" class="flex justify-center py-4">
|
|
67
|
+
<UIcon name="i-lucide-loader-2" class="animate-spin w-6 h-6" />
|
|
68
|
+
</div>
|
|
69
|
+
<p v-else-if="todos.status.value === 'error'" class="py-4 text-center text-red-500">
|
|
70
|
+
Error: {{ todos.error.value?.message || 'Failed to load todos' }}
|
|
71
|
+
</p>
|
|
72
|
+
<p v-else-if="todos.data.value?.length === 0" class="py-4 text-center">
|
|
73
|
+
No todos yet. Add one above!
|
|
74
|
+
</p>
|
|
75
|
+
<ul v-else class="space-y-2">
|
|
76
|
+
<li
|
|
77
|
+
v-for="todo in todos.data.value"
|
|
78
|
+
:key="todo.id"
|
|
79
|
+
class="flex items-center justify-between rounded-md border p-2"
|
|
80
|
+
>
|
|
81
|
+
<div class="flex items-center gap-2">
|
|
82
|
+
<UCheckbox
|
|
83
|
+
:model-value="todo.completed"
|
|
84
|
+
@update:model-value="() => handleToggleTodo(todo.id, todo.completed)"
|
|
85
|
+
:id="`todo-${todo.id}`"
|
|
86
|
+
/>
|
|
87
|
+
<label
|
|
88
|
+
:for="`todo-${todo.id}`"
|
|
89
|
+
:class="{ 'line-through text-muted': todo.completed }"
|
|
90
|
+
class="cursor-pointer"
|
|
91
|
+
>
|
|
92
|
+
{{ todo.text }}
|
|
93
|
+
</label>
|
|
94
|
+
</div>
|
|
95
|
+
<UButton
|
|
96
|
+
color="neutral"
|
|
97
|
+
variant="ghost"
|
|
98
|
+
size="sm"
|
|
99
|
+
square
|
|
100
|
+
@click="handleDeleteTodo(todo.id)"
|
|
101
|
+
aria-label="Delete todo"
|
|
102
|
+
icon="i-lucide-trash-2"
|
|
103
|
+
/>
|
|
104
|
+
</li>
|
|
105
|
+
</ul>
|
|
106
|
+
</UCard>
|
|
107
|
+
</div>
|
|
108
|
+
</template>
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { useQuery } from "@tanstack/react-query";
|
|
2
2
|
import { View, Text, ScrollView } from "react-native";
|
|
3
3
|
import { Container } from "@/components/container";
|
|
4
|
+
{{#if (eq api "orpc")}}
|
|
5
|
+
import { orpc } from "@/utils/orpc";
|
|
6
|
+
{{/if}}
|
|
7
|
+
{{#if (eq api "trpc")}}
|
|
4
8
|
import { trpc } from "@/utils/trpc";
|
|
9
|
+
{{/if}}
|
|
5
10
|
|
|
6
11
|
export default function Home() {
|
|
12
|
+
{{#if (eq api "orpc")}}
|
|
13
|
+
const healthCheck = useQuery(orpc.healthCheck.queryOptions());
|
|
14
|
+
{{/if}}
|
|
15
|
+
{{#if (eq api "trpc")}}
|
|
7
16
|
const healthCheck = useQuery(trpc.healthCheck.queryOptions());
|
|
17
|
+
{{/if}}
|
|
8
18
|
|
|
9
19
|
return (
|
|
10
20
|
<Container>
|
|
@@ -9,7 +9,12 @@ import {
|
|
|
9
9
|
import { StatusBar } from "expo-status-bar";
|
|
10
10
|
import { GestureHandlerRootView } from "react-native-gesture-handler";
|
|
11
11
|
import "../global.css";
|
|
12
|
+
{{#if (eq api "trpc")}}
|
|
12
13
|
import { queryClient } from "@/utils/trpc";
|
|
14
|
+
{{/if}}
|
|
15
|
+
{{#if (eq api "orpc")}}
|
|
16
|
+
import { queryClient } from "@/utils/orpc";
|
|
17
|
+
{{/if}}
|
|
13
18
|
import { NAV_THEME } from "@/lib/constants";
|
|
14
19
|
import React, { useRef } from "react";
|
|
15
20
|
import { useColorScheme } from "@/lib/use-color-scheme";
|
|
@@ -56,12 +61,12 @@ export default function RootLayout() {
|
|
|
56
61
|
<QueryClientProvider client={queryClient}>
|
|
57
62
|
<ThemeProvider value={isDarkColorScheme ? DARK_THEME : LIGHT_THEME}>
|
|
58
63
|
<StatusBar style={isDarkColorScheme ? "light" : "dark"} />
|
|
59
|
-
<GestureHandlerRootView style
|
|
64
|
+
<GestureHandlerRootView style=\{{ flex: 1 }}>
|
|
60
65
|
<Stack>
|
|
61
|
-
<Stack.Screen name="(drawer)" options
|
|
66
|
+
<Stack.Screen name="(drawer)" options=\{{ headerShown: false }} />
|
|
62
67
|
<Stack.Screen
|
|
63
68
|
name="modal"
|
|
64
|
-
options
|
|
69
|
+
options=\{{ title: "Modal", presentation: "modal" }}
|
|
65
70
|
/>
|
|
66
71
|
</Stack>
|
|
67
72
|
</GestureHandlerRootView>
|
|
@@ -16,9 +16,6 @@
|
|
|
16
16
|
"@react-navigation/native": "^7.0.14",
|
|
17
17
|
"@tanstack/react-form": "^1.0.5",
|
|
18
18
|
"@tanstack/react-query": "^5.69.2",
|
|
19
|
-
"@trpc/client": "^11.0.0",
|
|
20
|
-
"@trpc/server": "^11.0.0",
|
|
21
|
-
"@trpc/tanstack-react-query": "^11.0.0",
|
|
22
19
|
"expo": "^52.0.44",
|
|
23
20
|
"expo-constants": "~17.0.8",
|
|
24
21
|
"expo-linking": "~7.0.5",
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Nuxt dev/build outputs
|
|
2
|
+
.output
|
|
3
|
+
.data
|
|
4
|
+
.nuxt
|
|
5
|
+
.nitro
|
|
6
|
+
.cache
|
|
7
|
+
dist
|
|
8
|
+
|
|
9
|
+
# Node dependencies
|
|
10
|
+
node_modules
|
|
11
|
+
|
|
12
|
+
# Logs
|
|
13
|
+
logs
|
|
14
|
+
*.log
|
|
15
|
+
|
|
16
|
+
# Misc
|
|
17
|
+
.DS_Store
|
|
18
|
+
.fleet
|
|
19
|
+
.idea
|
|
20
|
+
|
|
21
|
+
# Local env files
|
|
22
|
+
.env
|
|
23
|
+
.env.*
|
|
24
|
+
!.env.example
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export default defineAppConfig({
|
|
2
|
+
// https://ui.nuxt.com/getting-started/theme#design-system
|
|
3
|
+
ui: {
|
|
4
|
+
colors: {
|
|
5
|
+
primary: 'emerald',
|
|
6
|
+
neutral: 'slate',
|
|
7
|
+
},
|
|
8
|
+
button: {
|
|
9
|
+
defaultVariants: {
|
|
10
|
+
// Set default button color to neutral
|
|
11
|
+
// color: 'neutral'
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
})
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { USeparator } from '#components';
|
|
3
|
+
import ModeToggle from './ModeToggle.vue'
|
|
4
|
+
{{#if auth}}
|
|
5
|
+
import UserMenu from './UserMenu.vue'
|
|
6
|
+
{{/if}}
|
|
7
|
+
|
|
8
|
+
const links = [
|
|
9
|
+
{ to: "/", label: "Home" },
|
|
10
|
+
{{#if auth}}
|
|
11
|
+
{ to: "/dashboard", label: "Dashboard" },
|
|
12
|
+
{{/if}}
|
|
13
|
+
{{#if (includes examples "todo")}}
|
|
14
|
+
{ to: "/todos", label: "Todos" },
|
|
15
|
+
{{/if}}
|
|
16
|
+
{{#if (includes examples "ai")}}
|
|
17
|
+
{ to: "/ai", label: "AI Chat" },
|
|
18
|
+
{{/if}}
|
|
19
|
+
];
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<template>
|
|
23
|
+
<div>
|
|
24
|
+
<div class="flex flex-row items-center justify-between px-2 py-1">
|
|
25
|
+
<nav class="flex gap-4 text-lg">
|
|
26
|
+
<NuxtLink
|
|
27
|
+
v-for="link in links"
|
|
28
|
+
:key="link.to"
|
|
29
|
+
:to="link.to"
|
|
30
|
+
class="text-foreground hover:text-primary"
|
|
31
|
+
active-class="text-primary font-semibold"
|
|
32
|
+
>
|
|
33
|
+
\{{ link.label }}
|
|
34
|
+
</NuxtLink>
|
|
35
|
+
</nav>
|
|
36
|
+
<div class="flex items-center gap-2">
|
|
37
|
+
<ModeToggle />
|
|
38
|
+
{{#if auth}}
|
|
39
|
+
<UserMenu />
|
|
40
|
+
{{/if}}
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
<USeparator />
|
|
44
|
+
</div>
|
|
45
|
+
</template>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const colorMode = useColorMode()
|
|
3
|
+
|
|
4
|
+
const isDark = computed({
|
|
5
|
+
get () {
|
|
6
|
+
return colorMode.value === 'dark'
|
|
7
|
+
},
|
|
8
|
+
set (value) {
|
|
9
|
+
colorMode.preference = value ? 'dark' : 'light'
|
|
10
|
+
}
|
|
11
|
+
})
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<template>
|
|
15
|
+
<div class="flex items-center">
|
|
16
|
+
<USwitch
|
|
17
|
+
v-model="isDark"
|
|
18
|
+
:checked-icon="isDark ? 'i-lucide-moon' : ''"
|
|
19
|
+
:unchecked-icon="!isDark ? 'i-lucide-sun' : ''"
|
|
20
|
+
class="mr-2"
|
|
21
|
+
/>
|
|
22
|
+
</div>
|
|
23
|
+
</template>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const { $orpc } = useNuxtApp()
|
|
3
|
+
import { useQuery } from '@tanstack/vue-query'
|
|
4
|
+
|
|
5
|
+
const TITLE_TEXT = `
|
|
6
|
+
██████╗ ███████╗████████╗████████╗███████╗██████╗
|
|
7
|
+
██╔══██╗██╔════╝╚══██╔══╝╚══██╔══╝██╔════╝██╔══██╗
|
|
8
|
+
██████╔╝█████╗ ██║ ██║ █████╗ ██████╔╝
|
|
9
|
+
██╔══██╗██╔══╝ ██║ ██║ ██╔══╝ ██╔══██╗
|
|
10
|
+
██████╔╝███████╗ ██║ ██║ ███████╗██║ ██║
|
|
11
|
+
╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝
|
|
12
|
+
|
|
13
|
+
████████╗ ███████╗████████╗ █████╗ ██████╗██╗ ██╗
|
|
14
|
+
╚══██╔══╝ ██╔════╝╚══██╔══╝██╔══██╗██╔════╝██║ ██╔╝
|
|
15
|
+
██║ ███████╗ ██║ ███████║██║ █████╔╝
|
|
16
|
+
██║ ╚════██║ ██║ ██╔══██║██║ ██╔═██╗
|
|
17
|
+
██║ ███████║ ██║ ██║ ██║╚██████╗██║ ██╗
|
|
18
|
+
╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
const healthCheck = useQuery($orpc.healthCheck.queryOptions())
|
|
22
|
+
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template>
|
|
26
|
+
<div class="container mx-auto max-w-3xl px-4 py-2">
|
|
27
|
+
<pre class="overflow-x-auto font-mono text-sm whitespace-pre-wrap">{{ TITLE_TEXT }}</pre>
|
|
28
|
+
<div class="grid gap-6 mt-4">
|
|
29
|
+
<section class="rounded-lg border p-4">
|
|
30
|
+
<h2 class="mb-2 font-medium">API Status</h2>
|
|
31
|
+
<div class="flex items-center gap-2">
|
|
32
|
+
<div class="flex items-center gap-2">
|
|
33
|
+
<div
|
|
34
|
+
class="w-2 h-2 rounded-full"
|
|
35
|
+
:class="{
|
|
36
|
+
'bg-yellow-500 animate-pulse': healthCheck.status.value === 'pending',
|
|
37
|
+
'bg-green-500': healthCheck.status.value === 'success',
|
|
38
|
+
'bg-red-500': healthCheck.status.value === 'error',
|
|
39
|
+
'bg-gray-400': healthCheck.status.value !== 'pending' &&
|
|
40
|
+
healthCheck.status.value !== 'success' &&
|
|
41
|
+
healthCheck.status.value !== 'error'
|
|
42
|
+
}"
|
|
43
|
+
></div>
|
|
44
|
+
<span class="text-sm text-muted-foreground">
|
|
45
|
+
<template v-if="healthCheck.status.value === 'pending'">
|
|
46
|
+
Checking...
|
|
47
|
+
</template>
|
|
48
|
+
<template v-else-if="healthCheck.status.value === 'success'">
|
|
49
|
+
Connected ({{ healthCheck.data.value }})
|
|
50
|
+
</template>
|
|
51
|
+
<template v-else-if="healthCheck.status.value === 'error'">
|
|
52
|
+
Error: {{ healthCheck.error.value?.message || 'Failed to connect' }}
|
|
53
|
+
</template>
|
|
54
|
+
<template v-else>
|
|
55
|
+
Idle
|
|
56
|
+
</template>
|
|
57
|
+
</span>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
</section>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</template>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DehydratedState,
|
|
3
|
+
VueQueryPluginOptions,
|
|
4
|
+
} from '@tanstack/vue-query'
|
|
5
|
+
import {
|
|
6
|
+
dehydrate,
|
|
7
|
+
hydrate,
|
|
8
|
+
QueryCache,
|
|
9
|
+
QueryClient,
|
|
10
|
+
VueQueryPlugin,
|
|
11
|
+
} from '@tanstack/vue-query'
|
|
12
|
+
|
|
13
|
+
export default defineNuxtPlugin((nuxt) => {
|
|
14
|
+
const vueQueryState = useState<DehydratedState | null>('vue-query')
|
|
15
|
+
|
|
16
|
+
const toast = useToast()
|
|
17
|
+
|
|
18
|
+
const queryClient = new QueryClient({
|
|
19
|
+
queryCache: new QueryCache({
|
|
20
|
+
onError: (error) => {
|
|
21
|
+
console.log(error)
|
|
22
|
+
toast.add({
|
|
23
|
+
title: 'Error',
|
|
24
|
+
description: error?.message || 'An unexpected error occurred.',
|
|
25
|
+
})
|
|
26
|
+
},
|
|
27
|
+
}),
|
|
28
|
+
})
|
|
29
|
+
const options: VueQueryPluginOptions = { queryClient }
|
|
30
|
+
|
|
31
|
+
nuxt.vueApp.use(VueQueryPlugin, options)
|
|
32
|
+
|
|
33
|
+
if (import.meta.server) {
|
|
34
|
+
nuxt.hooks.hook('app:rendered', () => {
|
|
35
|
+
vueQueryState.value = dehydrate(queryClient)
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (import.meta.client) {
|
|
40
|
+
nuxt.hooks.hook('app:created', () => {
|
|
41
|
+
hydrate(queryClient, vueQueryState.value)
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
})
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// https://nuxt.com/docs/api/configuration/nuxt-config
|
|
2
|
+
export default defineNuxtConfig({
|
|
3
|
+
compatibilityDate: '2024-11-01',
|
|
4
|
+
future: {
|
|
5
|
+
compatibilityVersion: 4
|
|
6
|
+
},
|
|
7
|
+
devtools: { enabled: true },
|
|
8
|
+
modules: ['@nuxt/ui'],
|
|
9
|
+
css: ['~/assets/css/main.css'],
|
|
10
|
+
devServer: {
|
|
11
|
+
port: 3001
|
|
12
|
+
},
|
|
13
|
+
ssr: false,
|
|
14
|
+
runtimeConfig: {
|
|
15
|
+
public: {
|
|
16
|
+
serverURL: process.env.NUXT_PUBLIC_SERVER_URL,
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "web",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "nuxt build",
|
|
7
|
+
"dev": "nuxt dev",
|
|
8
|
+
"generate": "nuxt generate",
|
|
9
|
+
"preview": "nuxt preview",
|
|
10
|
+
"postinstall": "nuxt prepare"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@nuxt/ui": "3.0.2",
|
|
14
|
+
"@tanstack/vue-query": "^5.74.5",
|
|
15
|
+
"nuxt": "^3.16.2",
|
|
16
|
+
"typescript": "^5.6.3",
|
|
17
|
+
"vue": "^3.5.13",
|
|
18
|
+
"vue-router": "^4.5.0",
|
|
19
|
+
"zod": "^3.24.3"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@tanstack/vue-query-devtools": "^5.74.5",
|
|
23
|
+
"@iconify-json/lucide": "^1.2.38"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
Binary file
|
package/templates/extras/_npmrc
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
node-linker=hoisted
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { AppRouter } from "../../server/src/routers";
|
|
2
|
-
import { QueryClient } from "@tanstack/react-query";
|
|
3
|
-
import { createTRPCClient, httpBatchLink } from "@trpc/client";
|
|
4
|
-
import { createTRPCOptionsProxy } from "@trpc/tanstack-react-query";
|
|
5
|
-
|
|
6
|
-
export const queryClient = new QueryClient();
|
|
7
|
-
|
|
8
|
-
const trpcClient = createTRPCClient<AppRouter>({
|
|
9
|
-
links: [
|
|
10
|
-
httpBatchLink({
|
|
11
|
-
url: `${process.env.EXPO_PUBLIC_SERVER_URL}/trpc`,
|
|
12
|
-
}),
|
|
13
|
-
],
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
export const trpc = createTRPCOptionsProxy<AppRouter>({
|
|
17
|
-
client: trpcClient,
|
|
18
|
-
queryClient,
|
|
19
|
-
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/auth/web/{react-router → react/react-router}/src/components/sign-in-form.tsx
RENAMED
|
File without changes
|
/package/templates/auth/web/{react-router → react/react-router}/src/components/sign-up-form.tsx
RENAMED
|
File without changes
|
/package/templates/auth/web/{react-router → react/react-router}/src/components/user-menu.tsx
RENAMED
|
File without changes
|
/package/templates/auth/web/{react-router → react/react-router}/src/routes/dashboard.tsx.hbs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/auth/web/{tanstack-router → react/tanstack-router}/src/components/user-menu.tsx
RENAMED
|
File without changes
|
/package/templates/auth/web/{tanstack-router → react/tanstack-router}/src/routes/dashboard.tsx.hbs
RENAMED
|
File without changes
|
|
File without changes
|
/package/templates/auth/web/{tanstack-start → react/tanstack-start}/src/components/sign-in-form.tsx
RENAMED
|
File without changes
|
/package/templates/auth/web/{tanstack-start → react/tanstack-start}/src/components/sign-up-form.tsx
RENAMED
|
File without changes
|
/package/templates/auth/web/{tanstack-start → react/tanstack-start}/src/components/user-menu.tsx
RENAMED
|
File without changes
|
/package/templates/auth/web/{tanstack-start → react/tanstack-start}/src/routes/dashboard.tsx.hbs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/examples/ai/web/{tanstack-router → react/tanstack-router}/src/routes/ai.tsx
RENAMED
|
File without changes
|
/package/templates/examples/ai/web/{tanstack-start → react/tanstack-start}/src/routes/ai.tsx
RENAMED
|
File without changes
|
/package/templates/examples/todo/web/{react-router → react/react-router}/src/routes/todos.tsx.hbs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/frontend/{react-router → react/react-router}/src/components/mode-toggle.tsx
RENAMED
|
File without changes
|
/package/templates/frontend/{react-router → react/react-router}/src/components/theme-provider.tsx
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|