# Filament panels with live notifications and edit locks

> One command: a bell that updates at once, who’s here, edit locks, and tables that refresh themselves.

Source: https://hibira.io/use-cases/filament

Filament panels are where teams spend their day: orders, tickets, content and approvals. By default the panel finds out about changes by polling, so the notification bell lags up to 30 seconds, tables go stale, and two people can save over each other's work. Filament already speaks to any Pusher-compatible service through Laravel Echo, and our `hibira-io/filament` plugin turns that on with one command, for Filament 3, 4 and 5. There is no WebSocket server to run and nothing to build with npm.

## What your team gets

- A notification bell that updates the moment a notification is stored, for every notification your app already sends.
- Avatars of who else is on the same page, and edit locks so only one person edits a record at a time.
- Tables, relation managers and record pages that update themselves when something changes, in the panel, a queued job or an API call.
- Progress bars for imports and exports, and a team chat page.

![An edit lock: Mei is editing the article, so saving is off for everyone else, with an Ask to edit button](https://hibira.io/portal/articles/filament-lock-en-light.webp)

## Built with

- **Laravel Broadcasting** with the `hibira` connection from `hibira-io/laravel`.
- **Filament's own Laravel Echo**, pointed at Hibira by the plugin.
- **Private channels** for notifications, tables and records; **presence channels** for who's here and edit locks.
- The **Channels HTTP API**, which the server uses to check who is still on a record before moving its lock.

```text
flow: Your app sends changes to Hibira when a request or job ends; the panels that have the page open update at once
Laravel|saves, notifications, imports --one message per request--> *Hibira|ws.hibira.io --WebSocket--> Filament panel|bell, tables, record pages
== Who may listen
Filament panel|`POST /broadcasting/auth` --canAccessPanel()--> Laravel|channel rules --signature--> *Hibira
```

## Step 1: install with one command

```shell
composer require hibira-io/filament
php artisan hibira:filament
```

The command adds the settings to `.env` and asks for your app ID, key and secret, turns on the broadcasting auth route, creates the notifications table, and adds the plugin to your panel providers. Then it checks the connection and each panel. Run it again at any time; it only changes what is missing. Add your site's address to **Allowed origins** on your app page so browsers can connect.

## Step 2: notifications that arrive at once

Nothing to change in your code. Every database notification updates the bell as soon as it is stored, including ones sent without `isEventDispatched: true`:

```php
Notification::make()
    ->title('Order #1024 shipped')
    ->success()
    ->sendToDatabase($user);
```

Filament stores its notifications from the queue, so keep `php artisan queue:work` running, or use `QUEUE_CONNECTION=sync` while developing.

## Step 3: who's here and edit locks

`hibira:filament` turns on the avatars. For edit locks, add one trait to an edit page:

```php
class EditPost extends EditRecord
{
    use InteractsWithHibiraLock;

    protected static string $resource = PostResource::class;
}
```

The first person to open the record holds the lock; others can look and ask for it. When the holder leaves, the next person takes it within seconds, with no heartbeat polling.

![The holder gets the request and can save before handing over](https://hibira.io/portal/articles/filament-lock-request-en-light.webp)

## Step 4: live tables and record pages

With `liveTables()` and `liveRecords()` on, tables and record pages update for everyone who has them open. A burst of changes, such as an import of a thousand rows, is sent once per request or queued job, not once per row. Edit pages say who changed the record and load only the changed fields, so unsaved edits stay.

After a mass update through the query builder, which fires no model events, mark the table yourself:

```php
Order::query()->where('paid', false)->update(['status' => 'cancelled']);

app(\Hibira\Filament\LiveTables::class)->touch(Order::class);
```

![Ken saved the post while Mei was editing it: the page says so, and Load changes brings in only his fields](https://hibira.io/portal/articles/filament-live-record-en-light.webp)

## Step 5: more for your panel

- `->importProgress()` shows how far each import and export has got, chunk by chunk.
- `->chat()` adds a chat page for the panel's users.
- AI agents can show up in who's here and take edit locks like a person: see the [Filament guide](https://hibira.io/guides/filament).
- A [collaborative rich text editor](https://hibira.io/guides/filament-collab), an [inbox for AI tool approvals](https://hibira.io/guides/filament-approvals) and [AI live chat support](https://hibira.io/guides/filament-support) build on the same plugin.

![Importing 1,000 rows: the card moves with each chunk while the table fills in](https://hibira.io/portal/articles/filament-import-en-light.webp)

## Coming from Reverb or polling

If your panel already uses Echo with Reverb or Pusher, the plugin replaces the `filament.broadcasting.echo` settings for the panel it is on, and your own events and channel rules keep working. If the panel polls today, `->databaseNotifications()` turns polling off; pass `polling: '60s'` to keep it as a fallback. The [migration page](https://hibira.io/migrate) lists what to check.

## Tips

- Create one app per environment (local, staging, production) so test events never reach real users.
- Panels that sign in with their own guard need the broadcasting routes registered with it; `hibira:filament` tells you when.
- A burst of changes goes out as one message per request or queued job, which keeps usage low; see [pricing](https://hibira.io/pricing) for what each plan includes.
