Turnstile Spin
Integrate Turnstile into the user's existing frontend and backend. Do not create a new backend, proxy Worker, or other infrastructure merely to host Siteverify. Current canonical guidance lives at Cloudflare Turnstile Spin.
Resolve the integration
Inspect the project before asking questions:
- identify the frontend framework and forms that need protection;
- locate the existing server-side submit handler;
- detect an existing Turnstile, reCAPTCHA, or hCaptcha integration; and
- resolve the production hostnames from project configuration when possible.
If no server-side handler exists, report that Turnstile cannot be completed securely in the current architecture and stop. Siteverify is mandatory and must run on the server.
Show the proposed forms and hostnames when a material choice remains. Do not broaden the task into form persistence, email delivery, payment, OAuth, styling, or framework migration.
Create or reuse the widget
- Run
scripts/auth-probe.shto resolve an account and the required Turnstile permission. Prefer credentials already available to the user's environment; never print a token or commit it. - If several accounts are available and the project does not resolve one, ask the user to select the account.
- For a new widget, use the current
wrangler turnstile widget createcommand when installed; otherwise usescripts/widget-create.sh. - Register only the intended hostnames. Include local hostnames only when local development requires them, and validate the production hostname returned by Siteverify in production.
- Put the returned secret directly into the user's existing secret store as
TURNSTILE_SECRET. Never inline it or save an extra copy.
For an existing sitekey, use scripts/fetch-secret.sh when authorized and keep
the current widget. Verify its domains and pre-clearance mode. Do not recreate a
widget merely to recover its secret, because that changes the sitekey used by
deployed pages.
Gate the existing handler
Embed the widget using the framework-specific reference:
- vanilla-html.md
- nextjs-app.md
- nextjs-pages.md
- astro.md
- sveltekit.md
- hugo.md
Send the resulting token to the existing backend and call the canonical
Siteverify endpoint there. Continue the original handler only when
success === true. Validate the returned hostname and any expected action or
customer data. Tokens expire and are single-use; never rely on client-side
success alone.
Preserve the original submit behavior. Turnstile gates the handler; it does not replace it.
Migrate another CAPTCHA carefully
Replace the provider script, widget/sitekey, response field, server verification endpoint, and secret together. Preserve intentional action names. Do not automatically translate reCAPTCHA v3 score thresholds or reCAPTCHA Enterprise policy; surface those semantic differences before editing.
Validate
Run scripts/validate.sh and the project's focused tests. Verify the chosen
forms contain the widget, the token reaches the backend, valid Siteverify output
allows the original handler, invalid or missing tokens are rejected, and the
secret is bound to the intended environment. Report provider setup, local code,
and live behavior separately.