<AuthProvider />
Provides AuthConfig and Solid Query context to installed Solid auth components.
Usage
Install the provider registry payload with npx shadcn@latest add https://better-auth-ui.com/r/solid/auth-provider.json. It copies src/components/auth/auth-provider.tsx and related provider support files. After install, these files are app-owned. Then wrap your application shell as shown in the Solid/Zaidan example.
import { deleteUserPlugin } from "@better-auth-ui/core/plugins/delete-user"
import type { AuthLinkProps } from "@better-auth-ui/solid"
import type { QueryClient } from "@tanstack/solid-query"
import {
Link as RouterLink,
useNavigate,
useParams
} from "@tanstack/solid-router"
import type { JSX } from "solid-js"
import { onCleanup, onMount, Show, splitProps } from "solid-js"
import { apiKeyPlugin } from "@/lib/auth/api-key-plugin"
import { emailOtpPlugin } from "@/lib/auth/email-otp-plugin"
import { magicLinkPlugin } from "@/lib/auth/magic-link-plugin"
import { multiSessionPlugin } from "@/lib/auth/multi-session-plugin"
import { organizationPlugin } from "@/lib/auth/organization-plugin"
import { passkeyPlugin } from "@/lib/auth/passkey-plugin"
import { themePlugin } from "@/lib/auth/theme-plugin"
import { twoFactorPlugin } from "@/lib/auth/two-factor-plugin"
import { usernamePlugin } from "@/lib/auth/username-plugin"
import { authClient } from "@/lib/auth-client"
import { syncDocumentThemePreference } from "@/lib/theme"
import { AuthProvider } from "./auth/auth-provider"
import { Toaster } from "./ui/sonner"
export type ProvidersProps = {
children?: JSX.Element | (() => JSX.Element)
queryClient?: QueryClient
}
const resolveProviderChildren = (children: ProvidersProps["children"]) =>
typeof children === "function" ? children() : children
function AuthLink(props: AuthLinkProps) {
const [local, linkProps] = splitProps(props, ["href"])
return <RouterLink {...linkProps} to={local.href} />
}
export function Providers(props: ProvidersProps) {
const navigate = useNavigate()
const params = useParams({ strict: false })
const organizationSlug = () => {
const slug = params()?.slug
if (typeof slug === "string" && slug.length > 0) return slug
return null
}
onMount(() => {
const cleanup = syncDocumentThemePreference()
onCleanup(cleanup)
})
return (
<Show keyed when={organizationSlug() ?? "personal"}>
<AuthProvider
authClient={authClient}
Link={AuthLink}
redirectTo="/settings/account"
navigate={navigate}
queryClient={props.queryClient}
socialProviders={["github"]}
plugins={[
multiSessionPlugin(),
apiKeyPlugin({
organization: true,
configurations: [
{ id: "default", label: "Personal", organization: false },
{ id: "organization", label: "Organization", organization: true }
]
}),
usernamePlugin({
usernamePrefix: "@",
localization: { usernamePlaceholder: "username" }
}),
magicLinkPlugin(),
emailOtpPlugin({
emailVerification: true,
passwordReset: true,
changeEmail: true
}),
twoFactorPlugin(),
passkeyPlugin(),
themePlugin(),
deleteUserPlugin(),
organizationPlugin({
slugPrefix: "@",
slug: organizationSlug(),
teams: true
})
]}
>
{() => (
<>
{resolveProviderChildren(props.children)}
<Toaster />
</>
)}
</AuthProvider>
</Show>
)
}Localization
Install the locale package:
bun add @better-auth-ui/localesImport one locale and pass it to AuthProvider:
import { deDE } from "@better-auth-ui/locales/de-DE"
<AuthProvider authClient={authClient} locale={deDE}>
{children}
</AuthProvider>Locale bundles include the core messages and all built-in plugin messages.
Use localization for product-specific text. These values take priority over the selected locale:
<AuthProvider
authClient={authClient}
locale={deDE}
localization={{ auth: { signIn: "Bei Acme anmelden" } }}
>
{children}
</AuthProvider>Match the browser language
In a client-only application, import the supported locales and match navigator.languages against that list:
import { matchAuthLocale } from "@better-auth-ui/locales"
import { deDE } from "@better-auth-ui/locales/de-DE"
import { enUS } from "@better-auth-ui/locales/en-US"
const locale = matchAuthLocale({
requested: navigator.languages,
supported: [enUS, deDE],
fallback: enUS
})For server rendering, resolve the same locale from a user preference or the Accept-Language header. Pass that locale during the first render to prevent a hydration mismatch.
Changing the locale prop updates mounted auth components. Email components do not read AuthProvider; pass their localization on the server.
Popup social sign-in
Set socialSignInMode="popup" to keep the current page open during social sign-in. Redirect mode remains the default.
Better Auth marks this API as experimental. Configure the server and client plugins before you enable it:
import { betterAuth } from "better-auth"
import { bearer, oauthPopup } from "better-auth/plugins"
export const auth = betterAuth({
plugins: [bearer(), oauthPopup()]
})import { createAuthClient } from "better-auth/solid"
import { oauthPopupClient } from "better-auth/client/plugins"
export const authClient = createAuthClient({
plugins: [oauthPopupClient()]
})Then select popup mode on the provider:
<AuthProvider
authClient={authClient}
navigate={navigate}
socialProviders={["github", "google"]}
socialSignInMode="popup"
>
{children}
</AuthProvider>Popup mode uses the same provider buttons and redirect target. It returns control to the current page, refreshes the session, and then runs the configured navigation.
Props
Prop
Type
Last updated on