This document reflects the current file organisation after the full refactoring (May 2026).
backend/
βββ controllers/
β βββ authController.js # signup, login, getCurrentUser, updateSettings
β βββ postController.js # CRUD, like, getMyPosts, getAllPosts (with pagination)
β βββ commentController.js # create, approve, reject, delete, like, reply
βββ middleware/
β βββ authMiddleware.js # auth (sets req.userId), optionalAuth
β βββ sanitizeBody.js # trims strings (kept, but will be replaced later)
β βββ validate.js # handles express-validator errors
βββ models/
β βββ User.js # preβsave hash, comparePassword method
β βββ Post.js # title, content, imageUrl, tags, category, author, likes, views, commentsCount
β βββ Comment.js # author (string), content, post, status, likes, replies (subdocs)
βββ routes/
β βββ auth.js # /signup, /login, /me, /settings (with validation)
β βββ posts.js # GET (public), POST/PUT/DELETE (protected), /mine, /:id/like
β βββ comments.js # GET (public), POST/PUT/DELETE (protected with admin checks)
βββ .env
βββ package.json
βββ server.js # security middleware, rate limiting, global error handler, graceful shutdown
frontend/
βββ public/ # static assets
βββ src/
β βββ components/
β β βββ auth/
β β β βββ ProtectedRoute.js # redirects to /signin if not authenticated
β β β βββ index.js
β β βββ layout/
β β β βββ Header.js # shows user menu, logout, new post button
β β β βββ Sidebar.js # navigation links, collapsible
β β β βββ Layout.js # conditionally shows sidebar/header based on route & auth
β β β βββ index.js
β β βββ modals/
β β β βββ NewPostModal.js # creates a post (uses API directly)
β β β βββ EditPostModal.js # edits a post (fetches via GET /posts/:id)
β β β βββ editPostModalStyles.js # style helpers
β β β βββ index.js
β β βββ ui/ # reusable primitives
β β β βββ BlogCard.js # displays post card with actions
β β β βββ Button.js
β β β βββ Card.js
β β β βββ Input.js
β β β βββ LoadingSpinner.js
β β β βββ Typography.js
β β β βββ index.js
β β βββ CommentCard.js # displays a single comment with replies, likes, moderation actions
β β βββ CommentFilter.js # filter buttons (all/pending/approved/spam)
β β βββ CommentForm.js # creates a comment (authenticated, uses API directly)
β β βββ CommentList.js # maps over comments, uses CommentCard
β β βββ CommentReplies.js # nested replies display
β β βββ CommentStats.js # stats cards (total, approved, pending, spam)
β β βββ ModerationActions.js # approve/reject/delete/reply buttons for admin
β β βββ ErrorBoundary.js # catches render errors
β β βββ index.js # exports all components
β βββ contexts/
β β βββ UserContext.js # loads user from /auth/me, stores token in localStorage
β β βββ ThemeContext.js # theme, accent colour, font size β persisted in localStorage
β β βββ SidebarContext.js # sidebar collapse / mobile open state
β βββ hooks/
β β βββ usePostStats.js # fetches /posts/mine, aggregates stats
β β βββ useComments.js # fetches /comments with filter, provides moderation handlers
β βββ pages/
β β βββ auth/
β β β βββ Login.js # uses /auth/login, expects { token, user }
β β β βββ Signup.js # registers then autoβlogin
β β βββ dashboard/
β β β βββ Dashboard.js # shows userβs posts, stats, delete/edit modals
β β β βββ Comments.js # admin comment moderation page (uses useComments)
β β β βββ Settings.js # user settings (profile, privacy, notifications, appearance, publishing)
β β β βββ Stats.js # analytics and charts
β β β βββ Theme.js # theme picker (updates ThemeContext)
β β β βββ settingsTabs/ # tab components for Settings page
β β β βββ ProfileTab.js
β β β βββ PrivacyTab.js
β β β βββ NotificationsTab.js
β β β βββ AppearanceTab.js
β β β βββ PublishingTab.js
β β β βββ index.js
β β βββ posts/
β β β βββ CreatePost.js # standalone create post page (or use modal)
β β β βββ EditPost.js # standalone edit page (GET /posts/:id, PUT)
β β β βββ PostDetail.js # view post, like, comment form, comment list
β β βββ PublicHome.js # landing page, fetches all posts (GET /posts)
β βββ services/
β β βββ commentsAPI.js # functions for getAllComments, approve, reject, delete, like, reply
β βββ utils/
β β βββ auth.js # setToken, getToken, removeToken, isAuthenticated, getUserFromToken
β β βββ axios.js # interceptors: attach token, handle 401
β β βββ postStats.js # getPostStats, formatPostStats, postStatsSummary
β β βββ toast.js # showSuccess, showError, showLoading (react-hot-toast)
β β βββ statusColors.js # helper for comment status badges
β βββ App.js # routes: public + protected
β βββ index.js
β βββ index.css # Tailwind imports + custom keyframes
βββ .env.development # REACT_APP_API_URL for local backend
βββ .env.production # REACT_APP_API_URL for deployed backend (Render)
βββ package.json
βββ tailwind.config.js
- All API responses from the backend use the
{ success, message, data }pattern (except/postswhich returns{ success, posts }and/posts/:idreturns{ success, post }). - Error handling in the frontend always looks at
err.response?.data?.message. - Authentication middleware attaches
req.userId(not the full user object). - The comment system uses
authoras a string (the loggedβin userβs username) β this is technical debt that can be migrated later to a properObjectIdreference. - The
.vscode/tasks.jsonprovides a oneβclick βStart Frontend Development Serverβ task β useful but not essential.
- Production frontend: https://blogify-teal.vercel.app/
- Production backend: https://blogify-uk2x.onrender.com/api
For local development, ensure the frontend .env.development uses http://localhost:5000/api and the backend .env uses your local MongoDB URI.