--- source_url: https://www.pubnub.com/docs/sdks/javascript title: JavaScript API & SDK Docs 10.2.3 updated_at: 2025-11-24T16:18:04.873Z --- # JavaScript API & SDK Docs 10.2.3 On this page :::note Chat SDK If you want to create a chat app, you can use our [Chat SDK](https://www.pubnub.com/docs/chat/chat-sdk), which relies on the JavaScript SDK, is written in TypeScript, and offers a set of chat-specific methods to manage users, channels, messages, typing indicators, quotes, mentions, threads, and many more. ::: This guide walks you through a simple "Hello, World" application that demonstrates the core concepts of PubNub: * Setting up a connection * Sending messages * Receiving messages in real-time ## Overview This guide helps you get up and running with PubNub in your JavaScript application. The JavaScript software development kit (SDK) provides a simple interface for integrating PubNub real-time messaging. Since JavaScript is commonly used across different platforms, we provide platform-specific guidance for: * **Web**: For developers building browser-based applications * **Node.js**: For server-side applications * **React Native**: For mobile app development The core PubNub concepts and API usage remain the same across all platforms, but implementation details like lifecycle management and UI updates differ. Select the appropriate tab in each section to see platform-specific guidance. You can use either JavaScript or TypeScript with any of these platforms. The only difference is in how you import PubNub: * For JavaScript files (`.js` extension): `const PubNub = require('pubnub');` * For TypeScript files (`.ts` extension): `import PubNub from 'pubnub';` JavaScript SDK supports a wide variety of environments including browsers, Node.js, React Native, React, Angular, Vue, and other JavaScript frameworks. ## Prerequisites Before we dive in, make sure you have: * A basic understanding of JavaScript * For browser applications: A modern web browser * For Node.js: Node.js installed (version 10 or later) * For React Native: React Native development environment set up * A PubNub account (we'll help you set this up!) * (Optional) If you want to use TypeScript: TypeScript installed (version 4.0 or later) ## Setup ### Get your PubNub keys First, get your PubNub keys: * [Sign in](https://admin.pubnub.com/#/login) or [create an account](https://admin.pubnub.com/#/signup) on the PubNub Admin Portal * Create an app (or use an existing one) * Find your publish and subscribe keys in the app dashboard When you create an app, PubNub automatically generates a keyset. You can use the same keyset for development and production, but we recommend separate keysets for each environment to improve security and management. ### Install the SDK :::note SDK version Always use the latest SDK version to have access to the newest features and avoid security vulnerabilities, bugs, and performance issues. ::: ### Web To integrate PubNub into your web project, add the JavaScript SDK to your HTML page using the CDN: ```html ``` You can also use the minified version for production: ```html ``` ### Node.js To integrate PubNub into your Node.js project, install the SDK using npm: ```bash npm install pubnub ``` Then import it in your project: ```javascript const PubNub = require('pubnub'); ``` ### React Native For React Native projects, install the PubNub SDK: ```bash npm install pubnub ``` Then import it in your project: ```javascript import PubNub from 'pubnub'; ``` ### Source code Clone the [GitHub repository](https://github.com/pubnub/javascript): ```bash git clone https://github.com/pubnub/javascript ``` ## Steps ### Initialize PubNub ### Web Create an instance of the PubNub class with your keys and a unique user ID: ```javascript const pubnub = new PubNub({ publishKey: "demo", subscribeKey: "demo", userId: "web-user-" + Math.floor(Math.random() * 1000) }); ``` Make sure to replace the demo keys with your app's publish and subscribe keys from the Admin Portal. ### Node.js Create an instance of the PubNub class with your keys and a unique user ID: ```javascript const pubnub = new PubNub({ publishKey: 'YOUR_PUBLISH_KEY', subscribeKey: 'YOUR_SUBSCRIBE_KEY', userId: 'YOUR_USER_ID', }); ``` ### React Native Create an instance of the PubNub class with your keys and a unique user ID: ```javascript const pubnub = new PubNub({ publishKey: "demo", subscribeKey: "demo", userId: "rn-user-" + Math.floor(Math.random() * 1000) }); ``` In a real React Native application, you would typically initialize PubNub inside a component using hooks for proper lifecycle management: ```javascript // Example of initialization in a React component (optional) useEffect(() => { // Clean up on component unmount return () => { if (pubnub) { pubnub.removeAllListeners(); pubnub.destroy(); } }; }, [pubnub]); ``` For more information, refer to the [Configuration](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration) section of the SDK documentation. ### Set up event listeners Listeners help the application react to events and messages. You can implement custom app logic to respond to each type of message or event. For complete details on subscribing and handling events, refer to the [Publish and Subscribe API Reference](https://www.pubnub.com/docs/sdks/javascript/api-reference/publish-and-subscribe#subscribe). ### Web ```javascript // Add listener to handle messages, presence events, and connection status pubnub.addListener({ message: function(event) { // Handle message event console.log("New message:", event.message); // Display message in the UI displayMessage(event.message); }, presence: function(event) { // Handle presence event console.log("Presence event:", event); console.log("Action:", event.action); // join, leave, timeout console.log("Channel:", event.channel); console.log("Occupancy:", event.occupancy); }, status: function(event) { // Handle status event console.log("Status event:", event); if (event.category === "PNConnectedCategory") { console.log("Connected to PubNub channels!"); } else if (event.category === "PNNetworkIssuesCategory") { console.log("Connection lost. Attempting to reconnect..."); } } }); // Function to display messages in the UI function displayMessage(message) { const messagesDiv = document.getElementById('messages'); const messageElement = document.createElement('div'); messageElement.className = 'message'; // Format message based on content let content = ''; if (typeof message === 'object' && message.text) { content = `${message.sender || 'User'}: ${message.text}`; } else { content = JSON.stringify(message); } messageElement.textContent = content; messagesDiv.appendChild(messageElement); messagesDiv.scrollTop = messagesDiv.scrollHeight; // Auto-scroll to bottom } ``` ### Node.js ```javascript // Add listener to handle messages, presence events, and connection status pubnub.addListener({ message: function (event: Subscription.Message) { // Handle message event console.log('New message:', event.message); // Format and display received message const displayText = (() => { if (typeof event.message === 'object' && event.message && 'text' in event.message) { const messageObj = event.message as { text?: string; sender?: string }; return `${messageObj.sender || 'User'}: ${messageObj.text}`; } else { return `Message: ${JSON.stringify(event.message)}`; } })(); console.log(displayText); }, presence: function (event: Subscription.Presence) { // Handle presence event console.log('Presence event:', event); console.log('Action:', event.action); // join, leave, timeout console.log('Channel:', event.channel); }, status: function (event) { // Handle status event if (event.category === 'PNConnectedCategory') { console.log('Connected to PubNub chat!'); console.log('Your user ID is:', pubnub.userId); } else if (event.category === 'PNNetworkIssuesCategory') { // if eventEngine is not enabled, this event will be triggered when subscription encounter network issues. console.log('Connection lost'); // handle reconnection } else if (event.category === 'PNDisconnectedUnexpectedlyCategory') { // If enableEventEngine: true set in the constructor, this event will be triggered when the connection is lost. console.log('Disconnected unexpectedly.'); } }, }); ``` ### React Native ```jsx // App.js or App.tsx for TypeScript projects // Imports import React, { useState, useEffect, useRef } from 'react'; import { SafeAreaView, StyleSheet, View, Text, TextInput, TouchableOpacity, FlatList, KeyboardAvoidingView, Platform, StatusBar, ActivityIndicator, Alert } from 'react-native'; import PubNub from 'pubnub'; // TypeScript interfaces (for TypeScript projects) // For JavaScript, you can remove this section interface ChatMessage { text: string; sender?: string; time?: string; } interface MessageItem { id: string; message: ChatMessage; } // Main App Component export default function App() { // State variables const [pubnub, setPubnub] = useState(null); const [messages, setMessages] = useState([]); const [inputText, setInputText] = useState(''); const [isConnected, setIsConnected] = useState(false); const [isLoading, setIsLoading] = useState(true); // Reference to the FlatList for auto-scrolling const flatListRef = useRef(null); // Initialize PubNub on component mount useEffect(() => { // Create a new PubNub instance const pubnubInstance = new PubNub({ publishKey: "demo", subscribeKey: "demo", userId: "rn-user-" + Math.floor(Math.random() * 1000) }); // Add listener to handle events pubnubInstance.addListener({ // Message handler - called when a message is received message: function(event) { setMessages(messages => [ ...messages, { id: event.timetoken || Date.now().toString(), message: event.message } ]); // Auto-scroll to bottom when new messages arrive setTimeout(() => { if (flatListRef.current && messages.length > 0) { flatListRef.current.scrollToEnd({ animated: true }); } }, 100); }, // Presence handler - called for join/leave events presence: function(event) { console.log("Presence event:", event); if (event.action === 'join') { // Someone joined the channel Alert.alert("User Joined", `${event.uuid} joined the chat`); } else if (event.action === 'leave' || event.action === 'timeout') { // Someone left the channel Alert.alert("User Left", `${event.uuid} left the chat`); } }, // Status handler - called for connection status changes status: function(event) { console.log("Status event:", event); if (event.category === "PNConnectedCategory") { setIsConnected(true); setIsLoading(false); console.log("Connected to PubNub!"); } else if (event.category === "PNNetworkIssuesCategory") { setIsConnected(false); console.log("Connection lost. Attempting to reconnect..."); } else if (event.category === "PNReconnectedCategory") { setIsConnected(true); console.log("Reconnected to PubNub!"); } } }); // Create a channel entity and subscription const channel = pubnubInstance.channel('hello_world'); const subscription = channel.subscription({ receivePresenceEvents: true }); // Subscribe to the channel subscription.subscribe(); // Update state with PubNub instance setPubnub(pubnubInstance); // Clean up on component unmount return () => { pubnubInstance.removeAllListeners(); pubnubInstance.destroy(); console.log("Cleaned up PubNub connection"); }; }, []); // Empty dependency array ensures this runs only once on mount // Function to publish a message const publishMessage = async () => { // Don't send empty messages or if not connected if (!inputText.trim() || !pubnub || !isConnected) return; try { // Create message object const messageObject: ChatMessage = { text: inputText, sender: pubnub.getUUID(), time: new Date().toISOString() }; // Publish to PubNub const result = await pubnub.publish({ message: messageObject, channel: 'hello_world' }); console.log("Message published with timetoken:", result.timetoken); // Clear input after successful send setInputText(''); } catch (error) { console.error("Publish failed:", error); Alert.alert( "Message Failed", "Could not send your message. Please try again." ); } }; // Render a message item for the FlatList const renderMessageItem = ({ item }) => { const isCurrentUser = item.message.sender === pubnub?.getUUID(); const messageTime = item.message.time ? new Date(item.message.time).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) : ''; return ( {isCurrentUser ? 'You' : (item.message.sender || 'User')} {item.message.text} {messageTime} ); }; // Main component render return ( {isLoading ? ( // Loading screen Connecting to PubNub... ) : ( // Chat UI {/* Header */} PubNub Chat {/* Messages List */} item.id} style={styles.messagesList} contentContainerStyle={styles.messagesContent} onContentSizeChange={() => flatListRef.current?.scrollToEnd({ animated: false }) } /> {/* Input Area */} Send )} ); } // Component styles const styles = StyleSheet.create({ safeArea: { flex: 1, backgroundColor: '#f5f5f5', }, container: { flex: 1, }, loadingContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', }, loadingText: { marginTop: 10, fontSize: 16, color: '#555', }, header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', padding: 16, borderBottomWidth: 1, borderBottomColor: '#e0e0e0', backgroundColor: '#fff', }, headerText: { fontSize: 18, fontWeight: 'bold', color: '#333', }, connectionIndicator: { width: 12, height: 12, borderRadius: 6, }, connected: { backgroundColor: '#4CAF50', }, disconnected: { backgroundColor: '#F44336', }, messagesList: { flex: 1, padding: 8, }, messagesContent: { paddingBottom: 8, }, messageContainer: { padding: 12, borderRadius: 16, marginVertical: 4, maxWidth: '80%', shadowColor: '#000', shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.1, shadowRadius: 1, elevation: 1, }, sentMessage: { alignSelf: 'flex-end', backgroundColor: '#DCF8C6', borderBottomRightRadius: 4, }, receivedMessage: { alignSelf: 'flex-start', backgroundColor: '#fff', borderBottomLeftRadius: 4, }, senderText: { fontWeight: 'bold', fontSize: 13, marginBottom: 4, color: '#333', }, messageText: { fontSize: 15, color: '#333', }, timeText: { fontSize: 11, color: '#999', alignSelf: 'flex-end', marginTop: 4, }, inputContainer: { flexDirection: 'row', padding: 12, borderTopWidth: 1, borderTopColor: '#e0e0e0', backgroundColor: '#fff', }, input: { flex: 1, height: 40, borderWidth: 1, borderColor: '#ddd', borderRadius: 20, paddingHorizontal: 16, marginRight: 8, backgroundColor: '#fff', color: '#333', }, sendButton: { height: 40, paddingHorizontal: 16, borderRadius: 20, backgroundColor: '#4b0082', justifyContent: 'center', alignItems: 'center', }, sendButtonDisabled: { backgroundColor: '#B39DDB', }, sendButtonText: { color: '#fff', fontWeight: 'bold', }, }); ``` To use this example in your React Native project: 1. Create a new React Native project: # Using Expo (easiest for beginners)npx create-expo-app PubNubChatAppcd PubNubChatApp # Or using React Native CLInpx react-native init PubNubChatAppcd PubNubChatApp 2. Install the PubNub SDK: npm install pubnub 3. Replace the content of App.js (or App.tsx for TypeScript) with the code above. 4. Run your app: # For Exponpx expo start # For React Native CLInpx react-native run-ios# ornpx react-native run-android The example includes: * PubNub initialization with proper cleanup * Real-time message sending and receiving * Messages display in a scrollable chat UI * Connection status indicator * Presence notifications (when users join/leave) * Auto-scrolling message list * Proper keyboard handling * Error handling for failed messages * Loading state while connecting * Full styling for a production-ready appearance ### Create a subscription To receive messages on a channel, you need to subscribe to it. PubNub offers an entity-based subscription approach which provides more control and flexibility: ### Web ```javascript // Create a channel entity const channel = pubnub.channel('hello_world'); // Create a subscription for this channel const subscription = channel.subscription(); // Subscribe subscription.subscribe(); ``` ### Node.js ```javascript // Create a channel entity const channel = pubnub.channel('hello_world'); // Create a subscription const subscription = channel.subscription({ receivePresenceEvents: true, // to receive presence events }); // Subscribe subscription.subscribe(); ``` ### React Native In React Native, we typically subscribe within a useEffect hook: ```javascript useEffect(() => { if (!pubnub) return; // Create a channel entity const channel = pubnub.channel('hello_world'); // Create a subscription const subscription = channel.subscription({ receivePresenceEvents: true }); // Subscribe subscription.subscribe(); // Clean up on unmount return () => { // First remove listeners to prevent callbacks during cleanup pubnub.removeAllListeners(); // Then unsubscribe if needed if (subscription) { subscription.unsubscribe(); } // Note: Only call destroy() if this component owns the pubnub instance // If the pubnub instance is shared, consider only removing listeners }; }, [pubnub]); ``` For more information, refer to the [Subscribe](https://www.pubnub.com/docs/sdks/javascript/api-reference/publish-and-subscribe#subscribe) section of the SDK documentation. ### Publish messages Once you've set up your subscription, you can start publishing messages to channels. When you publish a message to a channel, PubNub delivers that message to everyone who is subscribed to that channel. A message can be any type of JavaScript Object Notation (JSON)-serializable data (such as objects, arrays, integers, strings) that is smaller than 32 KiB. ### Web ```javascript // Function to publish a message async function publishMessage(text) { if (!text.trim()) return; try { const result = await pubnub.publish({ message: { text: text, sender: pubnub.getUUID(), time: new Date().toISOString() }, channel: 'hello_world' }); console.log("Message published with timetoken:", result.timetoken); } catch (error) { console.error("Publish failed:", error); } } // Example: Call this function when a button is clicked document.getElementById('send-button').addEventListener('click', function() { const input = document.getElementById('message-input'); publishMessage(input.value); input.value = ''; }); ``` ### Node.js ```javascript // Function to publish a message async function publishMessage(text: string) { if (!text.trim()) return; try { const result = await pubnub.publish({ message: { text: text, sender: pubnub.userId, time: new Date().toISOString(), }, channel: 'hello_world', }); console.log(`Message published with timetoken: ${result.timetoken}`); console.log(`You: ${text}`); } catch (error) { console.error( `Publish failed: ${error}.${ (error as PubNubError).status ? ` Additional information: ${(error as PubNubError).status}` : '' }`, ); } } // Example: publish a message const text_message = 'Hello, world!'; publishMessage(text_message); ``` ### React Native ```javascript // State for the input text const [inputText, setInputText] = useState(''); // Function to publish a message const publishMessage = async () => { if (!inputText.trim() || !pubnub) return; try { const result = await pubnub.publish({ message: { text: inputText, sender: pubnub.getUUID(), time: new Date().toISOString() }, channel: 'hello_world' }); console.log("Message published with timetoken:", result.timetoken); setInputText(''); // Clear input after sending } catch (error) { console.error("Publish failed:", error); Alert.alert("Error", "Failed to send message"); } }; // In your render function return ( ``` ### Node.js ```javascript // Save this file as index.js/.ts // 1. Import pubnub // import PubNub from 'pubnub'; // 2. Initialize PubNub with demo keys and a random user ID const pubnub = new PubNub({ publishKey: 'YOUR_PUBLISH_KEY', subscribeKey: 'YOUR_SUBSCRIBE_KEY', userId: 'YOUR_USER_ID', }); // 3. Add listener to handle messages, presence events, and connection status pubnub.addListener({ // Handle incoming messages message: function (event) { // Handle message event console.log('New message:', event.message); // Format and display received message const displayText = (() => { if (typeof event.message === 'object' && event.message && 'text' in event.message) { const messageObj = event.message as { text?: string; sender?: string }; return `${messageObj.sender || 'User'}: ${messageObj.text}`; } else { return `Message: ${JSON.stringify(event.message)}`; } })(); console.log(displayText); }, // Handle presence events (join, leave, timeout) presence: function (event) { // Handle presence event console.log('Presence event:', event); console.log('Action:', event.action); // join, leave, timeout console.log('Channel:', event.channel); }, // Handle connection status events status: function (event) { // Handle status event if (event.category === 'PNConnectedCategory') { console.log('Connected to PubNub chat!'); console.log('Your user ID is:', pubnub.userId); } else if (event.category === 'PNNetworkIssuesCategory') { // if eventEngine is not enabled, this event will be triggered when subscription encounter network issues. console.log('Connection lost'); // handle reconnection } else if (event.category === 'PNDisconnectedUnexpectedlyCategory') { // If enableEventEngine: true set in the constructor, this event will be triggered when the connection is lost. console.log('Disconnected unexpectedly.'); } }, }); // 4. Create a channel entity and subscription with presence const channel = pubnub.channel('hello_world'); const subscription = channel.subscription({ receivePresenceEvents: true, // to receive presence events }); // 5. Subscribe to the channel subscription.subscribe(); // 6. Function to publish messages async function publishMessage(text: string) { if (!text.trim()) return; try { // Create a message object with text, timestamp, and sender ID const message = { text: text, time: new Date().toISOString(), sender: pubnub.userId, }; // Publish the message to the channel const response = await pubnub.publish({ message: message, channel: 'hello_world', storeInHistory: true, // Save this message in history }); // Success message (timetoken is the unique ID for this message) console.log(`\nāœ… Message sent successfully!`); } catch (error) { // Handle publish errors console.error( `\nāŒ Failed to send message: ${error}.${ (error as PubNubError).status ? ` Additional information: ${(error as PubNubError).status}` : '' }`, ); } } // 7. define the message and Publish that message. const text_message = 'Hello, world!'; publishMessage(text_message); ``` ### React Native ```jsx // App.js or App.tsx for TypeScript projects // Imports import React, { useState, useEffect, useRef } from 'react'; import { SafeAreaView, StyleSheet, View, Text, TextInput, TouchableOpacity, FlatList, KeyboardAvoidingView, Platform, StatusBar, ActivityIndicator, Alert } from 'react-native'; import PubNub from 'pubnub'; // TypeScript interfaces (for TypeScript projects) // For JavaScript, you can remove this section interface ChatMessage { text: string; sender?: string; time?: string; } interface MessageItem { id: string; message: ChatMessage; } // Main App Component export default function App() { // State variables const [pubnub, setPubnub] = useState(null); const [messages, setMessages] = useState([]); const [inputText, setInputText] = useState(''); const [isConnected, setIsConnected] = useState(false); const [isLoading, setIsLoading] = useState(true); // Reference to the FlatList for auto-scrolling const flatListRef = useRef(null); // Initialize PubNub on component mount useEffect(() => { // Create a new PubNub instance const pubnubInstance = new PubNub({ publishKey: "demo", subscribeKey: "demo", userId: "rn-user-" + Math.floor(Math.random() * 1000) }); // Add listener to handle events pubnubInstance.addListener({ // Message handler - called when a message is received message: function(event) { setMessages(messages => [ ...messages, { id: event.timetoken || Date.now().toString(), message: event.message } ]); // Auto-scroll to bottom when new messages arrive setTimeout(() => { if (flatListRef.current && messages.length > 0) { flatListRef.current.scrollToEnd({ animated: true }); } }, 100); }, // Presence handler - called for join/leave events presence: function(event) { console.log("Presence event:", event); if (event.action === 'join') { // Someone joined the channel Alert.alert("User Joined", `${event.uuid} joined the chat`); } else if (event.action === 'leave' || event.action === 'timeout') { // Someone left the channel Alert.alert("User Left", `${event.uuid} left the chat`); } }, // Status handler - called for connection status changes status: function(event) { console.log("Status event:", event); if (event.category === "PNConnectedCategory") { setIsConnected(true); setIsLoading(false); console.log("Connected to PubNub!"); } else if (event.category === "PNNetworkIssuesCategory") { setIsConnected(false); console.log("Connection lost. Attempting to reconnect..."); } else if (event.category === "PNReconnectedCategory") { setIsConnected(true); console.log("Reconnected to PubNub!"); } } }); // Create a channel entity and subscription const channel = pubnubInstance.channel('hello_world'); const subscription = channel.subscription({ receivePresenceEvents: true }); // Subscribe to the channel subscription.subscribe(); // Update state with PubNub instance setPubnub(pubnubInstance); // Clean up on component unmount return () => { pubnubInstance.removeAllListeners(); pubnubInstance.destroy(); console.log("Cleaned up PubNub connection"); }; }, []); // Empty dependency array ensures this runs only once on mount // Function to publish a message const publishMessage = async () => { // Don't send empty messages or if not connected if (!inputText.trim() || !pubnub || !isConnected) return; try { // Create message object const messageObject: ChatMessage = { text: inputText, sender: pubnub.getUUID(), time: new Date().toISOString() }; // Publish to PubNub const result = await pubnub.publish({ message: messageObject, channel: 'hello_world' }); console.log("Message published with timetoken:", result.timetoken); // Clear input after successful send setInputText(''); } catch (error) { console.error("Publish failed:", error); Alert.alert( "Message Failed", "Could not send your message. Please try again." ); } }; // Render a message item for the FlatList const renderMessageItem = ({ item }) => { const isCurrentUser = item.message.sender === pubnub?.getUUID(); const messageTime = item.message.time ? new Date(item.message.time).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) : ''; return ( {isCurrentUser ? 'You' : (item.message.sender || 'User')} {item.message.text} {messageTime} ); }; // Main component render return ( {isLoading ? ( // Loading screen Connecting to PubNub... ) : ( // Chat UI {/* Header */} PubNub Chat {/* Messages List */} item.id} style={styles.messagesList} contentContainerStyle={styles.messagesContent} onContentSizeChange={() => flatListRef.current?.scrollToEnd({ animated: false }) } /> {/* Input Area */} Send )} ); } // Component styles const styles = StyleSheet.create({ safeArea: { flex: 1, backgroundColor: '#f5f5f5', }, container: { flex: 1, }, loadingContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', }, loadingText: { marginTop: 10, fontSize: 16, color: '#555', }, header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', padding: 16, borderBottomWidth: 1, borderBottomColor: '#e0e0e0', backgroundColor: '#fff', }, headerText: { fontSize: 18, fontWeight: 'bold', color: '#333', }, connectionIndicator: { width: 12, height: 12, borderRadius: 6, }, connected: { backgroundColor: '#4CAF50', }, disconnected: { backgroundColor: '#F44336', }, messagesList: { flex: 1, padding: 8, }, messagesContent: { paddingBottom: 8, }, messageContainer: { padding: 12, borderRadius: 16, marginVertical: 4, maxWidth: '80%', shadowColor: '#000', shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.1, shadowRadius: 1, elevation: 1, }, sentMessage: { alignSelf: 'flex-end', backgroundColor: '#DCF8C6', borderBottomRightRadius: 4, }, receivedMessage: { alignSelf: 'flex-start', backgroundColor: '#fff', borderBottomLeftRadius: 4, }, senderText: { fontWeight: 'bold', fontSize: 13, marginBottom: 4, color: '#333', }, messageText: { fontSize: 15, color: '#333', }, timeText: { fontSize: 11, color: '#999', alignSelf: 'flex-end', marginTop: 4, }, inputContainer: { flexDirection: 'row', padding: 12, borderTopWidth: 1, borderTopColor: '#e0e0e0', backgroundColor: '#fff', }, input: { flex: 1, height: 40, borderWidth: 1, borderColor: '#ddd', borderRadius: 20, paddingHorizontal: 16, marginRight: 8, backgroundColor: '#fff', color: '#333', }, sendButton: { height: 40, paddingHorizontal: 16, borderRadius: 20, backgroundColor: '#4b0082', justifyContent: 'center', alignItems: 'center', }, sendButtonDisabled: { backgroundColor: '#B39DDB', }, sendButtonText: { color: '#fff', fontWeight: 'bold', }, }); ``` The examples above showcase complete working code that integrates all the concepts covered in this guide: * PubNub initialization with proper configuration * Event listener setup for messages and connection status * Channel subscription using the entity-based approach * Message publishing with error handling * User interface components (where applicable) * Cleanup and resource management ## Next steps Great job! šŸŽ‰ You've successfully created your first PubNub JavaScript application. Here are some exciting things you can explore next: ### Build chat * Learn about the [JavaScript Chat SDK](https://www.pubnub.com/docs/chat/chat-sdk) for ready-to-use chat features. * Add typing indicators and read receipts. ### Advanced features * Try out [Presence](https://www.pubnub.com/docs/sdks/javascript/api-reference/presence) to track online/offline status. * Implement [Message Persistence](https://www.pubnub.com/docs/sdks/javascript/api-reference/storage-and-playback) to store and retrieve messages. * Use [Access Manager](https://www.pubnub.com/docs/sdks/javascript/api-reference/access-manager) to secure your channels. * Explore [Channel Groups](https://www.pubnub.com/docs/sdks/javascript/api-reference/channel-groups) to organize your channels. ### Real examples * Explore our GitHub repository for more code samples. * Follow these tutorials: IoT dashboard, Geolocation app, Delivery app ### More help * Check out the [SDK reference documentation](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration) for detailed API information. * Visit the [support portal](https://support.pubnub.com/) for additional resources. * Ask the AI assistant (the looking glass icon at the top of the page) for help.