Real-time Chat Example

Build real-time applications with MoroJS WebSockets and events. Features live messaging, user presence, typing indicators, and message persistence.

Chat Features

Real-time Messaging

  • • Instant message delivery
  • • Message persistence
  • • Message history
  • • Read receipts

User Presence

  • • Online/offline status
  • • Typing indicators
  • • User list management
  • • Last seen timestamps

Advanced Features

  • • Room-based chat
  • • File sharing
  • • Message reactions
  • • Push notifications

WebSocket Implementation

Chat Server Setup (Simplified Demo)

typescript

1// src/server.ts - Basic Implementation
2import { createApp, z, validate } from '@morojs/moro';
3
4// Create app with WebSocket support
5const app = createApp();
6
7// Simple in-memory storage for demo
8let users: any[] = [];
9let rooms: any[] = [
10  { id: 'general', name: 'General Chat', description: 'Main chat room' },
11  { id: 'random', name: 'Random', description: 'Random discussions' }
12];
13let messages: any[] = [];
14
15// Basic welcome endpoint
16app.get('/', (req, res) => {
17  return {
18    message: 'Real-time Chat API - Simple Demo',
19    status: 'running',
20    version: '1.0.0',
21    note: 'This is a simplified demo without database dependencies',
22    endpoints: [
23      'GET / - This message',
24      'GET /health - Health check',
25      'GET /rooms - Get available rooms',
26      'GET /test - WebSocket test client (open in browser)',
27      'POST /auth/register - Simple user registration (no persistence)',
28      'POST /auth/login - Simple user login (no persistence)',
29      'WebSocket /chat - Real-time chat functionality'
30    ],
31    websocket: {
32      url: 'ws://localhost:3000/chat',
33      events: ['join', 'message', 'leave']
34    }
35  };
36});
37
38// Simple authentication endpoints (no database)
39app.post('/auth/register', 
40  validate({
41    body: z.object({
42      username: z.string().min(3).max(20),
43      email: z.string().email(),
44      password: z.string().min(6)
45    })
46  }, async (req, res) => {
47    // Check if user already exists
48    const existingUser = users.find(u => u.email === req.body.email || u.username === req.body.username);
49    if (existingUser) {
50      res.status(400);
51      return { error: 'User already exists with this email or username' };
52    }
53
54    // Create user (in memory)
55    const user = {
56      id: Date.now().toString(),
57      username: req.body.username,
58      email: req.body.email,
59      createdAt: new Date().toISOString()
60    };
61    
62    users.push(user);
63    
64    return { 
65      user, 
66      token: `demo-token-${user.id}`,
67      message: 'User registered successfully (demo mode - no persistence)'
68    };
69  })
70);
71
72// Basic WebSocket handler
73app.websocket('/chat', {
74  connect: (socket: any) => {
75    console.log(`🔗 WebSocket client connected: ${socket.id}`);
76  },
77  
78  disconnect: (socket: any) => {
79    console.log(`❌ WebSocket client disconnected: ${socket.id}`);
80  },
81  
82  join: (socket: any, data: any) => {
83    console.log(`📝 Join event received:`, data);
84    const roomId = data.roomId || 'general';
85    const username = data.username || 'Anonymous';
86    
87    console.log(`👥 ${username} joined room ${roomId}`);
88    
89    return { 
90      success: true, 
91      message: `Joined room ${roomId}`,
92      room: rooms.find(r => r.id === roomId) || { id: roomId, name: roomId }
93    };
94  },
95  
96  message: (socket: any, data: any) => {
97    console.log(`💬 Message event received:`, data);
98    const roomId = data.roomId || 'general';
99    const username = data.username || 'Anonymous';
100    
101    const message = {
102      id: Date.now(),
103      content: data.message,
104      sender: username,
105      roomId,
106      timestamp: new Date().toISOString()
107    };
108    
109    // Store message in memory
110    messages.push(message);
111    console.log(`📨 Broadcasting message to room ${roomId}:`, message);
112    
113    return { success: true, message: 'Message sent' };
114  }
115});
116
117// REST API endpoints
118app.get('/rooms', (req, res) => {
119  return { 
120    rooms,
121    message: 'Available chat rooms'
122  };
123});
124
125app.get('/rooms/:roomId/messages', (req, res) => {
126  const roomMessages = messages
127    .filter(m => m.roomId === req.params.roomId)
128    .slice(-50); // Last 50 messages
129  
130  return { 
131    messages: roomMessages,
132    roomId: req.params.roomId,
133    count: roomMessages.length
134  };
135});
136
137const PORT = Number(process.env.PORT) || 3000;
138app.listen(PORT, () => {
139  console.log(`Real-time Chat Server running on port ${PORT}`);
140  console.log(`WebSocket endpoint: ws://localhost:${PORT}/chat`);
141  console.log(`Test client: http://localhost:${PORT}/test`);
142});

Run the Example

Getting Started

typescript

1# Clone and setup
2git clone https://github.com/Moro-JS/examples.git
3cd examples/real-time-chat
4
5# Install dependencies
6npm install
7
8# Start development server (no database setup required)
9npm run dev
10
11# Access the application:
12# - API: http://localhost:3000
13# - WebSocket Test Client: http://localhost:3000/test
14# - WebSocket: ws://localhost:3000/chat
15
16# Available endpoints:
17# GET  / - API documentation
18# GET  /rooms - Available chat rooms
19# POST /auth/register - User registration (in-memory)
20# POST /auth/login - User login (in-memory)
21# GET  /rooms/:roomId/messages - Get room messages
22
23# Available commands:
24npm run dev          # Start development server
25npm run build        # Build for production
26npm run start        # Start production server
27
28# Note: This is a simplified demo with in-memory storage
29# No database setup required for basic functionality

What You'll Learn

  • • WebSocket connection management
  • • Real-time event broadcasting
  • • Message persistence strategies
  • • User presence tracking
  • • Scaling real-time applications
  • • Client-server synchronization

Next Steps