Laravel forms package with built-in spam protection and optional Cloudflare Turnstile support.
You can require the package via composer:
composer require fuelviews/laravel-formsYou can install the package with:
php artisan forms:installYou can manually publish the config file with:
php artisan vendor:publish --tag="forms-config"You can publish the view files with:
php artisan vendor:publish --tag="forms-views"This package includes built-in support for Cloudflare Turnstile CAPTCHA to protect your forms from spam.
- Sign up for a free Cloudflare account if you don't have one
- Go to the Turnstile dashboard
- Create a new site and get your Site Key and Secret Key
Add these to your .env file:
FORMS_TURNSTILE_ENABLED=true
TURNSTILE_SITE_KEY=your_site_key_here
TURNSTILE_SECRET_KEY=your_secret_key_hereThe package configuration in config/forms.php supports flexible environment variables:
'turnstile' => [
'enabled' => env('FORMS_TURNSTILE_ENABLED', false),
'site_key' => env('TURNSTILE_SITE_KEY','1x00000000000000000000AA'),
'secret_key' => env('TURNSTILE_SECRET_KEY','1x0000000000000000000000000000000AA'),
],Include form method type, form method route, spam strap in the start and end of the form, form key, fake submit button, and a real submit button.
<form method="POST" action="{{ route('forms.validate') }}">
<input type="text" name="isSpam" style="display:none" />
/* Form fields here */
<x-forms::meta />
<input type="hidden" name="form_key" value="contact_us" />
<input type="text" name="gotcha" class="hidden" />
<x-forms::buttons.fake-button :buttonText="'Submit'" />
<x-forms::buttons.submit-button :buttonText="'Submit'" />
</form><form method="POST" action="{{ route('forms.validate') }}" class="mt-16">
<div class="grid grid-cols-1 gap-x-6 gap-y-2 sm:grid-cols-2">
<input type="text" name="gotcha" style="display:none" />
<div>
<label for="firstName" class="block text-sm font-semibold leading-6 text-gray-900">
First name
</label>
<div class="mt-1">
<input
type="text"
name="firstName"
id="firstName"
wire:model="firstName"
value="{{ old('firstName') }}"
autocomplete="given-name"
class="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
pattern="[A-Za-z]{2,}"
title="First name must be at least 2 letters and only contain letters." />
@error('firstName')
<span class="flex pl-1 pt-2 text-sm text-red-600">{{ $message }}</span>
@enderror
</div>
</div>
<div>
<label for="lastName" class="block text-sm font-semibold leading-6 text-gray-900">
Last name
</label>
<div class="mt-1">
<input
type="text"
name="first-name"
id="lastName"
wire:model="lastName"
value="{{ old('lastName') }}"
autocomplete="family-name"
class="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
pattern=".{2,}"
title="Last name must be at least 2 characters." />
@error('lastName')
<span class="flex pl-1 pt-2 text-sm text-red-600">{{ $message }}</span>
@enderror
</div>
</div>
<div class="sm:col-span-2">
<label for="email" class="block text-sm font-semibold leading-6 text-gray-900">
Email
</label>
<div class="mt-1">
<input
id="email"
name="email"
type="email"
wire:model="email"
value="{{ old('email') }}"
autocomplete="email"
class="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" />
@error('email')
<span class="flex pl-1 pt-2 text-sm text-red-600">{{ $message }}</span>
@enderror
</div>
</div>
<div class="sm:col-span-2">
<div class="flex justify-between text-sm leading-6">
<label for="phone" class="block font-semibold text-gray-900">Phone</label>
</div>
<div class="mt-1">
<input
type="tel"
name="phone"
id="phone"
wire:model="phone"
value="{{ old('phone') }}"
autocomplete="tel"
aria-describedby="phone-description"
class="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
pattern="[\s\d\-\(\)]*?(\d[\s\d\-\(\)]*?){7,11}"
title="Phone number must have 7 to 11 digits and may include parentheses, spaces, and hyphens."
/>
@error('phone')
<span class="flex pl-1 pt-2 text-sm text-red-600">{{ $message }}</span>
@enderror
</div>
</div>
<div class="sm:col-span-2">
<div class="flex justify-between text-sm leading-6">
<label for="message" class="block text-sm font-semibold leading-6 text-gray-900">
How can we help you?
</label>
<p id="message-description" class="text-gray-400">Max 255 characters</p>
</div>
<div class="mt-1">
<textarea
id="message"
name="message"
wire:model="message"
value="{{ old('messsage') }}"
rows="4"
aria-describedby="message-description"
class="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"></textarea>
@error('message')
<span class="flex pl-1 pt-2 text-sm text-red-600">{{ $message }}</span>
@enderror
</div>
</div>
</div>
<x-forms::meta />
<input type="hidden" name="form_key" value="contact_us" />
<input type="text" name="gotcha" class="hidden" />
<div class="mt-10 flex justify-end border-t border-gray-900/10 pt-8">
<x-forms::buttons.fake-button :buttonText="'Submit'" />
<x-forms::buttons.submit-button :buttonText="'Submit'" />
</div>
</form>
Include forms-modal into your layouts.app.blade.php file, trigger with a button.
You can customize which layout blade file is used in the config/forms.php file
<button onclick="Livewire.dispatch('openModal')">Show Modal</button>
@livewire('forms-modal')Add laravel-forms to your tailwind.config.js file.
content: [
'./vendor/fuelviews/laravel-forms/resources/**/*.blade.php',
]composer testPlease see CHANGELOG for more information on what has changed recently.
Please see CONTRIBUTING for details.
Please review our security policy on how to report security vulnerabilities.
Fuelviews is a web development agency based in Portland, Maine. You'll find an overview of all our projects on our website.
The MIT License (MIT). Please see License File for more information.