tigusigalpa/yandex-captcha-filament
Adds a Yandex SmartCaptcha field to Filament forms with server-side validation and simple configuration. Protect login, registration, and other public forms from bots and spam with minimal setup. Easy to install in your Laravel Filament admin panel and compatible with Filament form workflows.
composer require tigusigalpa/yandex-captcha-filament
php artisan vendor:publish --tag=yandex-captcha-filament-config
.env (YANDEX_CAPTCHA_SITE_KEY and YANDEX_CAPTCHA_SECRET_KEY — check the published config/yandex-captcha.php for exact variable names) and grab them from the Yandex Cloud console.use Tigusigalpa\FilamentYandexCaptcha\Forms\Components\YandexCaptcha;
public static function form(Form $form): Form
{
return $form->schema([
TextInput::make('email')->email()->required(),
Textarea::make('message')->required(),
YandexCaptcha::make('captcha')->required(),
]);
}
Where to look first: the README's Quick Start and the examples/ directory (six ready-made examples cover contact forms, login/registration pages, invisible mode, and JS callbacks). Skim those before reading source — the package is designed to be zero-config, so day-to-day usage is mostly "make it appear in the form."
First milestone: get a captcha token validated end-to-end locally using force_pass test mode (see Gotchas), then flip to prod mode with real keys before deploying.
Validation is automatic — don't hand-roll it. The component ships with YandexCaptchaRule, which performs the server-side token verification against Yandex. As long as you add YandexCaptcha::make('captcha') to the schema (and optionally ->required()), you don't need to touch a Form Request or validate() call. Treat the field like any other Filament input in terms of required() / unique() chaining.
Per-component overrides beat global config for multi-tenant or multi-form apps. If you have different Filament panels (admin, public, partner portal) you can override site keys and settings on each component instance rather than editing the config file. This is the cleaner pattern when keys differ per panel.
Invisible mode for low-friction forms. For login, registration, or any form where you don't want a visible widget, enable invisible captcha mode on the component. The token is still validated server-side, so your validation logic doesn't change — it's a UX-only toggle.
JS callbacks are the integration point for custom UX. Use the success / error / network-error callbacks to update Alpine state, show toasts, or re-enable a submit button. This is where you hook into Filament's Alpine-based form lifecycle — remember these callbacks run client-side, before Filament's livewire request fires.
Use the bundled examples as templates, not the README snippets. The README is intentionally minimal; the examples/ folder contains the actual copy-paste-ready patterns for login/registration, sections, and invisible mode.
Localization: supported locales (RU/EN/BE/KK/TT/UK/UZ/TR) and RTL-readiness are built in. Configure your app locale normally (app.locale) and the component picks it up — don't hardcode messages unless you need to override via the standard Laravel translation keys.
Testing strategy: in your test suite, set the mode to force_pass via env/config so CI doesn't hit Yandex. Reserve force_fail for negative-path tests (asserting your validation messages fire). Never ship a test config leaking into production — guard it behind app()->environment('local').
force_pass is a real footgun if it leaks to prod. These test modes bypass verification entirely. Put an explicit check in your deploy/CI (e.g. assert YANDEX_CAPTCHA_MODE=prod in a config test) so a copy-pasted .env from local doesn't silently disable captcha in production.
Keys must exist on both sides. The site key is used client-side (widget render), and the secret is used server-side (verification). Mismatched keys fail silently from a UX perspective — the widget renders, the token is submitted, and validation fails with a generic error. If users report "captcha works but form won't submit," check the secret key first.
Filament v4 only. The requirements are explicit: Filament ^4.0, Laravel ^10 | ^11 | ^12, PHP ^8.1. If you're still on Filament v3, this package won't install — don't fight Composer, use a v3-compatible captcha solution or plan a Filament upgrade. Likewise, this is a Yandex-specific integration; the underlying tigusigalpa/yandex-smartcaptcha-php package is a hard dependency.
Domain restriction is configured in Yandex, not here. SmartCaptcha keys are bound to allowed domains in the Yandex Cloud console. If you change staging/prod domains, update the key's allowed domains there — nothing in the Laravel config will fix a "widget renders but never passes" situation caused by a domain mismatch.
Enable logging during debugging. The package supports optional error logging (per the release notes). Turn it on to see the raw Yandex API response when verification fails — the default user-facing message is deliberately opaque, so logs are your only real signal.
Extension points to know:
YandexCaptchaRule — if you need custom verification semantics (e.g. wrapping additional checks), this is the class to extend or compose around, rather than reimplementing token validation.Theme follows Filament, don't hardcode. Light/dark switching is automatic in the widget; overriding the theme manually will desync from Filament's own theme toggle and look broken. Only force a theme if you're deliberately breaking the Filament theme contract.
Network errors are distinct from validation errors. The callbacks distinguish error vs. network-error; use the network one to surface a "connection problem, retry" message rather than the generic captcha-failed text — users on flaky connections will otherwise think their input is wrong.
How can I help you explore Laravel packages today?