Project 2: Blog App with Express + Mongoose
In this project, you'll build a basic Blog Application using Node.js, Express, and MongoDB via the Mongoose ODM. You'll be able to create, read, and display blog posts dynamically.
Project Objective
The app will allow users to:
- Create blog posts (title and body)
- Save blog posts in MongoDB
- View all blog posts on a homepage
- View individual blog post details
Folder Structure
blog-app/
├── models/
│ └── Post.js
├── views/
│ ├── index.ejs
│ ├── new.ejs
│ └── show.ejs
├── public/
├── app.js
├── package.json
Step 1: Initialize the App
mkdir blog-app
cd blog-app
npm init -y
npm install express mongoose ejs body-parser
Step 2: Connect to MongoDB with Mongoose
Create app.js
with the following code:
// app.js
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const Post = require("./models/Post");
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.set("view engine", "ejs");
mongoose.connect("mongodb://localhost:27017/blogApp", {
useNewUrlParser: true,
useUnifiedTopology: true,
});
app.listen(3000, () => {
console.log("Server started on http://localhost:3000");
});
Q: Why use Mongoose instead of MongoDB native driver?
A: Mongoose provides schema enforcement, easy model creation, and helpful methods that simplify working with MongoDB from Node.js.
Step 3: Create the Mongoose Model
Create models/Post.js
:
// models/Post.js
const mongoose = require("mongoose");
const postSchema = new mongoose.Schema({
title: String,
body: String,
createdAt: { type: Date, default: Date.now },
});
module.exports = mongoose.model("Post", postSchema);
Output:
Post model created with schema: title, body, createdAt
Step 4: Set Up Routes
Add the following routes to app.js
to list, create, and show posts:
// app.js (continued)
// Home - list all posts
app.get("/", async (req, res) => {
const posts = await Post.find().sort({ createdAt: -1 });
res.render("index", { posts });
});
// Show form to create a post
app.get("/new", (req, res) => {
res.render("new");
});
// Save post to database
app.post("/posts", async (req, res) => {
const { title, body } = req.body;
await Post.create({ title, body });
res.redirect("/");
});
// Show individual post
app.get("/posts/:id", async (req, res) => {
const post = await Post.findById(req.params.id);
res.render("show", { post });
});
Step 5: Create the Views (EJS)
views/index.ejs
<h1>All Blog Posts</h1>
<a href="/new">Create New Post</a>
<ul>
<% posts.forEach(post => { %>
<li>
<a href="/posts/<%= post._id %>"><%= post.title %></a>
</li>
<% }) %>
</ul>
views/new.ejs
<h1>New Blog Post</h1>
<form method="POST" action="/posts">
<input name="title" placeholder="Post Title"/><br/>
<textarea name="body" placeholder="Post Body"></textarea><br/>
<button type="submit">Create Post</button>
</form>
views/show.ejs
<h1><%= post.title %></h1>
<p><%= post.body %></p>
<a href="/">Back to Home</a>
Run the App
node app.js
Output:
Server started on http://localhost:3000
Test the App
- Visit
http://localhost:3000
to see all posts - Click "Create New Post" to add a new one
- Click on any post to see its details
Bonus Intuition
Q: Why use EJS instead of plain HTML?
A: EJS lets you dynamically inject data from your MongoDB database into your HTML templates. It's like templating HTML with logic!
Summary
This project taught you how to build a basic blog app using Express, Mongoose, and MongoDB. You learned how to model data, create RESTful routes, render views using EJS, and interact with MongoDB using Mongoose in a beginner-friendly way.
What's Next?
Try adding more features like post editing, deletion, or even user authentication using Passport.js!