Custom flows (headless)
The drop-in <SignUp> and
<ForgotPassword> cards handle the full flow
for you. When you need your own markup and copy, the
credential & flow hooks let you drive the exact
same flows. The network and parsing still run on the Torii runtime, so you don’t
reimplement (or pin) the security-critical logic: you only build the UI.
Everything here requires a <ToriiProvider>
ancestor.
Custom sign-up
Section titled “Custom sign-up”Sign-up is two steps: start() validates and emails a 6-digit code, then
verifyCode() confirms it and signs the user in. The session is applied
automatically on success.
import { useSignUp } from '@torii-js/torii-react';
function SignUp() { const { state, start, verifyCode, resend } = useSignUp();
if (state.status === 'needs-code' || state.status === 'code-invalid') { return ( <CodeForm invalid={state.status === 'code-invalid'} onSubmit={(code) => verifyCode(code)} onResend={resend} /> ); } if (state.status === 'code-expired') return <Expired onRestart={() => location.reload()} />;
return ( <DetailsForm busy={state.status === 'submitting'} error={state.status === 'error' ? state.error : null} onSubmit={(email, password) => start({ email, password, legalConsentAccepted: true })} /> );}Legal consent
Section titled “Legal consent”If the environment requires legal consent, useSignUp() surfaces what you need:
const { start, legalSettings } = useSignUp();// Render your consent checkbox from legalSettings, then:await start({ email, password, legalConsentAccepted: true });If you skip required consent, start() resolves to { status: 'error' } with
the reason in error.code.
Custom password reset
Section titled “Custom password reset”import { usePasswordReset } from '@torii-js/torii-react';
function ResetPassword() { const { state, request, confirm } = usePasswordReset();
if (state.status === 'idle' || state.status === 'requesting') { return <EmailForm busy={state.status === 'requesting'} onSubmit={(email) => request(email)} />; } if (state.status === 'done') return <Done />; // 'code-sent' | 'resetting' | 'code-invalid' | 'error' return ( <NewPasswordForm invalid={state.status === 'code-invalid'} onSubmit={(code, newPassword) => confirm({ code, newPassword })} /> );}request() always resolves to code-sent on success regardless of whether the
email exists, so your UI can’t be used to enumerate accounts.
Applying the session yourself
Section titled “Applying the session yourself”By default these hooks call useAuth().signIn(tokens) for you. To control it
(for example, “register but don’t log in yet”), opt out and apply the tokens
when you choose:
const { state, verifyCode } = useSignUp({ autoSignIn: false });const { signIn } = useAuth();
const next = await verifyCode(code);if (next.status === 'success') signIn(next.tokens);Next steps
Section titled “Next steps”- Credential & flow hooks reference: every hook, state, and option.