@svelte-put/cloudflare-turnstile
Githubaction for rendering Cloudflare turnstile into HTML node
Compatible with or powered directly bySvelte runes.
Still on Svelte 4? Seethe old docs site here.
Introduction
This implementation ofCloudflare Turnstile utilizesSvelte action. If you are looking for a component-oriented solution, check outghostdevv/svelte-turnstile instead.
Installation
npm install --save-dev @svelte-put/cloudflare-turnstilepnpm add -D @svelte-put/cloudflare-turnstileyarn add -D @svelte-put/cloudflare-turnstileNew to Svelte 5? SeeMigration Guides.
Quick Start
<script lang="ts">import {turnstile }from '@svelte-put/cloudflare-turnstile';// assume using SvelteKit and the '$env/static/public' module is availableimport {PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY }from '$env/static/public';let token = $state('');$inspect(token);</script><divuse:turnstileturnstile-sitekey={PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY}turnstile-theme="auto"turnstile-size="normal"turnstile-language="en"turnstile-response-field-name="turnstile"turnstile-response-fieldonturnstile={(e)=> (token = e.detail.token)}></div><p>Captured Token:<span class="hl-success px-2">{token ?? 'pending'}</span></p>PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY="1x00000000000000000000AA"Configuration Attributes
As seen inQuick Start,@svelte-put/cloudflare-turnstile can be customized by addingturnstile-* attributes, where* are properties as described inCloudflare Turnstile's client configuration documentation, except for*-callback properties, which can be specified via Svelte event handler syntaxonturnstile* (more inEvents).
If you have Typescript language server set up correctly, you should get autocomplete / intellisense for theseturnstile* attributes.
Theturnstile-sitekey is the only mandatory property. InQuick Start, it is set via environment variablePUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY, assuming usage withSvelteKit. See more inSvelteKit's docs on static public env.
<div use:turnstile turnstile-sitekey="1x00000000000000000000AA" turnstile-theme="auto" turnstile-size="normal" turnstile-language="en" turnstile-response-field-name="turnstile" turnstile-response-field turnstile-action="customer-feedback" turnstile-cData="customer-id-123" turnstile-execution="render" turnstile-tabindex="0" turnstile-retry="auto" turnstile-retry-interval="8000" turnstile-refresh-expired="auto" turnstile-refresh-timeout="auto" turnstile-appearance="always" turnstile-feedback-enabled></div>Additionally, you may provide theturnstile-script-src attribute, which specifies the URL to load Turnstile script from. The default URL is shown in below code snippet.
<div use:turnstile turnstile-sitekey="1x00000000000000000000AA" turnstile-script-src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit"></div>Finally, there are tworeadonly attributes that will be dynamically added by theturnstile at runtime:turnstile-widget-id is one returned from Cloudflare Turnstile API, andturnstile-rendered is added if the widget is successfully rendered.
<div [...truncated...] turnstile-widget-id="..." turnstile-rendered></div>Events
As seenQuick Start,turnstile is aCustomEvent invoked upon success of the challenge. The event detail contains a token that should be sent to backend for validation. otherturnstile*CustomEvents are mapped directly to those found inCloudflare Turnstile's documentation, without space or hyphen.
type TurnstileEventDetail<T extends Record<string,any> =Record<string,never>> = {widgetId:string;turnstile:Turnstile;} &T;type TurnstileEventAttributes = {'onturnstile'?: (event:CustomEvent<TurnstileEventDetail<{token:string }>>)=> void;'onturnstiletrror'?: (event:CustomEvent<TurnstileEventDetail<{code:string }>>)=> void;'onturnstiletxpired'?: (event:CustomEvent<TurnstileEventDetail>)=> void;'onturnstileteforeinteractive'?: (event:CustomEvent<TurnstileEventDetail>)=> void;'onturnstiletfterinteractive'?: (event:CustomEvent<TurnstileEventDetail>)=> void;'onturnstiletnsupported'?: (event:CustomEvent<TurnstileEventDetail>)=> void;'onturnstiletimeout'?: (event:CustomEvent<TurnstileEventDetail>)=> void;};Notice the event detail provides access towidgetId and theturnstile object, which is helpful if you need to execute custom JS such as reset the widget or check if it is expired.
<script lang="ts">import {turnstile }from '@svelte-put/cloudflare-turnstile';import type {TurnstileEventAttributes }from '@svelte-put/cloudflare-turnstile';const handleTurnstile: TurnstileEventAttributes['onturnstile']= (e)=> {const {token,turnstile,widgetId }= e.detail;// ...};</script><div use:turnstile turnstile-sitekey="1x00000000000000000000AA" onturnstile={handleTurnstile}>Theturnstile object has the following interface:
type Turnstile = {render: (element:string |HTMLElement,config:TurnstileConfig)=> string;reset: (widgetId:string)=> void;remove: (widgetId:string)=> void;getResponse: (widgetId:string)=> string |undefined;isExpired: (widgetId:string)=> boolean;execute: (container:string |HTMLElement,config?:TurnstileConfig)=> void;};Backend Integration (with SvelteKit)
Coming soon...
Migration Guides
V0 -> V1 (Svelte 5 in Runes mode)
When migrating to V1, you just need to remove any colon: in event attributes:
<div use:turnstile turnstile-sitekey="1x00000000000000000000AA" on:turnstile={handleTurnstile} onturnstile={handleTurnstile}>Happy turning in style! 👨💻