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

Discord Laravel Package

laravel-notification-channels/discord

Send Discord messages from your Laravel app through the notification system. This channel lets you post rich embeds, files, and webhook messages using Laravel's familiar notification classes.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit — good, with a hard scope boundary. This is a thin adapter into Laravel's existing notification pipeline: via() returns DiscordChannel::class, the notifiable exposes routeNotificationForDiscord(), and toDiscord() returns a DiscordMessage whose toArray() is literally the Discord webhook JSON body. There is no new runtime component to own — no bot process, no gateway connection, no Discord app registration, no inbound endpoint. That maps cleanly onto any roadmap item shaped like "tell a channel that something happened." It maps poorly onto anything a stakeholder might assume that implies: this is outbound, one-way, webhook-only. No replies, reactions, edits, threads, slash commands, or presence. Interactive payloads (buttons, select menus) are described as supported, but handling an interaction is a different package, different hosting, different permissions. Correct that assumption in the kickoff, not at demo time.

Integration feasibility — low effort, high confidence. composer require is the whole install: no config publish, no migration, no service-provider registration, no token. Auto-discovery wires it up and the only runtime dependency is Laravel's HTTP client. A first end-to-end alert into a single #ops channel is a ~15-minute exercise that exercises routing, payload building, and queueing at once. The package is small enough to read in full before committing, which is the cheapest possible due diligence.

Technical risk — concentrated in operations, not integration.

Risk Severity Note
Webhook URL is a bearer credential High No second factor, no signature, no expiry. Anyone with the URL can post. Must be encrypted at rest, hidden from serialization, scrubbed from Telescope/Sentry stack traces.
Payload limits fail as runtime 400s High Oversized content/embeds/fields blow up in production, not in tests. A 400 means the notification silently never arrived — the worst failure mode for an alerting channel.
Rate limits are normal operation Medium Discord returns 429 with retry_after; the channel surfaces this as an exception. Unqueued or undeduplicated senders turn a burst into a self-inflicted outage.
Rotated/deleted webhook Medium Presents as a permanent 401/404 stream into failed_jobs where nobody looks. Needs alerting on the Discord queue plus a written rotation drill.
Community maintenance / bus factor Medium 240 stars, 0 dependents, low cadence, MIT. Mitigated by the package being three readable classes — forking or vendoring is a day, not a quarter. Laravel 13 support arrived via a laravel-shift PR, which is a healthy signal for framework-compat churn but not for feature roadmap.
No global config default Low New users expect config/discord.php; there isn't one. A null route fails at runtime — gate the channel in via() so webhook-less notifiables skip rather than throw.

Key questions for engineering before we commit scope:

  1. Which roadmap items genuinely need Discord, and are any of them on-call paging? If yes, this is a channel we mirror, not the sole delivery path, until we've validated behaviour under a 429 burst.
  2. Do we need per-tenant or per-team webhook routing (column on a model, encrypted), or is a single config-driven #ops webhook sufficient for the first two quarters?
  3. Who owns webhook secrets and the rotation runbook — platform or the team that owns the Discord server?
  4. Do we stand up a dedicated notifications-discord queue, and is it in failed-job alerting on day one?
  5. Is interactivity (buttons that do something) anywhere on the roadmap? If so, budget a separate workstream; this package is not that.
  6. Do we accept a ^1.8 minor pin with a mandatory manual smoke test on every bump, and does the PHP floor implied by Laravel 13 clear our platform?

Recommendation: adopt (buy, don't build). The per-feature saving over an in-house webhook client is small, but it compounds across every roadmap item that posts to Discord, and it retires a recurring class of bespoke payload-formatting and retry bugs. The residual risks are operational hygiene we'd have to solve for a homegrown client anyway.

Integration Approach

Stack fit. Drops into via() alongside mail, database, and other channels with no orchestration changes. Release 1.8.0 is compatibility-only (Laravel 13.x, no API changes), so it can be taken before a framework upgrade to avoid stacking two constraint changes in one window — but confirm the implied PHP floor against our platform first. One routing subtlety to encode in our conventions: the channel calls routeNotificationForDiscord(), not routeNotificationFor('discord'), and on-demand routing (Notification::route('discord', $url)) bypasses the model method entirely.

Migration path.

  • From a bespoke HTTP client: wrap existing payload construction in DiscordMessage/DiscordEmbed, add a payload contract test asserting the JSON matches the current outbound shape, ship behind that test, then delete the old code. This is a parity exercise, not a rewrite.
  • From nothing: greenfield, start with the deploy/failure alert.
  • Schema impact: none, unless we want per-tenant webhooks — then one encrypted-cast column, added to $hidden, plus a rotation procedure. No data migration.

Compatibility and pinning. Pin ^1.8. Upgrade cadence is community-driven, so treat every bump as needing one real end-to-end smoke test — the package's test suite will not catch Discord API drift for us. Watch for minor releases that are framework-compat only (take those early) versus ones that touch the payload builder (test those deliberately).

Sequencing.

  1. Week 1 — prove it. Single internal #ops webhook, one DeployFailed notification, queued. Verify the payload by dumping toArray().
  2. Queue hardening. Dedicated notifications-discord queue with tries/backoff, plus failed-job alerting on that queue. This is not optional; it is the difference between a 429 blip and a silent alerting outage.
  3. Establish guardrails. Payload contract test pattern (asserting embed shape and Discord's size limits), a single severity→color map, and truncation helpers (Str::limit) applied to exception messages and stack snippets before they reach a field.
  4. Extend to system alerts. On-demand routing for cron monitors, failed jobs, health checks — the pattern where no user model exists.
  5. Multi-tenant routing (if question 2 says yes): encrypted webhook column, $hidden, redaction configured in error tracking, rotation runbook written before it's needed.
  6. Fan out to product-facing notifications alongside mail, gated in via() by webhook presence. Use allowedMentions(['parse' => []]) as the default posture and permit mentions deliberately on the one or two notifications that should page a human.

Explicitly out of sequence until validated under load: on-call paging.

Operational Impact

Maintenance. Our burden is our own notifications, payload tests, and secret handling — not the package. The integration surface is three classes (DiscordChannel, DiscordMessage, DiscordEmbed), readable in full and forkable in roughly a day under MIT. Budget an internal owner for the fork path rather than an SLA; there is no vendor support, only GitHub issues and PRs.

Support. Community-maintained, effectively one to two maintainers. Laravel 13 compatibility arriving via laravel-shift suggests the ecosystem keeps the framework constraint current, but nothing guarantees feature work. The realistic escalation path for a blocking bug is a local patch, so verify the package is vendorable in our deploy pipeline before we depend on it in a revenue-adjacent flow.

Scaling. Throughput is bounded by Discord's per-webhook and global rate limits, not by anything the package does — no connection pooling, no long-running process, no state to shard. The scaling model is therefore organizational and structural: a webhook per tenant/team, isolated queues so a 429 burst can't starve mail, and deduplication/collapse at the source. A monitor that fires on every failed health check will burn the limit and then fail all subsequent alerts; throttling belongs upstream of the queue, not inside it. Fan-out to N channels means N notifications — loop over webhook URLs rather than expecting one payload to multi-target.

Failure modes to instrument.

Symptom Cause Detection
Silent non-delivery 400 from payload limits or an empty message (no content, no embeds) Payload contract test in CI; assert non-empty before send
Retry storm / failed jobs 429 under burst, insufficient tries/backoff or no dedupe Queue depth and failed-job count on notifications-discord
Permanent failure Webhook rotated or deleted → 401/404 forever Alert on the Discord queue; rotation drill
Runtime job failure routeNotificationForDiscord() returns null Gate the channel in via()
Credential exposure Webhook URI persisted by Telescope/Sentry in an exception Redaction config; assume it will otherwise appear in a stack trace

Ramp-up. A Laravel-fluent engineer reaches a working notification in about 15 minutes; a production-grade pattern (queue isolation, payload tests, truncation, severity map, mention discipline) in roughly half a day; multi-tenant webhook storage plus a rotation runbook in one to two days. There is no new infrastructure to learn — no bot hosting, no Discord application or permission model — so the real ramp-up cost is learning Discord's payload semantics and limits, and internalizing that this is a deliberately narrow, one-way channel. Write that scope boundary down; it prevents the most likely stakeholder disappointment later.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource