Cloudflare Turnstile panel plugin for Filament v5. Register it once on a panel and login is protected automatically — optionally registration and password-reset request too. No form schema edits for the common case.
Requirements
| Dependency | Version |
|---|---|
| PHP | ^8.2 |
| Laravel | ^11 / ^12 |
| Filament | ^5.0 |
Installation
composer require muazzambuilds/filament-turnstilePublish the config (optional):
php artisan vendor:publish --tag=filament-turnstile-configAdd your keys to .env:
TURNSTILE_SITE_KEY=your-site-key
TURNSTILE_SECRET_KEY=your-secret-keyCreate a widget and get keys at dash.cloudflare.com → Turnstile.
Usage
Panel plugin (recommended)
Call ->plugin(...) after ->login() / ->registration() / ->passwordReset() so the plugin can swap the auth page classes:
use MuazzamBuilds\FilamentTurnstile\TurnstilePlugin;
public function panel(Panel $panel): Panel
{
return $panel
->login()
->registration()
->passwordReset()
->plugin(
TurnstilePlugin::make()
->protectRegistration() // opt-in
->protectPasswordReset() // opt-in (request page only)
);
}Defaults: login is protected; registration and password-reset request are not.
Widget options
TurnstilePlugin::make()
->theme('auto') // auto | light | dark
->size('flexible') // normal | flexible | compact
->language('en-US')
->enabled(true);Manual form field
For custom auth pages or any Filament form:
use MuazzamBuilds\FilamentTurnstile\Forms\Components\Turnstile;
Turnstile::make('cf-turnstile-response')
->theme('dark')
->size('compact')
->turnstileAction('contact');Disable auto-swap and extend or compose yourself:
->login(CustomLogin::class)
->plugin(TurnstilePlugin::make()->protectLogin(false))Custom auth pages
Extend the packaged pages or use the trait:
use MuazzamBuilds\FilamentTurnstile\Pages\Auth\Login as TurnstileLogin;
class Login extends TurnstileLogin
{
//
}Local / CI testing
Cloudflare test keys (any hostname, including localhost):
| Purpose | Site key | Secret key |
|---|---|---|
| Always passes | 1x00000000000000000000AA |
1x0000000000000000000000000000000AA |
| Always blocks | 2x00000000000000000000AB |
2x0000000000000000000000000000000AA |
If keys are missing, the widget is hidden and server validation is skipped so local apps without Turnstile still boot.
Configuration
// config/filament-turnstile.php
return [
'site_key' => env('TURNSTILE_SITE_KEY'),
'secret_key' => env('TURNSTILE_SECRET_KEY'),
'verify_url' => env('TURNSTILE_VERIFY_URL', 'https://challenges.cloudflare.com/turnstile/v0/siteverify'),
'theme' => env('TURNSTILE_THEME', 'auto'),
'size' => env('TURNSTILE_SIZE', 'flexible'),
'language' => env('TURNSTILE_LANGUAGE'),
'reset_event' => env('TURNSTILE_RESET_EVENT', 'turnstile-reset'),
];Publish views
php artisan vendor:publish --tag=filament-turnstile-viewsTesting this package
composer install
composer testSupport
If this package helps you, consider supporting development:
License
MIT — see LICENSE.
