wappler-cf-turnstile-client
v1.1.0
Published
Cloudflare Turnstile CAPTCHA client component for Wappler - Privacy-friendly bot protection with automatic form integration. Companion to wappler-cf-turnstile-server for token verification.
Downloads
9
Maintainers
Readme
Wappler Cloudflare Turnstile Component
A Wappler App Connect extension for Cloudflare Turnstile CAPTCHA - a privacy-first, user-friendly CAPTCHA alternative.
Features
- Full Cloudflare Turnstile API support
- Automatic API script loading
- Multiple theme support (Light, Dark, Auto)
- Configurable size (Normal, Compact)
- Multiple appearance modes
- Custom action tracking
- Reactive data binding
- Event dispatching (success, error, expired, timeout)
- Public methods (reset, getToken, execute)
- Proper cleanup on destroy
Installation
Install this extension directly from Wappler:
- Open your Wappler project
- Go to Project Settings → Extensions
- Click Add Extension
- Search for
wappler-cf-turnstile-client - Click Install
- Restart Wappler
The Turnstile component will appear in the Components panel under "Security Components".
Usage
Basic Usage
Get a Cloudflare Turnstile site key from: https://dash.cloudflare.com/
Add the Turnstile component to your page in Wappler
Configure the required
sitekeyproperty (see options below)Access the verification token with data binding:
{{turnstile1.token}}
Site Key Configuration Options
You have multiple ways to provide the Turnstile site key:
Option 1: Static Value (Simplest)
<dmx-turnstile
id="turnstile1"
sitekey="1x00000000000000000000AA">
</dmx-turnstile>Option 2: Server-Side Rendering (SSR) with EJS (Recommended)
Best for security - keeps your key in environment variables:
<!-- From environment variable -->
<dmx-turnstile
id="turnstile1"
sitekey="<%= process.env.TURNSTILE_SITEKEY %>">
</dmx-turnstile>
<!-- From Server Connect query (executed server-side) -->
<dmx-turnstile
id="turnstile1"
sitekey="<%= query.sitekey %>">
</dmx-turnstile>
<!-- From server-side database query -->
<dmx-turnstile
id="turnstile1"
sitekey="<%= config.turnstile_key %>">
</dmx-turnstile>Benefits of SSR/EJS:
- No extra HTTP requests - key is rendered directly into HTML
- Faster page load - no waiting for API calls
- More secure - key comes from server environment
- SEO-friendly - fully rendered on server
Option 3: Client-Side Data Binding (Dynamic)
Best for dynamic keys - when key changes based on user interaction:
<!-- From Server Connect (makes API call on page load) -->
<dmx-serverconnect id="config" url="/api/config"></dmx-serverconnect>
<dmx-turnstile
id="turnstile1"
dmx-bind:sitekey="config.data.turnstile_key">
</dmx-turnstile>When to use client-side binding:
- Key changes based on user selection
- Different keys for different environments shown dynamically
- Loading key from client-side state management
HTML Example
<dmx-turnstile
id="turnstile1"
sitekey="1x00000000000000000000AA"
theme="auto"
size="normal">
</dmx-turnstile>
<!-- Display verification status -->
<div dmx-show="turnstile1.isVerified">
- Verified! Token: {{turnstile1.token}}
</div>
<div dmx-show="!turnstile1.isVerified && !turnstile1.isLoading">
- - Please complete the verification
</div>With Form Submission
<form id="myForm" dmx-on:submit="submitForm.load()">
<input type="text" name="email" placeholder="Email">
<dmx-turnstile
id="turnstile1"
sitekey="1x00000000000000000000AA"
action="login">
</dmx-turnstile>
<button type="submit" dmx-bind:disabled="!turnstile1.isVerified">
Submit
</button>
</form>
<!-- Server Connect action with token -->
<dmx-serverconnect id="submitForm"
url="/api/submit"
dmx-param:email="myForm.email.value"
dmx-param:turnstile_token="turnstile1.token">
</dmx-serverconnect>Properties
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| id | text | - | Required - Unique component ID |
| sitekey | text | - | Required - Your Cloudflare Turnstile site key |
| theme | droplist | auto | Visual theme: light, dark, auto |
| size | droplist | normal | Widget size: normal, compact |
| action | text | - | Optional action name for analytics |
| cdata | text | - | Optional custom data to pass |
| language | text | auto | Language code (e.g., en, es, auto) |
| appearance | droplist | always | When widget appears: always, execute, interaction-only |
| retry | droplist | auto | Retry mode: auto, never |
| retryInterval | number | 8000 | Time between retries in ms (min 8000) |
| refreshExpired | droplist | auto | Token refresh: auto, manual, never |
Data Schema
Access these values via data binding (e.g., {{turnstile1.token}}):
| Property | Type | Description |
|----------|------|-------------|
| token | text | The verification token (pass to your backend) |
| isVerified | boolean | true when user is verified |
| isLoading | boolean | true while widget is loading |
| errorCode | text | Error code if verification failed |
Events
Listen to these events with dmx-on::
| Event | Description | Data |
|-------|-------------|------|
| success | Verification successful | { token: string } |
| verified | Same as success | { token: string } |
| error | Verification failed | { errorCode: string } |
| expired | Token expired | - |
| timeout | Verification timeout | - |
| reset | Widget was reset | - |
Event Example
<dmx-turnstile
id="turnstile1"
sitekey="your-key"
dmx-on:success="console.log('Verified!', $event)"
dmx-on:error="console.log('Error:', $event.errorCode)">
</dmx-turnstile>Methods
Call these methods via dynamic events or custom code:
| Method | Description | Returns |
|--------|-------------|---------|
| reset() | Reset the widget to initial state | - |
| getToken() | Get the current verification token | string |
| isVerified() | Check if currently verified | boolean |
| execute() | Manually execute widget (for execute appearance mode) | - |
Method Example
<!-- Reset button -->
<button dmx-on:click="turnstile1.reset()">Reset CAPTCHA</button>
<!-- Get token in custom code -->
<script>
const token = dmx.app.data.turnstile1.getToken();
console.log('Current token:', token);
</script>Server-Side Verification
After receiving the token from the client, verify it on your server:
Node.js Example
const fetch = require('node-fetch');
async function verifyTurnstile(token, remoteIP) {
const secretKey = process.env.TURNSTILE_SECRET_KEY;
const response = await fetch(
'https://challenges.cloudflare.com/turnstile/v0/siteverify',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret: secretKey,
response: token,
remoteip: remoteIP
})
}
);
const data = await response.json();
return data.success;
}Wappler Server Connect Module
For easy server-side verification in Wappler, install the companion server extension:
npm install wappler-cf-turnstile-serverThis provides a visual Server Connect module for token verification.
- NPM: https://www.npmjs.com/package/wappler-cf-turnstile-server
- GitHub: https://github.com/evaldas/wappler-cf-turnstile-server
See the server extension documentation for complete setup instructions.
Appearance Modes
Always (Default)
The widget is always visible and ready.
<dmx-turnstile sitekey="your-key" appearance="always"></dmx-turnstile>Execute
Widget renders but doesn't run until you call execute().
<dmx-turnstile id="turnstile1" sitekey="your-key" appearance="execute"></dmx-turnstile>
<button dmx-on:click="turnstile1.execute()">Verify</button>Interaction Only
Only shows when user interacts (invisible mode).
<dmx-turnstile sitekey="your-key" appearance="interaction-only"></dmx-turnstile>Testing
Use Cloudflare's test keys for development:
- Always passes:
1x00000000000000000000AA - Always blocks:
2x00000000000000000000AB - Force interactive:
3x00000000000000000000FF
<!-- For development/testing -->
<dmx-turnstile sitekey="1x00000000000000000000AA"></dmx-turnstile>Styling
The widget container has class cf-turnstile-container. You can add custom styles:
.cf-turnstile-container {
margin: 20px 0;
/* Your custom styles */
}Troubleshooting
Component not showing in Wappler
- Verify extension is in
project.json - Check JS file is copied to
public/js/ - Completely restart Wappler (quit and reopen)
Widget not rendering
- Check browser console for errors
- Verify sitekey is correct
- Check Turnstile API loaded:
console.log(window.turnstile)
Token not updating
- Make sure you're checking
turnstile1.tokennot justtoken - Use
dmx-bind:valuefor reactive updates - Check browser console for component logs
Resources
License
MIT
Support
For issues or questions, please open an issue on the repository or post in the Wappler community forums.
Version: 1.0.0
Tested with: Wappler 6.x
