Feed Section in MERN Stack Social Media Platform

Last Updated : 23 Jul, 2025

Social media platforms are integral to modern communication and have a range of key features. Here's an overview of some of the primary features you might find across different social media platforms:

Key Features

User Profiles:

  • Personal Information: Users can create profiles that include personal details, profile pictures, and bios.
  • Customizable Privacy Settings: Allows users to control who can see their information and posts.
  • Feeds and Timelines: Displays all the posts, user comments and likes.
  • Home Feed: Displays a chronological or algorithmically sorted list of posts from users or pages followed.
  • News Feed: A dynamic stream of updates, news, and content relevant to the user's interests.

Post Creation:

  • Text Posts: Share thoughts, updates, and status messages.
  • Multimedia Posts: Include images, videos, and audio clips.
  • Stories: Short-lived posts that disappear after a set time (e.g., 24 hours).

Engagement Features:

  • Likes and Reactions: Users can express approval or emotion towards posts.
  • Comments: Engage in discussions or provide feedback on posts.
  • Shares/Retweets: Repost content to your own feed or share with your followers.

Messaging and Communication:

  • Direct Messaging: Private one-on-one or group conversations.
  • Chatbots: Automated responses or interactions through messaging.

Notifications:

  • Activity Alerts: Notify users about interactions, mentions, or updates from followed accounts.
  • Customizable Settings: Users can manage their notification preferences.

Approach to Implement Social Media Platforms: feed

Backend

  • Setup: Initialize an Express application with middleware for JSON parsing, CORS, and cookie parsing.
  • Socket Integration: Configure Socket.IO for real-time communication and integrate with a SocketServer.
  • Routes: Define API routes for authentication, user management, posts, comments, notifications, and messaging.
  • Database Connection: Connect to MongoDB using Mongoose with provided credentials.
  • Post Model: Create a Mongoose schema and model for handling posts, including fields for content, images, likes, comments, and reports.
  • Post Controller: Implement CRUD operations for posts, including features like liking, unliking, saving, and reporting posts.
  • Pagination: Use a custom APIfeatures class to handle pagination and sorting of posts.
  • Error Handling: Include error handling for database operations and invalid requests to ensure robust API responses.

Frontend

  • Post Component: Displays individual posts with user info, images, content, likes, saves, comments, and interactions using Material-UI components.
  • PostPage Component: Fetches and displays a single post by ID, handling loading and error states.
  • HomePage Component: Manages a list of posts, including fetching posts, handling likes, saves, and unsaves with user feedback via Snackbar.
  • State Management: Uses useState and useEffect hooks for managing component state and side effects.
  • API Integration: Utilizes axios for API requests, including handling authentication via tokens and updating the UI based on API responses.

Backend Example:

JavaScript
// index.js

require("dotenv").config()
const express = require("express");
const mongoose = require("mongoose");
const cors = require("cors");
const cookieParser = require("cookie-parser");
const SocketServer = require("./socketServer");
const app = express();

app.use(express.json())
app.use(cors({
    origin: [, "http://localhost:5173"],
    methods: [
        "GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"
    ],
    allowedHeaders: ["Content-Type", "Authorization"],
    credentials: true,
}));
app.use(cookieParser())

app.use((req, res, next) => {
    res.header("Access-Control-Allow-Origin", "*");
    next();
})

//#region // !Socket
const http = require("http").createServer(app);
const io = require("socket.io")(http);

io.on("connection", socket => { SocketServer(socket); })

//#endregion
app.get("/",
    (req, res) => {
        res.send(
            "Hi Welcome to Social Media App API.....")
    })
//#region // !Routes
app.use("/api", require("./routes/authRouter"));
app.use("/api", require("./routes/userRouter"));
app.use("/api", require("./routes/postRouter"));

//#endregion

const URI = "Your MongoDB URI";
mongoose.connect(URI, {
    useCreateIndex: true,
    useFindAndModify: false,
    useNewUrlParser: true,
    useUnifiedTopology: true
},
    err => {
        if (err)
            throw err;
        console.log("Database Connected!!")
    })

const port = process.env.PORT || 3001;
http.listen(port,
    () => { console.log("Listening on ", port); });
            () => { console.log("Listening on ", port); });
JavaScript
// models/postModel.js

const mongoose = require("mongoose");
const { Schema } = mongoose;

const postSchema = new Schema(
    {
        content: String,
        images: {
            type: Array,
            required: true,
        },
        likes: [
            {
                type: mongoose.Types.ObjectId,
                ref: "user",
            },
        ],
        comments: [
            {
                type: mongoose.Types.ObjectId,
                ref: "comment",
            },
        ],
        user: {
            type: mongoose.Types.ObjectId,
            ref: "user",
        },
        reports: [
            {
                type: mongoose.Types.ObjectId,
                ref: "user",
            },
        ],
    },
    {
        timestamps: true,
    }
);


module.exports = mongoose.model('post', postSchema);
JavaScript
// middleware/auth.js

const Users = require("../models/userModel");
const jwt = require("jsonwebtoken");

const auth = async (req, res, next) => {
    try {
        const authHeader = req.header("Authorization");

        // Check if the token exists
        if (!authHeader) {
            return res.status(400).json({ msg: "You are not authorized" });
        }

        // Extract the token by removing 'Bearer ' prefix
        const token = authHeader.split(" ")[1];

        // Verify the token
        const decoded = jwt.verify(token, "AAAA");
        if (!decoded) {
            return res.status(400).json({ msg: "Invalid token" });
        }

        const user = await Users.findOne({ _id: decoded.id });

        req.user = user;
        next();
    } catch (err) {
        return res.status(500).json({ msg: err.message });
    }
}



module.exports = auth;
JavaScript
// middleware/upload.js

const multer = require("multer");
const path = require("path");

// Define Storage for Multer
const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, "uploads/"); // Upload destination folder
    },
    filename: (req, file, cb) => {
        cb(null,
            Date.now()
            + path.extname(
                file.originalname)); // Append timestamp
        // to file name
    },
});

// File filter to only allow image types
const fileFilter = (req, file, cb) => {
    const filetypes = /jpeg|jpg|png|gif/;
    const mimetype = filetypes.test(file.mimetype);
    const extname = filetypes.test(
        path.extname(file.originalname).toLowerCase());

    if (mimetype && extname) {
        return cb(null, true);
    }
    cb(new Error(
        "Only images (jpeg, jpg, png, gif) are allowed"));
};

// Set up Multer with storage, file size limit, and file
// filter
const upload = multer({
    storage: storage,
    limits: { fileSize: 5 * 1024 * 1024 }, // 5 MB limit
    fileFilter: fileFilter,
});

// Exporting the Multer upload function
module.exports = upload;
JavaScript
// contollers/postCtrl

const Posts = require("../models/postModel");
const Comments = require("../models/commentModel");
const Users = require("../models/userModel");

class APIfeatures {
    constructor(query, queryString) {
        this.query = query;
        this.queryString = queryString;
    }

    paginating() {
        const page = this.queryString.page * 1 || 1;
        const limit = this.queryString.limit * 1 || 9;
        const skip = (page - 1) * limit;
        this.query = this.query.skip(skip).limit(limit);
        return this;
    }
}

const postCtrl = {
    createPost: async (req, res) => {
        try {
            const { content } = req.body;

            // If no files (images) were uploaded
            if (!req.files || req.files.length === 0) {
                return res.status(400).json(
                    { msg: "Please add photo(s)" });
            }

            // Extract image paths from uploaded files
            const imagePaths
                = req.files.map(file => file.path);

            // Create a new post with the content and image
            // paths
            const newPost = new Posts({
                content,
                images: imagePaths,
                user: req.user._id, // Assuming req.user is
                // populated from auth
                // middleware
            });

            // Save the new post to the database
            await newPost.save();

            // Return a response with the created post data
            res.json({
                msg: "Post created successfully.",
                newPost: {
                    ...newPost._doc,
                    user: req.user, // Include user data in
                    // the response
                },
            });
        }
        catch (err) {
            return res.status(500).json(
                { msg: err.message });
        }
    },

    getPosts: async (req, res) => {
        try {
            const features = new APIfeatures(Posts.find({
                user: [
                    ...req.user.following,
                    req.user._id
                ],
            }),
                req.query)
                .paginating();
            const posts
                = await features.query.sort("-createdAt")
                    .populate(
                        "user likes",
                        "avatar username fullname followers")
                    .populate({
                        path: "comments",
                        populate: {
                            path: "user likes ",
                            select: "-password",
                        },
                    });

            res.json({
                msg: "Success",
                result: posts.length,
                posts,
            });
        }
        catch (err) {
            return res.status(500).json(
                { msg: err.message });
        }
    },

    updatePost: async (req, res) => {
        try {
            const { content, images } = req.body;

            const post
                = await Posts
                    .findOneAndUpdate(
                        { _id: req.params.id }, {
                        content,
                        images,
                    })
                    .populate("user likes",
                        "avatar username fullname")
                    .populate({
                        path: "comments",
                        populate: {
                            path: "user likes ",
                            select: "-password",
                        },
                    });

            res.json({
                msg: "Post updated successfully.",
                newPost: {
                    ...post._doc,
                    content,
                    images,
                },
            });
        }
        catch (err) {
            return res.status(500).json(
                { msg: err.message });
        }
    },

    likePost: async (req, res) => {
        try {
            const post = await Posts.find({
                _id: req.params.id,
                likes: req.user._id,
            });
            if (post.length > 0) {
                return res.status(400).json({
                    msg: "You have already liked this post"
                });
            }

            const like = await Posts.findOneAndUpdate(
                { _id: req.params.id }, {
                $push: { likes: req.user._id },
            },
                {
                    new: true,
                });

            if (!like) {
                return res.status(400).json(
                    { msg: "Post does not exist." });
            }

            res.json({ msg: "Post liked successfully." });
        }
        catch (err) {
            return res.status(500).json(
                { msg: err.message });
        }
    },

    unLikePost: async (req, res) => {
        try {
            const like = await Posts.findOneAndUpdate(
                { _id: req.params.id }, {
                $pull: { likes: req.user._id },
            },
                {
                    new: true,
                });

            if (!like) {
                return res.status(400).json(
                    { msg: "Post does not exist." });
            }

            res.json({ msg: "Post unliked successfully." });
        }
        catch (err) {
            return res.status(500).json(
                { msg: err.message });
        }
    },

    getUserPosts: async (req, res) => {
        try {
            const features
                = new APIfeatures(
                    Posts.find({ user: req.params.id }),
                    req.query)
                    .paginating();
            const posts
                = await features.query.sort("-createdAt");

            res.json({
                posts,
                result: posts.length,
            });
        }
        catch (err) {
            return res.status(500).json(
                { msg: err.message });
        }
    },

    getPost: async (req, res) => {
        try {
            const post
                = await Posts.findById(req.params.id)
                    .populate(
                        "user likes",
                        "avatar username fullname followers")
                    .populate({
                        path: "comments",
                        populate: {
                            path: "user likes ",
                            select: "-password",
                        },
                    });

            if (!post) {
                return res.status(400).json(
                    { msg: "Post does not exist." });
            }

            res.json({ post });
        }
        catch (err) {
            return res.status(500).json(
                { msg: err.message });
        }
    },

    getPostDiscover: async (req, res) => {
        try {
            const newArr =
                [...req.user.following, req.user._id];

            const num = req.query.num || 8;

            const posts = await Posts.aggregate([
                { $match: { user: { $nin: newArr } } },
                { $sample: { size: Number(num) } },
            ]);

            res.json({
                msg: "Success",
                result: posts.length,
                posts,
            });
        }
        catch (err) {
            return res.status(500).json(
                { msg: err.message });
        }
    },

    deletePost: async (req, res) => {
        try {
            const post = await Posts.findOneAndDelete({
                _id: req.params.id,
                user: req.user._id,
            });

            await Comments.deleteMany(
                { _id: { $in: post.comments } });

            res.json({
                msg: "Post deleted successfully.",
                newPost: { ...post, user: req.user }
            });
        }
        catch (err) {
            return res.status(500).json(
                { msg: err.message });
        }
    },

    reportPost: async (req, res) => {
        try {
            const post = await Posts.find({
                _id: req.params.id,
                reports: req.user._id,
            });
            if (post.length > 0) {
                return res.status(400).json({
                    msg:
                        "You have already reported this post"
                });
            }

            const report = await Posts.findOneAndUpdate(
                { _id: req.params.id }, {
                $push: { reports: req.user._id },
            },
                {
                    new: true,
                });

            if (!report) {
                return res.status(400).json(
                    { msg: "Post does not exist." });
            }

            res.json({ msg: "Post reported successfully." });
        }
        catch (err) {
            return res.status(500).json(
                { msg: err.message });
        }
    },

    savePost: async (req, res) => {
        try {
            const user = await Users.find({
                _id: req.user._id,
                saved: req.params.id,
            });
            if (user.length > 0) {
                return res.status(400).json({
                    msg:
                        "You have already saved this post."
                });
            }

            const save = await Users.findOneAndUpdate(
                { _id: req.user._id }, {
                $push: { saved: req.params.id },
            },
                {
                    new: true,
                });

            if (!save) {
                return res.status(400).json(
                    { msg: "User does not exist." });
            }

            res.json({ msg: "Post saved successfully." });
        }
        catch (err) {
            return res.status(500).json(
                { msg: err.message });
        }
    },

    unSavePost: async (req, res) => {
        try {
            const save = await Users.findOneAndUpdate(
                { _id: req.user._id }, {
                $pull: { saved: req.params.id },
            },
                {
                    new: true,
                });

            if (!save) {
                return res.status(400).json(
                    { msg: "User does not exist." });
            }

            res.json({
                msg:
                    "Post removed from collection successfully."
            });
        }
        catch (err) {
            return res.status(500).json(
                { msg: err.message });
        }
    },

    getSavePost: async (req, res) => {
        try {
            const features
                = new APIfeatures(
                    Posts.find(
                        { _id: { $in: req.user.saved } }),
                    req.query)
                    .paginating();

            const savePosts
                = await features.query.sort("-createdAt");

            res.json({ savePosts, result: savePosts.length })
        }
        catch (err) {
            return res.status(500).json(
                { msg: err.message });
        }
    },
};

module.exports = postCtrl;


Start Your backend using the below command:

node index.js

Frontend Example:

JavaScript
// App.jsx

import React from "react";
import {
    BrowserRouter as Router,
    Route,
    Routes
} from "react-router-dom";

import Login from "./components/Login";
import Navbar from "./components/Navbar";
import Register from "./components/Register";
import UserProfile from "./components/UserProfile.jsx";
import CreatePost from "./pages/CreatePost.jsx";
import HomePage from "./pages/HomePage";
import PostPage from "./pages/PostPage";
import SavedPostsPage from "./pages/SavedPostsPage";
import UserPostsPage from "./pages/UserPostsPage";

const App = () => {
    return (
        <Router><Navbar /><Routes>< Route path="/" element
            ={<HomePage />} />
            <Route path="/posts
              /: id " element={<PostPage />} />
            < Route path
                ="/user-posts" element
                ={<UserPostsPage />} />
            <Route path="/post
                                 " element={<CreatePost />} />
            < Route path
                ="/saved-posts" element
                ={<SavedPostsPage />} />
            <Route path="/user
              /: id " element={<UserProfile />} />
            < Route path
                ="/register" element
                ={<Register />} />
            <Route path="/login
                            " element={<Login />} />
            < /Routes>
        </Router >);
};

export default App;
JavaScript
// pages/SavedPostPages.jsx

import axios from "axios";
import React, { useEffect, useState } from "react";

import Post from "../components/Post";

const SavedPostsPage = () => {
    const [savedPosts, setSavedPosts] = useState([]);

    useEffect(() => {
        axios.get(`http://localhost:3001/api/getSavePosts%60, {
            headers: {
                Authorization: `Bearer ${token}`,
            },
        })
            .then(response => {
                setSavedPosts(response.data.savePosts);
            })
            .catch(error => {
                console.log(error);
            });
    }, []);

    return (
        <div>
            {savedPosts.map(post => (
                <Post key={post._id} post={post} />
            ))}
        </div>
    );
};

export default SavedPostsPage;
JavaScript
// src/pages/PostPage.jsx

import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import axios from 'axios';
import Post from '../components/Post';

const PostPage = () => {
    const { id } = useParams();
    const [post, setPost] = useState(null);

    useEffect(() => {
        axios.get(`http://localhost:3001/api/posts/$%7Bid%7D%60)
            .then(response => {
                setPost(response.data.post);
            })
            .catch(error => {
                console.log(error);
            });
    }, [id]);

    return post ? <Post post={post} /> : <div>Loading...</div>;
};

export default PostPage;
JavaScript
// src/pages/HomePage.jsx

import {
    Alert,
    CircularProgress,
    Container,
    Snackbar
} from "@mui/material";
import axios from "axios";
import React, { useEffect, useState } from "react";

import Post from "../components/Post";

const HomePage = () => {
    const [posts, setPosts] = useState([]);
    const [loading, setLoading] = useState(true); // Loading state
    const [error, setError] = useState(null); // Error state
    const [openSnackbar, setOpenSnackbar] = useState(false); // Snackbar for feedback
    const [snackbarMessage, setSnackbarMessage] = useState("");
    const token = localStorage.getItem("token");

    useEffect(() => {
        axios.get("http://localhost:3001/api/posts", {
            headers: {
                Authorization: `Bearer ${token}`,
            },
        })
            .then(response => {
                setPosts(response.data.posts);
                setLoading(false);
            })
            .catch(error => {
                setError("Failed to load posts. Please try again later.");
                setLoading(false);
            });
    }, [token]);

    const handleSnackbar = (message) => {
        setSnackbarMessage(message);
        setOpenSnackbar(true);
    };

    const handleLike = (postId) => {
        axios.patch(`http://localhost:3001/api/post/$%7BpostId%7D/like%60, {}, {
            headers: { Authorization: `Bearer ${token}` }
        }).then(() => {
            handleSnackbar("Post liked!");
            setPosts(prevPosts =>
                prevPosts.map(post =>
                    post._id === postId ? { ...post, isLiked: true, likes: post.likes + 1 } : post
                )
            );
        });
    };

    const handleUnlike = (postId) => {
        axios.patch(`http://localhost:3001/api/post/$%7BpostId%7D/unlike%60, {}, {
            headers: { Authorization: `Bearer ${token}` }
        }).then(() => {
            handleSnackbar("Post unliked!");
            setPosts(prevPosts =>
                prevPosts.map(post =>
                    post._id === postId ? { ...post, isLiked: false, likes: post.likes - 1 } : post
                )
            );
        });
    };

    const handleSave = (postId) => {
        axios.patch(`http://localhost:3001/api/post/$%7BpostId%7D/save%60, {}, {
            headers: { Authorization: `Bearer ${token}` }
        }).then(() => {
            handleSnackbar("Post saved!");
            setPosts(prevPosts =>
                prevPosts.map(post =>
                    post._id === postId ? { ...post, isSaved: true } : post
                )
            );
        });
    };

    const handleUnsave = (postId) => {
        axios.patch(`http://localhost:3001/api/post/$%7BpostId%7D/unsave%60, {}, {
            headers: { Authorization: `Bearer ${token}` }
        }).then(() => {
            handleSnackbar("Post unsaved!");
            setPosts(prevPosts =>
                prevPosts.map(post =>
                    post._id === postId ? { ...post, isSaved: false } : post
                )
            );
        });
    };

    return (
        <Container maxWidth="md">
            {/* Loading spinner */}
            {loading && <CircularProgress style={{ display: "block", margin: "20px auto" }} />}

            {/* Error message */}
            {error && <Alert severity="error" style={{ marginBottom: '20px' }}>{error}</Alert>}

            {/* Posts */}
            {!loading && !error && posts.length > 0 && (
                posts.map(post => (
                    <Post
                        key={post._id}
                        post={post}
                        handleLike={() => handleLike(post._id)}
                        handleUnlike={() => handleUnlike(post._id)}
                        handleSave={() => handleSave(post._id)}
                        handleUnsave={() => handleUnsave(post._id)}
                        isLiked={post.isLiked}
                        isSaved={post.isSaved}
                    />
                ))
            )}

            {/* Snackbar for user feedback */}
            <Snackbar
                open={openSnackbar}
                autoHideDuration={3000}
                onClose={() => setOpenSnackbar(false)}
                anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
            >
                <Alert onClose={() => setOpenSnackbar(false)} severity="success">
                    {snackbarMessage}
                </Alert>
            </Snackbar>
        </Container>
    );
};

export default HomePage;
JavaScript
// src/components/Post.jsx

import React from 'react';
import {
    Card,
    CardHeader,
    CardMedia,
    CardContent,
    Typography,
    IconButton,
    Avatar,
    Grid,
    Tooltip,
    Divider
} from '@mui/material';
import {
    Favorite,
    FavoriteBorder,
    Bookmark,
    BookmarkBorder,
    ChatBubbleOutline,
    Share
} from '@mui/icons-material';

const Post = ({ post, handleLike, handleUnlike, handleSave, handleUnsave, isLiked, isSaved }) => {
    const { user, content, images, likes, comments, createdAt } = post;

    return (
        <Card style={{ margin: '20px 0' }}>
            {/* User Info */}
            <CardHeader
                avatar={<Avatar src={user?.avatar} alt={user?.username} />} 
                title={<Typography variant="h6">{user?.username}</Typography>}
                subheader={new Date(createdAt).toLocaleDateString()}
            />

            {/* Post Image */}
            {images && images[0] && (
                <CardMedia
                    component="img"
                    height="300"
                    image={images[0]} // Use images[0] safely
                    alt="Post Image"
                    style={{ objectFit: 'cover' }}
                />
            )}

            {/* Post Content */}
            <CardContent>
                <Typography variant="body1" style={{ marginBottom: '10px' }}>
                    {content}
                </Typography>

                <Grid container alignItems="center" spacing={2}>
                    {/* Like and Unlike */}
                    <Grid item>
                        <IconButton onClick={isLiked ? handleUnlike : handleLike}>
                            {isLiked ? (
                                <Favorite color="error" />
                            ) : (
                                <FavoriteBorder />
                            )}
                        </IconButton>
                        <Typography variant="body2" component="span">{likes.length} Likes</Typography>
                    </Grid>

                    {/* Save and Unsave */}
                    <Grid item>
                        <IconButton onClick={isSaved ? handleUnsave : handleSave}>
                            {isSaved ? (
                                <Bookmark />
                            ) : (
                                <BookmarkBorder />
                            )}
                        </IconButton>
                    </Grid>

                    {/* Comment Section */}
                    <Grid item>
                        <Tooltip title="Comment">
                            <IconButton>
                                <ChatBubbleOutline />
                            </IconButton>
                        </Tooltip>
                    </Grid>

                    {/* Share */}
                    <Grid item>
                        <Tooltip title="Share">
                            <IconButton>
                                <Share />
                            </IconButton>
                        </Tooltip>
                    </Grid>
                </Grid>

                <Divider style={{ margin: '10px 0' }} />

                {/* Comment Section */}
                <Typography variant="subtitle1">Comments</Typography>
                <Grid container spacing={2}>
                    {comments?.length ? comments.map((comment, index) => (
                        <Grid item xs={12} key={index}>
                            {comment.user && comment.user.username ? (
                                <Typography variant="body2">
                                    <strong>{comment.user.username}:</strong> {comment.text}
                                </Typography>
                            ) : (
                                <Typography variant="body2">Anonymous:</Typography>
                            )}
                        </Grid>
                    )) : (
                        <Typography variant="body2">No comments yet.</Typography>
                    )}
                </Grid>
            </CardContent>
        </Card>
    );
};

export default Post;
JavaScript
// src/components/Navbar.jsx

import {
    AccountCircle,
    Notifications,
    Search
} from "@mui/icons-material";
import {
    AppBar,
    Avatar,
    Badge,
    Button,
    IconButton,
    InputBase,
    Menu,
    MenuItem,
    Toolbar,
    Typography
} from "@mui/material";
import { alpha, styled } from "@mui/material/styles";
import React, { useEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";

const SearchBar = styled("div")(
    ({ theme }) => ({
        position: "relative",
        borderRadius: theme.shape.borderRadius,
        backgroundColor:
            alpha(theme.palette.common.white, 0.15),
        "&:hover": {
            backgroundColor:
                alpha(theme.palette.common.white, 0.25),
        },
        marginRight: theme.spacing(2),
        marginLeft: 0,
        width: "100%",
        [theme.breakpoints.up("sm")]: {
            marginLeft: theme.spacing(3),
            width: "auto",
        },
    }));

const SearchIconWrapper
    = styled("div")(({ theme }) => ({
        padding: theme.spacing(0, 2),
        height: "100%",
        position: "absolute",
        pointerEvents: "none",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
    }));

const StyledInputBase = styled(InputBase)(
    ({ theme }) => ({
        color: "inherit",
        "& .MuiInputBase-input": {
            padding: theme.spacing(1, 1, 1, 0),
            // vertical padding + font size from searchIcon
            paddingLeft: `calc(1em + ${theme.spacing(4)})`,
            transition: theme.transitions.create("width"),
            width: "100%",
            [theme.breakpoints.up("md")]: {
                width: "20ch",
            },
        },
    }));

const Navbar = () => {
    const [anchorEl, setAnchorEl] = useState(null);
    const [user, setUser] = useState(null);
    const navigate = useNavigate();

    useEffect(() => {
        const loggedUser = localStorage.getItem("user");
        if (loggedUser) {
            setUser(JSON.parse(loggedUser));

        }
    }, []);

    const handleProfileMenuOpen = (event) => {
        setAnchorEl(event.currentTarget);
    };

    const handleMenuClose = () => {
        setAnchorEl(null);
    };

    const handleLogout = () => {
        localStorage.removeItem("user"); // Remove user from localStorage
        localStorage.removeItem("token"); // Remove token from localStorage
        setUser(null); // Set user state to null
        navigate("/login"); // Redirect to login page
    };

    const isMenuOpen = Boolean(anchorEl);
    const menuId = "primary-search-account-menu";

    return (
        <AppBar position="static">
            <Toolbar>
                <Typography variant="h6" sx={{ flexGrow: 1 }}>
                    Social Media App
                </Typography>

                {/* Search Bar */}
                <SearchBar>
                    <SearchIconWrapper>
                        <Search />
                    </SearchIconWrapper>
                    <StyledInputBase
                        placeholder="Searchâ€Ķ"
                        inputProps={{ 'aria-label': 'search' }}
                    />
                </SearchBar>

                {/* Navigation Links */}
                <Button color="inherit" component={Link} to="/">Feed</Button>
                <Button color="inherit" component={Link} to="/post">Create Post</Button>
                <Button color="inherit" component={Link} to="/user-posts">My Posts</Button>
                <Button color="inherit" component={Link} to="/saved-posts">Saved Posts</Button>

                {/* Notifications */}
                <IconButton color="inherit">
                    <Badge badgeContent={4} color="error">
                        <Notifications />
                    </Badge>
                </IconButton>

                {user?.fullname ? (
                    <>
                        {/* User Profile Dropdown */}
                        <IconButton
                            edge="end"
                            aria-label="account of current user"
                            aria-controls={menuId}
                            aria-haspopup="true"
                            onClick={handleProfileMenuOpen}
                            color="inherit"
                        >
                            <AccountCircle />
                        </IconButton>

                        {/* Dropdown Menu */}
                        <Menu
                            anchorEl={anchorEl}
                            anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
                            id={menuId}
                            keepMounted
                            transformOrigin={{ vertical: 'top', horizontal: 'right' }}
                            open={isMenuOpen}
                            onClose={handleMenuClose}
                        >
                            <MenuItem component={Link} to={`/user/${user._id}`}>Profile</MenuItem>
                            <MenuItem component={Link} to="/settings">Settings</MenuItem>
                            <MenuItem onClick={handleLogout}>Logout</MenuItem>
                        </Menu>
                    </>
                ) : (
                    <Button color="inherit" component={Link} to="/login">Login</Button>
                )}
            </Toolbar>
        </AppBar>
    );
};

export default Navbar;


Start your frontend using the below command:

npm run dev

Output

Comment