PHPackages                             sudiptpa/filament-turnstile - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Security](/categories/security)
4. /
5. sudiptpa/filament-turnstile

ActiveLibrary[Security](/categories/security)

sudiptpa/filament-turnstile
===========================

Cloudflare Turnstile form field for Filament v5. Protect any Filament form with a bot-resistant challenge widget.

v1.1(1mo ago)019↓100%MITPHPPHP &gt;=8.2,&lt;8.6CI passing

Since Apr 30Pushed 1w agoCompare

[ Source](https://github.com/sudiptpa/filament-turnstile)[ Packagist](https://packagist.org/packages/sudiptpa/filament-turnstile)[ RSS](/packages/sudiptpa-filament-turnstile/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (2)Dependencies (7)Versions (3)Used By (0)

Filament Turnstile
==================

[](#filament-turnstile)

[![CI](https://github.com/sudiptpa/filament-turnstile/actions/workflows/ci.yml/badge.svg)](https://github.com/sudiptpa/filament-turnstile/actions/workflows/ci.yml)[![Latest Version on Packagist](https://camo.githubusercontent.com/e08aa5ca19ceed6528b42e4b77585dbb8da5d837081a273c10087e75dfd1e7d9/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f73756469707470612f66696c616d656e742d7475726e7374696c652e737667)](https://packagist.org/packages/sudiptpa/filament-turnstile)[![PHP Version](https://camo.githubusercontent.com/344e820b219cee3234648531306104364bd684892ad13c5dc79e66eb82a15b90/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d382e322532422d626c7565)](https://www.php.net)[![Downloads](https://camo.githubusercontent.com/43df7753c37830296b19bc7536f86dadbf39b7c8b783d5753eabbbe54bbae573/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f73756469707470612f66696c616d656e742d7475726e7374696c65)](https://packagist.org/packages/sudiptpa/filament-turnstile)[![License](https://camo.githubusercontent.com/f8df3091bbe1149f398a5369b2c39e896766f9f6efba3477c63e9b4aa940ef14/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e)](LICENSE)

A Cloudflare Turnstile integration built for **Filament v5** and plain Laravel. Drop `TurnstileInput` into any Filament form schema, protect the admin login with one line, or use the standalone validation rule and Blade component in any Laravel controller, form request, or view — no CAPTCHA, no image puzzles, just a silent, privacy-respecting bot challenge.

---

Supported Versions
------------------

[](#supported-versions)

DependencyVersionPHP8.2, 8.3, 8.4Laravel^12.0, ^13.0Filament^5.0 (optional)Filament is only required when using `TurnstileInput` or the bundled `Login` page. The validation rule and Blade component work in any Laravel application.

---

Installation
------------

[](#installation)

```
composer require sudiptpa/filament-turnstile
```

The service provider is registered automatically via Laravel package auto-discovery.

Publish the config file:

```
php artisan vendor:publish --tag=filament-turnstile-config
```

Add your Cloudflare Turnstile keys to `.env`:

```
TURNSTILE_SITE_KEY=your-site-key
TURNSTILE_SECRET_KEY=your-secret-key
```

> Register your domain and get free API keys at [dash.cloudflare.com](https://dash.cloudflare.com) → **Turnstile**.

---

Usage
-----

[](#usage)

### 1. Any Filament Form

[](#1-any-filament-form)

Add `TurnstileInput` to any Filament schema like any other field. The widget renders automatically, the token is validated server-side on submit, and nothing is persisted to your model.

```
use Sujip\Filament\Turnstile\TurnstileInput;

public function form(Schema $schema): Schema
{
    return $schema->components([
        TextInput::make('name')->required(),
        TextInput::make('email')->email()->required(),
        Textarea::make('message')->required(),
        TurnstileInput::make('turnstile_token'),
    ]);
}
```

The field automatically hides itself when credentials are not configured, so local development without keys works out of the box.

---

### 2. Filament Admin Login

[](#2-filament-admin-login)

Swap the default Filament login page with the bundled one in your panel provider:

```
use Sujip\Filament\Turnstile\Pages\Auth\Login;

public function panel(Panel $panel): Panel
{
    return $panel
        ->login(Login::class)
        // ...
}
```

The login page renders the Turnstile widget when credentials are present and skips it when they are not — no conditional logic required in your application.

---

### 3. Plain Laravel — Blade Component

[](#3-plain-laravel--blade-component)

Use the `` component in any Blade template. The component accepts optional `theme`, `size`, and any additional HTML attributes.

```

    @csrf

    Send

```

Cloudflare automatically injects a hidden `cf-turnstile-response` field on challenge completion.

Available props:

PropDefaultOptions`theme``auto``light`, `dark`, `auto``size``normal``normal`, `compact````

```

---

### 4. Plain Laravel — Form Requests

[](#4-plain-laravel--form-requests)

```
use Sujip\Filament\Turnstile\Rules\TurnstileRule;

class ContactRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'name'                  => ['required', 'string'],
            'email'                 => ['required', 'email'],
            'cf-turnstile-response' => ['required', new TurnstileRule()],
        ];
    }
}
```

---

### 5. Plain Laravel — Controllers

[](#5-plain-laravel--controllers)

```
use Sujip\Filament\Turnstile\Rules\TurnstileRule;

public function store(Request $request): RedirectResponse
{
    $request->validate([
        'name'                  => ['required', 'string'],
        'email'                 => ['required', 'email'],
        'cf-turnstile-response' => ['required', new TurnstileRule()],
    ]);

    // handle the form ...
}
```

The `TurnstileRule` resolves its HTTP client from the service container automatically. You can also pass a client explicitly when needed (e.g. in tests):

```
new TurnstileRule(app(TurnstileClientContract::class))
```

---

Custom Key Resolver
-------------------

[](#custom-key-resolver)

By default, credentials are read from `config/filament-turnstile.php`. If your application resolves keys differently — for example, from a database, per-tenant settings, or a secrets manager — implement `TurnstileKeyResolverContract` and bind it in your `AppServiceProvider`:

```
use Sujip\Filament\Turnstile\Contracts\TurnstileKeyResolverContract;
use Sujip\Filament\Turnstile\Support\TurnstileCredentials;

final class YourKeyResolver implements TurnstileKeyResolverContract
{
    public function credentials(): ?TurnstileCredentials
    {
        $siteKey   = /* resolve from your source */;
        $secretKey = /* resolve from your source */;

        if (blank($siteKey) || blank($secretKey)) {
            return null;
        }

        return new TurnstileCredentials($siteKey, $secretKey);
    }
}
```

```
// AppServiceProvider::register()
$this->app->bind(TurnstileKeyResolverContract::class, YourKeyResolver::class);
```

Return `null` to indicate that credentials are unavailable — the widget will be suppressed and validation skipped automatically. `TurnstileInput`, the `Login` page, `TurnstileRule`, and `` all resolve credentials through this single contract.

---

Configuration Reference
-----------------------

[](#configuration-reference)

```
// 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'),
    'connect_timeout' => 5,
    'timeout'         => 10,
];
```

---

Testing Locally
---------------

[](#testing-locally)

Cloudflare provides official test keys that work on any domain, including `localhost`, without registration:

PurposeSite keySecret keyAlways passes`1x00000000000000000000AA``1x0000000000000000000000000000000AA`Always blocks`2x00000000000000000000AB``2x0000000000000000000000000000000AA`Forces interactive`3x00000000000000000000FF``3x0000000000000000000000000000000AA`Add these to your `.env.testing` or declare them in `phpunit.xml`:

```

```

---

Customising the Views
---------------------

[](#customising-the-views)

Publish the package views to override the widget HTML:

```
php artisan vendor:publish --tag=filament-turnstile-views
```

Views are published to `resources/views/vendor/filament-turnstile/`.

---

Running Package Tests
---------------------

[](#running-package-tests)

```
composer install
composer test        # PHPUnit
composer stan        # PHPStan level 8
composer coverage    # Coverage report (requires Xdebug)
```

---

Changelog
---------

[](#changelog)

See [CHANGELOG.md](CHANGELOG.md).

---

License
-------

[](#license)

MIT — see [LICENSE](LICENSE).

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance95

Actively maintained with recent releases

Popularity9

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

40d ago

PHP version history (2 changes)v1.0PHP &gt;=8.2 &lt;8.5

v1.1PHP &gt;=8.2,&lt;8.6

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/7222620?v=4)[Sujip Thapa](/maintainers/sudiptpa)[@sudiptpa](https://github.com/sudiptpa)

---

Top Contributors

[![sudiptpa](https://avatars.githubusercontent.com/u/7222620?v=4)](https://github.com/sudiptpa "sudiptpa (5 commits)")

---

Tags

laravelcaptchacloudflarefilamentfilament-pluginbot-protectionturnstilecloudflare turnstileform-field

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/sudiptpa-filament-turnstile/health.svg)

```
[![Health](https://phpackages.com/badges/sudiptpa-filament-turnstile/health.svg)](https://phpackages.com/packages/sudiptpa-filament-turnstile)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3325.1M337](/packages/psalm-plugin-laravel)[larastan/larastan

Larastan - Discover bugs in your code without running it. A phpstan/phpstan extension for Laravel

6.4k51.0M7.4k](/packages/larastan-larastan)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

76318.2M110](/packages/laravel-mcp)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

815320.5k3](/packages/defstudio-telegraph)[api-platform/laravel

API Platform support for Laravel

59156.3k10](/packages/api-platform-laravel)[ralphjsmit/laravel-glide

Auto-magically generate responsive images from static image files.

4923.6k5](/packages/ralphjsmit-laravel-glide)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
