Render a Turnstile widget, capture the token, then exchange it server-side via siteverify. The right pane stays in view as you tweak config.
Test keys:
1x00000000000000000000AA always passes,
2x00000000000000000000AB always blocks,
3x00000000000000000000FF forces challenge.
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.
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)
(token not yet captured)
(not rendered yet)
(no events yet)