orchid/alert
Orchid Alert adds dismissible alert notifications to Laravel Orchid admin panels, with success, info, warning, and danger styles, a Blade component, session flash integration, and configurable rendering for quick user feedback.
Before writing a single line of application code, establish whether this package is already in your tree and how it renders. Orchid commonly pulls orchid/* satellites transitively, so the cheapest integration is often no integration at all.
composer show orchid/alert # is it installed? which version?
composer why orchid/alert # transitive via orchid/platform, or direct?
composer why-not orchid/alert 11.0 # does the constraint admit your Laravel/PHP?
Then read the source — it should be a handful of files:
ls vendor/orchid/alert/src vendor/orchid/alert/resources/views
grep -rn "function \(success\|error\|warning\|info\|message\|render\)" vendor/orchid/alert/src
Note two things from that read: the exact facade/class name (commonly Orchid\Support\Facades\Alert) and the shipped Blade view name (it is included from your layout as @include('alert::alert') in most versions — confirm the namespace from the view path; if a render() method exists, {!! Alert::render() !!} is the alternative form). Also confirm whether the shipped view calls e()/{{ }} on the message body; that determines your escaping obligations later.
First use case — the 90% path. Flash a success message in a controller and render it in the admin layout after the redirect:
use Orchid\Support\Facades\Alert;
public function store(StoreProjectRequest $request)
{
$project = Project::create($request->validated());
Alert::success("Project «{$project->name}» saved.");
return redirect()->route('platform.projects');
}
{{-- resources/views/vendor/platform/layouts/app.blade.php --}}
@include('alert::alert')
Test this on an Orchid screen you already have. If messages appear with no layout change, your theme/layout already includes the partial and you are done integrating — everything below is hygiene.
Controller → redirect. The canonical loop: push on the request that mutates, render on the request after the redirect. All four levels (success, info, warning, error) behave identically; Alert::message($text) without a level falls back to info.
Orchid Screen / CommandBar / Action handlers. Same API, different entry point. Screens that return back() are the natural fit:
protected function commandBar(): array
{
return [
Button::make('Reindex')->method('reindex'),
];
}
public function reindex(): void
{
$count = $this->service->reindex();
Alert::success("Reindexed {$count} records.");
}
Batch/import flows. One aggregated message beats N messages — the session flash budget is small and stacked toasts are unreadable. Collect counters in the service, summarize at the boundary:
Alert::warning("Import finished with {$skipped} skipped rows (see log).");
Wrap it before you sprinkle it. Zero dependents and no release cadence means you should assume "no upstream fix." Keep the vendor namespace in exactly one file so a fork, inline replacement, or a swap to Laravel Notifications is mechanical:
namespace App\Support;
use Orchid\Support\Facades\Alert;
final class AdminAlerts
{
public static function success(string $m): void { Alert::success($m); }
public static function info(string $m): void { Alert::info($m); }
public static function warning(string $m): void { Alert::warning($m); }
public static function error(string $m): void { Alert::error($m); }
}
Controllers, screens, actions, and services call AdminAlerts::success(...). Code review rejects Orchid\Support\Facades\Alert outside app/Support/.
Custom markup. Publish the package views (php artisan vendor:publish and pick the alert tag, or copy the partial into resources/views/vendor/) and edit the wrapper classes to match your theme rather than restyling with !important overrides in the layout.
Testing. Flashing is session state, so assert on the response body rather than guessing a session key:
$this->actingAs($admin)->post(route('platform.projects.store'), $data)
->assertRedirect(route('platform.projects'));
$this->get(route('platform.projects'))
->assertSee('saved');
Multi-panel setups. If you run more than one Orchid panel or guard, verify a message flashed in panel A does not surface in panel B — session flash keys are shared unless the package namespaces them per-panel.
Silent non-rendering is the #1 failure mode. Messages push fine and never display if your layout (or a theme override) omits the partial. There is no exception, no log line. When "alerts stopped showing," check the layout and any published vendor/platform views before touching controllers. Add "re-verify alert rendering on two screens" to every Orchid upgrade checklist.
Leaking flashes on non-redirect responses. Alert::success() in a request that returns JSON or a Livewire-ish partial response leaves the flash sitting in the session; it then pops up on an unrelated page load minutes later. Only flash on requests that end in a redirect-and-render cycle, or explicitly clear the bag in that branch.
Escape user-controlled strings yourself. This is an admin panel — a filename or project title flowing into "Import failed: {filename}" is a stored-XSS vector in a privileged context if the shipped partial interpolates unescaped. Re-read the Blade view after every version bump and pass e($filename) when in doubt. Do not rely on the package.
Session size under the cookie driver. Flash lives in the session; the cookie driver caps around 4 KB. Long exception messages plus several stacked alerts can silently drop. Truncate exception text and log the detail server-side.
Auto-discovery is a convention, not a guarantee. Package discovery works in a normal Laravel skeleton. If you run a stripped-down or cached bootstrap, verify the provider registers (php artisan package:discover) before assuming the facade exists.
Pin the version. "orchid/alert": "x.y.*" — not ^x. A dormant single-maintainer package plus composer update is how you get a constraint conflict that blocks a Laravel or Orchid upgrade in six months. Check composer why-not against your target majors before committing to them.
Understand what it is not. Despite the name, this is session-flash UI glue: no mail, SMS, Slack, queue, persistence, routing, or audit trail. If a requirement mentions acknowledgement, history, severity escalation, or on-call paging, it belongs to Laravel Notifications with a real channel — not here. Push back early.
Exit path stays cheap. Because every call site goes through AdminAlerts, replacing this with a ~100-line session-flash helper plus one owned Blade partial is about a day. Budget that day mentally when you adopt; do not invest in extending the package's API, because nobody upstream will maintain your extension.
How can I help you explore Laravel packages today?