From 99bd88194c7794574776e22700f43542761e85d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Hertault?= Date: Sat, 10 Jan 2026 14:54:55 +0100 Subject: [PATCH 1/5] examples: add tanstack start with better auth example --- .../start-basic-better-auth/.env.example | 9 ++ .../react/start-basic-better-auth/.gitignore | 6 + .../react/start-basic-better-auth/README.md | 66 +++++++++ .../start-basic-better-auth/package.json | 32 +++++ .../src/components/DefaultCatchBoundary.tsx | 53 ++++++++ .../src/components/NotFound.tsx | 25 ++++ .../src/routeTree.gen.ts | 122 +++++++++++++++++ .../start-basic-better-auth/src/router.tsx | 19 +++ .../src/routes/__root.tsx | 125 ++++++++++++++++++ .../src/routes/api/auth/$.ts | 15 +++ .../src/routes/index.tsx | 50 +++++++ .../src/routes/login.tsx | 43 ++++++ .../src/routes/protected.tsx | 55 ++++++++ .../src/styles/app.css | 1 + .../src/utils/auth-client.ts | 3 + .../start-basic-better-auth/src/utils/auth.ts | 28 ++++ .../start-basic-better-auth/tsconfig.json | 24 ++++ .../start-basic-better-auth/vite.config.ts | 20 +++ 18 files changed, 696 insertions(+) create mode 100644 examples/react/start-basic-better-auth/.env.example create mode 100644 examples/react/start-basic-better-auth/.gitignore create mode 100644 examples/react/start-basic-better-auth/README.md create mode 100644 examples/react/start-basic-better-auth/package.json create mode 100644 examples/react/start-basic-better-auth/src/components/DefaultCatchBoundary.tsx create mode 100644 examples/react/start-basic-better-auth/src/components/NotFound.tsx create mode 100644 examples/react/start-basic-better-auth/src/routeTree.gen.ts create mode 100644 examples/react/start-basic-better-auth/src/router.tsx create mode 100644 examples/react/start-basic-better-auth/src/routes/__root.tsx create mode 100644 examples/react/start-basic-better-auth/src/routes/api/auth/$.ts create mode 100644 examples/react/start-basic-better-auth/src/routes/index.tsx create mode 100644 examples/react/start-basic-better-auth/src/routes/login.tsx create mode 100644 examples/react/start-basic-better-auth/src/routes/protected.tsx create mode 100644 examples/react/start-basic-better-auth/src/styles/app.css create mode 100644 examples/react/start-basic-better-auth/src/utils/auth-client.ts create mode 100644 examples/react/start-basic-better-auth/src/utils/auth.ts create mode 100644 examples/react/start-basic-better-auth/tsconfig.json create mode 100644 examples/react/start-basic-better-auth/vite.config.ts diff --git a/examples/react/start-basic-better-auth/.env.example b/examples/react/start-basic-better-auth/.env.example new file mode 100644 index 0000000000..6fb0f1821f --- /dev/null +++ b/examples/react/start-basic-better-auth/.env.example @@ -0,0 +1,9 @@ +# Better Auth Configuration +BETTER_AUTH_SECRET=your-secret-key-here-min-32-chars-long + +# Better Auth URL (base URL, no /api/auth suffix) +BETTER_AUTH_URL=http://localhost:10000 + +# GitHub OAuth Configuration (https://github.com/settings/developers) +GITHUB_CLIENT_ID=your-github-client-id +GITHUB_CLIENT_SECRET=your-github-client-secret diff --git a/examples/react/start-basic-better-auth/.gitignore b/examples/react/start-basic-better-auth/.gitignore new file mode 100644 index 0000000000..3479e16707 --- /dev/null +++ b/examples/react/start-basic-better-auth/.gitignore @@ -0,0 +1,6 @@ +node_modules +dist +.env +*.local +.DS_Store +.tanstack diff --git a/examples/react/start-basic-better-auth/README.md b/examples/react/start-basic-better-auth/README.md new file mode 100644 index 0000000000..fc15980da7 --- /dev/null +++ b/examples/react/start-basic-better-auth/README.md @@ -0,0 +1,66 @@ +# TanStack Start - Better Auth Example + +A TanStack Start example demonstrating authentication with Better Auth. + +- [TanStack Router Docs](https://tanstack.com/router) +- [Better Auth Documentation](https://www.better-auth.com/) + +## Start a new project based on this example + +To start a new project based on this example, run: + +```sh +npx gitpick TanStack/router/tree/main/examples/react/start-basic-better-auth start-basic-better-auth +``` + +## Setup + +This example requires environment variables for Better Auth configuration. Copy the `.env.example` file to `.env` and fill in your GitHub OAuth credentials: + +```sh +cp .env.example .env +``` + +### GitHub OAuth Setup + +1. Go to [GitHub Developer Settings](https://github.com/settings/developers) +2. Click "New OAuth App" +3. Fill in: + - Application name: Your app name + - Homepage URL: `http://localhost:10000` + - Authorization callback URL: `http://localhost:10000/api/auth/callback/github` +4. Copy the Client ID and Client Secret to your `.env` file + +## Getting Started + +From your terminal: + +```sh +pnpm install +pnpm dev +``` + +This starts your app in development mode, rebuilding assets on file changes. + +## Build + +To build the app for production: + +```sh +pnpm build +``` + +## Authentication Configuration + +This example demonstrates how to integrate Better Auth with TanStack Start. Check the source code for examples of: + +- Configuring social authentication providers +- Protecting routes with authentication +- Accessing session data in server functions + +### Key Files + +- `src/utils/auth.ts` - Better Auth server configuration +- `src/utils/auth-client.ts` - Better Auth client setup +- `src/routes/__root.tsx` - Session fetching and navigation +- `src/routes/protected.tsx` - Example of a protected route diff --git a/examples/react/start-basic-better-auth/package.json b/examples/react/start-basic-better-auth/package.json new file mode 100644 index 0000000000..eec836df46 --- /dev/null +++ b/examples/react/start-basic-better-auth/package.json @@ -0,0 +1,32 @@ +{ + "name": "tanstack-start-example-basic-better-auth", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview", + "start": "pnpx srvx --prod -s ../client dist/server/server.js" + }, + "dependencies": { + "@tanstack/react-router": "^1.147.0", + "@tanstack/react-router-devtools": "^1.147.0", + "@tanstack/react-start": "^1.147.0", + "better-auth": "^1.4.10", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tailwind-merge": "^2.6.0" + }, + "devDependencies": { + "@tailwindcss/vite": "^4.1.18", + "@types/node": "^22.5.4", + "@types/react": "^19.0.8", + "@types/react-dom": "^19.0.3", + "@vitejs/plugin-react": "^4.6.0", + "tailwindcss": "^4.1.18", + "typescript": "^5.7.2", + "vite": "^7.1.7", + "vite-tsconfig-paths": "^5.1.4" + } +} diff --git a/examples/react/start-basic-better-auth/src/components/DefaultCatchBoundary.tsx b/examples/react/start-basic-better-auth/src/components/DefaultCatchBoundary.tsx new file mode 100644 index 0000000000..2b0e48c6c8 --- /dev/null +++ b/examples/react/start-basic-better-auth/src/components/DefaultCatchBoundary.tsx @@ -0,0 +1,53 @@ +import { + ErrorComponent, + Link, + rootRouteId, + useMatch, + useRouter, +} from "@tanstack/react-router"; +import type { ErrorComponentProps } from "@tanstack/react-router"; + +export function DefaultCatchBoundary({ error }: ErrorComponentProps) { + const router = useRouter(); + const isRoot = useMatch({ + strict: false, + select: (state) => state.id === rootRouteId, + }); + + console.error("DefaultCatchBoundary Error:", error); + + return ( +
+ +
+ + {isRoot ? ( + + Home + + ) : ( + { + e.preventDefault(); + window.history.back(); + }} + > + Go Back + + )} +
+
+ ); +} diff --git a/examples/react/start-basic-better-auth/src/components/NotFound.tsx b/examples/react/start-basic-better-auth/src/components/NotFound.tsx new file mode 100644 index 0000000000..f22fabddca --- /dev/null +++ b/examples/react/start-basic-better-auth/src/components/NotFound.tsx @@ -0,0 +1,25 @@ +import { Link } from "@tanstack/react-router"; + +export function NotFound({ children }: { children?: any }) { + return ( +
+
+ {children ||

The page you are looking for does not exist.

} +
+

+ + + Start Over + +

+
+ ); +} diff --git a/examples/react/start-basic-better-auth/src/routeTree.gen.ts b/examples/react/start-basic-better-auth/src/routeTree.gen.ts new file mode 100644 index 0000000000..2f59e4ba33 --- /dev/null +++ b/examples/react/start-basic-better-auth/src/routeTree.gen.ts @@ -0,0 +1,122 @@ +/* eslint-disable */ + +// @ts-nocheck + +// noinspection JSUnusedGlobalSymbols + +// This file was automatically generated by TanStack Router. +// You should NOT make any changes in this file as it will be overwritten. +// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. + +import { Route as rootRouteImport } from './routes/__root' +import { Route as ProtectedRouteImport } from './routes/protected' +import { Route as LoginRouteImport } from './routes/login' +import { Route as IndexRouteImport } from './routes/index' +import { Route as ApiAuthSplatRouteImport } from './routes/api/auth/$' + +const ProtectedRoute = ProtectedRouteImport.update({ + id: '/protected', + path: '/protected', + getParentRoute: () => rootRouteImport, +} as any) +const LoginRoute = LoginRouteImport.update({ + id: '/login', + path: '/login', + getParentRoute: () => rootRouteImport, +} as any) +const IndexRoute = IndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => rootRouteImport, +} as any) +const ApiAuthSplatRoute = ApiAuthSplatRouteImport.update({ + id: '/api/auth/$', + path: '/api/auth/$', + getParentRoute: () => rootRouteImport, +} as any) + +export interface FileRoutesByFullPath { + '/': typeof IndexRoute + '/login': typeof LoginRoute + '/protected': typeof ProtectedRoute + '/api/auth/$': typeof ApiAuthSplatRoute +} +export interface FileRoutesByTo { + '/': typeof IndexRoute + '/login': typeof LoginRoute + '/protected': typeof ProtectedRoute + '/api/auth/$': typeof ApiAuthSplatRoute +} +export interface FileRoutesById { + __root__: typeof rootRouteImport + '/': typeof IndexRoute + '/login': typeof LoginRoute + '/protected': typeof ProtectedRoute + '/api/auth/$': typeof ApiAuthSplatRoute +} +export interface FileRouteTypes { + fileRoutesByFullPath: FileRoutesByFullPath + fullPaths: '/' | '/login' | '/protected' | '/api/auth/$' + fileRoutesByTo: FileRoutesByTo + to: '/' | '/login' | '/protected' | '/api/auth/$' + id: '__root__' | '/' | '/login' | '/protected' | '/api/auth/$' + fileRoutesById: FileRoutesById +} +export interface RootRouteChildren { + IndexRoute: typeof IndexRoute + LoginRoute: typeof LoginRoute + ProtectedRoute: typeof ProtectedRoute + ApiAuthSplatRoute: typeof ApiAuthSplatRoute +} + +declare module '@tanstack/react-router' { + interface FileRoutesByPath { + '/protected': { + id: '/protected' + path: '/protected' + fullPath: '/protected' + preLoaderRoute: typeof ProtectedRouteImport + parentRoute: typeof rootRouteImport + } + '/login': { + id: '/login' + path: '/login' + fullPath: '/login' + preLoaderRoute: typeof LoginRouteImport + parentRoute: typeof rootRouteImport + } + '/': { + id: '/' + path: '/' + fullPath: '/' + preLoaderRoute: typeof IndexRouteImport + parentRoute: typeof rootRouteImport + } + '/api/auth/$': { + id: '/api/auth/$' + path: '/api/auth/$' + fullPath: '/api/auth/$' + preLoaderRoute: typeof ApiAuthSplatRouteImport + parentRoute: typeof rootRouteImport + } + } +} + +const rootRouteChildren: RootRouteChildren = { + IndexRoute: IndexRoute, + LoginRoute: LoginRoute, + ProtectedRoute: ProtectedRoute, + ApiAuthSplatRoute: ApiAuthSplatRoute, +} +export const routeTree = rootRouteImport + ._addFileChildren(rootRouteChildren) + ._addFileTypes() + +import type { getRouter } from './router.tsx' +import type { createStart } from '@tanstack/react-start' +declare module '@tanstack/react-start' { + interface Register { + ssr: true + router: Awaited> + } +} diff --git a/examples/react/start-basic-better-auth/src/router.tsx b/examples/react/start-basic-better-auth/src/router.tsx new file mode 100644 index 0000000000..338900bf6f --- /dev/null +++ b/examples/react/start-basic-better-auth/src/router.tsx @@ -0,0 +1,19 @@ +import { createRouter } from "@tanstack/react-router"; +import { routeTree } from "./routeTree.gen"; +import { DefaultCatchBoundary } from "./components/DefaultCatchBoundary"; +import { NotFound } from "./components/NotFound"; +import type { RouterContext } from "./routes/__root"; + +export function getRouter() { + const router = createRouter({ + routeTree, + defaultPreload: "intent", + defaultErrorComponent: DefaultCatchBoundary, + defaultNotFoundComponent: () => , + scrollRestoration: true, + context: { + session: null, + } satisfies RouterContext, + }); + return router; +} diff --git a/examples/react/start-basic-better-auth/src/routes/__root.tsx b/examples/react/start-basic-better-auth/src/routes/__root.tsx new file mode 100644 index 0000000000..ff38c30e0c --- /dev/null +++ b/examples/react/start-basic-better-auth/src/routes/__root.tsx @@ -0,0 +1,125 @@ +/// +import type { ReactNode } from "react"; +import { + HeadContent, + Link, + Outlet, + Scripts, + createRootRouteWithContext, + useRouter, +} from "@tanstack/react-router"; +import { TanStackRouterDevtools } from "@tanstack/react-router-devtools"; +import { createServerFn } from "@tanstack/react-start"; +import { getRequestHeaders } from "@tanstack/react-start/server"; +import { auth, type AuthSession } from "~/utils/auth"; +import { authClient } from "~/utils/auth-client"; +import appCss from "~/styles/app.css?url"; + +export interface RouterContext { + session: AuthSession | null; +} + +const fetchSession = createServerFn({ method: "GET" }).handler(async () => { + const headers = getRequestHeaders(); + const session = await auth.api.getSession({ headers }); + return session; +}); + +export const Route = createRootRouteWithContext()({ + beforeLoad: async () => { + const session = await fetchSession(); + return { + session, + }; + }, + head: () => ({ + meta: [ + { + charSet: "utf-8", + }, + { + name: "viewport", + content: "width=device-width, initial-scale=1", + }, + { + title: "TanStack Start Auth Example", + }, + ], + links: [{ rel: "stylesheet", href: appCss }], + }), + component: RootComponent, +}); + +function RootComponent() { + return ( + + + + ); +} + +function RootDocument({ children }: { children: ReactNode }) { + return ( + + + + + + +
{children}
+ + + + + ); +} + +function NavBar() { + const router = useRouter(); + const routeContext = Route.useRouteContext(); + + const handleSignOut = async () => { + await authClient.signOut(); + await router.invalidate(); + await router.navigate({ to: "/" }); + }; + + return ( + + ); +} diff --git a/examples/react/start-basic-better-auth/src/routes/api/auth/$.ts b/examples/react/start-basic-better-auth/src/routes/api/auth/$.ts new file mode 100644 index 0000000000..79a36b6164 --- /dev/null +++ b/examples/react/start-basic-better-auth/src/routes/api/auth/$.ts @@ -0,0 +1,15 @@ +import { createFileRoute } from "@tanstack/react-router"; +import { auth } from "~/utils/auth"; + +/** + * Better Auth API route handler + * Handles all auth routes: /api/auth/* + */ +export const Route = createFileRoute("/api/auth/$")({ + server: { + handlers: { + GET: ({ request }) => auth.handler(request), + POST: ({ request }) => auth.handler(request), + }, + }, +}); diff --git a/examples/react/start-basic-better-auth/src/routes/index.tsx b/examples/react/start-basic-better-auth/src/routes/index.tsx new file mode 100644 index 0000000000..afc0c137f2 --- /dev/null +++ b/examples/react/start-basic-better-auth/src/routes/index.tsx @@ -0,0 +1,50 @@ +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/")({ + component: Home, +}); + +function Home() { + const { session } = Route.useRouteContext(); + const user = session?.user; + + return ( +
+

+ TanStack Start Better Auth Example +

+

+ This example demonstrates Better Auth integration with TanStack Start + using GitHub OAuth. +

+ +
+

Auth Status

+ + {session ? ( +
+

Authenticated

+ {user?.image && ( + Avatar + )} +

+ Name: {user?.name ?? "N/A"} +

+

+ Email: {user?.email ?? "N/A"} +

+
+ ) : ( +

+ You are not signed in. Click "Sign In" in the navigation bar to + authenticate with GitHub. +

+ )} +
+
+ ); +} diff --git a/examples/react/start-basic-better-auth/src/routes/login.tsx b/examples/react/start-basic-better-auth/src/routes/login.tsx new file mode 100644 index 0000000000..9f67a0bd78 --- /dev/null +++ b/examples/react/start-basic-better-auth/src/routes/login.tsx @@ -0,0 +1,43 @@ +import { createFileRoute, redirect } from "@tanstack/react-router"; +import { authClient } from "~/utils/auth-client"; + +export const Route = createFileRoute("/login")({ + beforeLoad: ({ context }) => { + if (context.session) { + throw redirect({ to: "/" }); + } + }, + component: Login, +}); + +function Login() { + const handleGitHubSignIn = () => { + authClient.signIn.social({ + provider: "github", + callbackURL: "/", + }); + }; + + return ( +
+

Sign In

+ +
+ + +

+ You'll be redirected to GitHub to complete the sign-in process. +

+
+
+ ); +} diff --git a/examples/react/start-basic-better-auth/src/routes/protected.tsx b/examples/react/start-basic-better-auth/src/routes/protected.tsx new file mode 100644 index 0000000000..05e8ebd83c --- /dev/null +++ b/examples/react/start-basic-better-auth/src/routes/protected.tsx @@ -0,0 +1,55 @@ +import { createFileRoute, redirect } from "@tanstack/react-router"; + +export const Route = createFileRoute("/protected")({ + beforeLoad: ({ context }) => { + if (!context.session) { + throw redirect({ to: "/login" }); + } + }, + component: Protected, +}); + +function Protected() { + const { session } = Route.useRouteContext(); + const user = session?.user; + + return ( +
+

Protected Page

+

+ This page is only accessible to authenticated users. +

+ +
+

+ Welcome, {user?.name ?? "User"}! +

+ + {user && ( +
+

+ Email: {user?.email ?? "N/A"} +

+ {user?.image && ( +
+ Avatar: + User avatar +
+ )} +
+ )} +
+ +
+

Session Data (Debug)

+
+          {JSON.stringify(session, null, 2)}
+        
+
+
+ ); +} diff --git a/examples/react/start-basic-better-auth/src/styles/app.css b/examples/react/start-basic-better-auth/src/styles/app.css new file mode 100644 index 0000000000..f1d8c73cdc --- /dev/null +++ b/examples/react/start-basic-better-auth/src/styles/app.css @@ -0,0 +1 @@ +@import "tailwindcss"; diff --git a/examples/react/start-basic-better-auth/src/utils/auth-client.ts b/examples/react/start-basic-better-auth/src/utils/auth-client.ts new file mode 100644 index 0000000000..f1012dd4ac --- /dev/null +++ b/examples/react/start-basic-better-auth/src/utils/auth-client.ts @@ -0,0 +1,3 @@ +import { createAuthClient } from "better-auth/react"; + +export const authClient = createAuthClient(); diff --git a/examples/react/start-basic-better-auth/src/utils/auth.ts b/examples/react/start-basic-better-auth/src/utils/auth.ts new file mode 100644 index 0000000000..05cf771468 --- /dev/null +++ b/examples/react/start-basic-better-auth/src/utils/auth.ts @@ -0,0 +1,28 @@ +import { betterAuth } from "better-auth"; +import { tanstackStartCookies } from "better-auth/tanstack-start"; + +/** + * Better Auth configuration for TanStack Start with GitHub + */ +export const auth = betterAuth({ + socialProviders: { + github: { + clientId: process.env.GITHUB_CLIENT_ID!, + clientSecret: process.env.GITHUB_CLIENT_SECRET!, + }, + }, + plugins: [ + // Must be last plugin in the array + tanstackStartCookies(), + ], + // Stateless sessions (no database required) + session: { + cookieCache: { + enabled: true, + maxAge: 60 * 60 * 24 * 7, + }, + }, +}); + +// Export session type for use in router context +export type AuthSession = typeof auth.$Infer.Session; diff --git a/examples/react/start-basic-better-auth/tsconfig.json b/examples/react/start-basic-better-auth/tsconfig.json new file mode 100644 index 0000000000..70cbbc5ce3 --- /dev/null +++ b/examples/react/start-basic-better-auth/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "allowSyntheticDefaultImports": true, + "baseUrl": ".", + "paths": { + "~/*": ["./src/*"] + } + }, + "include": ["src", "env.d.ts", "vite.config.ts"] +} diff --git a/examples/react/start-basic-better-auth/vite.config.ts b/examples/react/start-basic-better-auth/vite.config.ts new file mode 100644 index 0000000000..3a326e95cf --- /dev/null +++ b/examples/react/start-basic-better-auth/vite.config.ts @@ -0,0 +1,20 @@ +import { tanstackStart } from "@tanstack/react-start/plugin/vite"; +import { defineConfig } from "vite"; +import tsConfigPaths from "vite-tsconfig-paths"; +import viteReact from "@vitejs/plugin-react"; +import tailwindcss from "@tailwindcss/vite"; + +export default defineConfig({ + server: { + port: 10000, + strictPort: true, + }, + plugins: [ + tailwindcss(), + tsConfigPaths({ + projects: ["./tsconfig.json"], + }), + tanstackStart(), + viteReact(), + ], +}); From 1a90dfecd286b414611a39170683ffac8fc937b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Hertault?= Date: Sat, 11 Jul 2026 11:29:58 +0200 Subject: [PATCH 2/5] examples: align start-basic-better-auth with repo conventions and address review feedback - Bump internal @tanstack/* and tooling deps to match sibling examples (drop stale ^1.147.0) - Remove unused tailwind-merge and switch to Vite's resolve.tsconfigPaths (drop vite-tsconfig-paths) - auth: add baseURL + trustedOrigins for OAuth/CSRF; validate GitHub env vars instead of non-null assertions - protected: redact debug session output to avoid leaking tokens - root: add error handling to sign-out flow - NotFound: type children as ReactNode instead of any - tsconfig: fix include (drop non-existent env.d.ts) - Format all files with Prettier (single quotes, no semicolons) --- .../start-basic-better-auth/.env.example | 1 + .../start-basic-better-auth/package.json | 20 +++-- .../src/components/DefaultCatchBoundary.tsx | 18 ++--- .../src/components/NotFound.tsx | 7 +- .../start-basic-better-auth/src/router.tsx | 16 ++-- .../src/routes/__root.tsx | 75 ++++++++++--------- .../src/routes/api/auth/$.ts | 8 +- .../src/routes/index.tsx | 16 ++-- .../src/routes/login.tsx | 20 ++--- .../src/routes/protected.tsx | 29 ++++--- .../src/utils/auth-client.ts | 4 +- .../start-basic-better-auth/src/utils/auth.ts | 27 +++++-- .../start-basic-better-auth/tsconfig.json | 2 +- .../start-basic-better-auth/vite.config.ts | 23 +++--- 14 files changed, 145 insertions(+), 121 deletions(-) diff --git a/examples/react/start-basic-better-auth/.env.example b/examples/react/start-basic-better-auth/.env.example index 6fb0f1821f..17c68d690a 100644 --- a/examples/react/start-basic-better-auth/.env.example +++ b/examples/react/start-basic-better-auth/.env.example @@ -1,4 +1,5 @@ # Better Auth Configuration +# Generate a secure secret with: openssl rand -base64 32 BETTER_AUTH_SECRET=your-secret-key-here-min-32-chars-long # Better Auth URL (base URL, no /api/auth suffix) diff --git a/examples/react/start-basic-better-auth/package.json b/examples/react/start-basic-better-auth/package.json index eec836df46..0e6470084e 100644 --- a/examples/react/start-basic-better-auth/package.json +++ b/examples/react/start-basic-better-auth/package.json @@ -10,23 +10,21 @@ "start": "pnpx srvx --prod -s ../client dist/server/server.js" }, "dependencies": { - "@tanstack/react-router": "^1.147.0", - "@tanstack/react-router-devtools": "^1.147.0", - "@tanstack/react-start": "^1.147.0", + "@tanstack/react-router": "^1.170.17", + "@tanstack/react-router-devtools": "^1.167.0", + "@tanstack/react-start": "^1.168.27", "better-auth": "^1.4.10", "react": "^19.0.0", - "react-dom": "^19.0.0", - "tailwind-merge": "^2.6.0" + "react-dom": "^19.0.0" }, "devDependencies": { - "@tailwindcss/vite": "^4.1.18", + "@tailwindcss/vite": "^4.2.2", "@types/node": "^22.5.4", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", - "@vitejs/plugin-react": "^4.6.0", - "tailwindcss": "^4.1.18", - "typescript": "^5.7.2", - "vite": "^7.1.7", - "vite-tsconfig-paths": "^5.1.4" + "@vitejs/plugin-react": "^6.0.1", + "tailwindcss": "^4.2.2", + "typescript": "^6.0.2", + "vite": "^8.0.14" } } diff --git a/examples/react/start-basic-better-auth/src/components/DefaultCatchBoundary.tsx b/examples/react/start-basic-better-auth/src/components/DefaultCatchBoundary.tsx index 2b0e48c6c8..260c2ea41f 100644 --- a/examples/react/start-basic-better-auth/src/components/DefaultCatchBoundary.tsx +++ b/examples/react/start-basic-better-auth/src/components/DefaultCatchBoundary.tsx @@ -4,17 +4,17 @@ import { rootRouteId, useMatch, useRouter, -} from "@tanstack/react-router"; -import type { ErrorComponentProps } from "@tanstack/react-router"; +} from '@tanstack/react-router' +import type { ErrorComponentProps } from '@tanstack/react-router' export function DefaultCatchBoundary({ error }: ErrorComponentProps) { - const router = useRouter(); + const router = useRouter() const isRoot = useMatch({ strict: false, select: (state) => state.id === rootRouteId, - }); + }) - console.error("DefaultCatchBoundary Error:", error); + console.error('DefaultCatchBoundary Error:', error) return (
@@ -22,7 +22,7 @@ export function DefaultCatchBoundary({ error }: ErrorComponentProps) {
- ); + ) } diff --git a/examples/react/start-basic-better-auth/src/components/NotFound.tsx b/examples/react/start-basic-better-auth/src/components/NotFound.tsx index f22fabddca..8805751110 100644 --- a/examples/react/start-basic-better-auth/src/components/NotFound.tsx +++ b/examples/react/start-basic-better-auth/src/components/NotFound.tsx @@ -1,6 +1,7 @@ -import { Link } from "@tanstack/react-router"; +import type { ReactNode } from 'react' +import { Link } from '@tanstack/react-router' -export function NotFound({ children }: { children?: any }) { +export function NotFound({ children }: { children?: ReactNode }) { return (
@@ -21,5 +22,5 @@ export function NotFound({ children }: { children?: any }) {

- ); + ) } diff --git a/examples/react/start-basic-better-auth/src/router.tsx b/examples/react/start-basic-better-auth/src/router.tsx index 338900bf6f..8490d717b6 100644 --- a/examples/react/start-basic-better-auth/src/router.tsx +++ b/examples/react/start-basic-better-auth/src/router.tsx @@ -1,19 +1,19 @@ -import { createRouter } from "@tanstack/react-router"; -import { routeTree } from "./routeTree.gen"; -import { DefaultCatchBoundary } from "./components/DefaultCatchBoundary"; -import { NotFound } from "./components/NotFound"; -import type { RouterContext } from "./routes/__root"; +import { createRouter } from '@tanstack/react-router' +import { routeTree } from './routeTree.gen' +import { DefaultCatchBoundary } from './components/DefaultCatchBoundary' +import { NotFound } from './components/NotFound' +import type { RouterContext } from './routes/__root' export function getRouter() { const router = createRouter({ routeTree, - defaultPreload: "intent", + defaultPreload: 'intent', defaultErrorComponent: DefaultCatchBoundary, defaultNotFoundComponent: () => , scrollRestoration: true, context: { session: null, } satisfies RouterContext, - }); - return router; + }) + return router } diff --git a/examples/react/start-basic-better-auth/src/routes/__root.tsx b/examples/react/start-basic-better-auth/src/routes/__root.tsx index ff38c30e0c..823a1bd822 100644 --- a/examples/react/start-basic-better-auth/src/routes/__root.tsx +++ b/examples/react/start-basic-better-auth/src/routes/__root.tsx @@ -1,5 +1,5 @@ /// -import type { ReactNode } from "react"; +import type { ReactNode } from 'react' import { HeadContent, Link, @@ -7,55 +7,55 @@ import { Scripts, createRootRouteWithContext, useRouter, -} from "@tanstack/react-router"; -import { TanStackRouterDevtools } from "@tanstack/react-router-devtools"; -import { createServerFn } from "@tanstack/react-start"; -import { getRequestHeaders } from "@tanstack/react-start/server"; -import { auth, type AuthSession } from "~/utils/auth"; -import { authClient } from "~/utils/auth-client"; -import appCss from "~/styles/app.css?url"; +} from '@tanstack/react-router' +import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' +import { createServerFn } from '@tanstack/react-start' +import { getRequestHeaders } from '@tanstack/react-start/server' +import { auth, type AuthSession } from '~/utils/auth' +import { authClient } from '~/utils/auth-client' +import appCss from '~/styles/app.css?url' export interface RouterContext { - session: AuthSession | null; + session: AuthSession | null } -const fetchSession = createServerFn({ method: "GET" }).handler(async () => { - const headers = getRequestHeaders(); - const session = await auth.api.getSession({ headers }); - return session; -}); +const fetchSession = createServerFn({ method: 'GET' }).handler(async () => { + const headers = getRequestHeaders() + const session = await auth.api.getSession({ headers }) + return session +}) export const Route = createRootRouteWithContext()({ beforeLoad: async () => { - const session = await fetchSession(); + const session = await fetchSession() return { session, - }; + } }, head: () => ({ meta: [ { - charSet: "utf-8", + charSet: 'utf-8', }, { - name: "viewport", - content: "width=device-width, initial-scale=1", + name: 'viewport', + content: 'width=device-width, initial-scale=1', }, { - title: "TanStack Start Auth Example", + title: 'TanStack Start Auth Example', }, ], - links: [{ rel: "stylesheet", href: appCss }], + links: [{ rel: 'stylesheet', href: appCss }], }), component: RootComponent, -}); +}) function RootComponent() { return ( - ); + ) } function RootDocument({ children }: { children: ReactNode }) { @@ -71,37 +71,42 @@ function RootDocument({ children }: { children: ReactNode }) { - ); + ) } function NavBar() { - const router = useRouter(); - const routeContext = Route.useRouteContext(); + const router = useRouter() + const routeContext = Route.useRouteContext() const handleSignOut = async () => { - await authClient.signOut(); - await router.invalidate(); - await router.navigate({ to: "/" }); - }; + try { + await authClient.signOut() + await router.navigate({ to: '/' }) + } catch (error) { + console.error('Sign out failed:', error) + } finally { + await router.invalidate() + } + } return ( - ); + ) } diff --git a/examples/react/start-basic-better-auth/src/routes/api/auth/$.ts b/examples/react/start-basic-better-auth/src/routes/api/auth/$.ts index 79a36b6164..440657cbbd 100644 --- a/examples/react/start-basic-better-auth/src/routes/api/auth/$.ts +++ b/examples/react/start-basic-better-auth/src/routes/api/auth/$.ts @@ -1,15 +1,15 @@ -import { createFileRoute } from "@tanstack/react-router"; -import { auth } from "~/utils/auth"; +import { createFileRoute } from '@tanstack/react-router' +import { auth } from '~/utils/auth' /** * Better Auth API route handler * Handles all auth routes: /api/auth/* */ -export const Route = createFileRoute("/api/auth/$")({ +export const Route = createFileRoute('/api/auth/$')({ server: { handlers: { GET: ({ request }) => auth.handler(request), POST: ({ request }) => auth.handler(request), }, }, -}); +}) diff --git a/examples/react/start-basic-better-auth/src/routes/index.tsx b/examples/react/start-basic-better-auth/src/routes/index.tsx index afc0c137f2..751559ba7c 100644 --- a/examples/react/start-basic-better-auth/src/routes/index.tsx +++ b/examples/react/start-basic-better-auth/src/routes/index.tsx @@ -1,12 +1,12 @@ -import { createFileRoute } from "@tanstack/react-router"; +import { createFileRoute } from '@tanstack/react-router' -export const Route = createFileRoute("/")({ +export const Route = createFileRoute('/')({ component: Home, -}); +}) function Home() { - const { session } = Route.useRouteContext(); - const user = session?.user; + const { session } = Route.useRouteContext() + const user = session?.user return (
@@ -32,10 +32,10 @@ function Home() { /> )}

- Name: {user?.name ?? "N/A"} + Name: {user?.name ?? 'N/A'}

- Email: {user?.email ?? "N/A"} + Email: {user?.email ?? 'N/A'}

) : ( @@ -46,5 +46,5 @@ function Home() { )}
- ); + ) } diff --git a/examples/react/start-basic-better-auth/src/routes/login.tsx b/examples/react/start-basic-better-auth/src/routes/login.tsx index 9f67a0bd78..78a839fb72 100644 --- a/examples/react/start-basic-better-auth/src/routes/login.tsx +++ b/examples/react/start-basic-better-auth/src/routes/login.tsx @@ -1,22 +1,22 @@ -import { createFileRoute, redirect } from "@tanstack/react-router"; -import { authClient } from "~/utils/auth-client"; +import { createFileRoute, redirect } from '@tanstack/react-router' +import { authClient } from '~/utils/auth-client' -export const Route = createFileRoute("/login")({ +export const Route = createFileRoute('/login')({ beforeLoad: ({ context }) => { if (context.session) { - throw redirect({ to: "/" }); + throw redirect({ to: '/' }) } }, component: Login, -}); +}) function Login() { const handleGitHubSignIn = () => { authClient.signIn.social({ - provider: "github", - callbackURL: "/", - }); - }; + provider: 'github', + callbackURL: '/', + }) + } return (
@@ -39,5 +39,5 @@ function Login() {

- ); + ) } diff --git a/examples/react/start-basic-better-auth/src/routes/protected.tsx b/examples/react/start-basic-better-auth/src/routes/protected.tsx index 05e8ebd83c..61126f67d5 100644 --- a/examples/react/start-basic-better-auth/src/routes/protected.tsx +++ b/examples/react/start-basic-better-auth/src/routes/protected.tsx @@ -1,17 +1,17 @@ -import { createFileRoute, redirect } from "@tanstack/react-router"; +import { createFileRoute, redirect } from '@tanstack/react-router' -export const Route = createFileRoute("/protected")({ +export const Route = createFileRoute('/protected')({ beforeLoad: ({ context }) => { if (!context.session) { - throw redirect({ to: "/login" }); + throw redirect({ to: '/login' }) } }, component: Protected, -}); +}) function Protected() { - const { session } = Route.useRouteContext(); - const user = session?.user; + const { session } = Route.useRouteContext() + const user = session?.user return (
@@ -22,13 +22,13 @@ function Protected() {

- Welcome, {user?.name ?? "User"}! + Welcome, {user?.name ?? 'User'}!

{user && (

- Email: {user?.email ?? "N/A"} + Email: {user?.email ?? 'N/A'}

{user?.image && (
@@ -47,9 +47,18 @@ function Protected() {

Session Data (Debug)

-          {JSON.stringify(session, null, 2)}
+          {JSON.stringify(
+            {
+              user: {
+                name: user?.name,
+                email: user?.email,
+              },
+            },
+            null,
+            2,
+          )}
         
- ); + ) } diff --git a/examples/react/start-basic-better-auth/src/utils/auth-client.ts b/examples/react/start-basic-better-auth/src/utils/auth-client.ts index f1012dd4ac..fc6c795bfd 100644 --- a/examples/react/start-basic-better-auth/src/utils/auth-client.ts +++ b/examples/react/start-basic-better-auth/src/utils/auth-client.ts @@ -1,3 +1,3 @@ -import { createAuthClient } from "better-auth/react"; +import { createAuthClient } from 'better-auth/react' -export const authClient = createAuthClient(); +export const authClient = createAuthClient() diff --git a/examples/react/start-basic-better-auth/src/utils/auth.ts b/examples/react/start-basic-better-auth/src/utils/auth.ts index 05cf771468..79d65ec088 100644 --- a/examples/react/start-basic-better-auth/src/utils/auth.ts +++ b/examples/react/start-basic-better-auth/src/utils/auth.ts @@ -1,14 +1,29 @@ -import { betterAuth } from "better-auth"; -import { tanstackStartCookies } from "better-auth/tanstack-start"; +import { betterAuth } from 'better-auth' +import { tanstackStartCookies } from 'better-auth/tanstack-start' + +const clientId = process.env.GITHUB_CLIENT_ID +const clientSecret = process.env.GITHUB_CLIENT_SECRET + +if (!clientId || !clientSecret) { + console.warn( + 'Missing GITHUB_CLIENT_ID and/or GITHUB_CLIENT_SECRET environment variables. ' + + 'GitHub sign-in will not work until you copy .env.example to .env and fill in your GitHub OAuth credentials.', + ) +} /** * Better Auth configuration for TanStack Start with GitHub */ export const auth = betterAuth({ + // Base URL and trusted origins are required for OAuth callbacks and CSRF protection + baseURL: process.env.BETTER_AUTH_URL, + trustedOrigins: process.env.BETTER_AUTH_URL + ? [process.env.BETTER_AUTH_URL] + : [], socialProviders: { github: { - clientId: process.env.GITHUB_CLIENT_ID!, - clientSecret: process.env.GITHUB_CLIENT_SECRET!, + clientId: clientId ?? '', + clientSecret: clientSecret ?? '', }, }, plugins: [ @@ -22,7 +37,7 @@ export const auth = betterAuth({ maxAge: 60 * 60 * 24 * 7, }, }, -}); +}) // Export session type for use in router context -export type AuthSession = typeof auth.$Infer.Session; +export type AuthSession = typeof auth.$Infer.Session diff --git a/examples/react/start-basic-better-auth/tsconfig.json b/examples/react/start-basic-better-auth/tsconfig.json index 70cbbc5ce3..7bd5a41099 100644 --- a/examples/react/start-basic-better-auth/tsconfig.json +++ b/examples/react/start-basic-better-auth/tsconfig.json @@ -20,5 +20,5 @@ "~/*": ["./src/*"] } }, - "include": ["src", "env.d.ts", "vite.config.ts"] + "include": ["**/*.ts", "**/*.tsx", "**/*.d.ts"] } diff --git a/examples/react/start-basic-better-auth/vite.config.ts b/examples/react/start-basic-better-auth/vite.config.ts index 3a326e95cf..90f81aedf7 100644 --- a/examples/react/start-basic-better-auth/vite.config.ts +++ b/examples/react/start-basic-better-auth/vite.config.ts @@ -1,20 +1,15 @@ -import { tanstackStart } from "@tanstack/react-start/plugin/vite"; -import { defineConfig } from "vite"; -import tsConfigPaths from "vite-tsconfig-paths"; -import viteReact from "@vitejs/plugin-react"; -import tailwindcss from "@tailwindcss/vite"; +import { tanstackStart } from '@tanstack/react-start/plugin/vite' +import { defineConfig } from 'vite' +import viteReact from '@vitejs/plugin-react' +import tailwindcss from '@tailwindcss/vite' export default defineConfig({ server: { port: 10000, strictPort: true, }, - plugins: [ - tailwindcss(), - tsConfigPaths({ - projects: ["./tsconfig.json"], - }), - tanstackStart(), - viteReact(), - ], -}); + resolve: { + tsconfigPaths: true, + }, + plugins: [tailwindcss(), tanstackStart(), viteReact()], +}) From 5d1b4bf594b1570d86d22679748e84c407a8790e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Hertault?= Date: Sat, 11 Jul 2026 12:00:06 +0200 Subject: [PATCH 3/5] examples: bump better-auth to ^1.6.23 (latest stable) in start-basic-better-auth --- examples/react/start-basic-better-auth/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/react/start-basic-better-auth/package.json b/examples/react/start-basic-better-auth/package.json index 0e6470084e..92f96882fd 100644 --- a/examples/react/start-basic-better-auth/package.json +++ b/examples/react/start-basic-better-auth/package.json @@ -13,7 +13,7 @@ "@tanstack/react-router": "^1.170.17", "@tanstack/react-router-devtools": "^1.167.0", "@tanstack/react-start": "^1.168.27", - "better-auth": "^1.4.10", + "better-auth": "^1.6.23", "react": "^19.0.0", "react-dom": "^19.0.0" }, From 27a8c7ef2653ec90aa6a73fea90c116c938f3009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Hertault?= Date: Sat, 11 Jul 2026 12:19:52 +0200 Subject: [PATCH 4/5] examples: drop deprecated baseUrl from start-basic-better-auth tsconfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit baseUrl is deprecated in TS 6 (TS5101) and unnecessary — paths resolve relative to tsconfig. Matches sibling examples (start-basic, start-basic-authjs). --- examples/react/start-basic-better-auth/tsconfig.json | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/react/start-basic-better-auth/tsconfig.json b/examples/react/start-basic-better-auth/tsconfig.json index 7bd5a41099..e14d7324df 100644 --- a/examples/react/start-basic-better-auth/tsconfig.json +++ b/examples/react/start-basic-better-auth/tsconfig.json @@ -15,7 +15,6 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "allowSyntheticDefaultImports": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] } From 6a80b074f48e9e5a00eb1d66d69a59167f175589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Hertault?= Date: Sat, 11 Jul 2026 14:03:53 +0200 Subject: [PATCH 5/5] examples: add start-basic-better-auth to pnpm-lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the workspace importer entry and the better-auth@1.6.23 dependency subtree. Purely additive (279 insertions, 0 deletions) — no unrelated nightly/build-stack drift. Verified with a frozen-lockfile install and a successful example build. --- pnpm-lock.yaml | 279 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 279 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 96847b4044..88c06a7e29 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9195,6 +9195,52 @@ importers: specifier: ^8.0.14 version: 8.0.14(@types/node@25.0.9)(esbuild@0.27.4)(jiti@2.7.0)(sass@1.97.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.9.0) + examples/react/start-basic-better-auth: + dependencies: + '@tanstack/react-router': + specifier: workspace:* + version: link:../../../packages/react-router + '@tanstack/react-router-devtools': + specifier: workspace:^ + version: link:../../../packages/react-router-devtools + '@tanstack/react-start': + specifier: workspace:* + version: link:../../../packages/react-start + better-auth: + specifier: ^1.6.23 + version: 1.6.23(@prisma/client@7.0.0(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(typescript@6.0.2))(@tanstack/react-start@packages+react-start)(mysql2@3.15.3)(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.12)(vitest@4.1.4)(vue@3.5.25(typescript@6.0.2)) + react: + specifier: ^19.2.3 + version: 19.2.3 + react-dom: + specifier: ^19.2.3 + version: 19.2.3(react@19.2.3) + devDependencies: + '@tailwindcss/vite': + specifier: ^4.2.2 + version: 4.2.2(vite@8.0.14(@types/node@25.0.9)(esbuild@0.27.4)(jiti@2.7.0)(sass@1.97.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.9.0)) + '@types/node': + specifier: 25.0.9 + version: 25.0.9 + '@types/react': + specifier: ^19.2.8 + version: 19.2.9 + '@types/react-dom': + specifier: ^19.2.3 + version: 19.2.3(@types/react@19.2.9) + '@vitejs/plugin-react': + specifier: ^6.0.1 + version: 6.0.1(vite@8.0.14(@types/node@25.0.9)(esbuild@0.27.4)(jiti@2.7.0)(sass@1.97.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.9.0)) + tailwindcss: + specifier: ^4.2.2 + version: 4.2.2 + typescript: + specifier: ^6.0.2 + version: 6.0.2 + vite: + specifier: ^8.0.14 + version: 8.0.14(@types/node@25.0.9)(esbuild@0.27.4)(jiti@2.7.0)(sass@1.97.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.9.0) + examples/react/start-basic-cloudflare: dependencies: '@tanstack/react-router': @@ -14085,6 +14131,23 @@ packages: '@opentelemetry/api': optional: true + '@better-auth/core@1.6.23': + resolution: {integrity: sha512-beEhOs0uVeOxYOZKUfIEBd/nQV2Bd4/6wyLxZ0OFkn6CMTK2Vi+hXuZLnyPBeB6RdHpebEoJWiHqwHxBIxgPDQ==} + peerDependencies: + '@better-auth/utils': 0.4.2 + '@better-fetch/fetch': 1.3.1 + '@cloudflare/workers-types': '>=4' + '@opentelemetry/api': ^1.9.0 + better-call: 1.3.7 + jose: ^6.1.0 + kysely: ^0.28.5 || ^0.29.0 + nanostores: ^1.0.1 + peerDependenciesMeta: + '@cloudflare/workers-types': + optional: true + '@opentelemetry/api': + optional: true + '@better-auth/drizzle-adapter@1.6.19': resolution: {integrity: sha512-57C9ePorPmIEez6dHuQMz3hCTkYim0lfVRIoRtX7PiVfiRFB2bjXseQwrCJfQmkgMFlkp1s/c9nKgAjc2EvAIg==} peerDependencies: @@ -14095,6 +14158,16 @@ packages: drizzle-orm: optional: true + '@better-auth/drizzle-adapter@1.6.23': + resolution: {integrity: sha512-2+/PTVfIP9E7iz6af8TB3lhnowHUj9ljC66kECmHaFEdUqPgzHoWux9epotKwO7XDg2ui4ttWQ8CMeNFLvQeKQ==} + peerDependencies: + '@better-auth/core': ^1.6.23 + '@better-auth/utils': 0.4.2 + drizzle-orm: ^0.45.2 + peerDependenciesMeta: + drizzle-orm: + optional: true + '@better-auth/kysely-adapter@1.6.19': resolution: {integrity: sha512-DlmvllEd0nv8JL+plX3JB3WTmqDFnGFOmjmIiUDHo8R3PTAvC0ZaJq3Jk+LQLN5PyVQSUzXZKtvTQYaqRHzBaw==} peerDependencies: @@ -14105,12 +14178,28 @@ packages: kysely: optional: true + '@better-auth/kysely-adapter@1.6.23': + resolution: {integrity: sha512-zbNJsMbG09exfkGyvFqBLLqWoMPAUWjxCuUnEK5AsjbYoZeIjj/QGZgdf4CapVWryKxjA9Q6Jlr6fbiPpC3VAg==} + peerDependencies: + '@better-auth/core': ^1.6.23 + '@better-auth/utils': 0.4.2 + kysely: ^0.28.17 || ^0.29.0 + peerDependenciesMeta: + kysely: + optional: true + '@better-auth/memory-adapter@1.6.19': resolution: {integrity: sha512-cZ8iLRG/T8Oi/CqE9FTHj3z8pIOqRsINi50trWxPNwyY/Eyb7YCljrBi0PuqgIdyVs7BWfrrtEYTpO4ddfuwEw==} peerDependencies: '@better-auth/core': ^1.6.19 '@better-auth/utils': 0.4.2 + '@better-auth/memory-adapter@1.6.23': + resolution: {integrity: sha512-krIiR0pIVkaKlAzm690n5bcMW4NGbqeMg0HQSD9fz/KcQF/eWLqcq9gG/BhHTj2i/y96qH+W5JWPmaSOS5iTgQ==} + peerDependencies: + '@better-auth/core': ^1.6.23 + '@better-auth/utils': 0.4.2 + '@better-auth/mongo-adapter@1.6.19': resolution: {integrity: sha512-8AReXqhMGiGQIPEpGbmAhh+R4g70TsAVvzwdd6Aj4q+LTSwd3tqC89TFJ4eX8KSplxm9PFBZ6g6gsRmDd7urQg==} peerDependencies: @@ -14121,6 +14210,16 @@ packages: mongodb: optional: true + '@better-auth/mongo-adapter@1.6.23': + resolution: {integrity: sha512-7+QdevitGlKBbP6JbiSk5SBnzPsKV/mDrQBGBn8hwByQLeJwqpqbuBPw7ZI8vzUlFfAAnyFiqwP3Eb8mxnp7pA==} + peerDependencies: + '@better-auth/core': ^1.6.23 + '@better-auth/utils': 0.4.2 + mongodb: ^6.0.0 || ^7.0.0 + peerDependenciesMeta: + mongodb: + optional: true + '@better-auth/prisma-adapter@1.6.19': resolution: {integrity: sha512-pXZBhR7/bzJb48IUHlGMyz9SM9h1OCO5GIIuHEllJYt8MKgrjtsnXfUkwZh6pAUEIp3WxBEYMMK96bfkqHiWEg==} peerDependencies: @@ -14134,6 +14233,19 @@ packages: prisma: optional: true + '@better-auth/prisma-adapter@1.6.23': + resolution: {integrity: sha512-2qSdzidq4tkb1eS5TTqb4Nzg0mdZWm3Qky9SYeXeb8PpVQbC2sxqJhEM5mK7y12uU6I8hc64wO9f7AFVNL+6UQ==} + peerDependencies: + '@better-auth/core': ^1.6.23 + '@better-auth/utils': 0.4.2 + '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0 + prisma: ^5.0.0 || ^6.0.0 || ^7.0.0 + peerDependenciesMeta: + '@prisma/client': + optional: true + prisma: + optional: true + '@better-auth/telemetry@1.6.19': resolution: {integrity: sha512-bBaB6SMIsrD3WutDdm5YQ1bQyinANTimHD8RtpLWhNh/jIXvzgwVVCrDFqA256vcGC/ZRCydmtW8ZrUqNMW9Og==} peerDependencies: @@ -14141,6 +14253,13 @@ packages: '@better-auth/utils': 0.4.2 '@better-fetch/fetch': 1.3.1 + '@better-auth/telemetry@1.6.23': + resolution: {integrity: sha512-/R2Kb+z2BpDOOWwVHqOk+c0VNpuwfCv4Hp5Yr9003WIZPax/zyNraGLB9CFE8qF2gZW8Dsz419k4I8CPrGzpDA==} + peerDependencies: + '@better-auth/core': ^1.6.23 + '@better-auth/utils': 0.4.2 + '@better-fetch/fetch': 1.3.1 + '@better-auth/utils@0.4.2': resolution: {integrity: sha512-AUxrvu+HaaODsUyzDxFgwd/8RZ1yZaYo42LXKSrU2oGgR38pS1ij8nqQKNgtTWoYGpNevNXtCfgTy6loHveW9A==} @@ -20715,6 +20834,68 @@ packages: vue: optional: true + better-auth@1.6.23: + resolution: {integrity: sha512-4vOaRd9UiKGKm9R+ej0jjU1es3MiJIiNc9Qq3VCnYqOZ4/nb5272QqTxWYoDxyUXl5x6A2x2we5KZKQO9teTQQ==} + peerDependencies: + '@lynx-js/react': '*' + '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0 + '@sveltejs/kit': ^2.0.0 + '@tanstack/react-start': workspace:* + '@tanstack/solid-start': workspace:* + better-sqlite3: ^12.0.0 + drizzle-kit: '>=0.31.4' + drizzle-orm: ^0.45.2 + mongodb: ^6.0.0 || ^7.0.0 + mysql2: ^3.0.0 + next: ^14.0.0 || ^15.0.0 || ^16.0.0 + pg: ^8.0.0 + prisma: ^5.0.0 || ^6.0.0 || ^7.0.0 + react: ^19.2.3 + react-dom: ^19.2.3 + solid-js: 1.9.12 + svelte: ^4.0.0 || ^5.0.0 + vitest: ^2.0.0 || ^3.0.0 || ^4.0.0 + vue: ^3.0.0 + peerDependenciesMeta: + '@lynx-js/react': + optional: true + '@prisma/client': + optional: true + '@sveltejs/kit': + optional: true + '@tanstack/react-start': + optional: true + '@tanstack/solid-start': + optional: true + better-sqlite3: + optional: true + drizzle-kit: + optional: true + drizzle-orm: + optional: true + mongodb: + optional: true + mysql2: + optional: true + next: + optional: true + pg: + optional: true + prisma: + optional: true + react: + optional: true + react-dom: + optional: true + solid-js: + optional: true + svelte: + optional: true + vitest: + optional: true + vue: + optional: true + better-call@1.3.6: resolution: {integrity: sha512-no1jI+h6Bkxs1NVBo4rONbVIzsPjZ8IUu7IHaJBiFwVX1XEQGN8KpHots5fSWmXe9nNyLuLIcgx6WEUcE6EDaA==} peerDependencies: @@ -20723,6 +20904,14 @@ packages: zod: optional: true + better-call@1.3.7: + resolution: {integrity: sha512-Al51/hjp2SSp6CRTa3F2ptcx4yQVS1xWKoY6jcVXqNYOap6mHFP2jUBn5EwIL4iIed1/Sq4hlQ+Umm6EflZG+w==} + peerDependencies: + zod: ^4.0.0 + peerDependenciesMeta: + zod: + optional: true + better-path-resolve@1.0.0: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} @@ -27628,11 +27817,28 @@ snapshots: nanostores: 1.3.0 zod: 4.4.3 + '@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0)': + dependencies: + '@better-auth/utils': 0.4.2 + '@better-fetch/fetch': 1.3.1 + '@opentelemetry/semantic-conventions': 1.41.1 + '@standard-schema/spec': 1.1.0 + better-call: 1.3.7(zod@4.4.3) + jose: 6.1.3 + kysely: 0.29.2 + nanostores: 1.3.0 + zod: 4.4.3 + '@better-auth/drizzle-adapter@1.6.19(@better-auth/core@1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)': dependencies: '@better-auth/core': 1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) '@better-auth/utils': 0.4.2 + '@better-auth/drizzle-adapter@1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)': + dependencies: + '@better-auth/core': 1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) + '@better-auth/utils': 0.4.2 + '@better-auth/kysely-adapter@1.6.19(@better-auth/core@1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)(kysely@0.29.2)': dependencies: '@better-auth/core': 1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) @@ -27640,16 +27846,33 @@ snapshots: optionalDependencies: kysely: 0.29.2 + '@better-auth/kysely-adapter@1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)(kysely@0.29.2)': + dependencies: + '@better-auth/core': 1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) + '@better-auth/utils': 0.4.2 + optionalDependencies: + kysely: 0.29.2 + '@better-auth/memory-adapter@1.6.19(@better-auth/core@1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)': dependencies: '@better-auth/core': 1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) '@better-auth/utils': 0.4.2 + '@better-auth/memory-adapter@1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)': + dependencies: + '@better-auth/core': 1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) + '@better-auth/utils': 0.4.2 + '@better-auth/mongo-adapter@1.6.19(@better-auth/core@1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)': dependencies: '@better-auth/core': 1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) '@better-auth/utils': 0.4.2 + '@better-auth/mongo-adapter@1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)': + dependencies: + '@better-auth/core': 1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) + '@better-auth/utils': 0.4.2 + '@better-auth/prisma-adapter@1.6.19(@better-auth/core@1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)(@prisma/client@7.0.0(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(typescript@6.0.2))(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))': dependencies: '@better-auth/core': 1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) @@ -27658,12 +27881,26 @@ snapshots: '@prisma/client': 7.0.0(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(typescript@6.0.2) prisma: 7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2) + '@better-auth/prisma-adapter@1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)(@prisma/client@7.0.0(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(typescript@6.0.2))(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))': + dependencies: + '@better-auth/core': 1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) + '@better-auth/utils': 0.4.2 + optionalDependencies: + '@prisma/client': 7.0.0(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(typescript@6.0.2) + prisma: 7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2) + '@better-auth/telemetry@1.6.19(@better-auth/core@1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)': dependencies: '@better-auth/core': 1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) '@better-auth/utils': 0.4.2 '@better-fetch/fetch': 1.3.1 + '@better-auth/telemetry@1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)': + dependencies: + '@better-auth/core': 1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) + '@better-auth/utils': 0.4.2 + '@better-fetch/fetch': 1.3.1 + '@better-auth/utils@0.4.2': dependencies: '@noble/hashes': 2.0.1 @@ -34737,6 +34974,39 @@ snapshots: - '@cloudflare/workers-types' - '@opentelemetry/api' + better-auth@1.6.23(@prisma/client@7.0.0(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(typescript@6.0.2))(@tanstack/react-start@packages+react-start)(mysql2@3.15.3)(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.12)(vitest@4.1.4)(vue@3.5.25(typescript@6.0.2)): + dependencies: + '@better-auth/core': 1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) + '@better-auth/drizzle-adapter': 1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2) + '@better-auth/kysely-adapter': 1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)(kysely@0.29.2) + '@better-auth/memory-adapter': 1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2) + '@better-auth/mongo-adapter': 1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2) + '@better-auth/prisma-adapter': 1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)(@prisma/client@7.0.0(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(typescript@6.0.2))(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2)) + '@better-auth/telemetry': 1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1) + '@better-auth/utils': 0.4.2 + '@better-fetch/fetch': 1.3.1 + '@noble/ciphers': 2.2.0 + '@noble/hashes': 2.0.1 + better-call: 1.3.7(zod@4.4.3) + defu: 6.1.4 + jose: 6.1.3 + kysely: 0.29.2 + nanostores: 1.3.0 + zod: 4.4.3 + optionalDependencies: + '@prisma/client': 7.0.0(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(typescript@6.0.2) + '@tanstack/react-start': link:packages/react-start + mysql2: 3.15.3 + prisma: 7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + solid-js: 1.9.12 + vitest: 4.1.4(@types/node@25.0.9)(@vitest/ui@4.1.4)(jsdom@29.1.1(@noble/hashes@2.0.1))(msw@2.7.0(@types/node@25.0.9)(typescript@6.0.2))(vite@8.0.14(@types/node@25.0.9)(esbuild@0.27.4)(jiti@2.7.0)(sass@1.97.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.9.0)) + vue: 3.5.25(typescript@6.0.2) + transitivePeerDependencies: + - '@cloudflare/workers-types' + - '@opentelemetry/api' + better-call@1.3.6(zod@4.4.3): dependencies: '@better-auth/utils': 0.4.2 @@ -34746,6 +35016,15 @@ snapshots: optionalDependencies: zod: 4.4.3 + better-call@1.3.7(zod@4.4.3): + dependencies: + '@better-auth/utils': 0.4.2 + '@better-fetch/fetch': 1.3.1 + rou3: 0.7.12 + set-cookie-parser: 3.1.0 + optionalDependencies: + zod: 4.4.3 + better-path-resolve@1.0.0: dependencies: is-windows: 1.0.2