A lightweight and declarative Cloudflare Turnstile integration for Svelte and SvelteKit.
Live playground: battlefieldduck.github.io/turnstile-svelte
npm install @battlefieldduck/turnstile-svelte
+page.svelte<script lang="ts">
import { PUBLIC_TURNSTILE_SITE_KEY } from '$env/static/public';
import { turnstile } from '@battlefieldduck/turnstile-svelte';
</script>
<form method="POST">
<label>
Email
<input name="email" type="email" />
</label>
<label>
Password
<input name="password" type="password" />
</label>
<div {@attach turnstile({ sitekey: PUBLIC_TURNSTILE_SITE_KEY })}></div>
<button>Log in</button>
</form>
+page.server.tsimport { fail } from '@sveltejs/kit';
import { TURNSTILE_SECRET_KEY } from '$env/static/private';
import { validateTurnstile } from '@battlefieldduck/turnstile-svelte/server';
import type { Actions } from './$types';
export const actions = {
default: async (event) => {
const data = await event.request.formData();
const validation = await validateTurnstile({
secret: TURNSTILE_SECRET_KEY,
response: data.get('cf-turnstile-response'),
remoteip: event.getClientAddress()
});
if (!validation.success) {
console.warn('Turnstile failed', { errors: validation['error-codes'] });
return fail(400, { error: 'Invalid verification' });
}
// Token is valid - process the form
const email = data.get('email');
const password = data.get('password');
return { success: true };
}
} satisfies Actions;
Contributions are welcome! Please feel free to submit pull requests or open issues.
turnstile-svelte is licensed under the MIT License. See the LICENSE file for more details.