// backend/realtime.jsw import { publish } from 'wix-realtime'; /** * Broadcast a payload to everyone in a chat room. * Channel naming: room: */ export function broadcast(roomId, payload) { return publish(`room:${roomId}`, payload); }
top of page
0732CFC5-B1FE-4318-9E7A-0EA3DB558214.png

Pick Your Path

with a 1 time set up fee of $1,999

over $1700 savings that's money in your pocket already

with a 1 time set up fee of $599

Pay as you go creates flexibility 

bottom of page
// backend/data.js import { broadcast } from 'backend/realtime'; /** * Fires after a document is inserted into the Messages collection * (Collection name: Messages -> function name: Messages_afterInsert) */ export function Messages_afterInsert(item, context) { // Keep the payload lean; it's sent to all subscribers. const payload = { _id: item._id, text: item.text, userId: item.userId, userName: item.userName, roomId: item.roomId, createdAt: item.createdAt }; // Fire-and-forget broadcast; don't block the insert lifecycle. broadcast(item.roomId, payload); return item; } // backend/data.js import { broadcast } from 'backend/realtime'; /** * Fires after a document is inserted into the Messages collection * (Collection name: Messages -> function name: Messages_afterInsert) */ export function Messages_afterInsert(item, context) { // Keep the payload lean; it's sent to all subscribers. const payload = { _id: item._id, text: item.text, userId: item.userId, userName: item.userName, roomId: item.roomId, createdAt: item.createdAt }; // Fire-and-forget broadcast; don't block the insert lifecycle. broadcast(item.roomId, payload); return item; } // Page code (e.g., Chat page) import wixData from 'wix-data'; import wixUsers from 'wix-users'; import { subscribe, unsubscribe } from 'wix-realtime'; // If you use Wix Members profile names, you can also import: // import { currentMember } from 'wix-members'; let roomId = 'global'; // default room (or drive from #roomPicker) let myUser = null; let realtimeSub = null; $w.onReady(async () => { myUser = wixUsers.currentUser; initRepeaterItemUI(); await loadMessages(); // Realtime subscribe resubscribe(); // Send message $w('#sendButton').onClick(sendCurrentMessage); $w('#messageInput').onKeyPress((e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendCurrentMessage(); } }); // Optional: switch rooms if ($w('#roomPicker')) { $w('#roomPicker').onChange(async () => { roomId = $w('#roomPicker').value; await loadMessages(); resubscribe(); }); } }); function initRepeaterItemUI() { $w('#messagesRepeater').onItemReady(($item, itemData) => { const mine = itemData.userId === (myUser?.id ?? 'anon'); // Hide both by default, then show one $item('#leftBubble').collapse(); $item('#rightBubble').collapse(); if (mine) { $item('#rightText').text = itemData.text || ''; $item('#rightMeta').text = metaText(itemData); $item('#rightBubble').expand(); } else { $item('#leftText').text = itemData.text || ''; $item('#leftMeta').text = metaText(itemData); $item('#leftBubble').expand(); } }); } function metaText(item) { const name = item.userName || (item.userId ? `User ${item.userId.slice(0,6)}` : 'User'); const ts = item.createdAt ? new Date(item.createdAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) : ''; return `${name} • ${ts}`; } async function loadMessages() { const results = await wixData.query('Messages') .eq('roomId', roomId) .ascending('createdAt') .limit(200) // adjust / paginate as needed .find(); $w('#messagesRepeater').data = results.items; focusInput(); } function focusInput() { setTimeout(() => { if ($w('#messageInput')) $w('#messageInput').focus(); }, 50); } async function sendCurrentMessage() { const text = ($w('#messageInput').value || '').trim(); if (!text) return; const item = { text, userId: myUser?.id || 'anon', userName: await getDisplayName(), // or null roomId // createdAt is auto-set in the collection (Default: Now) }; await wixData.insert('Messages', item); // Triggers afterInsert -> broadcast $w('#messageInput').value = ''; } async function getDisplayName() { // Option A (simple): use email local-part if available try { if (myUser?.loggedIn) { const email = await myUser.getEmail(); if (email) return email.split('@')[0]; } } catch (e) { /* ignore */ } // Option B (comment in if using Wix Members): // try { // const member = await currentMember.getMember(); // return member?.profile?.nickname || member?.loginEmail || 'Member'; // } catch (e) {} return myUser?.loggedIn ? 'Member' : 'Guest'; } function resubscribe() { // Clean up the previous subscription if any if (realtimeSub) { try { unsubscribe(realtimeSub); } catch (e) {} realtimeSub = null; } // Subscribe to the current room channel realtimeSub = subscribe(`room:${roomId}`, (message) => { const payload = message?.payload; if (!payload) return; const data = $w('#messagesRepeater').data || []; data.push(payload); $w('#messagesRepeater').data = data; focusInput(); }); }