shadimage
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 · light
iconslucide-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
>

More from better-auth-ui

Browse all components in this library →