Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Discord Laravel Package

tomatophp/filament-discord

Connects your Filament admin panel to Discord. Send notifications and alerts to Discord channels via webhooks, manage integration settings from a simple Filament page, and keep your team informed without leaving the dashboard.

View on GitHub
Deep Wiki
Context7

Getting Started

Pin to your panel's major line before anything else. v5.0.0 is Filament v5 / Laravel 12–13 only; Filament v3 panels stay on the separate v3 branch. Check tags, then constrain explicitly:

composer show -a tomatophp/filament-discord

# Filament v5 panel
composer require tomatophp/filament-discord:"^5.0"

# Filament v3 panel — do NOT use ^5.0
composer require tomatophp/filament-discord:"^3.0"
php artisan vendor:publish --tag="filament-discord-config"

Put the credential in .env, never in the committed config:

DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/xxxx/yyyy

Where to look first, in order of authority

  1. README.md — confirms the actual call surface. Is it ->sendToDiscord() on a Filament Notification, a Laravel channel, or a facade? Verify the method name before writing code; the description is vague about this.
  2. config/filament-discord.php — the webhook key, the separate error webhook key, channel/username/avatar overrides, queue settings.
  3. tests/ — new in v5 and now the best documentation of real behaviour. The suite fakes Discord HTTP calls, so it shows exact endpoints, payload shapes, and config keys. When tests and README disagree, trust the tests.
  4. src/ — notification class, error reporter, service provider. Small enough to read entirely in five minutes.
  5. composer.json — confirm the Filament constraint matches your panel.

First use case: notify on record creation, wired into the resource hook. Put it in afterCreate() so it inherits panel auth context rather than living in a controller:

use Filament\Notifications\Notification;

protected function afterCreate(): void
{
    Notification::make()
        ->title('New order received')
        ->body("Order #{$this->record->id} — {$this->record->customer_name}")
        ->success()
        ->sendToDiscord(); // confirm exact method in README/tests
}

Smoke-test before you build on it. As of v5.0.0 a missing webhook is silently skipped — a typo'd env key behaves identically to a working setup with no destination configured. Trigger a throwaway send from Tinker or a temp action button and confirm the message lands in Discord before touching lifecycle hooks.

Implementation Patterns

Wrap the vendor call in your own helper — this is the highest-value pattern for a 2-star package.

final class Ops
{
    public static function alert(string $title, string $body): void
    {
        Notification::make()
            ->title($title)
            ->body(Str::limit($body, 1900))
            ->danger()
            ->sendToDiscord();

        Log::info('ops.alert', ['title' => $title]); // because sends swallow failures
    }
}

This isolates the rest of the app from a rename or abandonment, gives you one place to add logging and truncation, and makes the eventual vendor-and-fork trivial.

Drive it from observers and lifecycle hooks, not scattered calls. afterCreate, afterUpdate, model observers, or a queued listener — one obvious location per event. Keep payloads to IDs plus human labels and always link back into the panel; Discord is a paging surface, not an audit log:

->body("{$order->id} — " . OrderResource::getUrl('edit', ['record' => $order]))

Route by severity across multiple webhooks. Map Filament notification status to destination: success/info → #activity, warning/danger → #alerts, and the package's error reporter → a separate #errors channel with its own webhook key. Channel separation costs nothing but config.

Treat the error reporter as a second-tier safety net. v5's reporter never throws and no-ops on an empty error webhook, so it can never take down a request — but that also means it can never be your only signal. Keep Sentry/Bugsnag in front of it.

Queue everything triggered from a user request. Implement ShouldQueue on your wrapper or dispatch a queued job. This keeps Discord latency (and 429s) out of the request path and out of the UI.

Prefer scheduled digests over per-event spam. An Artisan command plus the scheduler producing rollups ("3 failed jobs, 12 new orders since 09:00") is dramatically less noisy and avoids most rate-limit incidents.

Test with faked HTTP, mirroring the package's own suite:

Http::fake(['discord.com/*' => Http::response([], 204)]);

// ... exercise the code path ...

Http::assertSent(fn ($request) =>
    str_contains($request->url(), 'discord.com')
    && str_contains($request->body(), 'New order received')
);

Set a dummy webhook URL in the test env — otherwise v5's skip-on-missing behaviour makes your "it sent" assertions pass vacuously against a no-op. If the package ships a Laravel notification channel, Notification::fake() plus a channel assertion is the cleaner path. Either way, CI must never hit a real webhook.

Add a panel-level affordance for day-to-day use. A page header action or a small custom Filament page with a channel select and message body lets non-developers broadcast from inside the admin panel — that's what turns this from a decoration into a tool the team actually opens.

Gotchas and Tips

  • The v5 jump is a hard Filament-major break. v5.0.0 is Filament v5 / Laravel 12–13 only; there is no release covering both lines. Plan it as a coupled panel-upgrade plus package-upgrade, not a routine composer update.
  • Missing webhook = silent skip (new in v5). A bad URL is no longer a failed HTTP call — the message is dropped before it's attempted. When messages "stop arriving," check the env var, the exact config key, and config cache before you check Discord's side.
  • Webhook URLs are bearer credentials. Anyone with the URL posts as your bot — including the error webhook. Rotate in Discord the moment one appears in a log, screenshot, or exception trace.
  • Rate limits are per-webhook (~30 req/min plus burst). A created observer on a busy model will hit 429s within minutes. Queue, batch, or debounce.
  • Hard content limits: ~2000 chars per message, 10 embeds. Str::limit($body, 1900) or you get a 400 that surfaces as a generic failed HTTP call.
  • Filament Notification ≠ Laravel Notification. The description says "native FilamentPHP Notification Facade" — that means the panel notification object, not Illuminate\Notifications\Notification. via() and toDiscord() do not belong in the same class. This is the single most common confusion with this package.
  • Config caching on production. After changing a webhook, run php artisan config:cache (or config:clear). Combined with skip-on-missing, a stale cache is doubly invisible: you may be posting to a dead channel, or nowhere, with no error either way.
  • Silent failure is the default on the send path. The error reporter never throws, and normal sends swallow HTTP failures so the UI notification still reports success. Log status inside your Ops wrapper or you'll debug "missing messages" with zero signal.
  • Deleted or rotated webhooks return 404/401 and never recover. Keep a small Artisan smoke command and run it after Discord channel maintenance.
  • Mention injection. If the body passes through verbatim, user-supplied content can inject @everyone / <@id>. Strip <@ sequences from anything user-derived — including exception messages going to the error reporter, which may contain attacker-controlled input.
  • Own the rendering, borrow the transport. Subclass the shipped notification class (or copy it into app/Notifications) so embeds, colors, mentions, and field ordering stay under your control while the package only handles delivery.
  • Version pinning is not optional. Two stars, zero dependents: treat it as unmaintained-by-default. Pin the exact version, keep the wrapper, and be ready to vendor the notification class if it stalls against a future Filament release.
  • PHP 8.4. The deprecation fix landed in v5. On PHP 8.3 + Filament v3 you're on the v3 branch carrying the unfixed deprecations.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core