CommunityCoding & Developmentgithub.com

Taldres/laravel-waitlist

Turn a taldres/laravel-waitlist waitlist into a launch: invite people in batches in signup order, let invited addresses register, announce the launch to everyone who agreed, and erase the list once its purpose is fulfilled.

What is laravel-waitlist?

laravel-waitlist is a Claude Code agent skill that turn a taldres/laravel-waitlist waitlist into a launch: invite people in batches in signup order, let invited addresses register, announce the launch to everyone who agreed, and erase the list once its purpose is fulfilled.

Works with~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Taldres/laravel-waitlist/tree/HEAD/resources/boost/skills/laravel-waitlist-launch

Installed? Explore more Coding & Development skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Laravel Waitlist: from waitlist to launch

Use this skill when an application using taldres/laravel-waitlist wants to let people in: early access invitations, a launch announcement, and cleaning up afterwards. The package has no invited state on purpose; build it on top.

Primary Goal

  • invite and announce only to addresses whose purpose is in force, record the invitation in the app, and erase the list when it has served its purpose

Workflow

1. Record invitations on your own model

// migration in the app
Schema::table('waitlist_entries', function (Blueprint $table) {
    $table->timestamp('invited_at')->nullable();
});
namespace App\Models;

use Taldres\Waitlist\Models\WaitlistEntry as BaseEntry;

class WaitlistEntry extends BaseEntry
{
    public function __construct(array $attributes = [])
    {
        $this->mergeFillable(['invited_at']);   // before the parent fills the model

        parent::__construct($attributes);
    }

    protected function casts(): array
    {
        return parent::casts() + ['invited_at' => 'datetime'];
    }
}
// config/waitlist.php
'model' => App\Models\WaitlistEntry::class,

If the subclass overrides booted(), it must call parent::booted().

2. Invite the next batch, first come first served

use Illuminate\Support\Facades\Mail;
use Taldres\Waitlist\Facades\Waitlist;
use Taldres\Waitlist\ScopedWaitlist;

// AppServiceProvider::boot()
ScopedWaitlist::macro('inviteNext', function (int $count = 10) {
    /** @var ScopedWaitlist $this */
    return $this->entries()
        ->whereConsentedTo('waitlist')   // the list's primary purpose: confirmed and still on the list
        ->whereNull('invited_at')
        ->oldest()
        ->limit($count)
        ->get()
        ->each(function ($entry) {
            $entry->forceFill(['invited_at' => now()])->save();
            Mail::to($entry->email)->queue(new YouAreInMail($entry, Waitlist::unsubscribeUrl($entry)));
        });
});
Waitlist::for('beta')->inviteNext(25);   // from a scheduled command, an admin action or Tinker

YouAreInMail carries an unsubscribe URL with a token; let it implement ShouldBeEncrypted so the queued mail is stored encrypted.

3. Let invited addresses in

$entry = Waitlist::for('beta')->find($request->string('email')->value());

abort_unless($entry?->invited_at !== null && $entry->hasConsentFor('waitlist'), 403);

find() also returns addresses that left; check hasConsentFor() or the status.

4. Announce the launch

use Taldres\Waitlist\Support\Recipient;

Waitlist::for('beta')->recipients()->each(
    fn (Recipient $recipient) => Mail::to($recipient->email)->locale($recipient->locale)->queue(new LaunchMail($recipient)),
);

recipients() returns everyone whose primary purpose is in force, once each, with an unsubscribe link and one-click headers for that list ($recipient->unsubscribeUrl(), $recipient->listUnsubscribeHeaders()).

5. Erase the list once its purpose is fulfilled

When the waitlist's purpose ("email me when early access opens") is fulfilled, erase it:

php artisan waitlist:forget --list=beta --all     # asks first; --force without a terminal

or Waitlist::for('beta')->forgetAll(). It erases every entry of the list with all its consents, optional ones such as a newsletter included. Consents cannot be moved: someone keeps the newsletter only through another list they joined themselves, a news list with newsletter as its primary purpose for example. Invite them to join it before erasing.

Rules, References, and Templates

Examples

  • "Invite 50 people from the beta waitlist every Monday": the macro from step 2 in a scheduled command.
  • "Only waitlisted people may register during early access": step 3 in the registration controller.
  • "We launched, clean up the waitlist": step 4, then step 5.

Anti-patterns

  • Inviting from entries() without whereConsentedTo(): it includes unconfirmed addresses and people who left.
  • Keeping the list forever after the launch "just in case".
  • Adding invited or rejected to the package's status or end reasons.
  • Putting a manage link into the invitation mail.

Individual skills in this repo

This repo contains 13 individual skills — each has its own dedicated page.

Taldres/laravel-waitlist

Use this skill when reviewing Laravel package compatibility across composer constraints, PHP versions, Laravel versions, Testbench versions, dependency stability lanes, Windows CI, or matrix-sensitive code and workflow changes.

Taldres/laravel-waitlist

Use this skill when creating or updating the bundled Laravel Boost skill under resources/boost/skills from the package implementation and package documentation. Trigger after public APIs, commands, config, routes, views, publish tags, README content, or examples change.

Taldres/laravel-waitlist

Use this skill when preparing Laravel package releases: CHANGELOG.md updates, generated release notes, GitHub release workflows, version checks, tags, release validation, or release automation changes. Never publish autonomously.

Taldres/laravel-waitlist

Use this skill when adding Laravel package capabilities or wiring them through the service provider: commands, migrations, routes, config merges, views, translations, assets, middleware, publish tags, workbench files, or console-only behavior.

Taldres/laravel-waitlist

Use this skill when writing, editing, fixing, or reviewing package tests with Pest 4/5 and Orchestra Testbench, including TDD, feature tests, unit tests, type coverage, arch tests, workbench behavior, commands, routes, config, migrations, and publishable resources.

Taldres/laravel-waitlist

Integrate taldres/laravel-waitlist in a Laravel application: define purposes, lists and fields, build the signup form, send the confirmation mail from events, add a preference page, and keep consent, retention and encryption intact.

Taldres/laravel-waitlist

Build the pages of a taldres/laravel-waitlist integration: the signup form with the registered wording, and the confirm, unsubscribe and preference pages, either in Laravel controllers (Blade, Livewire, Inertia) or in an SPA or static site over the package's JSON API, including CORS and bot protection.

Taldres/laravel-waitlist

Send the mails of a taldres/laravel-waitlist integration: the double opt-in confirmation, the preference page link, a welcome mail, launch mails and newsletters to the people who agreed, with the right unsubscribe links, one-click headers and a sender per project.

Taldres/laravel-waitlist

Operate a taldres/laravel-waitlist installation: answer access and erasure requests, withdraw a purpose on request, apply retention, erase a list once its purpose is fulfilled, rotate APP_KEY with waitlist:rekey, export a list, and check the setup before going live.

Taldres/laravel-waitlist

Run the waitlists of several products in one Laravel app with taldres/laravel-waitlist projects: define projects, scope facade calls with project(), resolve the project of HTTP signups, send mail per project, handle requests across all projects, or keep projects in a database for a central waitlist API.

Taldres/laravel-waitlist

Keep a newsletter tool such as Brevo, Mailchimp or Mailcoach in step with a taldres/laravel-waitlist waitlist: add confirmed contacts per purpose, remove them on withdrawal and erasure, and carry unsubscribes made at the provider back into the waitlist via a webhook.

Taldres/laravel-waitlist

Build waitlist statistics with taldres/laravel-waitlist: signups and confirmations per day for charts, totals and confirmation rates for a period, the confirmed count on any past day, and how many people are on a list right now, for dashboards, admin pages and API endpoints.

Taldres/laravel-waitlist

Write feature tests for an application's taldres/laravel-waitlist integration: get the plain tokens from events, assert the confirmation and other mails, test the signup, confirm and unsubscribe flows in PHP and over the package's HTTP routes, and bypass rate limits and bot checks in tests.

Related Skills