Episode 11 of 12

Express Router & MVC

Learn how to organize your Express app using the Router and the MVC (Model-View-Controller) architectural pattern.

As your application grows, keeping everything in one file becomes unmanageable. The Express Router and MVC pattern help you organize your code into a clean, maintainable structure.

Express Router

The Router lets you split routes into separate files:

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

router.get('/', (req, res) => {
    Blog.find().sort({ createdAt: -1 })
        .then(blogs => res.render('blogs/index', { blogs }))
        .catch(err => console.log(err));
});

router.post('/', (req, res) => {
    const blog = new Blog(req.body);
    blog.save()
        .then(() => res.redirect('/blogs'))
        .catch(err => console.log(err));
});

router.get('/:id', (req, res) => {
    Blog.findById(req.params.id)
        .then(blog => res.render('blogs/details', { blog }))
        .catch(err => console.log(err));
});

module.exports = router;
// app.js
const blogRoutes = require('./routes/blogRoutes');
app.use('/blogs', blogRoutes);

The MVC Pattern

MVC separates your application into three layers:

  • Model — Data structure and database logic (Mongoose schemas)
  • View — What the user sees (EJS templates)
  • Controller — Handles requests and connects models to views

Creating Controllers

// controllers/blogController.js
const Blog = require('../models/blog');

const blog_index = (req, res) => {
    Blog.find().sort({ createdAt: -1 })
        .then(blogs => res.render('blogs/index', { blogs }))
        .catch(err => console.log(err));
};

const blog_details = (req, res) => {
    Blog.findById(req.params.id)
        .then(blog => res.render('blogs/details', { blog }))
        .catch(err => res.status(404).render('404'));
};

const blog_create_post = (req, res) => {
    const blog = new Blog(req.body);
    blog.save()
        .then(() => res.redirect('/blogs'))
        .catch(err => console.log(err));
};

module.exports = {
    blog_index,
    blog_details,
    blog_create_post
};

Project Structure

project/
├── app.js
├── models/
│   └── blog.js
├── views/
│   ├── partials/
│   └── blogs/
├── controllers/
│   └── blogController.js
├── routes/
│   └── blogRoutes.js
└── public/
    └── styles.css

This clean separation makes your code easier to maintain, test, and scale.