A generic, role-based in-app chat system for Next.js applications
npm install @bernierllc/in-app-chatA 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.
- 🎯 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
``bash`
npm install @bernierllc/in-app-chat
`typescript
// app/layout.tsx
import { MessagingProvider } from '@bernierllc/in-app-chat';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
$3
`typescript
// components/Navigation.tsx
import { MessagesIcon, MessagesDropdown } from '@bernierllc/in-app-chat';export function Navigation() {
return (
);
}
`$3
`typescript
// app/messages/page.tsx
import { MessagesPage } from '@bernierllc/in-app-chat';export default function Messages() {
return ;
}
`Configuration
$3
`typescript
interface InAppChatConfig {
roles: string[];
permissions: Record;
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 enabled: boolean;
package: string;
description: string;
requiresAuth?: boolean;
platforms?: string[];
}>;
}
`$3
`typescript
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
$3
Enable bidirectional messaging with Slack workspaces:
`typescript
// 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:
`bash
SLACK_BOT_TOKEN=xoxb-your-bot-token
SLACK_SIGNING_SECRET=your-signing-secret
`Install Integration Package:
`bash
npm install @bernierllc/chat-integration-slack
`$3
`bash
npm install @bernierllc/chat-integration-discord
`$3
`bash
npm install @bernierllc/chat-integration-teams
`Slash Commands via NeverHub
$3
Commands are automatically discovered and registered when their packages come online:
`typescript
// 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'
}
}
};
`$3
Install the command packages you need:
`bash
Task management
npm install @bernierllc/slash-commands-tasksCalendar/scheduling
npm install @bernierllc/slash-commands-calendarAuthentication commands (admin only)
npm install @bernierllc/slash-commands-auth
`$3
1. in-app-chat registers with NeverHub as command router
2. Command packages register their capabilities with NeverHub
3. in-app-chat automatically discovers and registers commands
4. Commands work across all enabled platforms (in-app, Slack, Discord, Teams)
5. When packages go offline, commands are automatically deregistered
$3
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:
`sql
-- 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 conversations
- GET /api/messaging/conversations/[id] - Get specific conversation
- POST /api/messaging/conversations - Create new conversation
- GET /api/messaging/conversations/[id]/messages - Get conversation messages
- POST /api/messaging/conversations/[id]/messages - Send message
- PUT /api/messaging/messages/[id] - Edit message
- DELETE /api/messaging/messages/[id] - Delete message
- POST /api/messaging/messages/[id]/reactions - Add reaction
- GET /api/messaging/templates - Get message templates
- POST /api/messaging/bulk - Send bulk messagesComponents
$3
-
MessagingProvider - Main provider component
- MessagesIcon - Navigation icon with unread count
- MessagesDropdown - Quick access dropdown
- MessagesPage - Full messaging interface
- ConversationList - List of conversations
- MessageThread - Message thread view
- MessageInput - Message input component
- MessageBubble - Individual message display$3
-
RoleBasedFilters - Role-specific filtering
- BulkMessageModal - Bulk messaging interface
- TemplateSelector - Message template selector
- FileUpload - File attachment component
- MessageSearch - Search functionalityCustomization
$3
`typescript
// 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',
},
},
},
},
};
`$3
`typescript
// components/CustomMessageBubble.tsx
import { MessageBubble, MessageBubbleProps } from '@bernierllc/in-app-chat';export function CustomMessageBubble(props: MessageBubbleProps) {
return (
);
}
`Extending for Your App
$3
`typescript
// 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'];
};
}
`$3
`typescript
// 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
`typescript
// 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 (
conversations={studentConversations}
onSendMessage={sendMessage}
customFilters={[
{ label: 'Teachers', value: 'teacher' },
{ label: 'Classmates', value: 'student' },
]}
/>
);
}
`Testing
`typescript
// __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(
);
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
- 📚 Documentation
- 🛠️ Installation Guide
- 💡 Examples
- 🐛 Issue Tracker
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:
`bash
npm install --legacy-peer-deps
``This is a temporary workaround until official support is released.