Skip to content

<SignIn />

Sign-in form with social provider buttons above an email field and the email method buttons

<SignIn /> is the sign-in and sign-up form. It asks for an email address first, checks whether an account exists for it, and then continues with the matching step: sign in for an existing account, create an account for a new one. There’s no separate sign-up component. The methods it offers come from providers and sendEmails in src/convex/auth.constants.ts.

Quick start

The auth/routes registry item installs a /signin page that renders the component. You don’t need to add anything to use it:

src/routes/(auth)/signin/+page.svelte
src/app/signin/page.tsx

<UserButton /> also opens this form in a dialog for signed-out visitors, so most apps never link to /signin themselves. The route protection in src/hooks.server.tssrc/proxy.ts sends signed-out visitors of a protected page there.

In SvelteKit, the component reads api, authClient and authConstants from an <AuthProvider> ancestor, which the base item’s src/routes/+layout.svelte provides.

In Next.js, the component needs the ConvexClientProvider that the base item’s src/app/layout.tsx mounts, and the <Suspense> boundary, because it reads the query string with useSearchParams.

What it does

Email step

Social providers render as buttons above the email field, one per provider set to true in providers, separated from the email form by an “or” divider. The email field is followed by one button per email method:

Methods enabledButtons
One of password, emailOTP, magicLinkContinue
More than oneContinue with Password, Continue with Email OTP, Continue with Magic Link

emailOTP and magicLink only appear when sendEmails: true is also set. When no email method is enabled, only the social buttons render.

Selecting a method calls the Convex action api.users.actions.checkEmailAvailabilityAndValidity. It reports whether an account exists for the address. For a new address with validateEmails: true, it also checks that the address can receive mail and stops the flow with a message if it can’t (see Validate emails).

The heading reads “Sign in to” followed by brandName, with brandTagline below it. Without them in AUTH_CONSTANTS, the defaults are self hosted Auth and Plug & Play Auth Widgets for your application.

Password

Password step for an existing account, with the email shown read-only and a Forgot password link

For an existing account, the form asks for the password. With sendEmails: true it also shows Forgot password?, which emails a reset link to /reset-password (see Reset password). A sign-in that Better Auth rejects with status 403 shows “Please verify your email address.”

Create-account step for a new email, with full name and password fields and a strength meter

For a new address, the step becomes Create account with password: full name and a new password with a strength meter. The password must reach a strength score of 3 before the form submits. With sendEmails: true, Better Auth requires a verified email before a password user can sign in, so the form switches to “Check your email” after sign-up. The link in that email verifies the address and signs the user in. Without sendEmails, the new user is signed in at once and sent on like a sign-in.

Email code

Selecting the email code method sends a one-time code right away, then asks for it. For a new address, the same screen asks for a full name, which is saved after the code signs the user in.

For an existing account, selecting the magic link sends it right away and shows “Check your email”. For a new address, the form first asks for a full name, then sends the link. Opening the link signs the user in.

Social providers

A social button hands the browser to the provider. After the provider returns, the user lands on the redirect target or, without one, on the page they started from. Provider credentials and callback URLs are on Social providers.

When terms or privacy is set in AUTH_CONSTANTS, the form ends with “By continuing, you agree to our Terms and Privacy Policies”, linking each URL that is set. Empty strings hide the link.

Redirects

After a successful sign-in, the component waits until Convex reports the session as authenticated, calls onSignIn, and then navigates. It picks the target in this order:

  1. the redirectTo prop,
  2. the redirectTo query parameter,
  3. / when the form is on the /signin route.

Anywhere else, for example in the <UserButton /> dialog, it stays on the current page. The target must be a path on your own site: a redirectTo that points at another host, or at a //host path, is replaced with /. The same target, or the current page, is the callback URL for flows that leave the page: social providers, magic links and the verification link.

The route protection builds the query parameter for you. A signed-out request to a protected page goes to /signin?redirectTo=<path and query>, and a signed-in visitor of /signin goes to /. The public routes are /, /signin, /reset-password, /api/auth/*, /pricing, /docs/*, /about, /terms and /privacy. Edit the isPublic list in src/hooks.server.tssrc/proxy.ts to change them.

To send everyone to a fixed page after sign-in, pass redirectTo. It takes precedence over the query parameter:

src/routes/(auth)/signin/+page.svelte
src/app/signin/page.tsx

Reset password

Forgot password? calls Better Auth’s requestPasswordReset with redirectTo set to <origin>/reset-password. The emailed link opens that page with a token query parameter. The page, installed by auth/routes in both frameworks, asks for the new password twice, calls resetPassword, and returns to /signin. A missing token, or Better Auth’s error=INVALID_TOKEN, shows an invalid-link message instead.

Props

  • onSignIn runs once the session is authenticated in Convex, before the redirect. <UserButton /> uses it to close its dialog.
  • redirectTo sets the redirect target.
  • The classclassName prop is merged onto the form’s outer container.

The SvelteKit component also exports reset(), which returns the form to the email step. Call it on an instance bound with bind:this.

Behavior

The form is a set of step components in auth/ui: EmailStep, PasswordFlow, EmailOtpFlow, MagicLinkFlow and SocialFlow. They’re in your repository, so change a step there.

If a step’s method is disabled while the form shows it, the form returns to the email step. Errors from Better Auth appear as toasts, so keep the <Toaster /> from the base layout mounted.