Skip to content

Instantly share code, notes, and snippets.

@panphora
Created September 6, 2025 13:30
Show Gist options
  • Save panphora/fbd2045fc96a644357e5eb1c63142f41 to your computer and use it in GitHub Desktop.
Save panphora/fbd2045fc96a644357e5eb1c63142f41 to your computer and use it in GitHub Desktop.

Simple Markdown Blog for Cloudflare Pages

A minimal static blog generator that converts markdown files into a single HTML page. Perfect for hosting on Cloudflare Pages.

How It Works

This build system:

  1. Reads all .md files in your directory
  2. Converts them to HTML using the marked library
  3. Inserts them into your HTML template using JavaScript template literals
  4. Outputs a single index.html file

Files You'll Need

package.json

{
  "name": "simple-blog",
  "version": "1.0.0",
  "scripts": {
    "build": "node build.js"
  },
  "dependencies": {
    "marked": "^9.0.0"
  }
}

build.js

const fs = require('fs');
const { marked } = require('marked');

// Read and parse all markdown files
const posts = fs.readdirSync('.')
  .filter(f => f.endsWith('.md'))
  .sort()
  .map(file => {
    const content = fs.readFileSync(file, 'utf8');
    const html = marked(content);
    const name = file.replace('.md', '');
    
    // Extract first heading as title (optional)
    const titleMatch = content.match(/^# (.+)$/m);
    const title = titleMatch ? titleMatch[1] : name;
    
    // Extract date from filename if it starts with YYYY-MM-DD
    const dateMatch = file.match(/^(\d{4}-\d{2}-\d{2})/);
    const date = dateMatch ? dateMatch[1] : null;
    
    return {
      id: name,
      title,
      content: html,
      filename: file,
      date
    };
  });

// Sort by date if dates exist (newest first)
posts.sort((a, b) => {
  if (a.date && b.date) return b.date.localeCompare(a.date);
  return 0;
});

// Read template and evaluate as template literal
const template = fs.readFileSync('blog.html', 'utf8');
const output = eval('`' + template + '`');

// Write output
fs.writeFileSync('index.html', output);
console.log(`✓ Built blog with ${posts.length} posts`);

blog.html (Template)

<!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>
  <style>
    body {
      max-width: 700px;
      margin: 0 auto;
      padding: 2rem;
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
      line-height: 1.6;
      color: #333;
    }
    article {
      margin-bottom: 4rem;
      padding-bottom: 2rem;
      border-bottom: 1px solid #eee;
    }
    article:last-child {
      border-bottom: none;
    }
    h1 { color: #000; }
    h2 { margin-top: 2rem; }
    pre {
      background: #f6f6f6;
      padding: 1rem;
      border-radius: 4px;
      overflow-x: auto;
    }
    code {
      background: #f6f6f6;
      padding: 0.2em 0.4em;
      border-radius: 3px;
      font-size: 0.9em;
    }
    pre code {
      background: none;
      padding: 0;
    }
    .post-date {
      color: #666;
      font-size: 0.9em;
    }
  </style>
</head>
<body>
  <header>
    <h1>My Blog</h1>
  </header>
  
  <main>
    ${posts.map(post => `
      <article id="${post.id}">
        ${post.date ? `<div class="post-date">${post.date}</div>` : ''}
        ${post.content}
      </article>
    `).join('\n')}
  </main>
  
  <footer>
    <p>Total posts: ${posts.length}</p>
  </footer>
</body>
</html>

Example Markdown Post: 2024-01-15-hello-world.md

# Hello World

This is my first blog post using this simple static generator.

## Features

- Simple markdown parsing
- No complex build tools
- Single page output
- Perfect for Cloudflare Pages

Here's some `inline code` and a code block:

```js
console.log('Hello from my blog!');

Bold text and italic text work too, along with links.


## Deploying to Cloudflare Pages

### Step 1: Create a GitHub Repository

1. Create a new repository on GitHub
2. Add all the files above to your repo
3. Add your markdown posts (`.md` files)
4. Commit and push everything

### Step 2: Connect to Cloudflare Pages

1. Log into [Cloudflare Dashboard](https://dash.cloudflare.com/)
2. Go to "Pages" in the sidebar
3. Click "Create a project"
4. Choose "Connect to Git"
5. Select your GitHub repository

### Step 3: Configure Build Settings

When Cloudflare asks for build configuration, use:

- **Build command:** `npm run build`
- **Build output directory:** `/`
- **Root directory:** Leave empty (or `/`)
- **Node.js version:** Use default (or specify 18+)

### Step 4: Deploy

Click "Save and Deploy". Cloudflare will:
1. Clone your repository
2. Run `npm install` (installs `marked`)
3. Run `npm run build` (executes `build.js`)
4. Serve your generated `index.html`

## Adding New Posts

To add a new blog post:

1. Create a new `.md` file in your repository
2. Optionally use the format `YYYY-MM-DD-title.md` for automatic date sorting
3. Commit and push to GitHub
4. Cloudflare Pages will automatically rebuild and deploy

## Tips

- **Post Order:** Name files with dates (`2024-01-15-my-post.md`) for chronological sorting
- **Styling:** Modify the CSS in `blog.html` to customize appearance
- **Template Power:** You can use any JavaScript in the template - add navigation, categories, search, etc.
- **Images:** Store images in your repo and reference them with relative paths in markdown

## Troubleshooting

If the build fails on Cloudflare:
- Check the build logs in Cloudflare Pages dashboard
- Ensure `package.json` is in the root directory
- Verify all files are committed to GitHub
- Make sure there are no syntax errors in your template

That's it! Your blog will be live at `your-project.pages.dev` within minutes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment