TanStack Start
This guide covers integrating @daveyplate/better-auth-ui
with TanStack Start. We also install @daveyplate/better-auth-tanstack to handle the authentication state and queries.
Starter Project
Want to skip the installation? Check out the starter here:
Installation
Set up the Auth Provider
TanStack Start requires setting up providers slightly differently than a standard React application. Create a root-level provider component:
import { AuthQueryProvider } from "@daveyplate/better-auth-tanstack"
import { AuthUIProviderTanstack } from "@daveyplate/better-auth-ui/tanstack"
import { Link, useRouter } from "@tanstack/react-router"
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
import type { ReactNode } from "react"
import { authClient } from "./lib/auth-client"
// Create a client
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000 * 60
}
}
})
export function Providers({ children }: { children: ReactNode }) {
const router = useRouter()
return (
<QueryClientProvider client={queryClient}>
<AuthQueryProvider>
<AuthUIProviderTanstack
authClient={authClient}
navigate={(href) => router.navigate({ href })}
replace={(href) => router.navigate({ href, replace: true })}
Link={({ href, ...props }) => <Link to={href} {...props} />}
>
{children}
</AuthUIProviderTanstack>
</AuthQueryProvider>
</QueryClientProvider>
)
}
Note how we use TanStack Router's useRouter
hook and Link
component to handle navigation.
Configure the Root Route
Update your root route to use the Providers component:
import { HeadContent, Outlet, Scripts, createRootRoute } from "@tanstack/react-router"
import type { ReactNode } from "react"
import { Header } from "@/components/header"
import globalsCss from "@/styles/globals.css?url"
import { Providers } from "../providers"
export const Route = createRootRoute({
head: () => ({
meta: [
{
charSet: "utf-8"
},
{
name: "viewport",
content: "width=device-width, initial-scale=1"
},
{
title: "Better Auth TanStack Starter"
}
],
links: [
{ rel: "stylesheet", href: globalsCss },
{ rel: "icon", href: "/favicon.ico" },
{ rel: "apple-touch-icon", href: "/apple-touch-icon.png" },
{ rel: "manifest", href: "/manifest.webmanifest" }
]
}),
component: RootComponent
})
function RootComponent() {
return (
<RootDocument>
<Outlet />
</RootDocument>
)
}
function RootDocument({ children }: Readonly<{ children: ReactNode }>) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<meta
name="viewport"
content="initial-scale=1, viewport-fit=cover, width=device-width"
/>
<meta
name="theme-color"
media="(prefers-color-scheme: light)"
content="oklch(1 0 0)"
/>
<meta
name="theme-color"
media="(prefers-color-scheme: dark)"
content="oklch(0.145 0 0)"
/>
<HeadContent />
</head>
<body>
<Providers>
{children}
</Providers>
<Scripts />
</body>
</html>
)
}
Setting Up Auth Routes
TanStack Start uses a file-based routing system. Here's how to set up your authentication routes:
Create Auth Route
Create the following route files for authentication:
import { cn } from "@/lib/utils"
import { AuthCard } from "@daveyplate/better-auth-ui"
import { createFileRoute } from "@tanstack/react-router"
export const Route = createFileRoute("/auth/$pathname")({
component: RouteComponent
})
function RouteComponent() {
const { pathname } = Route.useParams()
return (
<main className="container flex grow flex-col items-center justify-center gap-3 self-center p-4 md:p-6">
<AuthCard pathname={pathname} />
<p
className={cn(
["callback", "settings", "sign-out"].includes(pathname) && "hidden",
"text-muted-foreground text-xs"
)}
>
Powered by{" "}
<a
className="text-warning underline"
href="https://better-auth.com"
target="_blank"
rel="noreferrer"
>
better-auth.
</a>
</p>
</main>
)
}
This dynamic route will handle all the authentication paths (sign-in, sign-up, etc.).
This setup provides a solid foundation for integrating Better Auth UI with TanStack Start. You'll get all the benefits of TanStack's powerful routing system along with Better Auth UI's authentication capabilities.