@bernierllc/in-app-chat
v2.2.0
Published
A generic, role-based in-app chat system for Next.js applications
Readme
@bernierllc/in-app-chat
A comprehensive, role-based in-app chat suite for Next.js applications with external platform integrations and slash command routing. This package provides a complete messaging solution that can be easily integrated into any Next.js application with support for Slack, Discord, Teams, and dynamic slash commands via NeverHub service discovery.
Note: Roles are fully configurable. You can use any string for roles (e.g., 'user', 'admin', 'moderator', 'customer', etc.) and configure permissions as needed. No roles are hardcoded.
Features
- 🎯 Role-based messaging - Different interfaces and features for different user types
- 🔒 Secure communication - Encrypted message IDs and access validation
- ⚡ Real-time updates - Live message delivery and status updates
- 📎 File attachments - Support for documents and media sharing
- 📝 Message templates - Role-specific pre-written messages
- 📨 Bulk messaging - Send messages to multiple recipients
- 🔍 Search and filtering - Advanced conversation management
- 📱 Responsive design - Works on desktop and mobile
- ♿ Accessibility - WCAG 2.1 AA compliant
- 🎨 Customizable - Easy to theme and extend
- 🚀 External Integrations - Slack, Discord, Teams bridging with user mapping
- ⚡ Slash Commands - Dynamic command routing via NeverHub service discovery
- 🔧 Live Configuration - Admin UI toggles for features and integrations
- 🌐 Service Discovery - Auto-register commands when packages come online
Quick Start
1. Install the package
npm install @bernierllc/in-app-chat2. Add to your Next.js app
// app/layout.tsx
import { MessagingProvider } from '@bernierllc/in-app-chat';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<MessagingProvider
config={{
roles: ['user', 'admin', 'moderator'],
permissions: {
user: ['send_message', 'view_conversations'],
admin: ['send_message', 'view_conversations', 'bulk_message', 'delete_messages'],
moderator: ['send_message', 'view_conversations', 'moderate_messages'],
},
}}
>
{children}
</MessagingProvider>
</body>
</html>
);
}3. Add messaging components to your navigation
// components/Navigation.tsx
import { MessagesIcon, MessagesDropdown } from '@bernierllc/in-app-chat';
export function Navigation() {
return (
<nav>
<MessagesIcon />
<MessagesDropdown />
</nav>
);
}4. Create a Messaging Page
// app/messages/page.tsx
import { MessagesPage } from '@bernierllc/in-app-chat';
export default function Messages() {
return <MessagesPage />;
}Configuration
Basic Configuration
interface InAppChatConfig {
roles: string[];
permissions: Record<string, string[]>;
features?: {
realTime?: boolean;
fileAttachments?: boolean;
templates?: boolean;
bulkMessaging?: boolean;
search?: boolean;
};
styling?: {
theme?: 'light' | 'dark' | 'auto';
primaryColor?: string;
borderRadius?: string;
};
database?: {
type: 'sqlite' | 'postgresql' | 'mysql';
connectionString?: string;
};
// NEW: External platform integrations
integrations?: {
slack?: {
enabled: boolean;
userMapping: 'external' | 'internal' | 'mixed';
bidirectional: boolean;
slashCommands: boolean;
};
discord?: { enabled: boolean; };
teams?: { enabled: boolean; };
};
// NEW: Slash command routing
slashCommands?: Record<string, {
enabled: boolean;
package: string;
description: string;
requiresAuth?: boolean;
platforms?: string[];
}>;
}Advanced Configuration with Integrations
const advancedConfig = {
roles: ['user', 'admin', 'moderator', 'support'],
permissions: {
user: ['send_message', 'view_conversations', 'edit_own_messages'],
admin: ['send_message', 'view_conversations', 'bulk_message', 'delete_messages', 'view_analytics'],
moderator: ['send_message', 'view_conversations', 'moderate_messages', 'pin_messages'],
support: ['send_message', 'view_conversations', 'view_support_tickets'],
},
features: {
realTime: true,
fileAttachments: true,
templates: true,
bulkMessaging: true,
search: true,
messageReactions: true,
messageThreading: true,
},
styling: {
theme: 'auto',
primaryColor: '#3b82f6',
borderRadius: '0.5rem',
},
database: {
type: 'postgresql',
connectionString: process.env.DATABASE_URL,
},
// External platform integrations
integrations: {
slack: {
enabled: true,
userMapping: 'external',
bidirectional: true,
slashCommands: true,
socketMode: true,
channelWhitelist: ['#general', '#support']
},
discord: { enabled: false },
teams: { enabled: false }
},
// Slash command routing via NeverHub
slashCommands: {
'/task': {
enabled: true,
package: '@bernierllc/slash-commands-tasks',
description: 'Create and manage tasks',
requiresAuth: true,
platforms: ['in-app', 'slack', 'discord']
},
'/schedule': {
enabled: true,
package: '@bernierllc/slash-commands-calendar',
description: 'Schedule meetings and events',
adminOnly: false
}
},
// NeverHub service discovery
neverhub: {
enabled: true,
serviceName: 'in-app-chat-suite',
autoRegisterCommands: true
}
};External Platform Integrations
Slack Integration
Enable bidirectional messaging with Slack workspaces:
// in-app-chat.config.js
module.exports = {
integrations: {
slack: {
enabled: true,
userMapping: 'external', // Show Slack users as "external" in browser
bidirectional: true, // Messages flow both ways
slashCommands: true, // Enable slash commands in Slack
socketMode: true, // Use Socket Mode for real-time
channelWhitelist: ['#general', '#support']
}
}
};Required Environment Variables:
SLACK_BOT_TOKEN=xoxb-your-bot-token
SLACK_SIGNING_SECRET=your-signing-secretInstall Integration Package:
npm install @bernierllc/chat-integration-slackDiscord Integration
npm install @bernierllc/chat-integration-discordMicrosoft Teams Integration
npm install @bernierllc/chat-integration-teamsSlash Commands via NeverHub
Dynamic Command Registration
Commands are automatically discovered and registered when their packages come online:
// in-app-chat.config.js
module.exports = {
slashCommands: {
'/task': {
enabled: true,
package: '@bernierllc/slash-commands-tasks',
description: 'Create and manage tasks',
requiresAuth: true,
platforms: ['in-app', 'slack', 'discord'],
aliases: ['/tasks', '/todo']
},
'/schedule': {
enabled: true,
package: '@bernierllc/slash-commands-calendar',
description: 'Schedule meetings and events'
}
}
};Available Slash Command Packages
Install the command packages you need:
# Task management
npm install @bernierllc/slash-commands-tasks
# Calendar/scheduling
npm install @bernierllc/slash-commands-calendar
# Authentication commands (admin only)
npm install @bernierllc/slash-commands-authService Discovery Flow
- in-app-chat registers with NeverHub as command router
- Command packages register their capabilities with NeverHub
- in-app-chat automatically discovers and registers commands
- Commands work across all enabled platforms (in-app, Slack, Discord, Teams)
- When packages go offline, commands are automatically deregistered
Admin UI Integration
Toggle commands and integrations live:
- Enable/disable individual slash commands
- Toggle integrations (Slack, Discord, Teams) on/off
- Manage permissions for role-based command access
- View integration status and health monitoring
Database Schema
The package includes a complete database schema that can be automatically generated:
-- Users table (extends your existing users)
CREATE TABLE messaging_users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
role VARCHAR(50) NOT NULL,
display_name VARCHAR(255) NOT NULL,
avatar_url TEXT,
is_online BOOLEAN DEFAULT false,
last_seen TIMESTAMP DEFAULT NOW(),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Conversations table
CREATE TABLE messaging_conversations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
title VARCHAR(255),
type VARCHAR(50) NOT NULL DEFAULT 'direct',
metadata JSONB,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Conversation participants
CREATE TABLE messaging_conversation_participants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
conversation_id UUID NOT NULL REFERENCES messaging_conversations(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES messaging_users(id) ON DELETE CASCADE,
role VARCHAR(50) NOT NULL,
joined_at TIMESTAMP DEFAULT NOW(),
left_at TIMESTAMP,
UNIQUE(conversation_id, user_id)
);
-- Messages table
CREATE TABLE messaging_messages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
conversation_id UUID NOT NULL REFERENCES messaging_conversations(id) ON DELETE CASCADE,
sender_id UUID NOT NULL REFERENCES messaging_users(id) ON DELETE CASCADE,
content TEXT NOT NULL,
message_type VARCHAR(50) DEFAULT 'text',
metadata JSONB,
reply_to_id UUID REFERENCES messaging_messages(id),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Message attachments
CREATE TABLE messaging_message_attachments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
message_id UUID NOT NULL REFERENCES messaging_messages(id) ON DELETE CASCADE,
file_name VARCHAR(255) NOT NULL,
file_url TEXT NOT NULL,
file_size INTEGER NOT NULL,
mime_type VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
-- Message templates
CREATE TABLE messaging_message_templates (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
category VARCHAR(100),
role VARCHAR(50) NOT NULL,
variables JSONB,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Message reactions
CREATE TABLE messaging_message_reactions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
message_id UUID NOT NULL REFERENCES messaging_messages(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES messaging_users(id) ON DELETE CASCADE,
reaction_type VARCHAR(50) NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
UNIQUE(message_id, user_id, reaction_type)
);
-- Message read receipts
CREATE TABLE messaging_message_read_receipts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
message_id UUID NOT NULL REFERENCES messaging_messages(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES messaging_users(id) ON DELETE CASCADE,
read_at TIMESTAMP DEFAULT NOW(),
UNIQUE(message_id, user_id)
);API Routes
The package provides a complete set of API routes:
GET /api/messaging/conversations- Get user conversationsGET /api/messaging/conversations/[id]- Get specific conversationPOST /api/messaging/conversations- Create new conversationGET /api/messaging/conversations/[id]/messages- Get conversation messagesPOST /api/messaging/conversations/[id]/messages- Send messagePUT /api/messaging/messages/[id]- Edit messageDELETE /api/messaging/messages/[id]- Delete messagePOST /api/messaging/messages/[id]/reactions- Add reactionGET /api/messaging/templates- Get message templatesPOST /api/messaging/bulk- Send bulk messages
Components
Core Components
MessagingProvider- Main provider componentMessagesIcon- Navigation icon with unread countMessagesDropdown- Quick access dropdownMessagesPage- Full messaging interfaceConversationList- List of conversationsMessageThread- Message thread viewMessageInput- Message input componentMessageBubble- Individual message display
Role-Specific Components
RoleBasedFilters- Role-specific filteringBulkMessageModal- Bulk messaging interfaceTemplateSelector- Message template selectorFileUpload- File attachment componentMessageSearch- Search functionality
Customization
Styling
// tailwind.config.js
module.exports = {
content: [
'./src/**/*.{js,ts,jsx,tsx}',
'./node_modules/@bernierllc/in-app-chat/dist/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {
colors: {
messaging: {
primary: '#3b82f6',
secondary: '#64748b',
success: '#10b981',
warning: '#f59e0b',
error: '#ef4444',
},
},
},
},
};Custom Components
// components/CustomMessageBubble.tsx
import { MessageBubble, MessageBubbleProps } from '@bernierllc/in-app-chat';
export function CustomMessageBubble(props: MessageBubbleProps) {
return (
<div className="custom-message-bubble">
<MessageBubble {...props} />
</div>
);
}Extending for Your App
1. Define Your User Types
// types/messaging.ts
export interface AppUser {
id: string;
name: string;
email: string;
role: 'student' | 'teacher' | 'admin';
avatar?: string;
}
export interface AppMessagingConfig {
roles: ['student', 'teacher', 'admin'];
permissions: {
student: ['send_message', 'view_conversations'];
teacher: ['send_message', 'view_conversations', 'bulk_message'];
admin: ['send_message', 'view_conversations', 'bulk_message', 'delete_messages'];
};
}2. Create Custom Hooks
// hooks/useAppMessaging.ts
import { useMessaging } from '@bernierllc/in-app-chat';
import { AppUser } from '../types/messaging';
export function useAppMessaging() {
const messaging = useMessaging();
// Add app-specific logic
const sendStudentMessage = (studentId: string, message: string) => {
return messaging.sendMessage({
recipientId: studentId,
recipientType: 'student',
message,
metadata: { appType: 'education' },
});
};
return {
...messaging,
sendStudentMessage,
};
}3. Add App-Specific Features
// components/StudentMessaging.tsx
import { MessagesPage, useMessaging } from '@bernierllc/in-app-chat';
export function StudentMessaging() {
const { conversations, sendMessage } = useMessaging();
const studentConversations = conversations.filter(
conv => conv.participants.some(p => p.role === 'student')
);
return (
<MessagesPage
conversations={studentConversations}
onSendMessage={sendMessage}
customFilters={[
{ label: 'Teachers', value: 'teacher' },
{ label: 'Classmates', value: 'student' },
]}
/>
);
}Testing
// __tests__/in-app-chat.test.tsx
import { render, screen } from '@testing-library/react';
import { MessagingProvider } from '@bernierllc/in-app-chat';
test('renders messaging interface', () => {
render(
<MessagingProvider config={{ roles: ['user'], permissions: { user: ['send_message'] } }}>
<MessagesPage />
</MessagingProvider>
);
expect(screen.getByText('Messages')).toBeInTheDocument();
});Performance
The package is optimized for performance:
- Code splitting - Only loads components when needed
- Virtual scrolling - Handles large message lists efficiently
- Optimistic updates - Immediate UI feedback
- Efficient caching - Reduces API calls
- Bundle optimization - Minimal impact on app size
Security
Built-in security features:
- Message encryption - Secure message IDs
- Access validation - Role-based permissions
- Input sanitization - XSS protection
- Rate limiting - Prevents abuse
- Audit logging - Track all activities
Support
License
MIT License - see LICENSE for details.
Monorepo Workspaces & Dependency Management
This package is part of a monorepo using npm workspaces. All dependencies are hoisted to the root. Always run npm install from the root directory.
React 19 and Testing Library Compatibility
This package uses React 19.1.0. If you see peer dependency warnings with Testing Library, use:
npm install --legacy-peer-depsThis is a temporary workaround until official support is released.
