Cloudflare Turnstile is a verification tool, much like CAPTCHA. It was added to the sign up form 12 December 2025.
Overview
- We use managed mode with proper race condition handling. The widget runs verification in the background, only showing a challenge UI when Cloudflare determines it’s necessary (managed mode).
- Server-side validation: We validate Turnstile tokens server-side with Cloudflare’s API before calling Supabase. This gives us granular control over which flows are protected, instead of turning on Supabase’s built-in CAPTCHA (which would also hit sign-in and other Auth endpoints).
To reiterate: we no longer use Supabase’s built-in CAPTCHA feature because it’s so wide-sweeping. All validation happens in our server actions before calling Supabase.
Where Turnstile applies today:
- Sign-up (
SignUpForm → signUpAction)
- Forgot password (
ForgotPasswordForm → forgotPasswordAction)
Sign-in still has no Turnstile. That is intentional for now.
- Normal users should still pass in the background without seeing a challenge.
- If Cloudflare decides a person needs an interactive challenge, the same mounted widget can become visible.
- We do not swap from an invisible widget to a new visible widget after our own timeout, because that can leave challenged users with a blank widget area and the “Security check didn’t complete” message. (This was the case until 10 April 2026, when PR #39 fixed the issue)
Implementation details
We use Turnstile’s managed variant, which:
- Runs invisibly by default: Most legitimate users never see a CAPTCHA challenge.
- Shows challenges when needed: Cloudflare automatically displays a challenge if it detects suspicious behaviour (managed mode).
- Handles race conditions: The form waits for token generation before submission, preventing premature form submits.
- Provides clear feedback: Users see "Verifying..." state while waiting, and error messages if verification fails.
Security model
Why this is secure even though Supabase doesn't know about the CAPTCHA: