WebSocket Chat Plugin

Real-Time Messaging for Bubble Native Mobile Apps

📋 Overview

The WebSocket Chat plugin enables real-time messaging in your Bubble native mobile apps. This guide will walk you through setting up a basic WebSocket server and connecting it to your Bubble app.

Note: This plugin requires a WebSocket server that you host. We'll show you how to create a simple one using Node.js.

🚀 Quick Start

1 Set Up WebSocket Server

First, let's create a simple WebSocket server. You'll need Node.js installed on your server.

Install Dependencies

mkdir websocket-chat-server
cd websocket-chat-server
npm init -y
npm install express ws

Create Server File

Create a file named server.js:

const express = require('express');
const http = require('http');
const WebSocket = require('ws');

const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });

// Store connected clients by room
const rooms = {};

// Store recent messages in memory (simple implementation)
const messageHistory = {};

// Helper: Add client to room
function addToRoom(roomId, ws) {
	if (!rooms[roomId]) {
		rooms[roomId] = new Set();
	}
	rooms[roomId].add(ws);
	console.log(`Client added to room ${roomId}. Total: ${rooms[roomId].size}`);
}

// Helper: Remove client from room
function removeFromRoom(roomId, ws) {
	if (rooms[roomId]) {
		rooms[roomId].delete(ws);
		if (rooms[roomId].size === 0) {
			delete rooms[roomId];
		}
	}
}

// Helper: Broadcast message to room
function broadcastToRoom(roomId, message) {
	if (!rooms[roomId]) return;
	
	const messageStr = JSON.stringify(message);
	rooms[roomId].forEach(client => {
		if (client.readyState === WebSocket.OPEN) {
			client.send(messageStr);
		}
	});
}

// Helper: Save message to history
function saveMessage(roomId, message) {
	if (!messageHistory[roomId]) {
		messageHistory[roomId] = [];
	}
	
	messageHistory[roomId].push(message);
	
	// Keep only last 100 messages
	if (messageHistory[roomId].length > 100) {
		messageHistory[roomId].shift();
	}
}

// Helper: Get message history
function getHistory(roomId, limit = 50) {
	if (!messageHistory[roomId]) return [];
	
	const history = messageHistory[roomId];
	const start = Math.max(0, history.length - limit);
	return history.slice(start);
}

// WebSocket connection handler
wss.on('connection', (ws) => {
	console.log('New client connected');
	let currentRoom = null;
	
	ws.on('message', (data) => {
		try {
			const message = JSON.parse(data);
			console.log('Received:', message);
			
			// Handle get_history request
			if (message.action === 'get_history') {
				currentRoom = message.room;
				addToRoom(currentRoom, ws);
				
				const history = getHistory(currentRoom, message.limit || 50);
				
				ws.send(JSON.stringify({
					type: 'history',
					messages: history
				}));
			}
			
			// Handle send_message request
			else if (message.action === 'send_message') {
				const roomId = message.room;
				
				const messageData = {
					id: Date.now().toString() + Math.random(),
					text: message.text,
					sender: message.sender,
					sender_id: message.user_id,
					timestamp: message.timestamp || new Date().toISOString()
				};
				
				// Save to history
				saveMessage(roomId, messageData);
				
				// Broadcast to all clients in room
				broadcastToRoom(roomId, {
					type: 'message',
					...messageData
				});
				
				console.log(`Message sent to room ${roomId}`);
			}
			
		} catch (error) {
			console.error('Error:', error);
		}
	});
	
	ws.on('close', () => {
		if (currentRoom) {
			removeFromRoom(currentRoom, ws);
		}
		console.log('Client disconnected');
	});
});

// HTTP endpoint for sending messages via API
app.use(express.json());

app.post('/api/send-message', (req, res) => {
	try {
		const { user_id, room, text, sender, timestamp } = req.body;
		
		if (!user_id || !room || !text) {
			return res.status(400).json({ 
				success: false, 
				error: 'Missing required fields: user_id, room, text' 
			});
		}
		
		const messageData = {
			id: Date.now().toString() + Math.random(),
			text: text,
			sender: sender || 'User',
			sender_id: user_id,
			timestamp: timestamp || new Date().toISOString()
		};
		
		// Save to history
		saveMessage(room, messageData);
		
		// Broadcast to WebSocket clients
		broadcastToRoom(room, {
			type: 'message',
			...messageData
		});
		
		res.json({ success: true, message_id: messageData.id });
		
	} catch (error) {
		res.status(500).json({ success: false, error: error.message });
	}
});

// Health check endpoint
app.get('/health', (req, res) => {
	res.json({ status: 'ok', connections: wss.clients.size });
});

// Start server
const PORT = process.env.PORT || 8080;
server.listen(PORT, () => {
	console.log('========================================');
	console.log(`WebSocket Server running on port ${PORT}`);
	console.log(`WebSocket: ws://localhost:${PORT}`);
	console.log(`HTTP API: http://localhost:${PORT}/api/send-message`);
	console.log('========================================');
});

Run the Server

node server.js
✓ Success! Your WebSocket server is now running on port 8080.

2 Configure Bubble Plugin

In your Bubble app, add the WebSocket Chat element and configure these properties:

Property Value Example
websocket_server Your server URL ws://your-domain.com:8080
current_user_id Current User's unique ID Current User's unique id
current_user_name Current User's name Current User's name
room_id Conversation/room identifier Get data from URL → room_id

3 Add Message Input

Create the UI for sending messages:

  1. Add a Text Input element
  2. Add a Button labeled "Send"
  3. Create a workflow on the button click:
    • Action: Plugins → WebSocket Chat → Send Message
    • Element: Your chat element
    • message_text: Input's value
  4. Add another action to clear the input

📡 Message Protocol

Messages Plugin Sends to Server

Get History Request

{
  "action": "get_history",
  "user_id": "user123",
  "room": "room456",
  "limit": 50
}

Send Message Request

{
  "action": "send_message",
  "text": "Hello, this is my message",
  "user_id": "user123",
  "sender": "John Doe",
  "room": "room456",
  "timestamp": "2026-01-11T22:38:04.014Z"
}

Messages Server Sends to Plugin

History Response

{
  "type": "history",
  "messages": [
	{
	  "id": "msg_001",
	  "text": "Hello!",
	  "sender": "Jane Smith",
	  "sender_id": "user789",
	  "timestamp": "2026-01-11T20:15:00.000Z"
	}
  ]
}

New Message Broadcast

{
  "type": "message",
  "id": "msg_003",
  "text": "New message here",
  "sender": "Jane Smith",
  "sender_id": "user789",
  "timestamp": "2026-01-11T22:38:04.014Z"
}

🔧 Sending Messages via HTTP API

You can send messages to the chat from your backend using the HTTP endpoint:

Using cURL

curl -X POST http://your-domain.com:8080/api/send-message \
  -H "Content-Type: application/json" \
  -d '{
	"user_id": "user123",
	"room": "room456",
	"text": "Hello from the server!",
	"sender": "Admin"
  }'

Using JavaScript

fetch('http://your-domain.com:8080/api/send-message', {
  method: 'POST',
  headers: {
	'Content-Type': 'application/json'
  },
  body: JSON.stringify({
	user_id: 'user123',
	room: 'room456',
	text: 'Hello from JavaScript!',
	sender: 'System'
  })
})
.then(response => response.json())
.then(data => console.log('Success:', data));

Using PHP

<?php
$url = 'http://your-domain.com:8080/api/send-message';

$data = array(
	'user_id' => 'user123',
	'room' => 'room456',
	'text' => 'Hello from PHP!',
	'sender' => 'Backend'
);

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));

$result = curl_exec($ch);
curl_close($ch);

echo $result;
?>

🎨 Customization Options

Display Options

Styling Properties

Customize colors, sizes, and appearance:

🚢 Production Deployment

Important: For production, you should:
  • Use wss:// (secure WebSocket) with SSL certificates
  • Use a process manager like PM2 to keep the server running
  • Add authentication and authorization
  • Store messages in a database instead of memory
  • Implement rate limiting and security measures

Using SSL (wss://)

To use secure WebSocket connections, modify your server:

const https = require('https');
const fs = require('fs');

const SSL_OPTIONS = {
  key: fs.readFileSync('/path/to/your/ssl.key'),
  cert: fs.readFileSync('/path/to/your/ssl.crt')
};

const server = https.createServer(SSL_OPTIONS, app);
// Then use wss://your-domain.com:8080

🔍 Troubleshooting

Can't Connect to Server

Messages Not Appearing

"My" Messages on Wrong Side

📚 Additional Resources

View Full Documentation Sample Code Repository Get Support