Social Media Platform
Build a social media platform with posts, comments, user profiles, and real-time features
150 min•By Priygop Team•Last 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.jsReal-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>
);
}