better-auth-ui
componentanonymoussource: ok · hit
Anonymous
Adds a Continue as guest button backed by Better Auth's anonymous plugin.
npx shadcn add "https://better-auth-ui.com/r/{style}/anonymous.json"free
No selection tags yet — empty means no evidence, not lack of support.
Dependencies
Bundle weight · lighticonslucide-react
Registry dependencies
buttonspinner
Files3 · source cached 10/9/2026, 6:04:44 PM
examples/start-shadcn-example/src/components/auth/anonymous/anonymous-button.tsx
"use client"
import { authMutationKeys } from "@better-auth-ui/core"
import type { AnonymousAuthClient } from "@better-auth-ui/core/plugins/anonymous"
import { useAuth, useAuthPlugin } from "@better-auth-ui/react"
import { useSignInAnonymous } from "@better-auth-ui/react/plugins/anonymous"
import { useIsMutating } from "@tanstack/react-query"
import { UserRound } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Spinner } from "@/components/ui/spinner"
import { anonymousPlugin } from "@/lib/auth/anonymous-plugin"
import { cn } from "cn"
/** Sign in with a temporary anonymous account. */
export function AnonymousButton() {
const { authClient, navigate, redirectTo } = useAuth()
const { localization } = useAuthPlugin(anonymousPlugin)
const { mutate: signInAnonymous, isPending: anonymousPending } =
useSignInAnonymous(authClient as AnonymousAuthClient, {
onSuccess: () => navigate({ to: redirectTo })
})
const signInMutating = useIsMutating({
mutationKey: authMutationKeys.signIn.all
})
const signUpMutating = useIsMutating({
mutationKey: authMutationKeys.signUp.all
})
const isPending = signInMutating + signUpMutating > 0
return (
<Button
type="button"
variant="outline"
disabled={isPending}
className={cn("w-full", isPending && "pointer-events-none")}
onClick={() => signInAnonymous()}
>
{anonymousPending ? (
<Spinner data-icon="inline-start" />
) : (
<UserRound data-icon="inline-start" />
)}
{localization.continueAsGuest}
</Button>
)
}
examples/start-shadcn-example/src/lib/auth/anonymous-plugin.ts
import { createAuthPlugin } from "@better-auth-ui/core"
import {
type AnonymousPluginOptions,
anonymousPlugin as coreAnonymousPlugin
} from "@better-auth-ui/core/plugins/anonymous"
import { AnonymousButton } from "@/components/auth/anonymous/anonymous-button"
export const anonymousPlugin = createAuthPlugin(
coreAnonymousPlugin.id,
(options: AnonymousPluginOptions = {}) => ({
...coreAnonymousPlugin(options),
authButtons: [AnonymousButton]
})
)
examples/start-shadcn-example/src/lib/auth/auth-plugin.ts
import type {
AuthPluginComponents,
AuthPlugin as AuthPluginPrimitive
} from "@better-auth-ui/react"
declare module "@better-auth-ui/core" {
/** Widens `useAuth().plugins` to the shadcn-typed `AuthPlugin`. */
interface AuthPluginRegister {
shadcn: AuthPlugin
}
}
/** Props the shadcn `<Auth>` router spreads onto plugin-contributed auth views. */
export type AuthViewProps = {
className?: string
socialLayout?: "auto" | "horizontal" | "vertical" | "grid"
socialPosition?: "top" | "bottom"
}
/** Props the shadcn `<Settings>` router spreads onto plugin-contributed settings views. */
export type SettingsViewProps = {
className?: string
}
/** Shadcn plugin type. Plugin authors import this from `@/lib/auth/auth-plugin`. */
export type AuthPlugin = AuthPluginPrimitive<
AuthPluginComponents,
AuthViewProps,
SettingsViewProps
>