kylerusby/laravel-waitlist
Composer 安装命令:
composer require kylerusby/laravel-waitlist
包简介
A package for laravel to allow users to sign up to a waitlist.
README 文档
README
A beautiful, ready-to-use Laravel package for managing waitlists. Collect email addresses from interested users with a stunning, pre-built landing page styled with Tailwind CSS. Perfect for product launches, beta releases, or any project that needs to build anticipation.
Requirements
- PHP 8.4 or higher
- Laravel 11.x or 12.x
Features
- 🎨 Beautiful Pre-built UI - Modern, responsive waitlist page with Tailwind CSS
- 📧 Email Collection - Simple form with validation and unique email constraint
- ⚙️ Highly Configurable - Customize text, colors, and behavior via config
- 🛣️ Flexible Routing - Enable/disable routes or override paths and middleware
- 🎯 Easy Integration - Works out of the box with zero configuration
- 🔒 Form Validation - Built-in request validation with custom error messages
- 🎭 Customizable Views - Publish and modify the Blade template to match your brand
Installation
Via Composer
composer require kylerusby/laravel-waitlist
Local Development
To use this package locally in your Laravel project:
- Add the path repository to your project's
composer.json:
{
"repositories": [
{
"type": "path",
"url": "/path/to/laravel-waitlist",
"options": {
"symlink": true
}
}
]
}
- Require the package:
composer require kylerusby/laravel-waitlist @dev
Publish and Run Migrations
php artisan vendor:publish --tag="waitlist-migrations"
php artisan migrate
Publish Configuration (Optional)
php artisan vendor:publish --tag="waitlist-config"
Publish Views (Optional)
php artisan vendor:publish --tag="waitlist-views"
Usage
Once installed, the package works immediately with zero configuration!
Quick Start
Visit /waitlist in your Laravel application to see the pre-built waitlist page. Users can enter their email addresses, and they'll be saved to the database.
Accessing Waitlist Data
use KyleRusby\LaravelWaitlist\Models\Waitlist; // Get all waitlist entries $entries = Waitlist::all(); // Get recent entries $recent = Waitlist::latest()->take(10)->get(); // Export emails $emails = Waitlist::pluck('email')->toArray(); // Count total signups $count = Waitlist::count();
Named Routes
The package registers named routes that you can use in your application:
// Generate URLs route('waitlist.index') // GET /waitlist route('waitlist.store') // POST /waitlist // In Blade templates <a href="{{ route('waitlist.index') }}">Join Waitlist</a> // In redirects return redirect()->route('waitlist.index');
Custom Controller Usage
If you disable the default routes, you can use the controller in your own routes:
use KyleRusby\LaravelWaitlist\Http\Controllers\WaitlistController; Route::get('/join-us', [WaitlistController::class, 'index'])->name('waitlist.index'); Route::post('/join-us', [WaitlistController::class, 'store'])->name('waitlist.store');
Configuration
After publishing the config file, you'll find it at config/waitlist.php. Here are the available options:
Enable/Disable Waitlist
Control whether the waitlist functionality is enabled:
// .env WAITLIST_ENABLED=true // Or in config/waitlist.php 'enabled' => env('WAITLIST_ENABLED', true),
Route Configuration
Customize the routes or disable them entirely:
'routes' => [ 'enabled' => true, // Enable/disable package routes 'prefix' => '', // Add a prefix (e.g., 'early-access') 'middleware' => ['web'], // Apply middleware 'paths' => [ 'index' => '/waitlist', // GET route path 'store' => '/waitlist', // POST route path ], ],
Examples:
Disable routes to use your own:
'routes' => [ 'enabled' => false, ],
Add a prefix and custom path:
'routes' => [ 'prefix' => 'early-access', 'paths' => [ 'index' => '/join', 'store' => '/join', ], ], // Routes will be: /early-access/join
Apply guest middleware:
'routes' => [ 'middleware' => ['web', 'guest'], ],
Page Content
Customize the waitlist page text and appearance:
'headline' => 'Be the First to Experience Something Amazing', 'subheadline' => 'Join our exclusive waitlist and get early access when we launch.', 'badge_text' => 'Limited Early Access', 'button_text' => 'Join Waitlist', 'success_message' => 'Thank you for joining! We\'ll be in touch soon.', 'member_count' => 1234, // Displayed as social proof
Note: The success message is displayed in the view template. The controller returns "Added to waitlist!" as a flash message. To customize both, publish the views and modify the template.
Form Validation
The package includes built-in form validation with custom error messages:
// Validation rules 'email' => [ 'required', 'email', 'unique:waitlist,email', ] // Custom error messages 'email.required' => 'Please provide an email address.' 'email.email' => 'Please provide a valid email address.' 'email.unique' => 'This email is already on the waitlist.'
Complete Configuration Example
<?php return [ 'enabled' => env('WAITLIST_ENABLED', true), 'routes' => [ 'enabled' => true, 'prefix' => 'beta', 'middleware' => ['web', 'throttle:60,1'], 'paths' => [ 'index' => '/signup', 'store' => '/signup', ], ], 'headline' => 'Join the Beta Program', 'subheadline' => 'Get exclusive early access to our new platform.', 'badge_text' => '🚀 Beta Access', 'button_text' => 'Get Early Access', 'success_message' => 'Welcome to the beta! Check your email for next steps.', 'member_count' => 500, ];
Cloudflare Turnstile (Optional)
Protect your waitlist form from bots using Cloudflare Turnstile. This package ships with a Blade component and server-side validation ready to use.
1) Enable and Configure
Add the following to your .env:
CLOUDFLARE_TURNSTILE_ENABLED=true CLOUDFLARE_SITE_KEY=your-site-key CLOUDFLARE_TURNSTILE_SECRET=your-secret-key # Optional (defaults shown) CLOUDFLARE_TURNSTILE_THEME=light CLOUDFLARE_TURNSTILE_SIZE=normal CLOUDFLARE_TURNSTILE_CALLBACK=onSuccess
The config lives under config/waitlist.php → turnstile.
2) Use with the Package’s Built-in View
If you’re using the provided stub at GET /waitlist, Turnstile is already included. Just set your .env values above and you’re done.
3) Include in Your Own Blade View
If you aren’t using the provided stub, you can include the component inside your form:
<form method="POST" action="{{ route('waitlist.store') }}"> @csrf <input type="email" name="email" required> {{-- Cloudflare Turnstile --}} <x-waitlist::turnstile /> <button type="submit">Join Waitlist</button> </form>
The component automatically:
- Loads the Turnstile script
- Renders the widget
- Provides
cf-turnstile-responsefor server-side validation
Prefer to embed manually? You can, but don’t include both the component and manual embed at the same time:
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script> <div class="cf-turnstile" data-sitekey="{{ config('waitlist.turnstile.site_key') }}" data-theme="{{ config('waitlist.turnstile.theme') }}" data-size="{{ config('waitlist.turnstile.size') }}" data-callback="{{ config('waitlist.turnstile.callback') }}" ></div>
4) Server-side Verification
When CLOUDFLARE_TURNSTILE_ENABLED=true, the package’s request validator automatically verifies the token for the built-in POST /waitlist route.
If you use your own controller/request, add the rule yourself:
use KyleRusby\LaravelWaitlist\Rules\TurnstileRule; // In a FormRequest public function rules(): array { return [ 'email' => ['required', 'email'], 'cf-turnstile-response' => ['required', new TurnstileRule($this->ip())], ]; }
Or in a controller/route closure:
use Illuminate\Http\Request; use KyleRusby\LaravelWaitlist\Rules\TurnstileRule; Route::post('/waitlist', function (Request $request) { $request->validate([ 'email' => ['required', 'email'], 'cf-turnstile-response' => ['required', new TurnstileRule($request->ip())], ]); // ...store email });
Notes:
- Tokens are single-use and valid for ~5 minutes.
- The widget auto-populates
cf-turnstile-responseon form submit.
Customization
Customizing the View
Publish the views to customize the waitlist page:
php artisan vendor:publish --tag="waitlist-views"
The view will be published to resources/views/vendor/laravel-waitlist/waitlist.blade.php. You can then modify the HTML, styling, and layout to match your brand.
Using Your Own View
If you've disabled the package routes, you can create your own controller and view:
// routes/web.php use Illuminate\Http\Request; use KyleRusby\LaravelWaitlist\Models\Waitlist; Route::get('/waitlist', function () { return view('my-custom-waitlist'); }); Route::post('/waitlist', function (Request $request) { $request->validate([ 'email' => 'required|email|unique:waitlist,email', ]); Waitlist::create([ 'email' => $request->email, ]); return back()->with('success', 'Added to waitlist!'); });
Database Model
The Waitlist model is a standard Eloquent model with the following attributes:
id- Primary keyemail- Unique email address (string, 255)created_at- Timestampupdated_at- Timestamp
You can extend or customize it by creating your own model that extends the package's model:
namespace App\Models; use KyleRusby\LaravelWaitlist\Models\Waitlist as BaseWaitlist; class Waitlist extends BaseWaitlist { // Add custom scopes public function scopeRecent($query, $days = 7) { return $query->where('created_at', '>=', now()->subDays($days)); } // Add custom methods public function notify() { // Send notification email } // Add custom attributes public function getIsRecentAttribute(): bool { return $this->created_at->isToday(); } }
Usage:
// Using custom scope $recentSignups = Waitlist::recent(30)->get(); // Using custom attribute $entry = Waitlist::first(); if ($entry->is_recent) { // Do something }
Advanced Usage
Exporting Waitlist
Export all emails to a CSV:
use KyleRusby\LaravelWaitlist\Models\Waitlist; Route::get('/export-waitlist', function () { $filename = 'waitlist-' . now()->format('Y-m-d') . '.csv'; $headers = [ 'Content-Type' => 'text/csv', 'Content-Disposition' => "attachment; filename=\"$filename\"", ]; $callback = function () { $file = fopen('php://output', 'w'); fputcsv($file, ['Email', 'Joined At']); Waitlist::chunk(200, function ($entries) use ($file) { foreach ($entries as $entry) { fputcsv($file, [ $entry->email, $entry->created_at->format('Y-m-d H:i:s'), ]); } }); fclose($file); }; return response()->stream($callback, 200, $headers); });
Email Notifications
Send notifications to new signups using model observers:
// In a service provider (e.g., AppServiceProvider) use KyleRusby\LaravelWaitlist\Models\Waitlist; use Illuminate\Support\Facades\Mail; public function boot() { Waitlist::created(function ($waitlist) { Mail::to($waitlist->email)->send(new WelcomeToWaitlist($waitlist)); }); }
Or create a custom observer:
// app/Observers/WaitlistObserver.php namespace App\Observers; use KyleRusby\LaravelWaitlist\Models\Waitlist; use Illuminate\Support\Facades\Mail; use App\Mail\WelcomeToWaitlist; class WaitlistObserver { public function created(Waitlist $waitlist): void { Mail::to($waitlist->email)->send(new WelcomeToWaitlist($waitlist)); } } // Register in AppServiceProvider use App\Observers\WaitlistObserver; public function boot() { Waitlist::observe(WaitlistObserver::class); }
Adding Additional Fields
If you need to collect more than just email addresses, follow these steps:
- Publish and modify the migration:
// database/migrations/create_waitlist_table.php Schema::create('waitlist', function (Blueprint $table) { $table->id(); $table->string('email')->unique(); $table->string('name')->nullable(); $table->string('company')->nullable(); $table->text('reason')->nullable(); $table->timestamps(); });
- Update the model's fillable attributes:
namespace App\Models; use KyleRusby\LaravelWaitlist\Models\Waitlist as BaseWaitlist; class Waitlist extends BaseWaitlist { protected $fillable = [ 'email', 'name', 'company', 'reason', ]; }
- Extend the form request validation:
namespace App\Http\Requests; use KyleRusby\LaravelWaitlist\Http\Requests\StoreWaitlistRequest; class CustomWaitlistRequest extends StoreWaitlistRequest { public function rules(): array { return array_merge(parent::rules(), [ 'name' => 'required|string|max:255', 'company' => 'nullable|string|max:255', 'reason' => 'nullable|string|max:1000', ]); } }
- Publish and modify the view to include the new form fields.
Testing
Run the test suite:
composer test
Run tests with coverage:
composer test-coverage
Run static analysis:
composer analyse
Format code:
composer format
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.
kylerusby/laravel-waitlist 适用场景与选型建议
kylerusby/laravel-waitlist 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 51 次下载、GitHub Stars 达 0, 最近一次更新时间为 2025 年 10 月 15 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「laravel」 「Kyle Rusby」 「laravel-waitlist」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 kylerusby/laravel-waitlist 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 kylerusby/laravel-waitlist 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 kylerusby/laravel-waitlist 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Alfabank REST API integration
Laravel package for Accurate Online API integration.
Shared RCX Laravel DataTables UI and configuration helpers.
Boot a Laravel project on any machine with one command: app:serve installs missing tools (PHP, Node, Composer, Herd, Docker), creates .env, sets up the database, runs migrations, builds assets, starts a queue worker and serves via Herd, Sail or artisan serve; app:down cleanly stops everything it sta
Branded, diagnostic error pages (500, 403, 404, 419, 503) for Filament — native Filament UI, dark mode and translations out of the box.
Turn any PDF into a Pingen-ready A4 letter (generated address cover page + A4 normalisation + safe margins) and send it through the Pingen print & mail API. Laravel-first.
统计信息
- 总下载量: 51
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 15
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-10-15