SnapStory is a modern, high-performance, full-stack blogging platform. It allows users to write articles, organize them with tags, upload cover images, search blogs, paginate through posts, and interact using threaded comments. Built on a robust architecture, SnapStory uses Redis for database caching and MongoDB for persistence, with JWT authentication securing resources.
- Robust User Authentication & Authorization:
- Secure registration and login.
- Password hashing with Bcrypt.
- JSON Web Tokens (JWT) for secure, stateless API authorization.
- Role-based permissions (
adminvs.user).
- Comprehensive Blog Management:
- Create, read, update, and search blog posts.
- Image cover association.
- Real-time search by keywords.
- High-performance paginated post retrieval.
- Interactive Discussion System:
- Threaded comment system linked to blog posts.
- Dynamic Tagging System:
- Categorize stories with unique tags.
- Filter and retrieve blogs by association.
- Performance & Security Layers:
- Redis-based caching middleware to accelerate frequent read requests.
- Express Validator schema validations to sanitize and reject bad request bodies.
- Logger integration using Morgan.
- Dockerized Services:
- Multi-container architecture orchestrating Frontend, Backend, MongoDB, and Redis.
- Core: React 19, Vite, TypeScript.
- Styling: TailwindCSS 4.
- Routing: React Router DOM.
- HTTP client: Axios.
- Icons: Lucide React.
- Utility:
jwt-decodefor decoding payload data.
- Core: Node.js, Express (ES Modules).
- ORM / Database: Mongoose (MongoDB).
- Caching: Redis (Node Redis Client).
- Authentication: JWT (
jsonwebtoken), Bcrypt. - Middleware: Express Validator, Cors, Body-parser, Morgan, Dotenv.
- Process Manager: Nodemon (Development).
SnapStory/
├── Backend/
│ ├── Dockerfile
│ ├── index.js # Server Entry Point
│ ├── src/
│ │ ├── config/
│ │ │ ├── database.js # MongoDB Mongoose connection
│ │ │ └── serverConfig.js # Environment variable configurations
│ │ ├── controller/ # Auth, Blog, Comment, and Tag controllers
│ │ ├── middleware/ # Redis Cache & request validators
│ │ ├── models/ # mongoose database schemas (Blog, Comment, Like, Tag, User)
│ │ ├── repository/ # Data access abstraction layer
│ │ ├── routes/ # Express routes (v1 API endpoints)
│ │ └── services/ # Business logic services
│ └── package.json
├── Frontend/
│ ├── Dockerfile
│ ├── index.html
│ ├── nginx.conf # Nginx config for frontend production builds
│ ├── src/
│ │ ├── App.tsx # Main router setup & layout
│ │ ├── api/ # Axios instance & request endpoints
│ │ ├── components/ # Shared components (Header, BlogCard, etc.)
│ │ ├── context/ # AuthContext & global state providers
│ │ ├── pages/ # Views: Home, BlogDetail, CreateBlog, Login, Signup
│ │ ├── types/ # TypeScript interfaces/types
│ │ └── index.css # Global CSS imports
│ ├── package.json
│ └── vite.config.ts
├── docker-compose.yml # Service orchestrator (db, redis, backend, frontend)
└── package.json
Create a .env file in the Backend/ directory with the following keys:
PORT=3000
MONGODB_URI=mongodb://localhost:27017/SnapStory
REDIS_URL=redis://localhost:6379
BCRYPT_SALT_ROUNDS=9To spin up all services (MongoDB, Redis, Backend, Frontend) with a single command:
- Make sure you have Docker and Docker Compose installed.
- In the root directory of the project, run:
docker-compose up --build
- Once all containers start:
- Frontend UI: http://localhost
- Backend API: http://localhost:3000
- Navigate to the backend directory:
cd Backend - Install dependencies:
npm install
- Create and configure your
.envfile as described in Configuration. - Run the development server (requires local MongoDB and Redis instances running):
npm start
- Navigate to the frontend directory:
cd Frontend - Install dependencies:
npm install
- Start the Vite dev server:
npm run dev
- Access the site on http://localhost:5173 (or the port specified by Vite).
All endpoints are prefixed with /api/v1.
| HTTP Method | Endpoint | Description | Request Body |
|---|---|---|---|
POST |
/api/v1/signup |
Register a new user | { "name": "...", "email": "...", "password": "..." } |
POST |
/api/v1/login |
Login and retrieve token | { "email": "...", "password": "..." } |
GET |
/api/v1/user/:id |
Fetch user info by user ID | None |
| HTTP Method | Endpoint | Description | Request Body |
|---|---|---|---|
POST |
/api/v1/blog |
Create a new blog post (Authenticated) | { "title": "...", "content": "...", "image": "...", "tag": "..." } |
GET |
/api/v1/blogs |
Get all blog posts | None |
GET |
/api/v1/blog/:id |
Get details of a single blog post | None |
POST |
/api/v1/blog/paginate |
Retrieve paginated list of blog posts | { "page": 1, "pageSize": 10 } |
GET |
/api/v1/blog/search/:keyword |
Search blog posts by keyword | None |
| HTTP Method | Endpoint | Description | Request Body |
|---|---|---|---|
POST |
/api/v1/:blogId/comment |
Add a comment to a specific blog | { "content": "...", "userId": "..." } |
GET |
/api/v1/:blogId/comments |
Retrieve comments for a specific blog | None |
| HTTP Method | Endpoint | Description | Request Body |
|---|---|---|---|
POST |
/api/v1/tags |
Create a new tag | { "title": "..." } |
GET |
/api/v1/tags |
Retrieve all available tags | None |
- Fork this repository.
- Create your feature branch (
git checkout -b feature/AmazingFeature). - Commit your changes (
git commit -m 'Add some AmazingFeature'). - Push to the branch (
git push origin feature/AmazingFeature). - Open a Pull Request.