@svelte-put/cloudflare-turnstile GitHub

action for rendering Cloudflare turnstile into HTML node

@svelte-put/cloudflare-turnstile @svelte-put/cloudflare-turnstile @svelte-put/cloudflare-turnstile changelog

Introduction

This implementation of Cloudflare Turnstile utilizes Svelte action. If you are looking for a component-oriented solution, check out ghostdevv/svelte-turnstile instead.

Installation

npm install --save-dev @svelte-put/cloudflare-turnstile
pnpm add -D @svelte-put/cloudflare-turnstile
yarn add -D @svelte-put/cloudflare-turnstile

Quick Start

Example

Captured Token: pending

<script lang="ts">
	import { turnstile } from '@svelte-put/cloudflare-turnstile';

	import { PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY } from '$env/static/public';

  let token: string;
  $: console.log(`Token:`, token);
</script>

<div
  use:turnstile
  turnstile-sitekey={PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY}
  turnstile-theme="auto"
  turnstile-size="normal"
  turnstile-language="en"
  turnstile-response-field-name="turnstile"
  turnstile-response-field
  on:turnstile={(e) => (token = e.detail.token)}
/>
<p class="text-center">
	Captured Token: <span class="bg-success-surface text-success-text px-2">{token ?? 'pending'}</span>
</p>
PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY="1x00000000000000000000AA"

Configuration Attributes

As seen in Quick Start, @svelte-put/cloudflare-turnstile can be customized by adding turnstile-* attributes, where * are properties as described in Cloudflare Turnstile’s client configuration documentation, except for *-callback properties, which can be specified via Svelte event handler syntax on:turnstile:* (more in Events).

If you have Typescript language server set up correctly, you should get autocomplete / intellisense for these turnstile-* attributes.

The turnstile-sitekey is the only mandatory property. In Quick Start, it is set via environment variable PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY, assuming usage with SvelteKit. See more in SvelteKit’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-appearance="always"
/>

Additionally, you may provide the turnstile-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"
/>

Finally, there are two readonly attributes that will be dynamically added by the turnstile at runtime: turnstile-widget-id is one returned from Cloudflare Turnstile API, and turnstile-rendered is added if the widget is successfully rendered.

<div [...truncated...] turnstile-widget-id="..." turnstile-rendered></div>

Events

As seen Quick Start, turnstile is a CustomEvent invoked upon success of the challenge. The event detail contains a token that should be sent to backend for validation. other turnstile:* CustomEvents are mapped directly to those found in Cloudflare Turnstile’s documentation.

type TurnstileEventDetail<T extends Record<string, any> = Record<string, never>> = {
	widgetId: string;
	turnstile: Turnstile;
} & T;

type TurnstileEventAttributes = {
	'on:turnstile'?: (event: CustomEvent<TurnstileEventDetail<{ token: string }>>) => void;
	'on:turnstile:error'?: (event: CustomEvent<TurnstileEventDetail<{ code: string }>>) => void;
	'on:turnstile:expired'?: (event: CustomEvent<TurnstileEventDetail>) => void;
	'on:turnstile:before-interactive'?: (event: CustomEvent<TurnstileEventDetail>) => void;
	'on:turnstile:after-interactive'?: (event: CustomEvent<TurnstileEventDetail>) => void;
	'on:turnstile:unsupported'?: (event: CustomEvent<TurnstileEventDetail>) => void;
	'on:turnstile:timeout'?: (event: CustomEvent<TurnstileEventDetail>) => void;
};

Notice the event detail provides access to widgetId and the turnstile 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['on:turnstile'] = (e) => {
		const { token, turnstile, widgetId } = e.detail;
		// ...
	};
</script>

<div use:turnstile turnstile-sitekey="1x00000000000000000000AA" on:turnstile={handleTurnstile}>

The turnstile 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...


Happy turning in style! 👨‍💻

Edit this page on Github