A RESTful API built with Node.js, Express, and MongoDB that allows users to create, manage, and publish blog posts.
This API supports JWT-based authentication, pagination, searching, filtering, and ordering of blog posts.
- User authentication with JWT (expires after 1 hour)
- Public and Private blog access
- Blog states:
draft
andpublished
- Pagination (default: 20 blogs per page)
- Searchable by author, title, or tags
- Orderable by read_count, reading_time, and timestamp
- Auto-increment
read_count
when a blog is viewed - Reading time automatically calculated
- CRUD operations for blog owners
- Uses MVC pattern for clean architecture
- Backend Framework: Node.js + Express
- Database: MongoDB + Mongoose
- Authentication: JWT (JSON Web Token)
- Environment Variables: dotenv
- Logger: morgan
- Security & CORS: cors
- Testing: Jest / Supertest (optional)
git clone https://github.com/<your-username>/blogging-api.git
cd blogging-api
npm install
touch .env
Add the following:
PORT=5000
MONGO_URI=your_mongodb_connection_string
JWT_SECRET=your_secret_key
NODE_ENV=development
Development Mode
npm run dev
Production Mode
npm start
Server will run on:
http://localhost:5000
.
โโโ config/
โ โโโ db.js # MongoDB connection
โ โโโ jwt.js # JWT helpers (sign/verify)
โโโ controllers/
โ โโโ blog.controller.js
โ โโโ user.controller.js
โโโ models/
โ โโโ Blog.js
โ โโโ User.js
โโโ routes/
โ โโโ blog.routes.js
โ โโโ user.routes.js
โโโ middlewares/
โ โโโ auth.middleware.js
โโโ server.js
โโโ package.json
โโโ README.md
This API uses JWT for authentication.
Once a user logs in, youโll receive a JWT token.
Add it to your headers for protected routes:
Authorization: Bearer <your_token>
Tokens expire after 1 hour.
POST /users/signup
Request Body:
{
"first_name": "Mareola",
"last_name": "Plate",
"email": "mareola@example.com",
"password": "123456"
}
Response:
{
"message": "User registered successfully",
"token": "<jwt_token>"
}
POST /users/login
Request Body:
{
"email": "mareola@example.com",
"password": "123456"
}
Response:
{
"message": "Login successful",
"token": "<jwt_token>"
}
GET /blogs?state=published&page=1&limit=20&author=mike&order_by=read_count
Supports:
- Pagination โ page, limit
- Filtering โ state
- Searching โ author, title, tags
- Ordering โ read_count, reading_time, timestamp
GET /blogs/:id
Automatically:
- Increments read_count by 1
- Returns author details
Response:
{
"title": "How to Learn Node.js",
"description": "A beginner guide",
"author": {
"first_name": "Mareola",
"last_name": "Plate"
},
"read_count": 45,
"reading_time": "3 mins",
"state": "published",
"tags": "nodejs", "backend",
"body": "Full blog content..."
}
POST /blogs
Header:
Authorization: Bearer <token>
Body:
{
"title": "My First Blog",
"description": "Introduction to blogging",
"tags": "intro", "blog",
"body": "This is my first blog post."
}
Created blogs start as draft.
PATCH /blogs/:id/state
Body:
{
"state": "published"
}
PUT /blogs/:id
Body:
{
"title": "Updated Blog Title",
"body": "Updated blog content."
}
DELETE /blogs/:id
Deletes the blog completely from the database.
GET /blogs/my-blogs?state=draft&page=1
Lists blogs created by the logged-in user.
The reading time is estimated based on word count:
const wordsPerMinute = 200
const readingTime = Math.ceil(wordCount / wordsPerMinute)
Result stored as: "3 mins read"
.
Run tests with:
npm test
You can use Jest or Supertest for endpoint testing.
For Render or Vercel deployment:
- Connect your GitHub repo.
- Add environment variables under project settings.
- Use the start command:
npm start
Render automatically detects Express and sets up a web service.
Mareola
Software Engineer | Backend Developer | Tech Innovator
MIT License ยฉ 2025 Mareola