Mini Full-Stack Project (Blog/E-commerce API)
Congratulations! You've learned all the individual pieces of Express.js. Now it's time to put everything together into a **complete full-stack project**. In this chapter, we'll build a Blog/E-commerce API that demonstrates all the concepts you've learned.
Project Options
Choose the project that interests you most:
- Blog API: Posts, comments, categories, tags, authors.
- E-commerce API: Products, categories, shopping cart, orders, users.
This project is your capstone – it brings together everything: routing, middleware, database, authentication, file uploads, error handling, and best practices.
Option 1: Blog API Features
- User registration & login (JWT)
- Create, read, update, delete posts
- Add comments to posts
- Categories and tags for posts
- Upload featured images for posts
- Search and filter posts
- Role-based access (admin, author, reader)
Option 2: E-commerce API Features
- User registration & login (JWT)
- Product catalog with categories
- Product images upload
- Shopping cart functionality
- Place orders
- Order history for users
- Admin panel for managing products
Project Structure (Both Options)
project-root/├── models/│ ├── User.js│ ├── Post.js (or Product.js)│ ├── Comment.js (or Order.js)│ └── Category.js├── controllers/│ ├── authController.js│ ├── postController.js (or productController.js)│ └── commentController.js (or orderController.js)├── routes/│ ├── authRoutes.js│ ├── postRoutes.js (or productRoutes.js)│ └── commentRoutes.js (or orderRoutes.js)├── middleware/│ ├── auth.js│ ├── upload.js (multer config)│ └── errorHandler.js├── utils/│ ├── catchAsync.js│ └── AppError.js├── config/│ └── db.js├── uploads/ (for file uploads)├── .env├── app.js└── server.jsKey Models (Blog API)
Post Model
const postSchema = new mongoose.Schema({ title: { type: String, required: true, trim: true }, slug: { type: String, unique: true }, content: { type: String, required: true }, excerpt: { type: String, maxlength: 500 }, featuredImage: { type: String }, categories: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Category' }], tags: [String], author: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true }, status: { type: String, enum: ['draft', 'published'], default: 'draft' }, viewCount: { type: Number, default: 0 }}, { timestamps: true });Comment Model
const commentSchema = new mongoose.Schema({ content: { type: String, required: true }, post: { type: mongoose.Schema.Types.ObjectId, ref: 'Post', required: true }, user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true }, status: { type: String, enum: ['pending', 'approved'], default: 'pending' }}, { timestamps: true });Key Features Implementation
1. Slug Generation for Posts
postSchema.pre('validate', function(next) { if (this.title && !this.slug) { this.slug = this.title .toLowerCase() .replace(/[^a-z0-9]+/g, '-') .replace(/^-|-$/g, ''); } next();});2. Increment View Count
router.get('/:slug', catchAsync(async (req, res) => { const post = await Post.findOneAndUpdate( { slug: req.params.slug }, { $inc: { viewCount: 1 } }, { new: true } ).populate('author categories'); res.json({ status: 'success', data: { post } });});3. Search and Filter
router.get('/', catchAsync(async (req, res) => { const { search, category, tag, sort } = req.query; let filter = { status: 'published' }; if (search) { filter.$or = [ { title: { $regex: search, $options: 'i' } }, { content: { $regex: search, $options: 'i' } } ]; } if (category) filter.categories = category; if (tag) filter.tags = tag; let query = Post.find(filter).populate('author'); if (sort === 'oldest') query = query.sort('createdAt'); else query = query.sort('-createdAt'); <!-- Pagination --> const page = req.query.page * 1 || 1; const limit = req.query.limit * 1 || 10; const skip = (page - 1) * limit; query = query.skip(skip).limit(limit); const posts = await query; const total = await Post.countDocuments(filter); res.json({ status: 'success', results: posts.length, total, page, pages: Math.ceil(total / limit), data: { posts } });});Testing Your API
Use tools to test your API:
- Postman: Popular API testing tool
- Insomnia: Alternative to Postman
- Swagger UI: For API documentation
Deployment Considerations
- Use environment variables for all configuration
- Set up MongoDB Atlas for cloud database
- Use a process manager like PM2
- Consider using Docker for containerization
- Deploy to platforms like Heroku, Render, or AWS
Two Minute Drill
- This capstone project combines everything you've learned about Express.js.
- Choose between Blog API or E-commerce API based on your interest.
- Implement proper data relationships between models.
- Add features like search, pagination, and file uploads.
- Test thoroughly and deploy to a cloud platform.
Need more clarification?
Drop us an email at career@quipoinfotech.com
