Turnstile + siteverify POC

Render a Turnstile widget, capture the token, then exchange it server-side via siteverify. The right pane stays in view as you tweak config.

1. Site key

Test keys: 1x00000000000000000000AA always passes, 2x00000000000000000000AB always blocks, 3x00000000000000000000FF forces challenge.

2. Widget config

Visual dimensions when shown.

always: shows success bar. execute: hidden until execute() is called. interaction-only: only shows if user input needed.

render: challenge starts immediately. execute: defers until you call execute().

What happens if the challenge fails (network error, bot detected, etc.). auto: widget retries on its own. never: stops, fires error-callback, you decide. Use never when you want to log/telemetry the failure or show a custom UI before retrying.

What happens when a token expires (~5 min unused). auto: silently re-issues a new token. manual: shows a button the user clicks. never: just fires expired-callback. Use manual/never on long forms where you want to refresh only at submit time so you don't burn tokens.

A short tag (max 32 chars, [a-z0-9_-]) that gets signed into the token and echoed back in the siteverify response. The BE compares it to the action it expects for that endpoint, so a token solved for signup can't be replayed against password-reset. Use one per protected endpoint.

Opaque string (max 255 chars) signed into the token and returned in siteverify. Common uses: a request/session ID for log correlation, the user-id-being-acted-on so a token can't be reused for a different account, or a hash of form fields to bind the token to specific input.

3. siteverify exchange

Test secrets: 1x...AA always passes, 2x...AA always fails, 3x...AA token already spent. Never expose a real secret in the browser.

(token not yet captured)
(token not yet captured)
siteverify has no CORS, so run this in a terminal.
(token not yet captured)
Shows DNS / TCP / TLS / TTFB split. Most siteverify slowness is TLS handshake on cold connections.

Widget preview

(not rendered yet)
(no events yet)