BETTER-AUTH. UI
Plugins

Phone Number

Add phone verification-code and password sign-in to Solid and Zaidan applications.

The Solid/Zaidan registry item adds phone verification-code and password sign-in, phone password recovery, and verified phone-number management.

Setup

Configure Better Auth

src/lib/auth.ts
import { betterAuth } from "better-auth"
import { phoneNumber } from "better-auth/plugins"

export const auth = betterAuth({
  plugins: [
    phoneNumber({
      otpLength: 6,
      requireVerification: true,
      sendOTP: ({ phoneNumber, code }) => {
        void sms.send({ to: phoneNumber, body: `Your code is ${code}` })
      },
      sendPasswordResetOTP: ({ phoneNumber, code }) => {
        void sms.send({ to: phoneNumber, body: `Your reset code is ${code}` })
      }
    })
  ]
})

Normalize numbers on the server and do not log codes in production.

Update the schema and client

Generate or migrate the Better Auth schema so the user model has nullable phoneNumber and phoneNumberVerified fields. Keep phoneNumber unique.

src/lib/auth-client.ts
import { createAuthClient } from "@better-auth-ui/solid"
import { phoneNumberClient } from "better-auth/client/plugins"

export const authClient = createAuthClient({
  plugins: [phoneNumberClient()]
})

Add the registry item

bunx --bun shadcn@latest add https://better-auth-ui.com/r/solid/phone-number.json

Register the UI plugin

src/components/providers.tsx
import { phoneNumberPlugin } from "@/lib/auth/phone-number-plugin"

<AuthProvider
  authClient={authClient}
  navigate={navigate}
  plugins={[
    phoneNumberPlugin({
      signIn: true,
      passwordSignIn: true,
      passwordReset: true,
      changePhoneNumber: true
    })
  ]}
>
  {props.children}
</AuthProvider>

Allow the plugin route segments

src/routes/auth/$path.tsx
import { viewPaths } from "@better-auth-ui/core"
import { phoneNumberPlugin } from "@/lib/auth/phone-number-plugin"

const validAuthPathSegments = new Set([
  ...Object.values(viewPaths.auth),
  ...Object.values(phoneNumberPlugin().viewPaths.auth)
])

Flow options

UI optionDefaultServer requirement
signIntruesendOTP
passwordSignInfalseA password credential
passwordResetfalsesendPasswordResetOTP
changePhoneNumbertruesendOTP
otpLength6Must match Better Auth otpLength

Passwordless phone verification bypasses Better Auth 2FA. Phone number and password sign-in still follows the configured second-factor flow.

Set Better Auth signUpOnVerification when an unknown verified number should create an account. Build a custom view when verification also needs other required user fields.

Options and localization

Prop

Type

Prop

Type

The copied components use sendPhoneNumberOtpOptions and the other Solid phone-number mutation factories. See the Better Auth phone-number plugin for server behavior and advanced options.

Last updated on

On this page