NewsPulse is a full-stack news publishing and reading application built with React, Vite, Express, MongoDB, and Socket.IO. The project combines a responsive public-facing news experience with an admin dashboard for creating, editing, deleting, and managing articles, comments, users, and saved content.
The application exists to provide a lightweight content platform where readers can discover articles, search by topic, comment on posts, save favorite stories, and interact with live updates while administrators can manage content through a dedicated dashboard. The system is designed around a simple architecture: a React client renders the user experience, an Express API handles authentication and content management, MongoDB stores persistent records, and Socket.IO provides real-time notifications and comment updates.
- Project Overview
- Features
- System Overview
- Architecture
- Project Structure
- Technology Stack
- Installation
- Configuration
- Running the Project
- Application Workflow
- API Documentation
- Machine Learning Pipeline
- Frontend
- Backend
- Database
- Performance
- Security
- Error Handling
- Testing
- Deployment
- Limitations
- Future Work
- Contributing
- License
- Authors
- Acknowledgements
NewsPulse is a content-centric web application that serves two main user groups:
- Readers who browse, search, and engage with articles
- Administrators who publish and maintain the content catalog
The system supports local authentication, Google OAuth sign-in, article creation with rich text and image uploads, comment threads, article bookmarking, and a dashboard for administrative actions. The project is implemented as a monorepo with a dedicated frontend and backend package.
The high-level workflow is straightforward:
- A user visits the public site and browses or searches articles.
- The frontend requests article data from the backend API.
- Authenticated users can create comments, save articles, and manage their profiles.
- Administrators can publish and edit posts from the dashboard.
- The backend persists content in MongoDB and emits live updates through Socket.IO.
Administrators can create, edit, and delete posts through the dashboard and editor interfaces. Posts include a title, category, image, rich-text content, slug, and metadata such as view count. Slugs are generated from the title to create readable, SEO-friendly URLs. The create and edit flows are implemented in dedicated pages that submit data to the backend API and navigate users to the published article.
Readers can browse the latest posts on the home page, search articles by keyword, filter by category, sort by recency, and load additional results incrementally. The search experience is implemented as a routing-based query interface where the browser URL carries search parameters such as category and sort order.
The application supports two authentication flows:
- Local sign-up and sign-in using email and password with JWT-based cookies
- Google OAuth using Passport.js with a callback flow that issues the same JWT cookie on success
Authenticated users are recognized by the backend through a cookie-based verification middleware and are permitted to access protected operations such as commenting, saving articles, and updating profile information.
Users can add comments to articles, like comments, edit their own comments, and delete their own comments. The comment system uses a dedicated backend controller and a real-time broadcast channel so that clients viewing the same post receive newly created comments without reloading the page.
Signed-in users can bookmark articles for later reading. The saved articles feature uses a dedicated collection that associates a user with a post so that the dashboard can present a personalized saved-content list.
Administrators see a dashboard with summary cards for users, comments, and posts, plus management tables for users, posts, and comments. The dashboard uses server-side paginated responses and links to the relevant management views.
The application exposes a live online-user count in the header and broadcasts breaking news and comments through Socket.IO. This allows the client to reflect current activity without polling.
Article and profile images are uploaded through Appwrite Storage. The frontend uploads files from the create-post and profile-edit flows, obtains a preview URL, and then persists the resulting URL in the corresponding database document.
The application is organized around a clear client-server boundary:
- The frontend is a React/Vite application that renders pages, handles forms, manages state, and communicates with the backend using fetch requests and Socket.IO.
- The backend is an Express application that exposes REST endpoints for authentication, posts, comments, users, and saved articles.
- MongoDB stores user accounts, posts, comments, and saved article references.
- Appwrite Storage handles uploaded media assets.
- Socket.IO provides live updates for comments and breaking news.
flowchart LR
User[Reader or Admin] --> Frontend[React/Vite Frontend]
Frontend --> API[Express API]
Frontend --> Socket[Socket.IO]
API --> DB[(MongoDB)]
API --> Appwrite[Appwrite Storage]
API --> Google[Google OAuth]
Socket --> Frontend
The frontend uses React with functional components and React Router for page navigation. Redux Toolkit manages authentication state, while redux-persist keeps the user session available across refreshes. The UI is built with Tailwind CSS and a set of custom shared components located under the components directory. The app uses route-based pages for the home screen, search, article details, authentication, and dashboard.
The backend is organized into route, controller, model, and utility layers. Express route modules expose high-level endpoints, controllers implement the business logic, Mongoose models define database schemas, and utility modules handle JWT verification, Passport configuration, and centralized error shaping.
The frontend communicates with the backend via REST calls for data retrieval and mutations. The backend returns JSON payloads and sets authentication cookies. Socket.IO is used for connection-oriented events such as live comments and online-user notifications. The public page also uses a lightweight client-side view-count mechanism that increments the server record when a post is first viewed.
A typical article flow looks like this:
- The user opens a page or searches for content.
- The client requests article data from the backend using a query string.
- The backend queries MongoDB for posts matching the filters.
- The client renders the result cards or full article view.
- When a user comments or saves an article, the frontend sends a request to the API.
- The backend writes to MongoDB and, when relevant, emits a Socket.IO event to connected clients.
sequenceDiagram
participant U as User
participant F as Frontend
participant B as Backend
participant M as MongoDB
participant S as Socket.IO
U->>F: Open article or dashboard
F->>B: GET/POST/PUT/DELETE request
B->>M: Read or write document
M-->>B: Result
B-->>F: JSON response
B->>S: Emit live update if needed
S-->>F: Broadcast comment or breaking news
The repository is organized as follows:
NewsApp/
├── backend/
│ ├── controllers/
│ │ ├── auth.controller.js
│ │ ├── comment.controller.js
│ │ ├── post.controller.js
│ │ ├── savedArticle.controller.js
│ │ └── user.contoller.js
│ ├── models/
│ │ ├── comment.model.js
│ │ ├── post.model.js
│ │ ├── savedArticle.model.js
│ │ └── user.model.js
│ ├── routes/
│ │ ├── auth.route.js
│ │ ├── comment.route.js
│ │ ├── post.route.js
│ │ ├── savedArticle.route.js
│ │ └── user.route.js
│ ├── utils/
│ │ ├── error.js
│ │ ├── passport.js
│ │ └── verifyUser.js
│ ├── index.js
│ ├── package.json
│ └── socket.js
├── frontend/
│ ├── public/
│ ├── src/
│ │ ├── assets/
│ │ ├── auth/
│ │ │ └── forms/
│ │ ├── components/
│ │ │ ├── shared/
│ │ │ └── ui/
│ │ ├── hooks/
│ │ ├── lib/
│ │ │ ├── appwrite/
│ │ │ └── socket.js
│ │ ├── pages/
│ │ ├── redux/
│ │ ├── App.jsx
│ │ ├── firebase.js
│ │ ├── index.css
│ │ └── main.jsx
│ ├── .env
│ ├── package.json
│ ├── tailwind.config.js
│ ├── vite.config.js
│ └── vercel.json
└── README.md
- The backend directory contains everything required to run the API server, including auth, content, comment, saved-article, and user-management modules.
- The frontend directory contains the React application, UI components, page components, Redux store, and the Vite configuration.
- The Appwrite integration is implemented in the frontend library layer rather than in the backend.
| Category | Technology | Purpose |
|---|---|---|
| Frontend | React | Component-based UI rendering |
| Frontend | Vite | Fast development server and build pipeline |
| Frontend | React Router | Client-side page navigation |
| Frontend | Redux Toolkit | Authentication and shared UI state |
| Frontend | Tailwind CSS | Utility-first styling |
| Frontend | React Hook Form and Zod | Form handling and schema validation |
| Frontend | Socket.IO Client | Real-time event subscriptions |
| Backend | Express | REST API server |
| Backend | MongoDB + Mongoose | Persistent data storage and schema modeling |
| Backend | JSON Web Tokens | Authentication and session identity |
| Backend | Passport.js | Google OAuth integration |
| Backend | Socket.IO | Real-time broadcast layer |
| Storage | Appwrite Storage | Image upload and file delivery |
| Utilities | Axios | HTTP client layer (configured, though the current UI mostly uses fetch) |
| Utilities | Firebase SDK | Initialized in the application code but not used for the main auth flow |
Before installing, ensure that the following tools are available:
- Node.js 18 or newer
- npm 9 or newer
- A MongoDB instance reachable by URI
- A Google Cloud project with OAuth credentials if Google sign-in will be used
- An Appwrite project with a storage bucket if image uploads will be used
- Change into the backend directory.
- Install dependencies:
npm install- Create a backend environment file named .env with the values described in the Configuration section.
- Start the backend in development mode:
npm run devThe backend listens on port 5000 by default.
- Change into the frontend directory.
- Install dependencies:
npm install- Create or update the frontend .env file with the variables described below.
- Start the development server:
npm run devThe frontend dev server runs on port 5173 by default and proxies API and Socket.IO traffic to the backend.
The application reads environment variables from the backend process environment and the frontend Vite environment. The repository currently includes a frontend .env file but no backend .env file template.
| Variable | Purpose | Default / Example | Required |
|---|---|---|---|
| MONGO_URI | MongoDB connection string | None | Yes |
| JWT_SECRET | Secret used to sign JWTs | None | Yes |
| SESSION_SECRET | Session secret used by Express session middleware | newsPulse_session_secret | No |
| GOOGLE_CLIENT_ID | Google OAuth client ID | None | Yes for Google OAuth |
| GOOGLE_CLIENT_SECRET | Google OAuth client secret | None | Yes for Google OAuth |
| GOOGLE_CALLBACK_URL | Passport callback URL | None | Yes for Google OAuth |
| CLIENT_URL | Frontend base URL used for OAuth redirects | http://localhost:5173 | No |
| PORT | Backend server port | 5000 | No |
| NODE_ENV | Runtime environment | development | No |
| VITE_API_URL | Frontend API base URL used by the client | http://localhost:5000 or empty for same-origin proxy | No |
| VITE_APPWRITE_PROJECT_ID | Appwrite project ID | None | Yes for image uploads |
| VITE_APPWRITE_STORAGE_ID | Appwrite storage bucket ID | None | Yes for image uploads |
| VITE_APPWRITE_URL | Appwrite endpoint | https://fra.cloud.appwrite.io/v1 | Yes for image uploads |
| VITE_FIREBASE_API_KEY | Firebase SDK API key | None | No for current app flow |
Example backend configuration:
MONGO_URI=mongodb://127.0.0.1:27017/newspulse
JWT_SECRET=replace-with-a-strong-secret
SESSION_SECRET=replace-with-a-session-secret
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_CALLBACK_URL=http://localhost:5000/api/auth/google/callback
CLIENT_URL=http://localhost:5173
PORT=5000
NODE_ENV=developmentExample frontend configuration:
VITE_API_URL=http://localhost:5000
VITE_APPWRITE_PROJECT_ID=your-appwrite-project-id
VITE_APPWRITE_STORAGE_ID=your-appwrite-storage-id
VITE_APPWRITE_URL=https://fra.cloud.appwrite.io/v1
VITE_FIREBASE_API_KEY=your-firebase-api-keyStart the backend:
cd backend
npm run devStart the frontend in a separate terminal:
cd frontend
npm run devOnce both services are running, open the frontend at http://localhost:5173. The frontend will proxy API calls to http://localhost:5000.
Build the frontend bundle:
cd frontend
npm run buildRun the backend in production mode:
cd backend
npm startThe project does not currently include a Dockerfile or docker-compose file. Deployment is currently implied by the frontend Vercel rewrite configuration and the backend Express server used behind a Node host such as Render.
A typical user journey begins on the home page, where the client fetches the latest posts from the backend. The user can then navigate to the search page to filter by category or search term. When the user opens an article, the frontend requests the post details, displays the content, and triggers a view-count update. If the user is authenticated, they can comment, like, or save the post. Those actions create or update records in MongoDB and emit live updates through Socket.IO for other connected viewers.
For administrators, the workflow is slightly different. An admin logs in, opens the dashboard, and manages users, posts, and comments through dedicated views. Creating or editing a post requires the client to collect title, category, content, and image data, upload the image to Appwrite if provided, and submit the payload to the backend. Upon successful persistence, the backend returns the created or updated post and the frontend redirects the user to the article page.
The backend exposes the following significant endpoints.
| Method | Endpoint | Purpose | Auth | Request Body / Notes |
|---|---|---|---|---|
| POST | /api/auth/signup | Create a local user account | No | JSON body with username, email, password |
| POST | /api/auth/signin | Sign in with email and password | No | JSON body with email, password |
| GET | /api/auth/google | Start Google OAuth flow | No | Redirects browser to Google |
| GET | /api/auth/google/callback | OAuth callback | No | Passport callback, then redirects to frontend callback route |
| GET | /api/auth/me | Return the currently authenticated user | Yes | Reads JWT from cookie |
| PUT | /api/user/update/:userId | Update a user profile | Yes | JSON body with username, email, password, profilePicture |
| DELETE | /api/user/delete/:userId | Delete a user account | Yes | User or admin only |
| POST | /api/user/signout | Clear authentication cookie | No | Ends the current session |
| GET | /api/user/getusers | Fetch users for the admin dashboard | Yes, admin | Supports pagination via query params |
| GET | /api/user/:userId | Fetch a user by ID | No | Used for public author lookup |
| POST | /api/post/create | Create a post | Yes, admin | JSON body with title, content, category, image |
| GET | /api/post/getposts | Fetch posts with optional filters | No | Supports userId, category, slug, postId, searchTerm, startIndex, limit, sort |
| GET | /api/post/trending | Fetch top posts by view count | No | Optional limit query |
| PUT | /api/post/incrementViews/:postId | Increment the post view count | No | Optional JSON body with userId |
| DELETE | /api/post/deletepost/:postId/:userId | Delete a post | Yes, admin | Validates requester identity |
| PUT | /api/post/updatepost/:postId/:userId | Update a post | Yes, admin | JSON body with title, content, category, image |
| POST | /api/comment/create | Create a comment | Yes | JSON body with content, postId, userId |
| GET | /api/comment/getPostComments/:postId | Fetch comments for a specific post | No | Returns comments ordered by creation time |
| PUT | /api/comment/likeComment/:commentId | Toggle a like on a comment | Yes | Uses current authenticated user |
| PUT | /api/comment/editComment/:commentId | Edit a comment | Yes | Validates ownership or admin access |
| DELETE | /api/comment/deleteComment/:commentId | Delete a comment | Yes | Validates ownership or admin access |
| GET | /api/comment/getcomments | Fetch comments for the admin dashboard | Yes, admin | Supports pagination |
| POST | /api/saved/:postId | Save an article for the authenticated user | Yes | Saves a post reference |
| GET | /api/saved | Fetch saved articles for the authenticated user | Yes | Returns populated post data |
| DELETE | /api/saved/:postId | Remove a saved article | Yes | Removes the association |
The API uses a consistent error response shape:
{
"success": false,
"statusCode": 400,
"message": "A descriptive error message"
}Successful responses typically return the created or updated resource, or a confirmation message.
No machine learning pipeline is implemented in the current repository. The application is a content-management and news-reading platform rather than a model-driven product. There are no training scripts, model files, evaluation metrics, or inference services in the codebase. The system relies on CRUD operations, search, and real-time UI behavior rather than predictive or generative models.
The frontend is the user-facing experience of the platform. It includes the following major pages:
- Home: landing page with featured content, feature highlights, and latest articles
- About: informational page about the product mission
- Search: searchable and filterable article browser
- PostDetails: full article page with comments, saved-article action, social sharing, and related content
- Dashboard: profile, saved articles, posts, users, and comments management
- CreatePost: admin-only article creation form with rich text editing
- EditPost: admin-only article update form
- SignInForm and SignUpForm: local-auth UI and Google auth entry points
- OAuthCallback: callback landing page for Google authentication
The frontend uses Redux for user state, react-router-dom for navigation, Tailwind CSS for styling, and a set of reusable UI primitives in the components/ui folder. The app does not currently use the Axios client in the UI layer; most requests are issued directly using the fetch API.
The backend is built around Express and Mongoose with a modular folder structure:
- controllers: implement request handling for auth, posts, comments, saved articles, and users
- routes: expose endpoint definitions and attach authentication middleware
- models: define the MongoDB document schemas
- utils: provide token verification, Passport setup, and error shaping
- socket.js: manages Socket.IO server events and online-user tracking
The request lifecycle is straightforward: a route accepts a request, a controller performs validation and business logic, the database layer handles persistence, and the controller returns JSON. Error handling is centralized through a single middleware that formats responses consistently.
The application uses MongoDB with Mongoose schemas.
| Collection | Purpose |
|---|---|
| User | Stores authentication data, profile metadata, admin status, and OAuth fields |
| Post | Stores article content, category, image, slug, and view statistics |
| Comment | Stores comment text, post association, author association, and likes |
| SavedArticle | Associates a user with a saved post and prevents duplicate saves |
- A post belongs to a user via userId.
- A comment belongs to a post and a user.
- A saved article joins a user and a post through object references.
The schema includes a unique compound index on the saved article collection to prevent duplicate saves for the same user and post.
The current implementation includes several practical performance characteristics:
- Pagination is supported for posts, users, and comments to avoid loading excessive data at once.
- The home page and search page use a limited number of results by default.
- The app uses skeleton loaders to improve perceived performance during page loading.
- Post view counting uses a localStorage-based guard to reduce repeated increments for the same browser session.
- Socket.IO is event-driven and avoids polling for live updates.
The codebase does not currently implement advanced caching, background jobs, or database-level optimization beyond the basic query shapes and pagination already present.
The application includes a small but meaningful security layer:
- JWTs are issued and stored in HTTP-only cookies for browser-based authentication.
- Protected routes require a token via the verifyToken middleware.
- The backend validates ownership before allowing users to update or delete their own data.
- Admin-only operations are guarded by checks against the isAdmin flag.
- Google OAuth is configured through environment variables rather than hard-coded credentials.
- The backend uses secure cookie settings in production and same-site policies appropriate for cross-site requests.
The repository does not currently include rate limiting, content moderation, CSRF protection beyond cookie handling, or a dedicated secrets manager. These are areas for future hardening.
The backend uses a centralized error middleware that converts thrown or constructed errors into a consistent JSON response. Route-level controllers also perform local validation for required fields, invalid credentials, and authorization failures. The frontend handles API errors through toasts and form-level error states. Socket.IO errors are treated as non-fatal so that the main request flow still succeeds even if live events fail.
No formal test suite was found in the repository. There are no dedicated test files, no test runner configuration, and no test scripts in the package manifests. The project therefore currently depends on manual validation and developer review rather than automated regression testing.
The frontend includes a Vercel configuration file that rewrites /api requests to a backend URL. The backend is expected to run as a Node.js service with access to MongoDB and the required environment variables. The current repository does not include a Dockerfile, docker-compose.yml, or deployment pipeline configuration.
- Frontend: hosted on Vercel or another static-hosting platform
- Backend: hosted on Render, Railway, Fly.io, or a similar Node.js environment
- Database: MongoDB Atlas or another managed MongoDB service
- File storage: Appwrite Storage or a similar object-storage service
The current implementation has several practical limitations:
- There is no automated test suite.
- There is no Docker configuration for local or production containerization.
- The API does not currently implement rate limiting or advanced abuse prevention.
- The content model is simple and does not yet include moderation, tagging, scheduling, or localization features.
- The frontend and backend are not yet fully separated by an explicit service layer or shared schema definitions.
- The repository does not currently document a formal release or CI/CD process.
The following improvements would make the project more robust and production-ready:
- Add automated tests for frontend and backend components
- Introduce CI/CD pipelines for linting, testing, and deployment
- Add rate limiting, request validation middleware, and audit logging
- Implement caching for frequently requested posts
- Add richer moderation tools and content status workflows
- Introduce image optimization and a more complete media pipeline
- Add pagination and filtering improvements for large content datasets
- Expand the dashboard with analytics and content insights