diff --git a/examples/tanstack-example/.env.example b/examples/tanstack-example/.env.example
new file mode 100644
index 0000000000..8eb3eeae80
--- /dev/null
+++ b/examples/tanstack-example/.env.example
@@ -0,0 +1,6 @@
+BETTER_AUTH_SECRET=
+DISCORD_CLIENT_ID=
+DISCORD_CLIENT_SECRET=
+GITHUB_CLIENT_ID=
+GITHUB_CLIENT_SECRET=
+BETTER_AUTH_URL=
\ No newline at end of file
diff --git a/examples/tanstack-example/README.md b/examples/tanstack-example/README.md
index 76198bccc3..714c9639dd 100644
--- a/examples/tanstack-example/README.md
+++ b/examples/tanstack-example/README.md
@@ -3,13 +3,15 @@ An example of using Better Auth with [TanStack Start](https://tanstack.com/start
## Setup
-To install dependencies:
+1. Move .env.example to .env and provide necessary variables
+
+2. install dependencies:
```bash
pnpm install
```
-To migrate Better-Auth:
+3. migrate required tables:
```bash
pnpx @better-auth/cli migrate
@@ -22,6 +24,4 @@ pnpm dev
```
## Preview
-
-
-
+
\ No newline at end of file
diff --git a/examples/tanstack-example/app.config.ts b/examples/tanstack-example/app.config.ts
index 557a912b38..38b3f4c907 100644
--- a/examples/tanstack-example/app.config.ts
+++ b/examples/tanstack-example/app.config.ts
@@ -2,11 +2,11 @@ import { defineConfig } from "@tanstack/start/config";
import viteTsConfigPaths from "vite-tsconfig-paths";
export default defineConfig({
- vite: {
- plugins: [
- viteTsConfigPaths({
- projects: ["./tsconfig.json"],
- }),
- ],
- },
+ vite: {
+ plugins: [
+ viteTsConfigPaths({
+ projects: ["./tsconfig.json"],
+ }),
+ ],
+ },
});
diff --git a/examples/tanstack-example/app/components/login-form.tsx b/examples/tanstack-example/app/components/login-form.tsx
index c35cc23c0b..d2d3825ac5 100644
--- a/examples/tanstack-example/app/components/login-form.tsx
+++ b/examples/tanstack-example/app/components/login-form.tsx
@@ -12,7 +12,7 @@ import {
} from "~/components/ui/card";
import { Input } from "~/components/ui/input";
import { Label } from "~/components/ui/label";
-import { signIn } from "~/lib/client/auth";
+import { signIn } from "~/lib/auth-client";
export function LoginForm() {
function handleSubmit(e: React.FormEvent) {
@@ -66,6 +66,53 @@ export function LoginForm() {
Sign In
+
+
+
+
Don't have an account?{" "}
diff --git a/examples/tanstack-example/app/components/register-form.tsx b/examples/tanstack-example/app/components/register-form.tsx
index da59cad597..eefbc9f03d 100644
--- a/examples/tanstack-example/app/components/register-form.tsx
+++ b/examples/tanstack-example/app/components/register-form.tsx
@@ -12,7 +12,7 @@ import {
} from "~/components/ui/card";
import { Input } from "~/components/ui/input";
import { Label } from "~/components/ui/label";
-import { signUp } from "~/lib/client/auth";
+import { signUp } from "~/lib/auth-client";
export function RegisterForm() {
function handleSubmit(e: React.FormEvent) {
diff --git a/examples/tanstack-example/app/components/ui/avatar.tsx b/examples/tanstack-example/app/components/ui/avatar.tsx
new file mode 100644
index 0000000000..05e961cd38
--- /dev/null
+++ b/examples/tanstack-example/app/components/ui/avatar.tsx
@@ -0,0 +1,50 @@
+"use client"
+
+import * as React from "react"
+import * as AvatarPrimitive from "@radix-ui/react-avatar"
+
+import { cn } from "~/lib/utils"
+
+const Avatar = React.forwardRef<
+ React.ElementRef
,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+Avatar.displayName = AvatarPrimitive.Root.displayName
+
+const AvatarImage = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+AvatarImage.displayName = AvatarPrimitive.Image.displayName
+
+const AvatarFallback = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
+
+export { Avatar, AvatarImage, AvatarFallback }
diff --git a/examples/tanstack-example/app/components/ui/dialog.tsx b/examples/tanstack-example/app/components/ui/dialog.tsx
new file mode 100644
index 0000000000..9850daa418
--- /dev/null
+++ b/examples/tanstack-example/app/components/ui/dialog.tsx
@@ -0,0 +1,122 @@
+"use client"
+
+import * as React from "react"
+import * as DialogPrimitive from "@radix-ui/react-dialog"
+import { X } from "lucide-react"
+
+import { cn } from "~/lib/utils"
+
+const Dialog = DialogPrimitive.Root
+
+const DialogTrigger = DialogPrimitive.Trigger
+
+const DialogPortal = DialogPrimitive.Portal
+
+const DialogClose = DialogPrimitive.Close
+
+const DialogOverlay = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
+
+const DialogContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+ {children}
+
+
+ Close
+
+
+
+))
+DialogContent.displayName = DialogPrimitive.Content.displayName
+
+const DialogHeader = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => (
+
+)
+DialogHeader.displayName = "DialogHeader"
+
+const DialogFooter = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => (
+
+)
+DialogFooter.displayName = "DialogFooter"
+
+const DialogTitle = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DialogTitle.displayName = DialogPrimitive.Title.displayName
+
+const DialogDescription = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DialogDescription.displayName = DialogPrimitive.Description.displayName
+
+export {
+ Dialog,
+ DialogPortal,
+ DialogOverlay,
+ DialogClose,
+ DialogTrigger,
+ DialogContent,
+ DialogHeader,
+ DialogFooter,
+ DialogTitle,
+ DialogDescription,
+}
diff --git a/examples/tanstack-example/app/lib/auth-client.ts b/examples/tanstack-example/app/lib/auth-client.ts
new file mode 100644
index 0000000000..d90fce6f23
--- /dev/null
+++ b/examples/tanstack-example/app/lib/auth-client.ts
@@ -0,0 +1,9 @@
+import { twoFactorClient } from "better-auth/plugins";
+import { createAuthClient } from "better-auth/react";
+
+export const { useSession, signIn, signOut, signUp, twoFactor } = createAuthClient({
+ baseURL: "http://localhost:3000",
+ plugins: [twoFactorClient({
+ twoFactorPage: "/auth/two-factor",
+ })]
+});
diff --git a/examples/tanstack-example/app/lib/auth.ts b/examples/tanstack-example/app/lib/auth.ts
new file mode 100644
index 0000000000..8cea4375eb
--- /dev/null
+++ b/examples/tanstack-example/app/lib/auth.ts
@@ -0,0 +1,23 @@
+import { twoFactor } from 'better-auth/plugins';
+import { betterAuth } from "better-auth";
+import Database from "better-sqlite3";
+
+export const auth = betterAuth({
+ database: new Database("data.db"),
+ emailAndPassword: {
+ enabled: true,
+ },
+ socialProviders: {
+ discord: {
+ enabled: true,
+ clientId: process.env.DISCORD_CLIENT_ID!,
+ clientSecret: process.env.DISCORD_CLIENT_SECRET!,
+ },
+ github: {
+ enabled: true,
+ clientId: process.env.GITHUB_CLIENT_ID!,
+ clientSecret: process.env.GITHUB_CLIENT_SECRET!,
+ },
+ },
+ plugins: [twoFactor()]
+});
diff --git a/examples/tanstack-example/app/lib/client/auth.ts b/examples/tanstack-example/app/lib/client/auth.ts
deleted file mode 100644
index 46ff103613..0000000000
--- a/examples/tanstack-example/app/lib/client/auth.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { createAuthClient } from "better-auth/react";
-
-export const { useSession, signIn, signOut, signUp } = createAuthClient({
- baseURL: "http://localhost:3000",
-});
diff --git a/examples/tanstack-example/app/lib/icons/X.tsx b/examples/tanstack-example/app/lib/icons/X.tsx
new file mode 100644
index 0000000000..f3ba2a487c
--- /dev/null
+++ b/examples/tanstack-example/app/lib/icons/X.tsx
@@ -0,0 +1,4 @@
+import { X } from 'lucide-react-native';
+import { iconWithClassName } from './iconWithClassName';
+iconWithClassName(X);
+export { X };
\ No newline at end of file
diff --git a/examples/tanstack-example/app/lib/icons/iconWithClassName.ts b/examples/tanstack-example/app/lib/icons/iconWithClassName.ts
new file mode 100644
index 0000000000..aec4575d5e
--- /dev/null
+++ b/examples/tanstack-example/app/lib/icons/iconWithClassName.ts
@@ -0,0 +1,14 @@
+import type { LucideIcon } from 'lucide-react-native';
+import { cssInterop } from 'nativewind';
+
+export function iconWithClassName(icon: LucideIcon) {
+cssInterop(icon, {
+ className: {
+ target: 'style',
+ nativeStyleToProp: {
+ color: true,
+ opacity: true,
+ },
+ },
+});
+}
\ No newline at end of file
diff --git a/examples/tanstack-example/app/lib/server/auth.ts b/examples/tanstack-example/app/lib/server/auth.ts
deleted file mode 100644
index f546bdd3c1..0000000000
--- a/examples/tanstack-example/app/lib/server/auth.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { betterAuth } from "better-auth";
-import Database from "better-sqlite3";
-
-export const auth = betterAuth({
- database: new Database("data.db"),
- emailAndPassword: {
- enabled: true,
- },
-});
diff --git a/examples/tanstack-example/app/routeTree.gen.ts b/examples/tanstack-example/app/routeTree.gen.ts
index bf4275411e..f7087562cf 100644
--- a/examples/tanstack-example/app/routeTree.gen.ts
+++ b/examples/tanstack-example/app/routeTree.gen.ts
@@ -12,6 +12,7 @@
import { Route as rootRoute } from './routes/__root'
import { Route as IndexImport } from './routes/index'
+import { Route as AuthTwoFactorImport } from './routes/auth/two-factor'
import { Route as AuthSignupImport } from './routes/auth/signup'
import { Route as AuthSigninImport } from './routes/auth/signin'
@@ -23,6 +24,12 @@ const IndexRoute = IndexImport.update({
getParentRoute: () => rootRoute,
} as any)
+const AuthTwoFactorRoute = AuthTwoFactorImport.update({
+ id: '/auth/two-factor',
+ path: '/auth/two-factor',
+ getParentRoute: () => rootRoute,
+} as any)
+
const AuthSignupRoute = AuthSignupImport.update({
id: '/auth/signup',
path: '/auth/signup',
@@ -60,6 +67,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AuthSignupImport
parentRoute: typeof rootRoute
}
+ '/auth/two-factor': {
+ id: '/auth/two-factor'
+ path: '/auth/two-factor'
+ fullPath: '/auth/two-factor'
+ preLoaderRoute: typeof AuthTwoFactorImport
+ parentRoute: typeof rootRoute
+ }
}
}
@@ -69,12 +83,14 @@ export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/auth/signin': typeof AuthSigninRoute
'/auth/signup': typeof AuthSignupRoute
+ '/auth/two-factor': typeof AuthTwoFactorRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
'/auth/signin': typeof AuthSigninRoute
'/auth/signup': typeof AuthSignupRoute
+ '/auth/two-factor': typeof AuthTwoFactorRoute
}
export interface FileRoutesById {
@@ -82,14 +98,15 @@ export interface FileRoutesById {
'/': typeof IndexRoute
'/auth/signin': typeof AuthSigninRoute
'/auth/signup': typeof AuthSignupRoute
+ '/auth/two-factor': typeof AuthTwoFactorRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
- fullPaths: '/' | '/auth/signin' | '/auth/signup'
+ fullPaths: '/' | '/auth/signin' | '/auth/signup' | '/auth/two-factor'
fileRoutesByTo: FileRoutesByTo
- to: '/' | '/auth/signin' | '/auth/signup'
- id: '__root__' | '/' | '/auth/signin' | '/auth/signup'
+ to: '/' | '/auth/signin' | '/auth/signup' | '/auth/two-factor'
+ id: '__root__' | '/' | '/auth/signin' | '/auth/signup' | '/auth/two-factor'
fileRoutesById: FileRoutesById
}
@@ -97,12 +114,14 @@ export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
AuthSigninRoute: typeof AuthSigninRoute
AuthSignupRoute: typeof AuthSignupRoute
+ AuthTwoFactorRoute: typeof AuthTwoFactorRoute
}
const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
AuthSigninRoute: AuthSigninRoute,
AuthSignupRoute: AuthSignupRoute,
+ AuthTwoFactorRoute: AuthTwoFactorRoute,
}
export const routeTree = rootRoute
@@ -119,7 +138,8 @@ export const routeTree = rootRoute
"children": [
"/",
"/auth/signin",
- "/auth/signup"
+ "/auth/signup",
+ "/auth/two-factor"
]
},
"/": {
@@ -130,6 +150,9 @@ export const routeTree = rootRoute
},
"/auth/signup": {
"filePath": "auth/signup.tsx"
+ },
+ "/auth/two-factor": {
+ "filePath": "auth/two-factor.tsx"
}
}
}
diff --git a/examples/tanstack-example/app/routes/__root.tsx b/examples/tanstack-example/app/routes/__root.tsx
index 7d6076f2c0..8012349668 100644
--- a/examples/tanstack-example/app/routes/__root.tsx
+++ b/examples/tanstack-example/app/routes/__root.tsx
@@ -3,7 +3,7 @@ import { Outlet, ScrollRestoration } from "@tanstack/react-router";
import { Body, Head, Html, Meta, Scripts } from "@tanstack/start";
import type * as React from "react";
import { useEffect, useState } from "react";
-import { signOut, useSession } from "~/lib/client/auth";
+import { signOut, useSession } from "~/lib/auth-client";
import globalStylesheet from "~/lib/style/global.css?url";
import "~/lib/style/global.css";
import { DoorOpen, LoaderCircle, Moon, Sun } from "lucide-react";
@@ -42,9 +42,9 @@ export const Route = createRootRoute({
function RootComponent() {
const [theme, setTheme] = useState<"light" | "dark">("light");
- const [loading, setLoading] = useState(true);
- const { data, isPending } = useSession();
+ const { data, isPending, error } = useSession();
const { navigate } = useRouter();
+ console.log()
useEffect(() => {
if (!data?.user) {
@@ -61,11 +61,6 @@ function RootComponent() {
);
}, [data, navigate]);
- useEffect(() => {
- if (!isPending) {
- setLoading(false);
- }
- }, [isPending]);
useEffect(() => {
const root = window.document.documentElement;
@@ -77,12 +72,7 @@ function RootComponent() {
return (
- {loading ? (
-
-
-
- ) : (
- <>
+ <>