Building a Full-Stack Blog Application with Node.js, Express, and MongoDB

Building a Full-Stack Blog Application with Node.js, Express, and MongoDB

In today's digital landscape, having a strong online presence is crucial for professionals and businesses alike. One of the most effective ways to showcase your expertise and engage with your audience is through a blog. In this article, I'll guide you through creating a full-stack blog application using Node.js, Express, and MongoDB.

Project Overview

We'll build a blog application with the following features:

  • Display all blog posts
  • Create new blog posts
  • View individual blog posts
  • Edit existing blog posts

Our tech stack includes:

  • Node.js and Express for the backend
  • MongoDB for the database
  • EJS for templating
  • CSS for styling

Project Structure

Let's start by setting up our project structure:

blog-site/
├── models/
│   └── blog.js
├── routes/
│   └── blogs.js
├── views/
│   ├── partials/
│   │   ├── header.ejs
│   │   └── footer.ejs
│   ├── blogs/
│   │   ├── index.ejs
│   │   ├── new.ejs
│   │   ├── show.ejs
│   │   └── edit.ejs
│   └── error.ejs
├── public/
│   └── css/
│       └── style.css
├── index.js
├── .env
└── package.json        

Setting Up the Server

Our index.js file will be the entry point of our application:

const express = require('express');
const mongoose = require('mongoose');
const path = require('path');
const dotenv = require('dotenv');
const blogsRouter = require('./routes/blogs');
const methodOverride = require('method-override');

dotenv.config();
const app = express();
const port = process.env.PORT || 3000;

// Middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static(path.join(__dirname, 'public')));
app.use(methodOverride('_method'));

// Set view engine
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));

// Routes
app.use('/blogs', blogsRouter);
app.use((req, res, next) => {
  res.status(404).render('error', { title: '404 Not Found' });
});

// Database connection
mongoose.connect(process.env.MONGO_URI, {
  useNewUrlParser: true,
  useUnifiedTopology: true
}).then(() => {
  console.log('Connected to MongoDB');
  app.listen(port, () => {
    console.log(`Server running on https://localhost:${port}`);
  });
}).catch(err => {
  console.error('Error connecting to MongoDB', err);
});        

Defining the Blog Model

In models/blog.js, we define our MongoDB schema:

const mongoose = require('mongoose');

const blogSchema = new mongoose.Schema({
  title: String,
  content: String,
  author: String
});

module.exports = mongoose.model('Blog', blogSchema);        

Setting Up Routes

Our routes/blogs.js file handles all blog-related routes:

const express = require('express');
const router = express.Router();
const Blog = require('../models/blog');

// Route for displaying all blogs
router.get('/', async (req, res) => {
    try {
        const blogs = await Blog.find();
        res.render('blogs/index', { blogs, title: 'All Blogs' });
    } catch (err) {
        res.status(500).send('Error retrieving blogs');
    }
});

// Route for creating a new blog (form)
router.get('/new', (req, res) => {
    res.render('blogs/new', { title: 'Create New Blog' });
});

// Route for showing a single blog
router.get('/:id', async (req, res) => {
    try {
        const blog = await Blog.findById(req.params.id);
        res.render('blogs/show', { blog, title: blog.title });
    } catch (err) {
        res.status(404).send('Blog not found');
    }
});

// Route for editing a blog (form)
router.get('/:id/edit', async (req, res) => {
    try {
        const blog = await Blog.findById(req.params.id);
        res.render('blogs/edit', { blog, title: 'Edit Blog' });
    } catch (err) {
        res.status(404).send('Blog not found');
    }
});

// Route for updating a blog
router.put('/:id', async (req, res) => {
    try {
        const blog = await Blog.findByIdAndUpdate(req.params.id, req.body, { new: true });
        res.redirect(`/blogs/${blog._id}`);
    } catch (err) {
        res.status(400).send('Error updating blog');
    }
});

// Route for creating a new blog
router.post('/', async (req, res) => {
    try {
        const blog = new Blog(req.body);
        await blog.save();
        res.redirect('/blogs');
    } catch (err) {
        res.status(400).send('Error creating blog');
    }
});

module.exports = router;        

Creating Views

Now, let's set up our EJS templates. Here's an example of our views/blogs/index.ejs:

<%- include('../partials/header', { title: 'All Blogs' }) %>

<div class="container">
    <h2>All Blogs</h2>
    <ul>
        <% blogs.forEach(blog => { %>
            <li><a href="/blogs/<%= blog._id %>"><%= blog.title %></a></li>
        <% }) %>
    </ul>
</div>

<%- include('../partials/footer') %>        

Styling Our Application

Finally, let's add some basic styling in public/css/style.css:

body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
}

.container {
    width: 80%;
    margin: 0 auto;
    padding: 20px;
}

header {
    background: #333;
    color: #fff;
    padding: 10px 0;
}

/* More styles... */        

Conclusion

By following these steps, you'll have a functional, full-stack blog application. This project demonstrates the power of Node.js, Express, and MongoDB in creating robust web applications. It's a great starting point for more complex projects and can be easily extended with additional features like user authentication, comments, and more.

Remember, the key to becoming a proficient full-stack developer is practice and continuous learning. Don't hesitate to explore and add new features to this project!

Daxesh Italiya

Founder and CTO @TST Technology | Developing Cutting-Edge SaaS | Providing Cloud-based Solutions | Leveraging AI

7 个月

AYTEK?N KAPLAN Your article is helpful. Another thing you can add is Nodejs server monitoring. I suggest you explore the tool Wooffer https://wooffer.io/, It will be a beneficial part of your article.

要查看或添加评论,请登录

Aytekin Kaplan的更多文章

社区洞察

其他会员也浏览了