Panels
Panels are the main configuration surface for Wirechat. Instead of scattering package setup across multiple files, you can keep routing, access rules, visual settings, chat-list behavior, and feature flags in one provider.
Most applications start with one panel, then add more panels when different user areas need different chat behavior.
Default Panel Setup
When you install Wirechat, a default panel is created at app/Providers/Wirechat/ChatsPanelProvider.php. The chat UI is available at '/chats' by default.
Creating Panels
You can create multiple panels to support different user roles, such as:
- Admins accessing exclusive features at
/admin. - Regular users accessing chats at
/chats.
To create a panel named support, run:
php artisan make:wirechat-panel support
This creates app/Providers/Wirechat/SupportPanelProvider.php and mounts the panel at /support by default. Use a different panel name when you want a different generated provider and default path.
Wirechat attempts to register the provider automatically. If the panel route is not available, add the generated provider to bootstrap/providers.php.
Generated Chat Routes
When route registration is enabled, each panel registers two main chat routes:
| Method | Path | Route name | Purpose |
|---|---|---|---|
GET |
{panel-path} |
wirechat.{panel-path}.chats |
Shows the chats list |
GET |
{panel-path}/{conversation} |
wirechat.{panel-path}.chat |
Shows a single conversation |
For the default panel id chats mounted at /chats, those routes are:
GET /chats wirechat.chats.chats
GET /chats/{conversation} wirechat.chats.chat
Use the panel route helpers when you need to link to them from application code:
$panel->chatsRoute();
$panel->chatRoute($conversation);
When group invitations are enabled, Wirechat also registers panel-owned public invite routes used by copied invite links.
If you disable route registration with registerRoutes(false), Wirechat skips the generated full-page chat routes. Embedded/widget Livewire navigation can still open chats internally. Set mountUrl() to the app page where this panel is mounted when browser hand-offs still need a destination.
Quick Example
Here is a realistic panel provider example that combines some of the most commonly used panel methods:
use Wirechat\Wirechat\Panel;
use Wirechat\Wirechat\Enums\ColorTone;
use Wirechat\Wirechat\Support\Color;
use Wirechat\Wirechat\Support\Enums\EmojiPickerPosition;
use Wirechat\Wirechat\Support\Enums\UnreadIndicatorType;
public function panel(Panel $panel): Panel
{
return $panel
->id('chats')
->path('chats')
->middleware(['web', 'auth'])
->chatMiddleware(['verified'])
->chatsSearch()
->unreadIndicator(type: UnreadIndicatorType::Count)
->settings()
->emojiPicker(position: EmojiPickerPosition::Docked)
->attachments()
->colors([
'primary' => Color::Blue,
])
->colorTone(ColorTone::Soft)
->heading('Chat')
->createChatAction()
->createGroupAction()
->redirectToHomeAction(url: '/dashboard')
->default();
}
Api
Panel ID
The panel ID identifies the panel across the application. Set it using the id() method:
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->id('chats');
}
Path
Customize the panel’s URL path using the path() method:
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->path('chats');
}
To use the root URL (no prefix), set an empty path:
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->path('');
}
Note: Ensure routes/web.php does not define a conflicting '' or '/' route, as it takes precedence.
Register Routes
Wirechat registers panel routes by default. Disable route registration when you want to render Wirechat components inside your own routes instead:
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->registerRoutes(false);
}
When route registration is disabled, Wirechat skips the generated chat routes for that panel. Embedded/widget Livewire navigation remains supported, so internal chat actions can still open conversations inside the mounted component.
Use mountUrl() when your app hosts Wirechat on its own route and public Wirechat links need somewhere to continue:
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->registerRoutes(false)
->mountUrl('/app/messages');
}
With a mount URL configured, public invite links, notification clicks, message-request redirects, and Pro tray expand actions can hand users back to the page that renders Wirechat. Without a mount URL, those browser hand-offs stay disabled while generated routes are disabled. For the embedded page setup, see Standalone Widget.
Middleware
Apply additional middleware to Wirechat routes using the middleware() method:
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->middleware(['web', 'auth']);
}
Chat Middleware
The belongsToConversation middleware is automatically applied to /chats/{conversation} to restrict access to authorized users, such as conversation members. Add custom middleware to modify chat access:
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->chatMiddleware([
// Additional middleware
]);
}
Enable Chats Search
Enable the chat search field in the Wirechat UI:
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->chatsSearch();
}
Note: Disable search by passing false: ->chatsSearch(false).
modifyConversationsQuery()
Use modifyConversationsQuery() to apply panel-specific constraints to the conversations shown in the chats list, such as showing only private chats.
use Illuminate\Database\Eloquent\Builder;
use Wirechat\Wirechat\Enums\ConversationType;
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->modifyConversationsQuery(function (Builder $query) {
return $query->where('type', ConversationType::PRIVATE);
});
}
The callback receives the conversations query. It can also receive the authenticated model when the filter needs user-specific data. You may mutate the builder directly or return a builder.
Wirechat applies this hook before ordering and cursor pagination. Use it for panel-level list filtering, such as showing only private, self, or group conversations. If the same rule is an authorization boundary, also enforce it in your application middleware or policies.
Parse Message URLs
Enable message link parsing so URLs and recognized bare domains (like example.com) render as clickable links inside chat bubbles:
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->parseMessageUrls();
}
Disable it explicitly by passing false:
->parseMessageUrls(false);
This feature only wraps the URL segments, leaving the rest of the message body unchanged. Link recognition respects the wirechat.message_url_parsing config settings.
You can tune link recognition globally in config/wirechat.php:
'message_url_parsing' => [
// Allow domains like "example.com" without http/https.
'allow_bare_domains' => true,
// Limit recognized TLDs for bare domains.
// Set to null to allow all TLDs, or [] to block all.
'allowed_tlds' => [
'com', 'net', 'org', 'io', 'co', 'me', 'app', 'dev', 'ai', 'gg', 'tv',
'info', 'biz', 'xyz', 'site', 'store', 'shop', 'pro', 'cloud',
],
],
Unread Messages Indicator
Use unreadIndicator() to control how unread conversations are highlighted in the chats list.
By default, Wirechat uses a small unread dot, so existing panels keep the current behavior without needing any changes:
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->unreadIndicator();
}
If you prefer a numeric unread badge, pass the UnreadIndicatorType enum:
use Wirechat\Wirechat\Panel;
use Wirechat\Wirechat\Support\Enums\UnreadIndicatorType;
public function panel(Panel $panel): Panel
{
return $panel
//...
->unreadIndicator(type: UnreadIndicatorType::Count);
}
You may also disable the unread indicator completely:
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->unreadIndicator(false);
}
This setting affects the chats list in both full-page and widget mode.
If you are upgrading from earlier panel examples, unReadMessages() still works as a backward-compatible alias, but unreadIndicator() is now the preferred name.
Conversation Tabs
Organize the chats list into focused views such as All, Unread, or Groups.
Conversation tabs are available in Wirechat Pro. See Tabs for the full API and examples.
use Wirechat\Wirechat\Panel;
use Wirechat\Wirechat\Support\Tabs\Tab;
public function panel(Panel $panel): Panel
{
return $panel
//...
->tabs(
Tab::make('all'),
Tab::make('groups')->count(),
)
->defaultTab('all');
}
conversationContexts()
List and open context conversations in this panel.
Conversation contexts are available in Wirechat Pro. See Conversation Contexts for the full guide.
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->conversationContexts();
}
When conversationContexts() is enabled, the chats list shows only conversations that have a context relationship. Normal private chats and group chats stay hidden in that panel.
When it is disabled, context conversations stay hidden and normal conversations continue to show. You do not need modifyConversationsQuery() just to make a context-only panel.
Enable Emoji Picker
Enable Emoji Picker element in Chat
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->emojiPicker();
}
By default the emoji picker has position floating. You can change it to docked using the enum:
use Wirechat\Wirechat\Panel;
use Wirechat\Wirechat\Support\Enums\EmojiPickerPosition;
public function panel(Panel $panel): Panel
{
return $panel
//...
->emojiPicker(position:EmojiPickerPosition::Docked);
}
Web Push Notifications
Wirechat web push notifications keep you connected to conversations via browser notifications, even when the app is not active:
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->webPushNotifications();
}
Note: Disable notifications by passing false: ->webPushNotifications(false).
Settings Drawer
Enable the Settings entry in the chats header:
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->settings();
}
The Settings drawer is opt-in and exposes user-owned preferences such as notifications and group privacy. For the full guide, see Settings.
Pass false to disable it: ->settings(false).
Messages Queue
High Priority (messages): For real-time broadcasting of messages to users in a conversation.
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->messagesQueue('messages');
}
Events Queue
Default Priority (default): For notifications like updating chat lists or showing unread message counts.
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->eventsQueue('default');
}
Layout
Wirechat uses the default layout wirechat::layouts.app. Override it with a custom layout:
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->layout('layouts.app');
}
Attachments
Enable both file and media attachments:
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->attachments();
}
Setting to false disables attachments entirely: ->attachments(false).
File Attachments
Allow only document uploads (e.g., PDFs, ZIPs, text files):
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->fileAttachments();
}
Media Attachments
Allow only image and video uploads:
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->mediaAttachments();
}
Content Viewer
Browse shared media, documents, and links from a conversation-level viewer inside the chat details panel.
Content Viewer is available in Wirechat Pro. See Content Viewer for the full guide.
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->contentViewer();
}
Pass false to disable it: ->contentViewer(false).
Color theme
Use colors() to choose the primary hue, then use colorTone() to choose soft or solid primary surfaces.
use Wirechat\Wirechat\Enums\ColorTone;
use Wirechat\Wirechat\Panel;
use Wirechat\Wirechat\Support\Color;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->colors([
'primary' => Color::Blue,
])
->colorTone(ColorTone::Soft);
}
Heading
Set a custom heading for the chat panel:
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->heading('Chats');
}
Favicon
Customize the chat panel with a favicon that reflects your brand.
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->favicon(url:asset('favicon.ico'));
}
Actions
Wirechat panel actions let you control shortcuts such as creating chats, creating groups, clearing chats, deleting chats, returning home, and deleting messages.
For full action documentation, including icon and icon-attribute configuration, see the Actions page.
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
//...
->createChatAction()
->createGroupAction()
->clearChatAction()
->deleteChatAction()
->redirectToHomeAction(url: '/dashboard')
->deleteMessageActions()
->messageReplyAction();
}