Freedom Sale
Independence Day Special — Unlock the AI Path 70% off our most popular AI course · Limited time offer
--Days
--Hrs
--Min
--Sec
Claim Your Discount
✦ Intermediate ⏱ 40 min

✍️ Build a Markdown Blog with HTML, CSS & JavaScript

🎯 What You'll Build

A lightweight blog where posts are written in Markdown files and rendered beautifully in the browser — no server, no CMS, no database needed.

📋 What You'll Need

1

Understand the approach

We write posts as .md files, load them with fetch(), parse Markdown to HTML using a tiny parser, and render them. The whole blog runs from a single index.html.

// File structure:
// index.html        ← the app shell
// style.css         ← styling
// posts/
//   hello-world.md  ← your first post
//   my-second-post.md
2

Write your first Markdown post

Create posts/hello-world.md — standard Markdown syntax works out of the box.

---
title: Hello World
date: 2026-08-09
author: Your Name
---

# Hello, World!

Welcome to my blog. This post is written in **Markdown** and rendered live in the browser.

## Why Markdown?

- Clean and readable as plain text
- Converts to HTML automatically
- Portable — works with any static site generator

## Code example

```python
def greet(name):
    return f"Hello, {name}!"

print(greet("World"))
```

> *"The best way to predict the future is to build it."*
3

Build the HTML shell and Markdown parser

Create index.html with a simple Markdown-to-HTML parser using regex replacements.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My Blog</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>

<?php require_once __DIR__ . '/../promo_banner.php'; ?>

  <header>
    <a href="#" onclick="showList()" class="logo">My Blog</a>
  </header>
  <main id="app"></main>
  <script>
  // Simple Markdown → HTML parser
  function parseMarkdown(md) {
    // Remove frontmatter (--- ... ---)
    md = md.replace(/^---[\s\S]*?---\n/, '');

    return md
      .replace(/^### (.+)$/gm, '<h3>$1</h3>')
      .replace(/^## (.+)$/gm,  '<h2>$1</h2>')
      .replace(/^# (.+)$/gm,   '<h1>$1</h1>')
      .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
      .replace(/\*(.+?)\*/g,     '<em>$1</em>')
      .replace(/`([^`]+)`/g,     '<code>$1</code>')
      .replace(/```[\w]*\n([\s\S]*?)```/g, '<pre><code>$1</code></pre>')
      .replace(/^> (.+)$/gm,     '<blockquote>$1</blockquote>')
      .replace(/^\- (.+)$/gm,    '<li>$1</li>')
      .replace(/(<li>.*<\/li>\n?)+/g, '<ul>$&</ul>')
      .replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>')
      .replace(/\n\n/g, '</p><p>')
      .replace(/^(?!<[hupbac])/gm, '<p>')
      .replace(/(?<![>])$/gm, '</p>');
  }

  // Extract frontmatter value
  function getMeta(md, key) {
    const match = md.match(new RegExp(`^${key}:\\s*(.+)$`, 'm'));
    return match ? match[1].trim() : '';
  }
  </script>
  <script src="app.js"></script>
</body>
</html>
4

Load and display posts

Define your post list in app.js, load them with fetch(), and render them.

// app.js

// List all your posts here
const POSTS = [
  { slug: 'hello-world',    title: 'Hello World',         date: '2026-08-09' },
  { slug: 'my-second-post', title: 'My Second Post',      date: '2026-08-10' },
];

function showList() {
  const app = document.getElementById('app');
  app.innerHTML = `
    <div class="post-list">
      <h1>All Posts</h1>
      ${POSTS.map(p => `
        <div class="post-card" onclick="showPost('${p.slug}')">
          <div class="post-date">${p.date}</div>
          <h2>${p.title}</h2>
          <span class="read-link">Read →</span>
        </div>
      `).join('')}
    </div>`;
}

async function showPost(slug) {
  const res  = await fetch(`posts/${slug}.md`);
  const text = await res.text();
  const html = parseMarkdown(text);
  const title = getMeta(text, 'title');
  const date  = getMeta(text, 'date');

  document.getElementById('app').innerHTML = `
    <article class="post">
      <div class="post-meta">
        <span class="back" onclick="showList()">← All Posts</span>
        <span>${date}</span>
      </div>
      <div class="post-content">${html}</div>
    </article>`;
}

// Start on the post list
showList();
[Blog homepage shows:]
  All Posts
  ─────────────────────────
  2026-08-09  Hello World         Read →
  2026-08-10  My Second Post      Read →

[Click a post — beautifully rendered Markdown with headings, code blocks, bold text]
💡 Tip: To deploy this blog for free: push the folder to a GitHub repo, go to Settings → Pages, and set source to "main branch / root". Your blog is live at yourusername.github.io/repo-name in under 2 minutes.

🎉 You Did It!

Your blog has no backend, no database, no hosting costs. Add a new post by dropping a .md file in /posts/ and adding one line to the POSTS array in app.js. For syntax highlighting in code blocks, add highlight.js with one script tag.

Found something wrong?

Spotted a bug, broken code, or something that doesn't look right? Tell us what's off and we'll fix it.