Skip to main content
Course/Module 9/Topic 2 of 4Advanced

Social Media Platform

Build a social media platform with posts, comments, user profiles, and real-time features

150 minBy Priygop TeamLast updated: Feb 2026

Project Overview

Create a social media platform with user authentication, posts, comments, likes, user profiles, and real-time notifications.

Core Features

Example
// Social media app features
- User authentication and profiles
- Create, edit, and delete posts
- Like and comment on posts
- Follow/unfollow users
- Real-time notifications
- News feed with infinite scroll
- User search and discovery
- Direct messaging
- Post sharing and bookmarking

// Main components structure
src/
├── components/
│   ├── auth/
│   │   ├── LoginModal.js
│   │   ├── RegisterModal.js
│   │   └── AuthGuard.js
│   ├── post/
│   │   ├── PostCard.js
│   │   ├── PostForm.js
│   │   ├── PostDetail.js
│   │   ├── CommentList.js
│   │   └── LikeButton.js
│   ├── profile/
│   │   ├── ProfileHeader.js
│   │   ├── ProfilePosts.js
│   │   ├── ProfileStats.js
│   │   └── EditProfile.js
│   ├── feed/
│   │   ├── NewsFeed.js
│   │   ├── FeedFilter.js
│   │   └── InfiniteScroll.js
│   └── common/
│       ├── Header.js
│       ├── Sidebar.js
│       ├── NotificationBell.js
│       └── SearchBar.js
├── hooks/
│   ├── usePosts.js
│   ├── useAuth.js
│   ├── useInfiniteScroll.js
│   └── useNotifications.js
├── context/
│   ├── AuthContext.js
│   ├── PostContext.js
│   └── NotificationContext.js
└── utils/
    ├── api.js
    ├── socket.js
    └── helpers.js

Real-time Features

Example
// Real-time features with WebSocket
import { useEffect, useState } from 'react';
import io from 'socket.io-client';

// WebSocket connection
const socket = io('http://localhost:3001');

// Real-time notifications
function useNotifications() {
    const [notifications, setNotifications] = useState([]);

    useEffect(() => {
        socket.on('notification', (notification) => {
            setNotifications(prev => [notification, ...prev]);
        });

        socket.on('like', (data) => {
            // Handle real-time like updates
            console.log('Post liked:', data);
        });

        socket.on('comment', (data) => {
            // Handle real-time comment updates
            console.log('New comment:', data);
        });

        return () => {
            socket.off('notification');
            socket.off('like');
            socket.off('comment');
        };
    }, []);

    return { notifications };
}

// Post management with real-time updates
function usePosts() {
    const [posts, setPosts] = useState([]);
    const [loading, setLoading] = useState(false);

    useEffect(() => {
        // Listen for real-time post updates
        socket.on('newPost', (post) => {
            setPosts(prev => [post, ...prev]);
        });

        socket.on('postUpdate', (updatedPost) => {
            setPosts(prev => prev.map(post => 
                post.id === updatedPost.id ? updatedPost : post
            ));
        });

        socket.on('postDelete', (postId) => {
            setPosts(prev => prev.filter(post => post.id !== postId));
        });

        return () => {
            socket.off('newPost');
            socket.off('postUpdate');
            socket.off('postDelete');
        };
    }, []);

    const createPost = async (postData) => {
        setLoading(true);
        try {
            const response = await fetch('/api/posts', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(postData),
            });
            const newPost = await response.json();
            
            // Emit real-time update
            socket.emit('createPost', newPost);
            
            setPosts(prev => [newPost, ...prev]);
        } catch (error) {
            console.error('Error creating post:', error);
        } finally {
            setLoading(false);
        }
    };

    const likePost = async (postId) => {
        try {
            await fetch(`/api/posts/${postId}/like`, { method: 'POST' });
            socket.emit('likePost', { postId });
        } catch (error) {
            console.error('Error liking post:', error);
        }
    };

    return { posts, loading, createPost, likePost };
}

// Post components
function PostCard({ post }) {
    const { likePost } = usePosts();
    const [liked, setLiked] = useState(post.liked);
    const [likeCount, setLikeCount] = useState(post.likeCount);

    const handleLike = async () => {
        await likePost(post.id);
        setLiked(!liked);
        setLikeCount(prev => liked ? prev - 1 : prev + 1);
    };

    return (
        <div className="post-card">
            <div className="post-header">
                <img src={post.author.avatar} alt={post.author.name} />
                <div>
                    <h4>{post.author.name}</h4>
                    <span>{new Date(post.createdAt).toLocaleDateString()}</span>
                </div>
            </div>
            <div className="post-content">
                <p>{post.content}</p>
                {post.image && <img src={post.image} alt="Post" />}
            </div>
            <div className="post-actions">
                <button 
                    onClick={handleLike}
                    className={`like-btn ${liked ? 'liked' : ''}`}
                >
                    ❤️ {likeCount}
                </button>
                <button className="comment-btn">💬 {post.commentCount}</button>
                <button className="share-btn">📤 Share</button>
            </div>
        </div>
    );
}

// Infinite scroll feed
function NewsFeed() {
    const { posts, loading } = usePosts();
    const [page, setPage] = useState(1);
    const [hasMore, setHasMore] = useState(true);

    const loadMorePosts = async () => {
        if (loading || !hasMore) return;

        try {
            const response = await fetch(`/api/posts?page=${page + 1}`);
            const newPosts = await response.json();
            
            if (newPosts.length === 0) {
                setHasMore(false);
            } else {
                setPosts(prev => [...prev, ...newPosts]);
                setPage(prev => prev + 1);
            }
        } catch (error) {
            console.error('Error loading more posts:', error);
        }
    };

    useEffect(() => {
        const handleScroll = () => {
            if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 1000) {
                loadMorePosts();
            }
        };

        window.addEventListener('scroll', handleScroll);
        return () => window.removeEventListener('scroll', handleScroll);
    }, [page, hasMore, loading]);

    return (
        <div className="news-feed">
            {posts.map(post => (
                <PostCard key={post.id} post={post} />
            ))}
            {loading && <div className="loading">Loading more posts...</div>}
            {!hasMore && <div className="end">No more posts to load</div>}
        </div>
    );
}

Additional Resources

Recommended Reading

  • React Project Best Practices
  • Deployment Strategies Guide
  • Performance Optimization Tips

Online Resources

  • Real-World React Projects
  • Portfolio Building Guide
  • React Deployment Tutorial
Chat on WhatsApp
Priygop - Leading Professional Development Platform | Expert Courses & Interview Prep