Better Auth UI for React
Use the installed package exports as the authority for the API version. This skill covers the 1.7 package structure.
Select the UI
- For copied shadcn/ui components, read the shadcn integration.
- For packaged HeroUI components, use
@better-auth-ui/herouiand itsbetter-auth-ui-herouiskill when available. - For a custom interface, use the provider and hooks from
@better-auth-ui/reactdirectly.
@better-auth-ui/react is the shared data layer. It does not export the copied shadcn Auth, Settings, or UserButton components.
Configure the application
- Configure Better Auth and mount its handler in the application's server routes.
- Create the React client with
createAuthClientfrombetter-auth/react. - Wrap auth consumers with the selected UI's
AuthProvider. - Pass
authClient, a router-compatiblenavigate, and the application'squeryClient. - Configure redirect destinations, UI paths, and plugins to match the application's routes.
The navigation callback receives { to, replace? }. Adapt Next.js router.push and router.replace to this object instead of passing them directly.
The React provider selects an explicit QueryClient first, then an existing Query context, then a fallback. Pass a request-scoped client for SSR.
Use client boundaries for interactive providers and hooks in Next.js. Keep server configuration, secrets, and /server imports outside those boundaries.
Read and change authentication data
import { useSession, useSignInEmail } from "@better-auth-ui/react"
const session = useSession(authClient, { staleTime: 5_000 })
const signIn = useSignInEmail(authClient)
Call these hooks inside a React component or custom hook. Supply the auth client explicitly.
Queries expose TanStack Query state such as data, isPending, and error. Mutations expose mutate, mutateAsync, and isPending.
Use useSession from Better Auth UI when consumers share its Query cache. Better Auth's own authClient.useSession() uses a different subscription path.
Import optional hooks from @better-auth-ui/react/plugins/<plugin>. Import loader factories and helpers from @better-auth-ui/core or its plugin entrypoints.
Keep page headings, navigation, and independent content mounted while queries resolve. Show pending states only for unresolved values and dependent actions.
Loaders and SSR
Use ensureSession(queryClient, authClient) for browser loaders. Use ensureSessionServer(queryClient, auth, { headers }) from @better-auth-ui/core/server on the server.
Create one QueryClient per server request. Pass the same client to loaders, hydration, and AuthProvider.
For TanStack Start, use the documented Router/Query SSR integration. For Next.js, keep direct server calls in server-only code.
Do not cache one user's session in a module-level server QueryClient. Enforce permissions in server endpoints as well as route guards.
Plugins and organizations
Enable each feature in three places when applicable: the Better Auth server, its client plugin, and the selected UI plugin.
Use the UI plugin shipped with the selected component system. Core plugins provide shared behavior but do not supply copied UI views.
Include plugin view paths in route validation. Hardcoded base auth paths can reject valid invitation or two-factor routes.
Select organizations from the route slug or an explicit ID. Pass organizationPlugin({ slug }), using null for personal-account routes.
Keep this value current when the route changes. Do not use session active-organization state or setActive as the source of access.
References
- React queries
- React mutations
- React SSR
- shadcn Next.js integration
- shadcn TanStack Start integration
- Documentation index
Website examples follow the current release. Check the installed package before using an API from newer documentation.