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 minimalThe 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
| Name | Type | Required | Description |
|---|---|---|---|
token | string | No | Token from your verification URL. When omitted the component shows a manual code-entry form. |
onSuccess | () => void | No | Called 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
"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.