SimpleAuth
ReactComponents

VerifyEmailCallback

Landing page component that verifies the email token on load.

Overview

VerifyEmailCallback mounts useVerifyEmail with the token from your verification link and verifies it on load. Use it on the route your verification emails point to.

When no token is present in the URL the component automatically switches to a manual-entry mode where the user can paste the code from the email instead. This means the page works whether the user clicks the link or types the code by hand.

Configure the path in the dashboard

The path that appears in verification emails (e.g. /verify-email) is set per-app under Dashboard → App Settings → Verify email path. The route you create in your app must match that setting. If you leave it blank, SimpleAuth defaults to /verify-email.

Preview

Interactive preview requires JavaScript.

Install

npx @simpleauthjs/react add verify-email --style minimal

The install snippet uses --style minimal. You can also use --style modern. Style variants compares those two in the live preview. Run npx @simpleauthjs/react add --help for every --style slug the CLI accepts.

Requires add sign-up first.

Props

NameTypeRequiredDescription
tokenstringNoToken from your verification URL. When omitted the component shows a manual code-entry form.
onSuccess() => voidNoCalled when verification succeeds.

Usage

Pass the token from the query string when it is present — the component handles the missing-token case itself.

"use client"

import { VerifyEmailCallback } from "@/components/simpleauth"
import { useRouter } from "next/navigation"

export function VerifyEmailClient({ token }: { token?: string }) {
  const router = useRouter()

  return <VerifyEmailCallback token={token} onSuccess={() => router.replace("/login")} />
}
// app/verify-email/page.tsx  (or whatever path you set in the dashboard)
import { VerifyEmailClient } from "./verify-email-client"

export default function Page({ searchParams }: { searchParams: { token?: string } }) {
  return <VerifyEmailClient token={searchParams.token} />
}

Source

components/simpleauth/hooks/use-verify-email.ts
"use client"

import { useCallback, useEffect, useRef, useState } from "react"
import { SimpleAuthError, type SuccessResponse } from "@simpleauthjs/core"
import { useSimpleAuthClient } from "../provider"

function getErrorMessage(error: unknown) {
  if (error instanceof SimpleAuthError) {
    return error.message
  }

  if (error instanceof Error) {
    return error.message
  }

  return "Unable to verify email."
}

type UseVerifyEmailOptions = {
  token?: string
}

export function useVerifyEmail(options: UseVerifyEmailOptions = {}) {
  const { token: initialToken } = options
  const auth = useSimpleAuthClient()
  const [isLoading, setIsLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [data, setData] = useState<SuccessResponse | null>(null)
  const autoRunRef = useRef(false)

  const verify = useCallback(
    async (token: string) => {
      setIsLoading(true)
      setError(null)

      try {
        const response = await auth.verifyEmail({ token })
        setData(response)
        return response
      } catch (requestError) {
        setData(null)
        setError(getErrorMessage(requestError))
        throw requestError
      } finally {
        setIsLoading(false)
      }
    },
    [auth],
  )

  useEffect(() => {
    if (!initialToken || autoRunRef.current) {
      return
    }

    autoRunRef.current = true
    verify(initialToken).catch(() => {})
  }, [initialToken, verify])

  function reset() {
    autoRunRef.current = false
    setData(null)
    setError(null)
    setIsLoading(false)
  }

  return {
    verify,
    data,
    error,
    isError: Boolean(error),
    isLoading,
    isSuccess: Boolean(data?.success),
    reset,
  }
}

Customisation

Owned by you

Files live at components/simpleauth/ui/verify-email-callback.tsx and components/simpleauth/styles/verify-email-callback.css.

On this page