what

Turnstile

Add invisible bot protection to any form. Cloudflare Turnstile is free, privacy-first, and replaces CAPTCHA without annoying users.

What Is Turnstile?

Cloudflare Turnstile is a free CAPTCHA alternative that verifies visitors are human without making them solve puzzles or click fire hydrants. It runs a series of browser challenges invisibly in the background and shows a simple checkbox only if the challenge fails.

  • Free — no usage limits or billing required
  • Privacy-first — doesn't use cookies or track users across sites
  • Drop-in — one component tag in your form, server verification is automatic
  • No external dependencies — the What framework loads the Turnstile script automatically when configured

Get Your Keys

  1. Go to the Cloudflare Dashboard
  2. Select Turnstile from the left sidebar
  3. Click Add Site
  4. Enter your site name and domain (use localhost for local development)
  5. Choose widget type: Managed (recommended) or Non-interactive
  6. Click Create
  7. Copy the Site Key (public) and Secret Key (server-side)
Tip: Add localhost as a domain in your Turnstile widget settings so it works during development. You can add multiple domains to a single widget.

Configure what.toml

Add your keys to the [cloudflare] section. The site key is public and embedded in the page. Keep the secret key in an environment variable.

what.toml
[cloudflare]
turnstile_site_key = "0x4AAAAAAA..."
turnstile_secret_key = "${CF_TURNSTILE_SECRET}"
.env
CF_TURNSTILE_SECRET=0x4AAAAAAA_your_secret_key_here
Note: The secret key must never appear in client-side HTML. Always use ${ENV_VAR} syntax for the secret key. The site key is safe to include directly since it's public.

Add to Forms

Drop <what-turnstile/> inside any form. That's the entire integration on your side — the What framework handles the client script, token collection, and server-side verification automatically.

site/comments.html
<form w-action="create" w-store="comments" w-redirect="/comments" w-validate>
  <label>Comment</label>
  <textarea name="body" w-required placeholder="Leave a comment..."></textarea>

  <label>Name</label>
  <input type="text" name="author" w-required placeholder="Your name">

  <what-turnstile/>

  <button type="submit" class="btn btn-primary">Post Comment</button>
</form>

The component renders a Turnstile widget in the form. On submission, the browser includes the challenge token and What verifies it against the Cloudflare API before saving the record. Requests that fail verification are rejected with a 400 error.

Customization

The <what-turnstile/> component accepts two optional props:

PropValuesDefaultDescription
themelight, dark, autoautoWidget color scheme
sizenormal, compactnormalWidget dimensions
<!-- Dark theme, compact size -->
<what-turnstile theme="dark" size="compact"/>

<!-- Auto theme (matches user's OS preference) -->
<what-turnstile theme="auto"/>

The compact size is useful when vertical space is tight, such as inline forms or sidebars. The auto theme switches between light and dark based on the user's operating system preference.

How Verification Works

When a form with <what-turnstile/> is submitted:

  1. The Turnstile JavaScript widget runs browser-side challenges silently
  2. A token is written into a hidden cf-turnstile-response field in the form
  3. The form submits normally via POST — the token is included with the other fields
  4. What extracts the token server-side and calls the Cloudflare verification API
  5. If verification passes, the form action proceeds (create/update/delete)
  6. If verification fails, the request is rejected with an error response

This all happens transparently. You don't write any of this code — the component and the framework handle it end to end.

Dev Mode

If turnstile_site_key is not set in what.toml, the <what-turnstile/> component renders a visible warning banner in place of the widget:

<div class="alert alert-warn">
  Turnstile not configured. Add turnstile_site_key to [cloudflare] in what.toml.
</div>

This makes it obvious during development if the component is placed in a form but keys haven't been set up yet. In development, server-side verification is also skipped when no secret key is configured, so forms still submit successfully.

Tip: Cloudflare provides test keys that always pass or always fail verification, useful for automated testing. See the Turnstile testing docs for the test key values.