BETTER-AUTH. UI
Integrations

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:

GitHub - Demo

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:

app/providers.tsx
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:

app/routes/__root.tsx
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:

app/routes/auth/$pathname.tsx
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="flex grow flex-col items-center justify-center gap-4 p-4">
            <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.

On this page