Better Auth UI Companion
Add optional auth and account pages to an application that already runs Better Auth.
Best for
Teams already operating Better Auth that want its auth and account UI composed into the maintained BTST framework paths.
Add auth and account routes to a BTST client stack that already has a Better Auth backend.
BTST supplies
- Auth and account route definitions backed by @btst/better-auth-ui
- Sign-in, sign-up, recovery, account, security, and settings UI
- A CLI scaffold that creates one browser client for the existing auth endpoint
- Framework-native session refresh wiring for the maintained integration paths
You supply
- An existing Better Auth server, schema, migrations, providers, and secrets
- A Better Auth browser client configured for the adopter-owned endpoint
- Any optional Better Auth server and client plugins used by the application
- Deployment, session policy, and separate BTST authorization mapping when needed
You own and customize
Your application keeps the Better Auth server, database, providers, secrets, sessions, and deployment. The companion supplies client routes and UI; it does not create or host authentication.
Compatibility and dependencies
Maintained: Next.js 15+ App Router, React Router v7, TanStack Start.
Requires: An existing Better Auth backend and browser client; The supported @btst/better-auth-ui and Better Auth package cohort.
External services: The adopter's existing Better Auth endpoint; BTST does not host it.
From registration to result
A semantic workflow, not a setup shortcut
- 1Operate Better Auth
Keep the existing server endpoint, schema, providers, secrets, and browser client.
- 2Add the companion
Register auth and account client plugins in the BTST client stack.
- 3Mount routes
Serve sign-in, recovery, account, security, and settings views under your site path.
- 4Refresh sessions
Use the generated framework-native refresh seam after session changes.
@btst/better-auth-ui
is the separately maintained Better Auth UI companion for BTST v3. It adds
resolved auth and account routes while Better Auth UI continues to read its own
session and native permissions from your Better Auth client.
This integration assumes your application already owns a Better Auth server endpoint. It does not generate a Better Auth backend, database adapter, schema, migrations, authentication providers, secrets, or deployment configuration.
Generate the minimal integration
Select the companion explicitly; it is never part of the default scaffold.
npx @btst/codegen init --plugins better-auth-uiThe generated result:
- registers only
authClientPlugin()andaccountClientPlugin(); - creates one browser client for the existing
/api/authendpoint; - mounts routes under the resolved BTST site path (
/pages/auth/*and/pages/account/*by default); - configures API, site, and QueryClient runtime only once in
createClientStack(); and - refreshes the framework explicitly after a Better Auth session change.
Organization, API-key, passkey, multi-session, and other Better Auth extensions are not enabled by the generated code. Add one only after the matching Better Auth server and client plugin are configured in your application.
The stable package publishes API-key and passkey as required declaration
peers because its
synthetic full AuthClient type exposes their surfaces. The CLI therefore
installs their aligned 1.6.16 packages to keep strict dependency trees clean,
but it does not import, register, or enable either runtime feature. Activation
remains an explicit application choice and requires the matching Better Auth
server/client plugins.
Supported release cohort
The stable companion release is @btst/better-auth-ui@2.0.0. Its
stable-v3 compatibility contract retains these exact versions:
| Package | Version |
|---|---|
better-auth, @better-auth/core | 1.6.16 |
@better-auth/api-key, @better-auth/passkey | 1.6.16 |
@better-auth/utils | 0.4.1 |
@better-fetch/fetch | 1.2.2 |
better-call | 1.3.6 |
@btst/db and BTST database adapters | 2.2.3 |
Do not combine this companion release with a Better Auth 1.7 dependency graph.
The CLI installs the corrected auth cohort without changing the retained
@btst/db@2.2.3 or adapter versions.
For a manual installation, add the companion and exact auth cohort alongside your existing BTST dependencies:
pnpm add @btst/better-auth-ui@2.0.0 \
better-auth@1.6.16 @better-auth/core@1.6.16 \
@better-auth/api-key@1.6.16 @better-auth/passkey@1.6.16 \
@better-auth/utils@0.4.1 @better-fetch/fetch@1.2.2 better-call@1.3.6The package declares its component-library peers. Resolve any peer warning against the companion's published manifest. These optional data-adapter subpaths add their own peers; do not install or import them unless you select that integration:
| Optional subpath | Additional peers |
|---|---|
@btst/better-auth-ui/tanstack | @daveyplate/better-auth-tanstack@^1.3.6 |
@btst/better-auth-ui/instantdb | @instantdb/react@>=0.18.0 |
@btst/better-auth-ui/triplit | @triplit/client@>=1.0.0, @triplit/react@>=1.0.0 |
Browser client and resolved routes
The CLI generates the following application-owned seam:
import { createAuthClient } from "better-auth/react"
export function createAppAuthClient(baseURL?: string) {
return createAuthClient({
...(baseURL ? { baseURL } : {}),
basePath: "/api/auth",
})
}Change basePath only when your existing Better Auth handler uses a different
path. The companion route bases are not configured here: they derive from the
site runtime passed once to createClientStack().
import { accountClientPlugin, authClientPlugin } from "@btst/better-auth-ui/client"
import { createClientStack } from "@btst/stack/client"
return createClientStack({
api: { baseURL: apiOrigin, basePath: "/api/data" },
site: { baseURL: siteOrigin, basePath: "/pages" },
queryClient,
plugins: {
auth: authClientPlugin(),
account: accountClientPlugin(),
},
})Provider overrides
The resolved stack infers both override keys. Configure the Better Auth client
once under auth; account-specific settings remain under account.
<StackProvider
stack={browserStack}
router={frameworkRouter}
overrides={{
auth: {
authClient,
redirectTo: "/pages/account/settings",
onSessionChange: refreshThroughTheFramework,
},
account: {
account: true,
// Avatar customization belongs here:
// avatar: { upload, delete: deleteAvatar, size: 128 },
},
}}
>
{children}
</StackProvider>Use the framework-native synchronization generated for your target:
onSessionChange: () => router.refresh()onSessionChange: () => revalidator.revalidate()onSessionChange: () => router.invalidate()The bridge performs no hidden BTST identity refetch. If business plugins use
BTST authorization, map the Better Auth session separately with BTST's generic
createClientAuth and createServerAuth contracts and keep server
authorization authoritative.