jansuchanek / nchat
Reusable real-time admin chat extension for Nette Framework with WebSocket support (Soketi/Pusher), typing indicators, presence, read receipts, and optional AI responder.
v1.1.0
2026-03-19 09:59 UTC
Requires
- php: >=8.1
- nette/application: ^3.2
- nette/di: ^3.1
- nette/http: ^3.2
Suggests
- doctrine/dbal: For raw SQL queries
- doctrine/orm: For entity management
README
Reusable real-time chat extension for Nette Framework admin panels with WebSocket support (Soketi/Pusher), typing indicators, presence detection, read receipts, emoji reactions, sound alerts, and browser push notifications.
Features
- ๐ฌ Broadcast + DM + Group chat
- โก WebSocket real-time (Soketi/Pusher) with polling fallback
- โ๏ธ Typing indicators โ "Jan pรญลกeโฆ"
- ๐ฅ Online presence โ instant online/offline
- โโ Read receipts โ DM delivery confirmation
- ๐ Emoji reactions โ ๐โค๏ธ๐๐ฎ๐ข๐
- ๐ Sound alerts โ Web Audio API ping (toggleable)
- ๐ข Push notifications โ Browser Notification API
- ๐ค AI Bot integration โ pluggable via
AiResponderInterface - ๐๏ธ Database agnostic โ
ChatStorageInterface(DBAL included)
Installation
{
"repositories": [
{"type": "vcs", "url": "git@gitlab.com:JanSuchanek/nchat.git"}
],
"require": {
"jansuchanek/nchat": "dev-main"
}
}
Configuration
extensions: nchat: NChat\ChatExtension nchat: websocket: host: soketi port: 6001 appId: my-app key: my-key secret: my-secret storage: NChat\Storage\DbalChatStorage # or your own ai: enabled: true responder: App\Model\MyAiResponder # implements AiResponderInterface
Usage
Add the trait to any presenter:
final class AdminPresenter extends BasePresenter { use NChat\Presenter\ChatPresenterTrait; }
Then add chat action names to your allowed actions:
$openActions = array_merge(['dashboard'], self::getChatActionNames());
Custom Database Storage
Implement ChatStorageInterface for any database:
class SqliteChatStorage implements ChatStorageInterface { public function saveMessage(array $data): int { /* ... */ } public function fetchMessages(int $userId, array $criteria = []): array { /* ... */ } // ...8 methods total }
Custom AI Responder
class MyAiResponder implements AiResponderInterface { public function respond(string $context): string { /* call OpenAI/Claude/Gemini */ } public function getSystemPrompt(): string { return 'You are...'; } public function getBotName(): string { return '๐ค Bot'; } }
License
MIT