### Setup project and run development server (Bash) Source: https://github.com/shwosner/realtime-chat-supabase-react/blob/master/README.md Installs project dependencies, starts the local development server on port 3000, and builds the React client for production. These commands are executed in a terminal within the project root. ```bash npm install ``` ```bash npm run dev ``` ```bash npm run build ``` -------------------------------- ### Development and Deployment Script (Bash) Source: https://context7.com/shwosner/realtime-chat-supabase-react/llms.txt Provides essential commands for setting up, building, and deploying the application locally using npm. Includes environment variable setup for Supabase credentials. ```bash # Install dependencies npm install # Create environment file cat > .env << EOF VITE_SUPABASE_KEY=your_supabase_anon_key VITE_SUPABASE_URL=https://your-project.supabase.co EOF # Run development server (default port 5173) npm run dev # Build for production npm run build # Preview production build locally npm run preview ``` -------------------------------- ### Configure Supabase Client for React App Source: https://context7.com/shwosner/realtime-chat-supabase-react/llms.txt Sets up the Supabase client using environment variables for URL and API key. This client is essential for interacting with Supabase's database and authentication services. It relies on VITE_SUPABASE_URL and VITE_SUPABASE_KEY from the environment. ```javascript import { createClient } from "@supabase/supabase-js"; const supabaseUrl = import.meta.env.VITE_SUPABASE_URL; const supabaseKey = import.meta.env.VITE_SUPABASE_KEY; const supabase = createClient(supabaseUrl, supabaseKey); export default supabase; // .env file setup // VITE_SUPABASE_KEY=your_supabase_anon_key_here // VITE_SUPABASE_URL=https://your-project.supabase.co ``` -------------------------------- ### Create messages table in Supabase PostgreSQL (SQL) Source: https://github.com/shwosner/realtime-chat-supabase-react/blob/master/README.md Defines the database schema required for storing chat messages. Includes fields for user identification, message text, country flag, authentication status, and timestamp. Run this SQL in Supabase to enable real‑time updates. ```sql CREATE TABLE messages ( id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, username VARCHAR NOT NULL, text TEXT NOT NULL, country VARCHAR, is_authenticated BOOLEAN DEFAULT FALSE, timestamp timestamp default now() NOT NULL ); ``` -------------------------------- ### React App Context for Chat State Management Source: https://context7.com/shwosner/realtime-chat-supabase-react/llms.txt Implements a React context provider (AppContextProvider) to manage global application state for a chat application. It handles messages, user sessions, authentication status, loading states, and error handling. It also sets up real-time subscriptions for new messages using Supabase's 'postgres_changes' feature. ```javascript import { createContext, useContext, useEffect, useRef, useState } from "react"; import supabase from "../supabaseClient"; const AppContext = createContext({}); const AppContextProvider = ({ children }) => { const [username, setUsername] = useState(""); const [session, setSession] = useState(null); const [messages, setMessages] = useState([]); const [error, setError] = useState(""); const [loadingInitial, setLoadingInitial] = useState(true); const [countryCode, setCountryCode] = useState(""); const scrollRef = useRef(); // Initialize user session and username useEffect(() => { supabase.auth.getSession().then(({ data: { session } }) => { setSession(session); const username = session ? session.user.user_metadata.user_name : localStorage.getItem("username") || `@user${Date.now().toString().slice(-4)}`; setUsername(username); localStorage.setItem("username", username); }); getMessagesAndSubscribe(); }, []); // Fetch initial messages and subscribe to real-time updates const getMessagesAndSubscribe = async () => { const { data, error } = await supabase .from("messages") .select() .range(0, 49) .order("id", { ascending: false }); if (!error) { setMessages(data); setLoadingInitial(false); } // Subscribe to real-time message updates const channel = supabase .channel("custom-all-channel") .on( "postgres_changes", { event: "*", schema: "public", table: "messages" }, (payload) => { setMessages((prevMessages) => [payload.new, ...prevMessages]); } ) .subscribe(); }; return ( {children} ); }; const useAppContext = () => useContext(AppContext); export { AppContextProvider, useAppContext }; ``` -------------------------------- ### GitHub OAuth Authentication in React with Supabase Source: https://context7.com/shwosner/realtime-chat-supabase-react/llms.txt The Header component in React implements GitHub OAuth for login and logout using Supabase Auth. It provides buttons to initiate the GitHub login flow and to sign out. The component also displays the logged-in username. Configuration details for Supabase GitHub OAuth are provided as comments. ```javascript // src/layout/Header.jsx import { Button, Grid, GridItem } from "@chakra-ui/react"; import { FaGithub } from "react-icons/fa"; import supabase from "../supabaseClient"; import { useAppContext } from "../context/appContext"; export default function Header() { const { username, setUsername, session } = useAppContext(); const handleGitHubLogin = () => { supabase.auth.signInWithOAuth({ provider: "github", redirectTo: window.location.origin, }); }; const handleLogout = () => { const { error } = supabase.auth.signOut(); if (error) { console.error("Error signing out:", error); return; } // Generate random username for anonymous user const newUsername = `@user${Date.now().toString().slice(-4)}`; setUsername(newUsername); localStorage.setItem("username", newUsername); }; return ( {session ? ( <> Welcome {username} ) : ( ); } // GitHub OAuth Setup in Supabase: // 1. Go to Authentication > Providers > GitHub // 2. Enable GitHub provider // 3. Add Client ID and Client Secret from GitHub OAuth App // 4. Set Authorization callback URL to: https://your-project.supabase.co/auth/v1/callback ``` -------------------------------- ### Create Supabase Messages Table Schema Source: https://context7.com/shwosner/realtime-chat-supabase-react/llms.txt Defines the SQL schema for the 'messages' table in Supabase. This table stores chat messages, including username, text, country, authentication status, and timestamp. It also includes instructions on enabling real-time updates for this table via the Supabase dashboard. ```sql CREATE TABLE messages ( id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, username VARCHAR NOT NULL, text TEXT NOT NULL, country VARCHAR, is_authenticated BOOLEAN DEFAULT FALSE, timestamp timestamp default now() NOT NULL ); -- Enable real-time updates for the messages table -- In Supabase dashboard: Database > Tables > messages > Enable Realtime ``` -------------------------------- ### React Username Management Form Source: https://context7.com/shwosner/realtime-chat-supabase-react/llms.txt Implements an inline editing form for users to change their display names. Uses React state management and local storage for persistence. Relies on Chakra UI components for styling and icons. ```javascript import { useEffect, useRef, useState } from "react"; import { Input, Stack, IconButton } from "@chakra-ui/react"; import { BiSave, BiEdit } from "react-icons/bi"; import { useAppContext } from "../context/appContext"; export default function NameForm() { const { username, setUsername } = useAppContext(); const [newUsername, setNewUsername] = useState(username); const [isEditing, setIsEditing] = useState(false); const inputRef = useRef(null); useEffect(() => { if (isEditing) { inputRef.current.focus(); } }, [isEditing]); const handleSubmit = (e) => { e.preventDefault(); setIsEditing(false); if (!newUsername) { setNewUsername(username); return; } setUsername(newUsername); localStorage.setItem("username", newUsername); }; return (
{isEditing ? ( setNewUsername(e.target.value)} value={newUsername} onBlur={handleSubmit} ref={inputRef} maxLength="15" /> ) : ( setIsEditing(true)} style={{ cursor: "pointer" }}> Welcome {newUsername} )} isEditing ? handleSubmit(e) : setIsEditing(true)} > {isEditing ? : }
); } ``` -------------------------------- ### Infinite Scroll Implementation (JavaScript) Source: https://context7.com/shwosner/realtime-chat-supabase-react/llms.txt Implements infinite scrolling to load older messages when the user scrolls to the top of the chat window. Uses Supabase to fetch data and updates the message list accordingly. Includes logic to prevent snapping to the top of the scrollable area. ```javascript const onScroll = async ({ target }) => { // Detect if scrolled to bottom if (target.scrollHeight - target.scrollTop <= target.clientHeight + 1) { setUnviewedMessageCount(0); setIsOnBottom(true); } else { setIsOnBottom(false); } // Load more messages when reaching top (infinite scroll) if (target.scrollTop === 0) { const { data, error } = await supabase .from("messages") .select() .range(messages.length, messages.length + 49) .order("id", { ascending: false }); if (!error) { target.scrollTop = 1; // Prevent snapping to top setMessages((prevMessages) => [...prevMessages, ...data]); } } }; // Usage in Chat component ``` -------------------------------- ### Display Real-time Messages in React with Supabase Source: https://context7.com/shwosner/realtime-chat-supabase-react/llms.txt The Messages component displays chat messages fetched from Supabase, supporting real-time updates. It handles loading and error states, reversing messages to show the newest at the bottom. Dependencies include Chakra UI for components and context for data fetching. ```javascript // src/components/Messages.jsx import { Alert, Box, Button, Spinner } from "@chakra-ui/react"; import { useAppContext } from "../context/appContext"; import Message from "./Message"; export default function Messages() { const { username, loadingInitial, error, getMessagesAndSubscribe, messages } = useAppContext(); // Reverse messages to show newest at bottom const reversed = [...messages].reverse(); if (loadingInitial) { return ( ); } if (error) { return ( {error} ); } if (!messages.length) { return No messages 😞; } return reversed.map((message) => { const isYou = message.username === username; return ; }); } ``` -------------------------------- ### Country Detection (JavaScript) Source: https://context7.com/shwosner/realtime-chat-supabase-react/llms.txt Automatically detects the user's country code using the db-ip.com API. Stores the country code in local storage for persistence. Handles potential errors during API calls and displays error messages. ```javascript const getLocation = async () => { try { const res = await fetch("https://api.db-ip.com/v2/free/self"); const { countryCode, error } = await res.json(); if (error) throw new Error(error); setCountryCode(countryCode); localStorage.setItem("countryCode", countryCode); } catch (error) { console.error("Error getting location:", error.message); } }; // Initialize on mount useEffect(() => { const storedCountryCode = localStorage.getItem("countryCode"); if (storedCountryCode && storedCountryCode !== "undefined") { setCountryCode(storedCountryCode); } else { getLocation(); } }, []); ``` -------------------------------- ### Send Messages in React with Supabase Source: https://context7.com/shwosner/realtime-chat-supabase-react/llms.txt The MessageForm component in React handles sending chat messages. It uses Supabase to insert messages into a database table, tracking the message text, username, country, and authentication status. It also includes UI states for sending and error handling. ```javascript // src/components/MessageForm.jsx import { useState } from "react"; import { Input, Stack, IconButton } from "@chakra-ui/react"; import { BiSend } from "react-icons/bi"; import { useAppContext } from "../context/appContext"; import supabase from "../supabaseClient"; export default function MessageForm() { const { username, country, session } = useAppContext(); const [message, setMessage] = useState(""); const [isSending, setIsSending] = useState(false); const handleSubmit = async (e) => { e.preventDefault(); if (!message) return; setIsSending(true); setMessage(""); try { const { error } = await supabase.from("messages").insert([ { text: message, username, country, is_authenticated: session ? true : false, }, ]); if (error) { console.error(error.message); // Show error toast notification } } catch (error) { console.log("Error sending message:", error); } finally { setIsSending(false); } }; return (
setMessage(e.target.value)} value={message} maxLength="500" autoFocus /> } type="submit" disabled={!message} isLoading={isSending} />
); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.