Create a Markdown Blog Using EJS and Express (Node.js)

by Khaleel Gibran

So, recently, I switched over my blogging from to here, which is It really is nice to have an in-built blog within your website using code without using a framework like Gatsby or Hexo. In this blog post, I'll be explaining how I created this blog, with all the code provided.

For this blog, I used Express along with EJS to magically render .md files. Assuming that you have a basic Express server set up, I'm gonna create a folder named blog.

mkdir blog
touch index.ejs
touch blog.ejs

Then, in your main Node.js script file (mine is server.js, most people have their main script at index.js), we need to configure the markdown parser, EJS and the blog directory. For that, we'll need to install a few packages.

npm i ejs markdown-it gray-matter body-parser

Once we've done that, we need to require all our dependencies in server.js (or index.js or whatever). We'll also be using the path module, but we don't need to install it because it is an in-built module.

// body parser
var bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: true }));

// path for the ejs folder
const path = require("path");

app.set("views", path.join(__dirname, "blog"));
app.set("view engine", "ejs");

// gray-matter to read the .md files better
const matter = require('gray-matter');

Then, we need to define our GET routes for the blog posts.

app.get("/blog/:article", (req, res) => {
  const file = + '/blog/' + req.params.article + '.md');
  var md = require("markdown-it")();
  let content = file.content;
  var result = md.render(content);
  res.render("index", {
    post: result,
    slug: req.params.article,

What is happening here is that, whenever a user visits /blog/article, the fs module looks in the blog directory for a .md file named article. (The URL of the blog post is taken from the file name minus the .md part).

Now, for this to work properly, every blog post markdown file should be in the following format:

title: Title Here
description: A nice description of this post
img: A nice image, mainly meant for the <meta> tags

Blog post content her

The format is the reason why I used the gray-matter package. And markdown-it converts the Markdown stuff to HTML.

Also, we need a GET route to show all our blog posts (blog.ejs).

app.get("/blog", (req, res) => {
  const posts = fs.readdirSync(__dirname + '/blog').filter(file => file.endsWith('.md'));
  res.render("blog", {
    posts: posts

And finally, for our EJS files. index.ejs

    <div id="blog">
      <%- post %>


    <div id="blog">
      <% for (post of posts) { %>
        <div class="post">
          <%= post.toUpperCase() %>  
      <% } %>

And that's it!

Of course, this is just a basic template for you to use, you can always add more HTML and style using CSS to customise according to your needs!

Any questions, tweet me on Twitter or send me a mail at

About the author 👦

Khaleel Gibran

I'm a thirteen year old web developer. I love donuts so much that it has become my symbol. I enjoy creating websites using HTML, CSS, JS, (severly obsessed with) Node.js, and (learning) React, by sitting on my bean bag and thinking a lot.

Made with , my laptop, Glitch, HTML, CSS, JavaScript, yadda yadda yadda by me.