create-better-t-stack 3.9.0 → 3.10.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/README.md +2 -1
- package/dist/cli.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{src-DLvUK0Qf.mjs → src-QkFdHtZE.mjs} +17 -14
- package/package.json +38 -38
- package/templates/auth/better-auth/convex/backend/convex/auth.config.ts.hbs +5 -7
- package/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs +16 -16
- package/templates/auth/better-auth/convex/backend/convex/http.ts.hbs +4 -4
- package/templates/auth/better-auth/convex/web/react/next/src/app/api/auth/[...all]/route.ts.hbs +2 -2
- package/templates/auth/better-auth/convex/web/react/next/src/components/user-menu.tsx.hbs +10 -10
- package/templates/auth/better-auth/convex/web/react/next/src/lib/auth-server.ts.hbs +13 -5
- package/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/user-menu.tsx.hbs +14 -12
- package/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/user-menu.tsx.hbs +13 -16
- package/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-server.ts.hbs +11 -5
- package/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/api/auth/$.ts.hbs +4 -4
- package/templates/auth/better-auth/fullstack/tanstack-start/src/routes/api/auth/$.ts.hbs +1 -1
- package/templates/auth/better-auth/web/react/next/src/components/user-menu.tsx.hbs +17 -15
- package/templates/auth/better-auth/web/react/react-router/src/components/user-menu.tsx.hbs +16 -15
- package/templates/auth/better-auth/web/react/{tanstack-start/src/components/user-menu.tsx → tanstack-router/src/components/user-menu.tsx.hbs} +16 -15
- package/templates/auth/better-auth/web/react/{tanstack-router/src/components/user-menu.tsx → tanstack-start/src/components/user-menu.tsx.hbs} +16 -15
- package/templates/backend/convex/packages/backend/convex/README.md +4 -4
- package/templates/backend/convex/packages/backend/convex/tsconfig.json.hbs +1 -1
- package/templates/frontend/react/next/package.json.hbs +8 -7
- package/templates/frontend/react/next/src/app/layout.tsx.hbs +28 -1
- package/templates/frontend/react/next/src/components/mode-toggle.tsx.hbs +4 -6
- package/templates/frontend/react/next/src/components/providers.tsx.hbs +14 -4
- package/templates/frontend/react/react-router/package.json.hbs +2 -1
- package/templates/frontend/react/{tanstack-router/src/components/mode-toggle.tsx → react-router/src/components/mode-toggle.tsx.hbs} +4 -6
- package/templates/frontend/react/tanstack-router/package.json.hbs +2 -1
- package/templates/frontend/react/{react-router/src/components/mode-toggle.tsx → tanstack-router/src/components/mode-toggle.tsx.hbs} +4 -6
- package/templates/frontend/react/tanstack-start/package.json.hbs +2 -1
- package/templates/frontend/react/tanstack-start/src/router.tsx.hbs +6 -0
- package/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs +13 -14
- package/templates/frontend/react/tanstack-start/vite.config.ts.hbs +5 -0
- package/templates/frontend/react/web-base/components.json +5 -2
- package/templates/frontend/react/web-base/src/components/ui/button.tsx.hbs +57 -0
- package/templates/frontend/react/web-base/src/components/ui/card.tsx.hbs +103 -0
- package/templates/frontend/react/web-base/src/components/ui/checkbox.tsx.hbs +26 -0
- package/templates/frontend/react/web-base/src/components/ui/dropdown-menu.tsx.hbs +262 -0
- package/templates/frontend/react/web-base/src/components/ui/input.tsx.hbs +20 -0
- package/templates/frontend/react/web-base/src/components/ui/label.tsx.hbs +20 -0
- package/templates/frontend/react/web-base/src/components/ui/skeleton.tsx.hbs +13 -0
- package/templates/frontend/react/web-base/src/components/ui/sonner.tsx.hbs +44 -0
- package/templates/frontend/react/web-base/src/index.css.hbs +57 -63
- package/templates/frontend/react/web-base/src/components/ui/button.tsx +0 -56
- package/templates/frontend/react/web-base/src/components/ui/card.tsx +0 -75
- package/templates/frontend/react/web-base/src/components/ui/checkbox.tsx +0 -27
- package/templates/frontend/react/web-base/src/components/ui/dropdown-menu.tsx +0 -228
- package/templates/frontend/react/web-base/src/components/ui/input.tsx +0 -21
- package/templates/frontend/react/web-base/src/components/ui/label.tsx +0 -19
- package/templates/frontend/react/web-base/src/components/ui/skeleton.tsx +0 -13
- package/templates/frontend/react/web-base/src/components/ui/sonner.tsx +0 -25
- /package/templates/auth/better-auth/web/react/tanstack-router/src/components/{sign-in-form.tsx → sign-in-form.tsx.hbs} +0 -0
- /package/templates/auth/better-auth/web/react/tanstack-router/src/components/{sign-up-form.tsx → sign-up-form.tsx.hbs} +0 -0
- /package/templates/auth/better-auth/web/react/tanstack-router/src/routes/{login.tsx → login.tsx.hbs} +0 -0
- /package/templates/auth/better-auth/web/react/tanstack-start/src/components/{sign-in-form.tsx → sign-in-form.tsx.hbs} +0 -0
- /package/templates/auth/better-auth/web/react/tanstack-start/src/components/{sign-up-form.tsx → sign-up-form.tsx.hbs} +0 -0
- /package/templates/auth/better-auth/web/react/tanstack-start/src/routes/{login.tsx → login.tsx.hbs} +0 -0
- /package/templates/auth/better-auth/web/solid/src/components/{sign-in-form.tsx → sign-in-form.tsx.hbs} +0 -0
- /package/templates/auth/better-auth/web/solid/src/components/{sign-up-form.tsx → sign-up-form.tsx.hbs} +0 -0
- /package/templates/auth/better-auth/web/solid/src/routes/{login.tsx → login.tsx.hbs} +0 -0
- /package/templates/frontend/react/react-router/src/components/{theme-provider.tsx → theme-provider.tsx.hbs} +0 -0
- /package/templates/frontend/react/tanstack-router/src/components/{theme-provider.tsx → theme-provider.tsx.hbs} +0 -0
- /package/templates/frontend/react/web-base/src/lib/{utils.ts → utils.ts.hbs} +0 -0
|
@@ -1,16 +1,19 @@
|
|
|
1
|
+
import Link from "next/link";
|
|
2
|
+
import { useRouter } from "next/navigation";
|
|
3
|
+
|
|
1
4
|
import {
|
|
2
5
|
DropdownMenu,
|
|
3
6
|
DropdownMenuContent,
|
|
7
|
+
DropdownMenuGroup,
|
|
4
8
|
DropdownMenuItem,
|
|
5
9
|
DropdownMenuLabel,
|
|
6
10
|
DropdownMenuSeparator,
|
|
7
11
|
DropdownMenuTrigger,
|
|
8
12
|
} from "@/components/ui/dropdown-menu";
|
|
9
13
|
import { authClient } from "@/lib/auth-client";
|
|
14
|
+
|
|
10
15
|
import { Button } from "./ui/button";
|
|
11
16
|
import { Skeleton } from "./ui/skeleton";
|
|
12
|
-
import { useRouter } from "next/navigation";
|
|
13
|
-
import Link from "next/link";
|
|
14
17
|
|
|
15
18
|
export default function UserMenu() {
|
|
16
19
|
const router = useRouter();
|
|
@@ -22,25 +25,24 @@ export default function UserMenu() {
|
|
|
22
25
|
|
|
23
26
|
if (!session) {
|
|
24
27
|
return (
|
|
25
|
-
<
|
|
26
|
-
<
|
|
27
|
-
</
|
|
28
|
+
<Link href="/login">
|
|
29
|
+
<Button variant="outline">Sign In</Button>
|
|
30
|
+
</Link>
|
|
28
31
|
);
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
return (
|
|
32
35
|
<DropdownMenu>
|
|
33
|
-
<DropdownMenuTrigger
|
|
34
|
-
|
|
36
|
+
<DropdownMenuTrigger render={<Button variant="outline" />}>
|
|
37
|
+
{session.user.name}
|
|
35
38
|
</DropdownMenuTrigger>
|
|
36
39
|
<DropdownMenuContent className="bg-card">
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
<
|
|
40
|
+
<DropdownMenuGroup>
|
|
41
|
+
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
|
42
|
+
<DropdownMenuSeparator />
|
|
43
|
+
<DropdownMenuItem>{session.user.email}</DropdownMenuItem>
|
|
44
|
+
<DropdownMenuItem
|
|
42
45
|
variant="destructive"
|
|
43
|
-
className="w-full"
|
|
44
46
|
onClick={() => {
|
|
45
47
|
authClient.signOut({
|
|
46
48
|
fetchOptions: {
|
|
@@ -52,8 +54,8 @@ export default function UserMenu() {
|
|
|
52
54
|
}}
|
|
53
55
|
>
|
|
54
56
|
Sign Out
|
|
55
|
-
</
|
|
56
|
-
</
|
|
57
|
+
</DropdownMenuItem>
|
|
58
|
+
</DropdownMenuGroup>
|
|
57
59
|
</DropdownMenuContent>
|
|
58
60
|
</DropdownMenu>
|
|
59
61
|
);
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
+
import { Link, useNavigate } from "react-router";
|
|
2
|
+
|
|
1
3
|
import {
|
|
2
4
|
DropdownMenu,
|
|
3
5
|
DropdownMenuContent,
|
|
6
|
+
DropdownMenuGroup,
|
|
4
7
|
DropdownMenuItem,
|
|
5
8
|
DropdownMenuLabel,
|
|
6
9
|
DropdownMenuSeparator,
|
|
7
10
|
DropdownMenuTrigger,
|
|
8
11
|
} from "@/components/ui/dropdown-menu";
|
|
9
12
|
import { authClient } from "@/lib/auth-client";
|
|
10
|
-
|
|
13
|
+
|
|
11
14
|
import { Button } from "./ui/button";
|
|
12
15
|
import { Skeleton } from "./ui/skeleton";
|
|
13
|
-
import { Link } from "react-router";
|
|
14
16
|
|
|
15
17
|
export default function UserMenu() {
|
|
16
18
|
const navigate = useNavigate();
|
|
@@ -22,25 +24,24 @@ export default function UserMenu() {
|
|
|
22
24
|
|
|
23
25
|
if (!session) {
|
|
24
26
|
return (
|
|
25
|
-
<
|
|
26
|
-
<
|
|
27
|
-
</
|
|
27
|
+
<Link to="/login">
|
|
28
|
+
<Button variant="outline">Sign In</Button>
|
|
29
|
+
</Link>
|
|
28
30
|
);
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
return (
|
|
32
34
|
<DropdownMenu>
|
|
33
|
-
<DropdownMenuTrigger
|
|
34
|
-
|
|
35
|
+
<DropdownMenuTrigger render={<Button variant="outline" />}>
|
|
36
|
+
{session.user.name}
|
|
35
37
|
</DropdownMenuTrigger>
|
|
36
38
|
<DropdownMenuContent className="bg-card">
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
<
|
|
39
|
+
<DropdownMenuGroup>
|
|
40
|
+
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
|
41
|
+
<DropdownMenuSeparator />
|
|
42
|
+
<DropdownMenuItem>{session.user.email}</DropdownMenuItem>
|
|
43
|
+
<DropdownMenuItem
|
|
42
44
|
variant="destructive"
|
|
43
|
-
className="w-full"
|
|
44
45
|
onClick={() => {
|
|
45
46
|
authClient.signOut({
|
|
46
47
|
fetchOptions: {
|
|
@@ -52,8 +53,8 @@ export default function UserMenu() {
|
|
|
52
53
|
}}
|
|
53
54
|
>
|
|
54
55
|
Sign Out
|
|
55
|
-
</
|
|
56
|
-
</
|
|
56
|
+
</DropdownMenuItem>
|
|
57
|
+
</DropdownMenuGroup>
|
|
57
58
|
</DropdownMenuContent>
|
|
58
59
|
</DropdownMenu>
|
|
59
60
|
);
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
+
import { Link, useNavigate } from "@tanstack/react-router";
|
|
2
|
+
|
|
1
3
|
import {
|
|
2
4
|
DropdownMenu,
|
|
3
5
|
DropdownMenuContent,
|
|
6
|
+
DropdownMenuGroup,
|
|
4
7
|
DropdownMenuItem,
|
|
5
8
|
DropdownMenuLabel,
|
|
6
9
|
DropdownMenuSeparator,
|
|
7
10
|
DropdownMenuTrigger,
|
|
8
11
|
} from "@/components/ui/dropdown-menu";
|
|
9
12
|
import { authClient } from "@/lib/auth-client";
|
|
10
|
-
|
|
13
|
+
|
|
11
14
|
import { Button } from "./ui/button";
|
|
12
15
|
import { Skeleton } from "./ui/skeleton";
|
|
13
|
-
import { Link } from "@tanstack/react-router";
|
|
14
16
|
|
|
15
17
|
export default function UserMenu() {
|
|
16
18
|
const navigate = useNavigate();
|
|
@@ -22,25 +24,24 @@ export default function UserMenu() {
|
|
|
22
24
|
|
|
23
25
|
if (!session) {
|
|
24
26
|
return (
|
|
25
|
-
<
|
|
26
|
-
<
|
|
27
|
-
</
|
|
27
|
+
<Link to="/login">
|
|
28
|
+
<Button variant="outline">Sign In</Button>
|
|
29
|
+
</Link>
|
|
28
30
|
);
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
return (
|
|
32
34
|
<DropdownMenu>
|
|
33
|
-
<DropdownMenuTrigger
|
|
34
|
-
|
|
35
|
+
<DropdownMenuTrigger render={<Button variant="outline" />}>
|
|
36
|
+
{session.user.name}
|
|
35
37
|
</DropdownMenuTrigger>
|
|
36
38
|
<DropdownMenuContent className="bg-card">
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
<
|
|
39
|
+
<DropdownMenuGroup>
|
|
40
|
+
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
|
41
|
+
<DropdownMenuSeparator />
|
|
42
|
+
<DropdownMenuItem>{session.user.email}</DropdownMenuItem>
|
|
43
|
+
<DropdownMenuItem
|
|
42
44
|
variant="destructive"
|
|
43
|
-
className="w-full"
|
|
44
45
|
onClick={() => {
|
|
45
46
|
authClient.signOut({
|
|
46
47
|
fetchOptions: {
|
|
@@ -54,8 +55,8 @@ export default function UserMenu() {
|
|
|
54
55
|
}}
|
|
55
56
|
>
|
|
56
57
|
Sign Out
|
|
57
|
-
</
|
|
58
|
-
</
|
|
58
|
+
</DropdownMenuItem>
|
|
59
|
+
</DropdownMenuGroup>
|
|
59
60
|
</DropdownMenuContent>
|
|
60
61
|
</DropdownMenu>
|
|
61
62
|
);
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
+
import { Link, useNavigate } from "@tanstack/react-router";
|
|
2
|
+
|
|
1
3
|
import {
|
|
2
4
|
DropdownMenu,
|
|
3
5
|
DropdownMenuContent,
|
|
6
|
+
DropdownMenuGroup,
|
|
4
7
|
DropdownMenuItem,
|
|
5
8
|
DropdownMenuLabel,
|
|
6
9
|
DropdownMenuSeparator,
|
|
7
10
|
DropdownMenuTrigger,
|
|
8
11
|
} from "@/components/ui/dropdown-menu";
|
|
9
12
|
import { authClient } from "@/lib/auth-client";
|
|
10
|
-
|
|
13
|
+
|
|
11
14
|
import { Button } from "./ui/button";
|
|
12
15
|
import { Skeleton } from "./ui/skeleton";
|
|
13
|
-
import { Link } from "@tanstack/react-router";
|
|
14
16
|
|
|
15
17
|
export default function UserMenu() {
|
|
16
18
|
const navigate = useNavigate();
|
|
@@ -22,25 +24,24 @@ export default function UserMenu() {
|
|
|
22
24
|
|
|
23
25
|
if (!session) {
|
|
24
26
|
return (
|
|
25
|
-
<
|
|
26
|
-
<
|
|
27
|
-
</
|
|
27
|
+
<Link to="/login">
|
|
28
|
+
<Button variant="outline">Sign In</Button>
|
|
29
|
+
</Link>
|
|
28
30
|
);
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
return (
|
|
32
34
|
<DropdownMenu>
|
|
33
|
-
<DropdownMenuTrigger
|
|
34
|
-
|
|
35
|
+
<DropdownMenuTrigger render={<Button variant="outline" />}>
|
|
36
|
+
{session.user.name}
|
|
35
37
|
</DropdownMenuTrigger>
|
|
36
38
|
<DropdownMenuContent className="bg-card">
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
<
|
|
39
|
+
<DropdownMenuGroup>
|
|
40
|
+
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
|
41
|
+
<DropdownMenuSeparator />
|
|
42
|
+
<DropdownMenuItem>{session.user.email}</DropdownMenuItem>
|
|
43
|
+
<DropdownMenuItem
|
|
42
44
|
variant="destructive"
|
|
43
|
-
className="w-full"
|
|
44
45
|
onClick={() => {
|
|
45
46
|
authClient.signOut({
|
|
46
47
|
fetchOptions: {
|
|
@@ -54,8 +55,8 @@ export default function UserMenu() {
|
|
|
54
55
|
}}
|
|
55
56
|
>
|
|
56
57
|
Sign Out
|
|
57
|
-
</
|
|
58
|
-
</
|
|
58
|
+
</DropdownMenuItem>
|
|
59
|
+
</DropdownMenuGroup>
|
|
59
60
|
</DropdownMenuContent>
|
|
60
61
|
</DropdownMenu>
|
|
61
62
|
);
|
|
@@ -6,7 +6,7 @@ See https://docs.convex.dev/functions for more.
|
|
|
6
6
|
A query function that takes two arguments looks like:
|
|
7
7
|
|
|
8
8
|
```ts
|
|
9
|
-
//
|
|
9
|
+
// convex/myFunctions.ts
|
|
10
10
|
import { query } from "./_generated/server";
|
|
11
11
|
import { v } from "convex/values";
|
|
12
12
|
|
|
@@ -36,7 +36,7 @@ export const myQueryFunction = query({
|
|
|
36
36
|
Using this query function in a React component looks like:
|
|
37
37
|
|
|
38
38
|
```ts
|
|
39
|
-
const data = useQuery(api.
|
|
39
|
+
const data = useQuery(api.myFunctions.myQueryFunction, {
|
|
40
40
|
first: 10,
|
|
41
41
|
second: "hello",
|
|
42
42
|
});
|
|
@@ -45,7 +45,7 @@ const data = useQuery(api.functions.myQueryFunction, {
|
|
|
45
45
|
A mutation function looks like:
|
|
46
46
|
|
|
47
47
|
```ts
|
|
48
|
-
//
|
|
48
|
+
// convex/myFunctions.ts
|
|
49
49
|
import { mutation } from "./_generated/server";
|
|
50
50
|
import { v } from "convex/values";
|
|
51
51
|
|
|
@@ -73,7 +73,7 @@ export const myMutationFunction = mutation({
|
|
|
73
73
|
Using this mutation function in a React component looks like:
|
|
74
74
|
|
|
75
75
|
```ts
|
|
76
|
-
const mutation = useMutation(api.
|
|
76
|
+
const mutation = useMutation(api.myFunctions.myMutationFunction);
|
|
77
77
|
function handleButtonPress() {
|
|
78
78
|
// fire and forget, the most common way to use mutations
|
|
79
79
|
mutation({ first: "Hello!", second: "me" });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
/* This TypeScript project config describes the environment that
|
|
3
3
|
* Convex functions run in and is used to typecheck them.
|
|
4
|
-
* You can modify it, but some settings required to use Convex.
|
|
4
|
+
* You can modify it, but some settings are required to use Convex.
|
|
5
5
|
*/
|
|
6
6
|
"compilerOptions": {
|
|
7
7
|
/* These settings are not required by Convex and can be modified. */
|
|
@@ -3,20 +3,21 @@
|
|
|
3
3
|
"version": "0.1.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"scripts": {
|
|
6
|
-
"dev": "next dev",
|
|
6
|
+
"dev": "next dev --port 3001",
|
|
7
7
|
"build": "next build",
|
|
8
8
|
"start": "next start"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"
|
|
11
|
+
"@base-ui/react": "^1.0.0",
|
|
12
|
+
"shadcn": "^3.6.2",
|
|
12
13
|
"@tanstack/react-form": "^1.27.3",
|
|
13
14
|
"class-variance-authority": "^0.7.1",
|
|
14
15
|
"clsx": "^2.1.1",
|
|
15
16
|
"lucide-react": "^0.546.0",
|
|
16
|
-
"next": "^16.0
|
|
17
|
+
"next": "^16.1.0",
|
|
17
18
|
"next-themes": "^0.4.6",
|
|
18
|
-
"react": "19.2.3",
|
|
19
|
-
"react-dom": "19.2.3",
|
|
19
|
+
"react": "^19.2.3",
|
|
20
|
+
"react-dom": "^19.2.3",
|
|
20
21
|
"sonner": "^2.0.5",
|
|
21
22
|
"tailwind-merge": "^3.3.1",
|
|
22
23
|
"tw-animate-css": "^1.3.4",
|
|
@@ -25,8 +26,8 @@
|
|
|
25
26
|
"devDependencies": {
|
|
26
27
|
"@tailwindcss/postcss": "^4.1.10",
|
|
27
28
|
"@types/node": "^20",
|
|
28
|
-
"@types/react": "19.2.7",
|
|
29
|
-
"@types/react-dom": "19.2.3",
|
|
29
|
+
"@types/react": "^19.2.7",
|
|
30
|
+
"@types/react-dom": "^19.2.3",
|
|
30
31
|
"tailwindcss": "^4.1.10",
|
|
31
32
|
"typescript": "^5"
|
|
32
33
|
}
|
|
@@ -2,7 +2,10 @@ import type { Metadata } from "next";
|
|
|
2
2
|
import { Geist, Geist_Mono } from "next/font/google";
|
|
3
3
|
import "../index.css";
|
|
4
4
|
{{#if (eq auth "clerk")}}{{#if (eq backend "convex")}}import { ClerkProvider } from "@clerk/nextjs";
|
|
5
|
-
{{/if}}{{/if}}
|
|
5
|
+
{{/if}}{{/if}}{{#if (and (eq backend "convex") (eq auth "better-auth"))}}
|
|
6
|
+
import { getToken } from "@/lib/auth-server";
|
|
7
|
+
{{/if}}
|
|
8
|
+
import Providers from "@/components/providers";
|
|
6
9
|
import Header from "@/components/header";
|
|
7
10
|
|
|
8
11
|
const geistSans = Geist({
|
|
@@ -20,6 +23,29 @@ export const metadata: Metadata = {
|
|
|
20
23
|
description: "{{projectName}}",
|
|
21
24
|
};
|
|
22
25
|
|
|
26
|
+
{{#if (and (eq backend "convex") (eq auth "better-auth"))}}
|
|
27
|
+
export default async function RootLayout({
|
|
28
|
+
children,
|
|
29
|
+
}: Readonly<{
|
|
30
|
+
children: React.ReactNode;
|
|
31
|
+
}>) {
|
|
32
|
+
const token = await getToken();
|
|
33
|
+
return (
|
|
34
|
+
<html lang="en" suppressHydrationWarning>
|
|
35
|
+
<body
|
|
36
|
+
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
|
37
|
+
>
|
|
38
|
+
<Providers initialToken={token}>
|
|
39
|
+
<div className="grid grid-rows-[auto_1fr] h-svh">
|
|
40
|
+
<Header />
|
|
41
|
+
{children}
|
|
42
|
+
</div>
|
|
43
|
+
</Providers>
|
|
44
|
+
</body>
|
|
45
|
+
</html>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
{{else}}
|
|
23
49
|
export default function RootLayout({
|
|
24
50
|
children,
|
|
25
51
|
}: Readonly<{
|
|
@@ -47,3 +73,4 @@ export default function RootLayout({
|
|
|
47
73
|
</html>
|
|
48
74
|
);
|
|
49
75
|
}
|
|
76
|
+
{{/if}}
|
|
@@ -16,12 +16,10 @@ export function ModeToggle() {
|
|
|
16
16
|
|
|
17
17
|
return (
|
|
18
18
|
<DropdownMenu>
|
|
19
|
-
<DropdownMenuTrigger
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
<span className="sr-only">Toggle theme</span>
|
|
24
|
-
</Button>
|
|
19
|
+
<DropdownMenuTrigger render={<Button variant="outline" size="icon" />}>
|
|
20
|
+
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
|
21
|
+
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
|
22
|
+
<span className="sr-only">Toggle theme</span>
|
|
25
23
|
</DropdownMenuTrigger>
|
|
26
24
|
<DropdownMenuContent align="end">
|
|
27
25
|
<DropdownMenuItem onClick={() => setTheme("light")}>
|
|
@@ -6,7 +6,7 @@ import { useAuth } from "@clerk/nextjs";
|
|
|
6
6
|
import { ConvexReactClient } from "convex/react";
|
|
7
7
|
import { ConvexProviderWithClerk } from "convex/react-clerk";
|
|
8
8
|
{{else if (eq auth "better-auth")}}
|
|
9
|
-
import {
|
|
9
|
+
import { ConvexReactClient } from "convex/react";
|
|
10
10
|
import { ConvexBetterAuthProvider } from "@convex-dev/better-auth/react";
|
|
11
11
|
import { authClient } from "@/lib/auth-client";
|
|
12
12
|
{{else}}
|
|
@@ -32,9 +32,15 @@ const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
|
|
|
32
32
|
{{/if}}
|
|
33
33
|
|
|
34
34
|
export default function Providers({
|
|
35
|
-
children
|
|
35
|
+
children,
|
|
36
|
+
{{#if (and (eq backend "convex") (eq auth "better-auth"))}}
|
|
37
|
+
initialToken,
|
|
38
|
+
{{/if}}
|
|
36
39
|
}: {
|
|
37
|
-
children: React.ReactNode
|
|
40
|
+
children: React.ReactNode;
|
|
41
|
+
{{#if (and (eq backend "convex") (eq auth "better-auth"))}}
|
|
42
|
+
initialToken?: string | null;
|
|
43
|
+
{{/if}}
|
|
38
44
|
}) {
|
|
39
45
|
return (
|
|
40
46
|
<ThemeProvider
|
|
@@ -49,7 +55,11 @@ export default function Providers({
|
|
|
49
55
|
{children}
|
|
50
56
|
</ConvexProviderWithClerk>
|
|
51
57
|
{{else if (eq auth "better-auth")}}
|
|
52
|
-
<ConvexBetterAuthProvider
|
|
58
|
+
<ConvexBetterAuthProvider
|
|
59
|
+
client={convex}
|
|
60
|
+
authClient={authClient}
|
|
61
|
+
initialToken={initialToken}
|
|
62
|
+
>
|
|
53
63
|
{children}
|
|
54
64
|
</ConvexBetterAuthProvider>
|
|
55
65
|
{{else}}
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"typecheck": "react-router typegen && tsc"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"
|
|
12
|
+
"@base-ui/react": "^1.0.0",
|
|
13
|
+
"shadcn": "^3.6.2",
|
|
13
14
|
"@react-router/fs-routes": "^7.10.1",
|
|
14
15
|
"@react-router/node": "^7.10.1",
|
|
15
16
|
"@react-router/serve": "^7.10.1",
|
|
@@ -14,12 +14,10 @@ export function ModeToggle() {
|
|
|
14
14
|
|
|
15
15
|
return (
|
|
16
16
|
<DropdownMenu>
|
|
17
|
-
<DropdownMenuTrigger
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
<span className="sr-only">Toggle theme</span>
|
|
22
|
-
</Button>
|
|
17
|
+
<DropdownMenuTrigger render={<Button variant="outline" size="icon" />}>
|
|
18
|
+
<Sun className="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90" />
|
|
19
|
+
<Moon className="absolute h-[1.2rem] w-[1.2rem] scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0" />
|
|
20
|
+
<span className="sr-only">Toggle theme</span>
|
|
23
21
|
</DropdownMenuTrigger>
|
|
24
22
|
<DropdownMenuContent align="end">
|
|
25
23
|
<DropdownMenuItem onClick={() => setTheme("light")}>Light</DropdownMenuItem>
|
|
@@ -14,12 +14,10 @@ export function ModeToggle() {
|
|
|
14
14
|
|
|
15
15
|
return (
|
|
16
16
|
<DropdownMenu>
|
|
17
|
-
<DropdownMenuTrigger
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
<span className="sr-only">Toggle theme</span>
|
|
22
|
-
</Button>
|
|
17
|
+
<DropdownMenuTrigger render={<Button variant="outline" size="icon" />}>
|
|
18
|
+
<Sun className="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90" />
|
|
19
|
+
<Moon className="absolute h-[1.2rem] w-[1.2rem] scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0" />
|
|
20
|
+
<span className="sr-only">Toggle theme</span>
|
|
23
21
|
</DropdownMenuTrigger>
|
|
24
22
|
<DropdownMenuContent align="end">
|
|
25
23
|
<DropdownMenuItem onClick={() => setTheme("light")}>Light</DropdownMenuItem>
|
|
@@ -35,7 +35,13 @@ export function getRouter() {
|
|
|
35
35
|
unsavedChangesWarning: false,
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
+
{{#if (eq auth "better-auth")}}
|
|
39
|
+
const convexQueryClient = new ConvexQueryClient(convex, {
|
|
40
|
+
expectAuth: true,
|
|
41
|
+
});
|
|
42
|
+
{{else}}
|
|
38
43
|
const convexQueryClient = new ConvexQueryClient(convex);
|
|
44
|
+
{{/if}}
|
|
39
45
|
|
|
40
46
|
const queryClient: QueryClient = new QueryClient({
|
|
41
47
|
defaultOptions: {
|
|
@@ -37,20 +37,12 @@ const fetchClerkAuth = createServerFn({ method: "GET" }).handler(async () => {
|
|
|
37
37
|
});
|
|
38
38
|
{{else if (and (eq backend "convex") (eq auth "better-auth"))}}
|
|
39
39
|
import { createServerFn } from "@tanstack/react-start";
|
|
40
|
-
import { getRequest, getCookie } from "@tanstack/react-start/server";
|
|
41
40
|
import { ConvexBetterAuthProvider } from "@convex-dev/better-auth/react";
|
|
42
|
-
import { fetchSession, getCookieName } from "@convex-dev/better-auth/react-start";
|
|
43
41
|
import { authClient } from "@/lib/auth-client";
|
|
44
|
-
import {
|
|
42
|
+
import { getToken } from "@/lib/auth-server";
|
|
45
43
|
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
const sessionCookieName = getCookieName(createAuth);
|
|
49
|
-
const token = getCookie(sessionCookieName);
|
|
50
|
-
return {
|
|
51
|
-
userId: session?.user.id,
|
|
52
|
-
token,
|
|
53
|
-
};
|
|
44
|
+
const getAuth = createServerFn({ method: "GET" }).handler(async () => {
|
|
45
|
+
return await getToken();
|
|
54
46
|
});
|
|
55
47
|
{{/if}}
|
|
56
48
|
|
|
@@ -113,11 +105,14 @@ export const Route = createRootRouteWithContext<RouterAppContext>()({
|
|
|
113
105
|
},
|
|
114
106
|
{{else if (and (eq backend "convex") (eq auth "better-auth"))}}
|
|
115
107
|
beforeLoad: async (ctx) => {
|
|
116
|
-
const
|
|
108
|
+
const token = await getAuth();
|
|
117
109
|
if (token) {
|
|
118
110
|
ctx.context.convexQueryClient.serverHttpClient?.setAuth(token);
|
|
119
111
|
}
|
|
120
|
-
return {
|
|
112
|
+
return {
|
|
113
|
+
isAuthenticated: !!token,
|
|
114
|
+
token,
|
|
115
|
+
};
|
|
121
116
|
},
|
|
122
117
|
{{/if}}
|
|
123
118
|
});
|
|
@@ -148,7 +143,11 @@ function RootDocument() {
|
|
|
148
143
|
{{else if (and (eq backend "convex") (eq auth "better-auth"))}}
|
|
149
144
|
const context = useRouteContext({ from: Route.id });
|
|
150
145
|
return (
|
|
151
|
-
<ConvexBetterAuthProvider
|
|
146
|
+
<ConvexBetterAuthProvider
|
|
147
|
+
client={context.convexClient}
|
|
148
|
+
authClient={authClient}
|
|
149
|
+
initialToken={context.token}
|
|
150
|
+
>
|
|
152
151
|
<html lang="en" className="dark">
|
|
153
152
|
<head>
|
|
154
153
|
<HeadContent />
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
-
"style": "
|
|
3
|
+
"style": "base-lyra",
|
|
4
4
|
"rsc": false,
|
|
5
5
|
"tsx": true,
|
|
6
6
|
"tailwind": {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"cssVariables": true,
|
|
11
11
|
"prefix": ""
|
|
12
12
|
},
|
|
13
|
+
"iconLibrary": "lucide",
|
|
13
14
|
"aliases": {
|
|
14
15
|
"components": "@/components",
|
|
15
16
|
"utils": "@/lib/utils",
|
|
@@ -17,5 +18,7 @@
|
|
|
17
18
|
"lib": "@/lib",
|
|
18
19
|
"hooks": "@/hooks"
|
|
19
20
|
},
|
|
20
|
-
"
|
|
21
|
+
"menuColor": "default",
|
|
22
|
+
"menuAccent": "subtle",
|
|
23
|
+
"registries": {}
|
|
21
24
|
}
|