create-better-t-stack 3.9.0 → 3.11.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 (77) hide show
  1. package/README.md +2 -1
  2. package/dist/cli.mjs +1 -1
  3. package/dist/index.d.mts +7 -3
  4. package/dist/index.mjs +1 -1
  5. package/dist/{src-DLvUK0Qf.mjs → src-XVvJUQ_h.mjs} +270 -93
  6. package/package.json +44 -44
  7. package/templates/auth/better-auth/convex/backend/convex/auth.config.ts.hbs +5 -7
  8. package/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs +17 -17
  9. package/templates/auth/better-auth/convex/backend/convex/http.ts.hbs +4 -4
  10. package/templates/auth/better-auth/convex/web/react/next/src/app/api/auth/[...all]/route.ts.hbs +2 -2
  11. package/templates/auth/better-auth/convex/web/react/next/src/components/user-menu.tsx.hbs +10 -10
  12. package/templates/auth/better-auth/convex/web/react/next/src/lib/auth-server.ts.hbs +13 -5
  13. package/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/user-menu.tsx.hbs +14 -12
  14. package/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/user-menu.tsx.hbs +13 -16
  15. package/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-server.ts.hbs +11 -5
  16. package/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/api/auth/$.ts.hbs +4 -4
  17. package/templates/auth/better-auth/fullstack/tanstack-start/src/routes/api/auth/$.ts.hbs +1 -1
  18. package/templates/auth/better-auth/web/react/next/src/components/user-menu.tsx.hbs +17 -15
  19. package/templates/auth/better-auth/web/react/react-router/src/components/user-menu.tsx.hbs +16 -15
  20. package/templates/auth/better-auth/web/react/tanstack-router/src/components/{user-menu.tsx → user-menu.tsx.hbs} +16 -15
  21. package/templates/auth/better-auth/web/react/tanstack-start/src/components/{user-menu.tsx → user-menu.tsx.hbs} +16 -15
  22. package/templates/backend/convex/packages/backend/convex/README.md +4 -4
  23. package/templates/backend/convex/packages/backend/convex/convex.config.ts.hbs +17 -0
  24. package/templates/backend/convex/packages/backend/convex/tsconfig.json.hbs +1 -1
  25. package/templates/examples/ai/convex/packages/backend/convex/agent.ts.hbs +9 -0
  26. package/templates/examples/ai/convex/packages/backend/convex/chat.ts.hbs +67 -0
  27. package/templates/examples/ai/native/bare/app/(drawer)/ai.tsx.hbs +301 -3
  28. package/templates/examples/ai/native/unistyles/app/(drawer)/ai.tsx.hbs +296 -10
  29. package/templates/examples/ai/native/uniwind/app/(drawer)/ai.tsx.hbs +180 -1
  30. package/templates/examples/ai/web/react/next/src/app/ai/page.tsx.hbs +172 -9
  31. package/templates/examples/ai/web/react/react-router/src/routes/ai.tsx.hbs +156 -6
  32. package/templates/examples/ai/web/react/tanstack-router/src/routes/ai.tsx.hbs +156 -4
  33. package/templates/examples/ai/web/react/tanstack-start/src/routes/ai.tsx.hbs +159 -6
  34. package/templates/frontend/react/next/package.json.hbs +8 -7
  35. package/templates/frontend/react/next/src/app/layout.tsx.hbs +28 -1
  36. package/templates/frontend/react/next/src/components/mode-toggle.tsx.hbs +4 -6
  37. package/templates/frontend/react/next/src/components/providers.tsx.hbs +14 -4
  38. package/templates/frontend/react/react-router/package.json.hbs +2 -1
  39. package/templates/frontend/react/{tanstack-router/src/components/mode-toggle.tsx → react-router/src/components/mode-toggle.tsx.hbs} +4 -6
  40. package/templates/frontend/react/tanstack-router/package.json.hbs +2 -1
  41. package/templates/frontend/react/{react-router/src/components/mode-toggle.tsx → tanstack-router/src/components/mode-toggle.tsx.hbs} +4 -6
  42. package/templates/frontend/react/tanstack-start/package.json.hbs +2 -1
  43. package/templates/frontend/react/tanstack-start/src/router.tsx.hbs +6 -0
  44. package/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs +13 -14
  45. package/templates/frontend/react/tanstack-start/vite.config.ts.hbs +5 -0
  46. package/templates/frontend/react/web-base/components.json +5 -2
  47. package/templates/frontend/react/web-base/src/components/ui/button.tsx.hbs +57 -0
  48. package/templates/frontend/react/web-base/src/components/ui/card.tsx.hbs +103 -0
  49. package/templates/frontend/react/web-base/src/components/ui/checkbox.tsx.hbs +26 -0
  50. package/templates/frontend/react/web-base/src/components/ui/dropdown-menu.tsx.hbs +262 -0
  51. package/templates/frontend/react/web-base/src/components/ui/input.tsx.hbs +20 -0
  52. package/templates/frontend/react/web-base/src/components/ui/label.tsx.hbs +20 -0
  53. package/templates/frontend/react/web-base/src/components/ui/skeleton.tsx.hbs +13 -0
  54. package/templates/frontend/react/web-base/src/components/ui/sonner.tsx.hbs +44 -0
  55. package/templates/frontend/react/web-base/src/index.css.hbs +58 -64
  56. package/templates/auth/better-auth/convex/backend/convex/convex.config.ts.hbs +0 -7
  57. package/templates/examples/ai/web/react/base/src/components/response.tsx.hbs +0 -22
  58. package/templates/frontend/react/web-base/src/components/ui/button.tsx +0 -56
  59. package/templates/frontend/react/web-base/src/components/ui/card.tsx +0 -75
  60. package/templates/frontend/react/web-base/src/components/ui/checkbox.tsx +0 -27
  61. package/templates/frontend/react/web-base/src/components/ui/dropdown-menu.tsx +0 -228
  62. package/templates/frontend/react/web-base/src/components/ui/input.tsx +0 -21
  63. package/templates/frontend/react/web-base/src/components/ui/label.tsx +0 -19
  64. package/templates/frontend/react/web-base/src/components/ui/skeleton.tsx +0 -13
  65. package/templates/frontend/react/web-base/src/components/ui/sonner.tsx +0 -25
  66. /package/templates/auth/better-auth/web/react/tanstack-router/src/components/{sign-in-form.tsx → sign-in-form.tsx.hbs} +0 -0
  67. /package/templates/auth/better-auth/web/react/tanstack-router/src/components/{sign-up-form.tsx → sign-up-form.tsx.hbs} +0 -0
  68. /package/templates/auth/better-auth/web/react/tanstack-router/src/routes/{login.tsx → login.tsx.hbs} +0 -0
  69. /package/templates/auth/better-auth/web/react/tanstack-start/src/components/{sign-in-form.tsx → sign-in-form.tsx.hbs} +0 -0
  70. /package/templates/auth/better-auth/web/react/tanstack-start/src/components/{sign-up-form.tsx → sign-up-form.tsx.hbs} +0 -0
  71. /package/templates/auth/better-auth/web/react/tanstack-start/src/routes/{login.tsx → login.tsx.hbs} +0 -0
  72. /package/templates/auth/better-auth/web/solid/src/components/{sign-in-form.tsx → sign-in-form.tsx.hbs} +0 -0
  73. /package/templates/auth/better-auth/web/solid/src/components/{sign-up-form.tsx → sign-up-form.tsx.hbs} +0 -0
  74. /package/templates/auth/better-auth/web/solid/src/routes/{login.tsx → login.tsx.hbs} +0 -0
  75. /package/templates/frontend/react/react-router/src/components/{theme-provider.tsx → theme-provider.tsx.hbs} +0 -0
  76. /package/templates/frontend/react/tanstack-router/src/components/{theme-provider.tsx → theme-provider.tsx.hbs} +0 -0
  77. /package/templates/frontend/react/web-base/src/lib/{utils.ts → utils.ts.hbs} +0 -0
package/package.json CHANGED
@@ -1,52 +1,61 @@
1
1
  {
2
2
  "name": "create-better-t-stack",
3
- "version": "3.9.0",
3
+ "version": "3.11.0",
4
4
  "description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
5
- "type": "module",
6
- "license": "MIT",
7
- "author": "Aman Varshney",
8
- "bin": {
9
- "create-better-t-stack": "dist/cli.mjs"
10
- },
11
- "files": [
12
- "templates",
13
- "dist"
14
- ],
15
5
  "keywords": [
6
+ "better-auth",
16
7
  "better-t-stack",
17
- "typescript",
8
+ "biome",
18
9
  "boilerplate",
19
- "starter",
20
10
  "cli",
21
- "turborepo",
22
- "trpc",
23
- "better-auth",
24
- "monorepo",
25
- "fullstack",
26
- "type-safety",
27
- "react",
28
- "react-native",
11
+ "drizzle",
12
+ "elysia",
29
13
  "expo",
14
+ "fullstack",
30
15
  "hono",
31
- "elysia",
32
- "drizzle",
16
+ "monorepo",
33
17
  "prisma",
34
- "tanstack",
35
- "tailwind",
36
- "shadcn",
37
18
  "pwa",
19
+ "react",
20
+ "react-native",
21
+ "shadcn",
22
+ "starter",
23
+ "tailwind",
24
+ "tanstack",
38
25
  "tauri",
39
- "biome"
26
+ "trpc",
27
+ "turborepo",
28
+ "type-safety",
29
+ "typescript"
40
30
  ],
31
+ "homepage": "https://better-t-stack.dev/",
32
+ "license": "MIT",
33
+ "author": "Aman Varshney",
41
34
  "repository": {
42
35
  "type": "git",
43
36
  "url": "git+https://github.com/AmanVarshney01/create-better-t-stack.git",
44
37
  "directory": "apps/cli"
45
38
  },
39
+ "bin": {
40
+ "create-better-t-stack": "dist/cli.mjs"
41
+ },
42
+ "files": [
43
+ "dist",
44
+ "templates"
45
+ ],
46
+ "type": "module",
47
+ "exports": {
48
+ ".": {
49
+ "types": "./dist/index.d.mts",
50
+ "import": "./dist/index.mjs"
51
+ },
52
+ "./cli": {
53
+ "import": "./dist/cli.mjs"
54
+ }
55
+ },
46
56
  "publishConfig": {
47
57
  "access": "public"
48
58
  },
49
- "homepage": "https://better-t-stack.dev/",
50
59
  "scripts": {
51
60
  "build": "tsdown --publint",
52
61
  "dev": "tsdown --watch",
@@ -57,22 +66,13 @@
57
66
  "test:ci": "bun run build && AGENT=1 bun test --bail=5",
58
67
  "prepublishOnly": "npm run build"
59
68
  },
60
- "exports": {
61
- ".": {
62
- "types": "./dist/index.d.mts",
63
- "import": "./dist/index.mjs"
64
- },
65
- "./cli": {
66
- "import": "./dist/cli.mjs"
67
- }
68
- },
69
69
  "dependencies": {
70
- "@better-t-stack/types": "^3.9.0",
70
+ "@better-t-stack/types": "^3.11.0",
71
71
  "@clack/prompts": "^1.0.0-alpha.8",
72
- "@orpc/server": "^1.12.2",
72
+ "@orpc/server": "^1.13.0",
73
73
  "consola": "^3.4.2",
74
74
  "execa": "^9.6.1",
75
- "fs-extra": "^11.3.2",
75
+ "fs-extra": "^11.3.3",
76
76
  "gradient-string": "^3.0.0",
77
77
  "handlebars": "^4.7.8",
78
78
  "jsonc-parser": "^3.3.1",
@@ -82,14 +82,14 @@
82
82
  "trpc-cli": "^0.12.1",
83
83
  "ts-morph": "^27.0.2",
84
84
  "yaml": "^2.8.2",
85
- "zod": "^4.1.13"
85
+ "zod": "^4.2.1"
86
86
  },
87
87
  "devDependencies": {
88
- "@types/bun": "^1.2.17",
88
+ "@types/bun": "^1.3.5",
89
89
  "@types/fs-extra": "^11.0.4",
90
- "@types/node": "^24.10.2",
90
+ "@types/node": "^25.0.3",
91
91
  "publint": "^0.3.16",
92
- "tsdown": "^0.17.2",
92
+ "tsdown": "^0.18.2",
93
93
  "typescript": "^5.9.3"
94
94
  }
95
95
  }
@@ -1,8 +1,6 @@
1
+ import { getAuthConfigProvider } from "@convex-dev/better-auth/auth-config";
2
+ import type { AuthConfig } from "convex/server";
3
+
1
4
  export default {
2
- providers: [
3
- {
4
- domain: process.env.CONVEX_SITE_URL,
5
- applicationID: "convex",
6
- },
7
- ],
8
- };
5
+ providers: [getAuthConfigProvider()],
6
+ } satisfies AuthConfig;
@@ -2,19 +2,21 @@ import { createClient, type GenericCtx } from "@convex-dev/better-auth";
2
2
  {{#if (or (includes frontend "native-bare") (includes frontend "native-uniwind") (includes frontend "native-unistyles"))}}
3
3
  import { convex } from "@convex-dev/better-auth/plugins";
4
4
  import { expo } from "@better-auth/expo";
5
+ {{else if (or (includes frontend "tanstack-router") (includes frontend "react-router") (includes frontend "nuxt") (includes frontend "svelte") (includes frontend "solid"))}}
6
+ import { convex, crossDomain } from "@convex-dev/better-auth/plugins";
5
7
  {{else}}
6
8
  import { convex } from "@convex-dev/better-auth/plugins";
7
9
  {{/if}}
8
- {{#if (or (includes frontend "tanstack-router") (includes frontend "react-router") (includes frontend "nuxt") (includes frontend "svelte") (includes frontend "solid"))}}
9
- import { crossDomain } from "@convex-dev/better-auth/plugins";
10
- {{/if}}
11
10
  import { components } from "./_generated/api";
12
11
  import { DataModel } from "./_generated/dataModel";
13
12
  import { query } from "./_generated/server";
14
13
  import { betterAuth } from "better-auth";
15
14
  import { v } from "convex/values";
15
+ import authConfig from "./auth.config";
16
16
 
17
- {{#if (or (includes frontend "tanstack-start") (includes frontend "next") (includes frontend "tanstack-router") (includes frontend "react-router") (includes frontend "nuxt") (includes frontend "svelte") (includes frontend "solid"))}}
17
+ {{#if (or (includes frontend "tanstack-start") (includes frontend "next"))}}
18
+ const siteUrl = process.env.SITE_URL!;
19
+ {{else if (or (includes frontend "tanstack-router") (includes frontend "react-router") (includes frontend "nuxt") (includes frontend "svelte") (includes frontend "solid"))}}
18
20
  const siteUrl = process.env.SITE_URL!;
19
21
  {{/if}}
20
22
  {{#if (or (includes frontend "native-bare") (includes frontend "native-uniwind") (includes frontend "native-unistyles"))}}
@@ -23,23 +25,19 @@ const nativeAppUrl = process.env.NATIVE_APP_URL || "mybettertapp://";
23
25
 
24
26
  export const authComponent = createClient<DataModel>(components.betterAuth);
25
27
 
26
- function createAuth(
27
- ctx: GenericCtx<DataModel>,
28
- { optionsOnly }: { optionsOnly?: boolean } = { optionsOnly: false }
29
- ) {
28
+ function createAuth(ctx: GenericCtx<DataModel>) {
30
29
  return betterAuth({
31
- logger: {
32
- disabled: optionsOnly,
33
- },
34
30
  {{#if (and (or (includes frontend "native-bare") (includes frontend "native-uniwind") (includes frontend "native-unistyles")) (or (includes frontend "tanstack-start") (includes frontend "next")))}}
35
31
  baseURL: siteUrl,
36
32
  trustedOrigins: [siteUrl, nativeAppUrl],
33
+ {{else if (and (or (includes frontend "native-bare") (includes frontend "native-uniwind") (includes frontend "native-unistyles")) (or (includes frontend "tanstack-router") (includes frontend "react-router") (includes frontend "nuxt") (includes frontend "svelte") (includes frontend "solid")))}}
34
+ trustedOrigins: [siteUrl, nativeAppUrl],
37
35
  {{else if (or (includes frontend "native-bare") (includes frontend "native-uniwind") (includes frontend "native-unistyles"))}}
38
36
  trustedOrigins: [nativeAppUrl],
39
37
  {{else if (or (includes frontend "tanstack-start") (includes frontend "next"))}}
40
38
  baseURL: siteUrl,
41
39
  trustedOrigins: [siteUrl],
42
- {{else}}
40
+ {{else if (or (includes frontend "tanstack-router") (includes frontend "react-router") (includes frontend "nuxt") (includes frontend "svelte") (includes frontend "solid"))}}
43
41
  trustedOrigins: [siteUrl],
44
42
  {{/if}}
45
43
  database: authComponent.adapter(ctx),
@@ -50,11 +48,13 @@ function createAuth(
50
48
  plugins: [
51
49
  {{#if (or (includes frontend "native-bare") (includes frontend "native-uniwind") (includes frontend "native-unistyles"))}}
52
50
  expo(),
53
- {{/if}}
54
- {{#if (or (includes frontend "tanstack-router") (includes frontend "react-router") (includes frontend "nuxt") (includes frontend "svelte") (includes frontend "solid"))}}
51
+ {{else if (or (includes frontend "tanstack-router") (includes frontend "react-router") (includes frontend "nuxt") (includes frontend "svelte") (includes frontend "solid"))}}
55
52
  crossDomain({ siteUrl }),
56
53
  {{/if}}
57
- convex(),
54
+ convex({
55
+ authConfig,
56
+ jwksRotateOnTokenGenerationError: true,
57
+ }),
58
58
  ],
59
59
  });
60
60
  }
@@ -64,7 +64,7 @@ export { createAuth };
64
64
  export const getCurrentUser = query({
65
65
  args: {},
66
66
  returns: v.any(),
67
- handler: async function (ctx, args) {
67
+ handler: async function (ctx) {
68
68
  return authComponent.getAuthUser(ctx);
69
69
  },
70
- });
70
+ });
@@ -3,10 +3,10 @@ import { authComponent, createAuth } from "./auth";
3
3
 
4
4
  const http = httpRouter();
5
5
 
6
- {{#if (or (includes frontend "tanstack-start") (includes frontend "next") (includes frontend "native-bare") (includes frontend "native-uniwind") (includes frontend "native-unistyles"))}}
7
- authComponent.registerRoutes(http, createAuth);
8
- {{else}}
6
+ {{#if (or (includes frontend "tanstack-router") (includes frontend "react-router") (includes frontend "nuxt") (includes frontend "svelte") (includes frontend "solid"))}}
9
7
  authComponent.registerRoutes(http, createAuth, { cors: true });
8
+ {{else}}
9
+ authComponent.registerRoutes(http, createAuth);
10
10
  {{/if}}
11
11
 
12
- export default http;
12
+ export default http;
@@ -1,3 +1,3 @@
1
- import { nextJsHandler } from "@convex-dev/better-auth/nextjs";
1
+ import { handler } from "@/lib/auth-server";
2
2
 
3
- export const { GET, POST } = nextJsHandler();
3
+ export const { GET, POST } = handler;
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  DropdownMenu,
3
3
  DropdownMenuContent,
4
+ DropdownMenuGroup,
4
5
  DropdownMenuItem,
5
6
  DropdownMenuLabel,
6
7
  DropdownMenuSeparator,
@@ -18,17 +19,16 @@ export default function UserMenu() {
18
19
 
19
20
  return (
20
21
  <DropdownMenu>
21
- <DropdownMenuTrigger asChild>
22
- <Button variant="outline">{user?.name}</Button>
22
+ <DropdownMenuTrigger render={<Button variant="outline" />}>
23
+ {user?.name}
23
24
  </DropdownMenuTrigger>
24
25
  <DropdownMenuContent className="bg-card">
25
- <DropdownMenuLabel>My Account</DropdownMenuLabel>
26
- <DropdownMenuSeparator />
27
- <DropdownMenuItem>{user?.email}</DropdownMenuItem>
28
- <DropdownMenuItem asChild>
29
- <Button
26
+ <DropdownMenuGroup>
27
+ <DropdownMenuLabel>My Account</DropdownMenuLabel>
28
+ <DropdownMenuSeparator />
29
+ <DropdownMenuItem>{user?.email}</DropdownMenuItem>
30
+ <DropdownMenuItem
30
31
  variant="destructive"
31
- className="w-full"
32
32
  onClick={() => {
33
33
  authClient.signOut({
34
34
  fetchOptions: {
@@ -40,8 +40,8 @@ export default function UserMenu() {
40
40
  }}
41
41
  >
42
42
  Sign Out
43
- </Button>
44
- </DropdownMenuItem>
43
+ </DropdownMenuItem>
44
+ </DropdownMenuGroup>
45
45
  </DropdownMenuContent>
46
46
  </DropdownMenu>
47
47
  );
@@ -1,6 +1,14 @@
1
- import { createAuth } from "@{{projectName}}/backend/convex/auth";
2
- import { getToken as getTokenNextjs } from "@convex-dev/better-auth/nextjs";
1
+ import { convexBetterAuthNextJs } from "@convex-dev/better-auth/nextjs";
3
2
 
4
- export const getToken = () => {
5
- return getTokenNextjs(createAuth);
6
- };
3
+ export const {
4
+ handler,
5
+ preloadAuthQuery,
6
+ isAuthenticated,
7
+ getToken,
8
+ fetchAuthQuery,
9
+ fetchAuthMutation,
10
+ fetchAuthAction,
11
+ } = convexBetterAuthNextJs({
12
+ convexUrl: process.env.NEXT_PUBLIC_CONVEX_URL!,
13
+ convexSiteUrl: process.env.NEXT_PUBLIC_CONVEX_SITE_URL!,
14
+ });
@@ -1,34 +1,36 @@
1
+ import { 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
- import { useNavigate } from "@tanstack/react-router";
11
- import { Button } from "./ui/button";
12
13
  import { useQuery } from "convex/react";
13
14
  import { api } from "@{{projectName}}/backend/convex/_generated/api";
14
15
 
16
+ import { Button } from "./ui/button";
17
+
15
18
  export default function UserMenu() {
16
19
  const navigate = useNavigate();
17
20
  const user = useQuery(api.auth.getCurrentUser)
18
21
 
19
22
  return (
20
23
  <DropdownMenu>
21
- <DropdownMenuTrigger asChild>
22
- <Button variant="outline">{user?.name}</Button>
24
+ <DropdownMenuTrigger render={<Button variant="outline" />}>
25
+ {user?.name}
23
26
  </DropdownMenuTrigger>
24
27
  <DropdownMenuContent className="bg-card">
25
- <DropdownMenuLabel>My Account</DropdownMenuLabel>
26
- <DropdownMenuSeparator />
27
- <DropdownMenuItem>{user?.email}</DropdownMenuItem>
28
- <DropdownMenuItem asChild>
29
- <Button
28
+ <DropdownMenuGroup>
29
+ <DropdownMenuLabel>My Account</DropdownMenuLabel>
30
+ <DropdownMenuSeparator />
31
+ <DropdownMenuItem>{user?.email}</DropdownMenuItem>
32
+ <DropdownMenuItem
30
33
  variant="destructive"
31
- className="w-full"
32
34
  onClick={() => {
33
35
  authClient.signOut({
34
36
  fetchOptions: {
@@ -42,8 +44,8 @@ export default function UserMenu() {
42
44
  }}
43
45
  >
44
46
  Sign Out
45
- </Button>
46
- </DropdownMenuItem>
47
+ </DropdownMenuItem>
48
+ </DropdownMenuGroup>
47
49
  </DropdownMenuContent>
48
50
  </DropdownMenu>
49
51
  );
@@ -1,49 +1,46 @@
1
1
  import {
2
2
  DropdownMenu,
3
3
  DropdownMenuContent,
4
+ DropdownMenuGroup,
4
5
  DropdownMenuItem,
5
6
  DropdownMenuLabel,
6
7
  DropdownMenuSeparator,
7
8
  DropdownMenuTrigger,
8
9
  } from "@/components/ui/dropdown-menu";
9
10
  import { authClient } from "@/lib/auth-client";
10
- import { useNavigate } from "@tanstack/react-router";
11
- import { Button } from "./ui/button";
12
11
  import { useQuery } from "convex/react";
13
12
  import { api } from "@{{projectName}}/backend/convex/_generated/api";
14
13
 
14
+ import { Button } from "./ui/button";
15
+
15
16
  export default function UserMenu() {
16
- const navigate = useNavigate();
17
17
  const user = useQuery(api.auth.getCurrentUser)
18
18
 
19
19
  return (
20
20
  <DropdownMenu>
21
- <DropdownMenuTrigger asChild>
22
- <Button variant="outline">{user?.name}</Button>
21
+ <DropdownMenuTrigger render={<Button variant="outline" />}>
22
+ {user?.name}
23
23
  </DropdownMenuTrigger>
24
24
  <DropdownMenuContent className="bg-card">
25
- <DropdownMenuLabel>My Account</DropdownMenuLabel>
26
- <DropdownMenuSeparator />
27
- <DropdownMenuItem>{user?.email}</DropdownMenuItem>
28
- <DropdownMenuItem asChild>
29
- <Button
25
+ <DropdownMenuGroup>
26
+ <DropdownMenuLabel>My Account</DropdownMenuLabel>
27
+ <DropdownMenuSeparator />
28
+ <DropdownMenuItem>{user?.email}</DropdownMenuItem>
29
+ <DropdownMenuItem
30
30
  variant="destructive"
31
- className="w-full"
32
31
  onClick={() => {
33
32
  authClient.signOut({
34
33
  fetchOptions: {
35
34
  onSuccess: () => {
36
- navigate({
37
- to: "/dashboard",
38
- });
35
+ location.reload();
39
36
  },
40
37
  },
41
38
  });
42
39
  }}
43
40
  >
44
41
  Sign Out
45
- </Button>
46
- </DropdownMenuItem>
42
+ </DropdownMenuItem>
43
+ </DropdownMenuGroup>
47
44
  </DropdownMenuContent>
48
45
  </DropdownMenu>
49
46
  );
@@ -1,6 +1,12 @@
1
- import { createAuth } from "@{{projectName}}/backend/convex/auth";
2
- import { setupFetchClient } from "@convex-dev/better-auth/react-start";
3
- import { getCookie } from "@tanstack/react-start/server";
1
+ import { convexBetterAuthReactStart } from "@convex-dev/better-auth/react-start";
4
2
 
5
- export const { fetchQuery, fetchMutation, fetchAction } =
6
- await setupFetchClient(createAuth, getCookie);
3
+ export const {
4
+ handler,
5
+ getToken,
6
+ fetchAuthQuery,
7
+ fetchAuthMutation,
8
+ fetchAuthAction,
9
+ } = convexBetterAuthReactStart({
10
+ convexUrl: process.env.VITE_CONVEX_URL!,
11
+ convexSiteUrl: process.env.VITE_CONVEX_SITE_URL!,
12
+ });
@@ -1,11 +1,11 @@
1
- import { reactStartHandler } from "@convex-dev/better-auth/react-start";
2
1
  import { createFileRoute } from "@tanstack/react-router";
2
+ import { handler } from "@/lib/auth-server";
3
3
 
4
4
  export const Route = createFileRoute("/api/auth/$")({
5
5
  server: {
6
6
  handlers: {
7
- GET: ({ request }) => reactStartHandler(request),
8
- POST: ({ request }) => reactStartHandler(request),
7
+ GET: ({ request }) => handler(request),
8
+ POST: ({ request }) => handler(request),
9
9
  },
10
10
  },
11
- });
11
+ });
@@ -12,4 +12,4 @@ export const Route = createFileRoute('/api/auth/$')({
12
12
  },
13
13
  },
14
14
  },
15
- })
15
+ })
@@ -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
- <Button variant="outline" asChild>
26
- <Link href="/login">Sign In</Link>
27
- </Button>
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 asChild>
34
- <Button variant="outline">{session.user.name}</Button>
36
+ <DropdownMenuTrigger render={<Button variant="outline" />}>
37
+ {session.user.name}
35
38
  </DropdownMenuTrigger>
36
39
  <DropdownMenuContent className="bg-card">
37
- <DropdownMenuLabel>My Account</DropdownMenuLabel>
38
- <DropdownMenuSeparator />
39
- <DropdownMenuItem>{session.user.email}</DropdownMenuItem>
40
- <DropdownMenuItem asChild>
41
- <Button
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
- </Button>
56
- </DropdownMenuItem>
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
- import { useNavigate } from "react-router";
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
- <Button variant="outline" asChild>
26
- <Link to="/login">Sign In</Link>
27
- </Button>
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 asChild>
34
- <Button variant="outline">{session.user.name}</Button>
35
+ <DropdownMenuTrigger render={<Button variant="outline" />}>
36
+ {session.user.name}
35
37
  </DropdownMenuTrigger>
36
38
  <DropdownMenuContent className="bg-card">
37
- <DropdownMenuLabel>My Account</DropdownMenuLabel>
38
- <DropdownMenuSeparator />
39
- <DropdownMenuItem>{session.user.email}</DropdownMenuItem>
40
- <DropdownMenuItem asChild>
41
- <Button
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
- </Button>
56
- </DropdownMenuItem>
56
+ </DropdownMenuItem>
57
+ </DropdownMenuGroup>
57
58
  </DropdownMenuContent>
58
59
  </DropdownMenu>
59
60
  );