Build and Deploy a Fullstack Social Media App with Authentication | React, Supabase, PostgreSQL

PedroTechAbout 12 min readMay 27, 2025Watch original
THE SUMMARYAI-generated

Key Concepts

  • Full-stack web application: A complete application encompassing both front-end (user interface) and back-end (server-side logic and database) components.
  • Superbase: An open-source Firebase alternative providing back-end-as-a-service features like authentication, database, storage, and real-time functionality.
  • React Query: A library for managing server state in React applications, handling data fetching, caching, and updates.
  • Tailwind CSS: A utility-first CSS framework for rapidly styling web applications.
  • React Router: A library for handling navigation and routing in React applications.
  • Context API: A React feature for managing and sharing state across components without prop drilling.
  • RLS (Row Level Security): Policies in Superbase that restrict access to data based on user roles and conditions.
  • RPC (Remote Procedure Call): A mechanism to execute database functions from the application code.

Project Setup and Initial Configuration

  • Creating a new Vite project: The video starts by creating a new React project using Vite with TypeScript. The command npx create vite . --template react-ts is used.
  • Installing dependencies: The following packages are installed using npm install:
    • @supabase/supabase-js: The Superbase JavaScript client library.
    • @tanstack/react-query: React Query for server state management.
    • tailwindcss, @tailwindcss/typography: Tailwind CSS for styling.
    • react-router-dom: React Router for navigation.
  • Folder structure: The project structure includes folders for components, routes (pages), and contexts.
  • Main.tsx setup: The main application file is modified to include:
    • BrowserRouter (renamed to Router) to enable React Router.
    • QueryClient and QueryClientProvider to enable React Query.
  • Tailwind CSS setup: The vite.config.ts file is updated to include the Tailwind CSS plugin. The index.css file is populated with Tailwind directives and custom styles.

Navigation Bar (Navbar) Component

  • Structure: The Navbar component includes sections for the logo, desktop links, mobile menu button, and mobile menu.
  • Logo: The logo is a link that navigates to the homepage. It uses a span to style parts of the text differently.
  • Desktop Links: Links for Home, Create Post, Communities, and Create Community pages.
  • Mobile Menu: A hamburger menu that toggles the visibility of the mobile links.
  • Responsiveness: Tailwind CSS classes are used to control the visibility of different sections based on screen size.
  • State Management: The menuOpen state is used to control the visibility of the mobile menu.

Authentication with Superbase

  • Superbase Project Setup: A new Superbase project is created, and the project URL and anonymous key are obtained.
  • Superbase Client: A supabaseClient.ts file is created to initialize the Superbase client using the project URL and anonymous key. The anonymous key is stored in an environment variable.
  • OAuth Context: An AuthContext is created to manage authentication state and functions. It includes:
    • user: The currently logged-in user (or null).
    • signInWithGitHub: A function to sign in with GitHub.
    • signOut: A function to sign out.
  • useAuth Hook: A custom hook useAuth is created to simplify access to the AuthContext.
  • GitHub OAuth Setup: A new OAuth app is created in GitHub, and the client ID and client secret are configured in Superbase.
  • Sign-in with GitHub: The signInWithGitHub function uses supabase.auth.signInWithOAuth to initiate the GitHub OAuth flow.
  • Session Management: A useEffect hook is used to:
    • Get the current session on component mount.
    • Set up a listener for authentication state changes using supabase.auth.onAuthStateChange.
    • Unsubscribe from the listener on component unmount to prevent memory leaks.
  • User Interface Updates: The Navbar is updated to display the user's avatar and username when logged in, and a sign-out button.

Creating Posts

  • Database Table: A posts table is created in Superbase with columns for id, created_at, title, content, and image_url.
  • Create Post Page: A CreatePostPage component is created with a form for entering the post title and content.
  • Create Post Component: A CreatePost component is created to handle the form and the logic for creating a new post.
  • State Management: The title and content states are used to store the form input values.
  • useMutation Hook: The useMutation hook from React Query is used to handle the asynchronous operation of inserting a new post into the database.
  • createPost Function: An asynchronous function createPost is created to make the Superbase API call to insert the new post.
  • Form Submission: The handleSubmit function is called when the form is submitted. It prevents the default form submission behavior and calls the mutate function to trigger the Superbase API call.
  • Error Handling: The isError state from the useMutation hook is used to display an error message if the API call fails.
  • Loading State: The isPending state from the useMutation hook is used to display a loading indicator while the API call is in progress.
  • Image Upload:
    • A file input is added to the form to allow the user to select an image.
    • The handleFileChange function is called when the user selects an image. It stores the selected file in the selectedFile state.
    • The createPost function is updated to upload the image to Superbase storage.
    • A unique file path is generated for the image using the post title and current date.
    • The supabase.storage.from('post-images').upload function is used to upload the image to Superbase storage.
    • The supabase.storage.from('post-images').getPublicUrl function is used to get the public URL of the uploaded image.
    • The image_url column in the posts table is updated with the public URL of the uploaded image.
  • RLS Policies: RLS policies are configured in Superbase to allow authenticated users to insert new posts and upload images to Superbase storage.

Displaying Posts

  • Database Table: The posts table is updated to include a user_avatar_url column to store the URL of the user's avatar.
  • Home Component: A Home component is created to display a list of recent posts.
  • Post List Component: A PostList component is created to fetch and display the list of posts.
  • useQuery Hook: The useQuery hook from React Query is used to fetch the list of posts from the database.
  • fetchPosts Function: An asynchronous function fetchPosts is created to make the Superbase API call to fetch the list of posts.
  • Error Handling: The isError state from the useQuery hook is used to display an error message if the API call fails.
  • Loading State: The isLoading state from the useQuery hook is used to display a loading indicator while the API call is in progress.
  • Post Item Component: A PostItem component is created to display each individual post.
  • Mapping: The map function is used to iterate over the list of posts and render a PostItem component for each post.
  • Post Type: A Post type is defined to represent the structure of a post object.
  • Dynamic Routing: React Router is used to create a dynamic route for each post, allowing users to navigate to a page with more details about the post.

Post Details Page

  • Post Page Component: A PostPage component is created to display the details of a single post.
  • useParams Hook: The useParams hook from React Router is used to get the post ID from the URL.
  • Post Detail Component: A PostDetail component is created to fetch and display the details of a single post.
  • fetchPostById Function: An asynchronous function fetchPostById is created to make the Superbase API call to fetch the details of a single post.
  • EQ Operator: The eq operator is used in the Superbase API call to filter the results and only return the post with the matching ID.
  • Date Formatting: The toLocaleDateString method is used to format the created_at date into a human-readable format.

Liking and Disliking Posts

  • Database Table: A votes table is created in Superbase with columns for id, post_id, user_id, and vote.
  • Like Button Component: A LikeButton component is created to handle the logic for liking and disliking posts.
  • useMutation Hook: The useMutation hook from React Query is used to handle the asynchronous operation of inserting a new vote into the database.
  • vote Function: An asynchronous function vote is created to make the Superbase API call to insert a new vote.
  • RLS Policies: RLS policies are configured in Superbase to allow authenticated users to insert new votes.
  • Vote Value: The vote column in the votes table is used to store the type of vote. A value of 1 represents a like, and a value of -1 represents a dislike.
  • Updating Votes: The vote function is updated to check if a vote already exists for the current user and post. If a vote exists, the function updates the existing vote instead of inserting a new one.
  • Deleting Votes: The vote function is updated to delete the existing vote if the user clicks the same button again (e.g., clicks the like button again after already liking the post).
  • Displaying Vote Counts:
    • The useQuery hook is used to fetch the number of likes and dislikes for each post.
    • The fetchVotes function is created to make the Superbase API call to fetch the number of likes and dislikes.
    • The filter method is used to count the number of likes and dislikes.
    • The invalidateQueries method is used to invalidate the query cache and refetch the data after a vote is added, updated, or deleted.
    • The refetchInterval option is used to automatically refetch the data every 5 seconds.
  • User Vote: The find method is used to determine if the current user has already voted on the post. The background color of the like and dislike buttons is updated based on the user's vote.

Comment Section

  • Database Table: A comments table is created in Superbase with columns for id, post_id, parent_comment_id, content, user_id, created_at, and author.
  • Comment Section Component: A CommentSection component is created to handle the logic for displaying and adding comments.
  • State Management: The newCommentText state is used to store the comment input value.
  • useMutation Hook: The useMutation hook from React Query is used to handle the asynchronous operation of inserting a new comment into the database.
  • createComment Function: An asynchronous function createComment is created to make the Superbase API call to insert a new comment.
  • Form Submission: The handleSubmit function is called when the form is submitted. It prevents the default form submission behavior and calls the mutate function to trigger the Superbase API call.
  • Error Handling: The isError state from the useMutation hook is used to display an error message if the API call fails.
  • Loading State: The isPending state from the useMutation hook is used to display a loading indicator while the API call is in progress.
  • Fetching Comments:
    • The useQuery hook is used to fetch the list of comments for each post.
    • The fetchComments function is created to make the Superbase API call to fetch the list of comments.
  • Comment Tree: A buildCommentTree function is created to transform the flat list of comments into a hierarchical tree structure.
  • Comment Item Component: A CommentItem component is created to display each individual comment.
  • Recursive Rendering: The CommentItem component is rendered recursively to display the nested comments.
  • Reply Functionality:
    • A showReply state is added to the CommentItem component to control the visibility of the reply form.
    • A replyText state is added to the CommentItem component to store the reply input value.
    • A handleReplySubmit function is created to handle the submission of the reply form.
    • A createReply function is created to make the Superbase API call to insert a new reply.
  • Invalidating Queries: The invalidateQueries method is used to invalidate the query cache and refetch the comments after a new comment or reply is added.

Displaying Comment and Like Counts

  • RPC Function: A postgress function get_posts_with_counts is created to fetch the list of posts along with the comment and like counts.
  • Post List Component: The PostList component is updated to use the get_posts_with_counts function to fetch the list of posts.
  • Post Item Component: The PostItem component is updated to display the comment and like counts.

Communities

  • Database Table: A communities table is created in Superbase with columns for id, name, and description.
  • Community ID: A community_id column is added to the posts table to associate each post with a community.
  • Create Community Page: A CreateCommunityPage component is created to allow users to create new communities.
  • Create Community Component: A CreateCommunity component is created to handle the form and the logic for creating a new community.
  • useMutation Hook: The useMutation hook from React Query is used to handle the asynchronous operation of inserting a new community into the database.
  • createCommunity Function: An asynchronous function createCommunity is created to make the Superbase API call to insert a new community.
  • Communities Page: A CommunitiesPage component is created to display a list of all the communities.
  • Community List Component: A CommunityList component is created to fetch and display the list of communities.
  • useQuery Hook: The useQuery hook from React Query is used to fetch the list of communities from the database.
  • fetchCommunities Function: An asynchronous function fetchCommunities is created to make the Superbase API call to fetch the list of communities.
  • Community Page: A CommunityPage component is created to display the posts for a specific community.
  • Community Display Component: A CommunityDisplay component is created to fetch and display the posts for a specific community.
  • fetchCommunityPosts Function: An asynchronous function fetchCommunityPosts is created to make the Superbase API call to fetch the posts for a specific community.

Deployment

  • GitHub Repository: The project code is pushed to a GitHub repository.
  • Vercel Deployment: The project is deployed to Vercel using the GitHub repository.
  • Environment Variables: The Superbase project URL and anonymous key are configured as environment variables in Vercel.
  • Vite Base Path: The vite.config.ts file is updated to include a base URL for the project.
  • GitHub OAuth Configuration: The GitHub OAuth app is updated with the URL of the deployed application.
  • Superbase Site URL: The Superbase site URL is updated with the URL of the deployed application.

Conclusion

The video provides a comprehensive guide to building a full-stack social media platform using Superbase, React, and Tailwind CSS. It covers a wide range of topics, including project setup, authentication, data management, and deployment. The video emphasizes best practices for state management, error handling, and security. The final product is a functional social media platform with features such as user authentication, post creation, liking, commenting, and community management.

AI summaries can miss context or contain errors. Check important details against the original video.

Go a little deeper.

Have a question about this video? Load its transcript to open the video chat.