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

Bearychat Laravel Package

laravel-notification-channels/bearychat

Send Laravel notifications to BearyChat with this channel driver. Post messages to BearyChat webhooks through Laravel's built-in notification system, keeping your team chat in sync with app events using a simple, familiar API.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first: this package is archived. You're not consuming a maintained dependency, you're adopting ~150 lines of source. That changes the workflow — you get leverage from this repo by reading and owning it, not by running composer require and hoping.

1. Verify it resolves before you write any app code. This is the whole risk surface.

composer show laravel-notification-channels/bearychat --all

Read the composer.json constraints against your PHP/Laravel versions. On Laravel 10/11/12 expect conflicts on illuminate/* or guzzlehttp/guzzle. If it fights you for more than ten minutes, stop — that's the signal to vendor.

2. The recommended path for day-to-day use: vendor it.

# Read the two source files, then copy them into your app
cp vendor/laravel-notification-channels/bearychat/src/BearyChatChannel.php \
   app/Notifications/Channels/
cp vendor/laravel-notification-channels/bearychat/src/BearyChatMessage.php \
   app/Notifications/Channels/
# Keep the MIT copyright header. Then drop the dependency.
composer remove laravel-notification-channels/bearychat

Now you own it, you can bump constraints, and you can debug it without patching vendor/.

3. Configure the webhook conventionally.

// config/services.php
'bearychat' => [
    'webhook' => env('BEARYCHAT_WEBHOOK'),
],
BEARYCHAT_WEBHOOK=https://hook.bearychat.com/=xxxx/incoming/yyyy

4. Write your first notification.

php artisan make:notification DeployFinished
use Illuminate\Notifications\Notification;
use App\Notifications\Channels\BearyChatMessage;

class DeployFinished extends Notification
{
    public function __construct(public string $env, public string $sha) {}

    public function via($notifiable): array
    {
        return ['bearychat'];
    }

    public function toBearyChat($notifiable): BearyChatMessage
    {
        return BearyChatMessage::create()
            ->markdown("**Deploy complete** `{$this->sha}` → *{$this->env}*");
    }
}

5. Send and verify in one shot.

Notification::route('bearychat', config('services.bearychat.webhook'))
    ->notify(new DeployFinished('production', 'a1b2c3d'));

Where to look first. Open BearyChatChannel.php and check two things: (a) how send() builds the HTTP request, and (b) whether it calls ->throw() on non-2xx — that single detail decides whether your observability works. Then read BearyChatMessage.php for the exact builder surface (text(), markdown(), and which payload fields actually get emitted). Two files, ten minutes, and you can maintain this yourself.

First use case. Internal ops alerting — deploy finished, CI failed, cron missed. Low stakes, high signal, and it lets you validate the webhook contract and markdown rendering in a channel nobody pages on.

Implementation Patterns

Route per notifiable instead of hardcoding one webhook. routeNotificationForBearyChat() is the single most useful extension point — one notification class, N destinations, no per-team code:

class Team extends Model
{
    public function routeNotificationForBearyChat(): string
    {
        return $this->bearychat_webhook; // store encrypted
    }
}

Queue it, on its own queue. BearyChat is an external HTTP hop and must never sit in the request cycle or share a worker pool with mail:

class DeployFinished extends Notification implements ShouldQueue
{
    public $queue    = 'notifications-chat';
    public $tries    = 3;
    public $backoff  = [10, 60, 300];
    public $timeout  = 10;
}

A dedicated queue means a BearyChat outage or a hung socket cannot back up your primary notification workers.

Gate the channel in via(), not inside the message builder. Staging noise is the fastest way to get the integration muted:

public function via($notifiable): array
{
    return app()->isProduction() ? ['bearychat'] : ['log'];
}

Keep a thin shared message factory. By the third notification you want one place that formats the header, environment tag, and bullet list:

class ChatMessage
{
    public static function alert(string $title, array $lines, string $level = 'info'): BearyChatMessage
    {
        $body = collect($lines)->map(fn ($l) => "- {$l}")->implode("\n");

        return BearyChatMessage::create()
            ->markdown("**[{$level}] {$title}**\n{$body}");
    }
}

Put the channel behind your own interface if chat is on the roadmap. Define ChatChannel / ChatMessage contracts in your app; let the BearyChat implementation be one of several (Slack, DingTalk, Feishu, Teams). Swapping destinations then costs a class, not a refactor.

Test the payload, not just the status. Http::fake() plus a shape assertion is what catches schema drift after a config or payload change:

Http::fake(['hook.bearychat.com/*' => Http::response(['ok' => true], 200)]);

Notification::route('bearychat', 'https://hook.bearychat.com/=t/incoming/x')
    ->notify(new DeployFinished('production', 'a1b2c3d'));

Http::assertSent(function ($request) {
    return str_contains($request['markdown'], 'Deploy complete')
        && $request->url() === 'https://hook.bearychat.com/=t/incoming/x';
});

Keep at least one contract test asserting the JSON keys — that's your regression net for a package with no upstream.

Observe failures instead of discovering them in a postmortem. Listen for NotificationFailed and feed it into your existing alerting so a rotated webhook surfaces as a metric, not as silence:

Event::listen(NotificationFailed::class, function ($event) {
    if ($event->channel === 'bearychat') {
        Log::warning('bearychat delivery failed', [
            'notification' => get_class($event->notification),
            // never log $event->data — it contains the webhook URL
        ]);
    }
});

Subclass the channel for custom behaviour. If you need request signing, an extra payload field, or a different HTTP client, extend BearyChatChannel and register that subclass — don't edit the copied source in place. Keeps your patches re-syncable against the original if you ever revisit it.

Gotchas and Tips

Verify whether non-2xx actually throws. Laravel's HTTP client only throws on ->throw() / ->throwIf(). If BearyChatChannel::send() posts without that, a 400 completes "successfully" and your notification vanishes silently. Check it, and if it's missing, wrap the call yourself:

Http::timeout(10)->retry(3, 200)->post($webhook, $payload)->throw();

The webhook URL is a credential. Anyone holding it can post into that channel. Store it in your secrets manager (not a committed .env), and scrub it from exception context and failed-job payloads — Laravel serialises notification data into failed_jobs, which is easy to overlook.

Don't fight Composer for an archived package. --ignore-platform-reqs and constraint hacks buy you a dependency you'll still have to read and debug. Vendor it and move on.

Message builder surface is small — check before assuming. Text and markdown only. Don't design around attachments, buttons, threading, or read receipts until you've confirmed them in BearyChatMessage.php.

Markdown and Unicode need care. User-supplied strings in markdown can break formatting or inject links — escape or code-fence anything from input (deployer name, branch, commit message). Emoji and CJK render fine in JSON but trip naive string-length assertions in tests.

Debug with a real curl before blaming the code.

curl -sS -X POST "$BEARYCHAT_WEBHOOK" \
  -H 'Content-Type: application/json' \
  -d '{"text":"hello from curl"}'

If that fails, it's the endpoint or network egress. If it succeeds but the notification doesn't, Http::fake() is probably still registered, or bearychat isn't in via().

Watch queue semantics on repeated failure. tries = 3 against a dead webhook means three timeouts per notification per retry window. Set timeout and backoff explicitly and route exhausted jobs to a monitored failed-jobs queue — otherwise a BearyChat outage surfaces three hours later as a "database problem."

Don't put it on the paging path. For an archived integration, use it for informational alerts only. If a message must be seen, route through something maintained and monitored.

Assign an owner and write one page. Where the channel lives, how to rotate the webhook, how to run the contract test. That's the entire onboarding cost for the next engineer, and it's what keeps this from becoming tribal knowledge in six months.

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.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums